🎉 init: 小龙的工作空间

This commit is contained in:
大海
2026-06-06 10:40:48 +08:00
commit a188ee1426
3201 changed files with 231817 additions and 0 deletions
+65
View File
@@ -0,0 +1,65 @@
/**
* PR-A Baseline Smoke Test
* Quick end-to-end sanity check before running full test suite.
* Verifies that essential tools are available and the system is in a testable state.
*/
import { describe, it } from "node:test";
import assert from "node:assert";
import { execSync } from "node:child_process";
import { existsSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
describe("PR-A Smoke Test", () => {
it("smoke: node version >= 22", () => {
const v = process.version;
const major = parseInt(v.split(".")[0].replace("v", ""));
console.log("[SMOKE] Node.js version:", v);
assert.ok(major >= 22, `node >= 22 required, got ${v}`);
});
it("smoke: openclaw CLI available", () => {
const out = execSync("openclaw --version 2>&1", {
timeout: 10000,
encoding: "utf8",
});
console.log("[SMOKE] openclaw:", out.trim().split("\n")[0]);
assert.ok(out.includes("OpenClaw"), "openclaw CLI must be available");
});
it("smoke: gateway is reachable", () => {
const out = execSync("openclaw status 2>&1", {
timeout: 15000,
encoding: "utf8",
});
const isRunning = out.includes("running") || out.includes("active") || out.includes("reachable");
console.log("[SMOKE] gateway running:", isRunning);
assert.ok(isRunning, "gateway must be running");
});
it("smoke: workspace exists", () => {
const ws = join(homedir(), ".openclaw", "workspace");
assert.ok(existsSync(ws), "workspace must exist");
console.log("[SMOKE] workspace:", ws);
});
it("smoke: memory system functional", () => {
const out = execSync("openclaw memory status --json 2>/dev/null", {
timeout: 15000,
encoding: "utf8",
});
const status = JSON.parse(out);
console.log("[SMOKE] memory status: OK");
assert.ok(Array.isArray(status), "memory status must be an array");
});
it("smoke: config loads without error", () => {
const out = execSync("openclaw config get gateway.port 2>&1", {
timeout: 10000,
encoding: "utf8",
});
console.log("[SMOKE] gateway port:", out.trim());
assert.ok(out.length > 0, "config must return value");
});
});
@@ -0,0 +1,91 @@
/**
* PR-A Baseline Test 01: Gateway Startup
* Verifies: gateway process is running and reachable
* Freezes: gateway startup contract
*/
import { describe, it } from "node:test";
import assert from "node:assert";
import { execSync } from "node:child_process";
import { request } from "node:http";
import { readFileSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
const AGENTS_HOME = join(homedir(), ".openclaw");
let _config, _port;
function loadConfig() {
if (!_config) {
_config = JSON.parse(readFileSync(join(AGENTS_HOME, "openclaw.json"), "utf8"));
_port = _config?.gateway?.port || 18789;
}
return { config: _config, gatewayPort: _port };
}
function httpGet(host, port, path) {
return new Promise((resolve, reject) => {
const req = request({ hostname: host, port, path, method: "GET", timeout: 10000 }, (res) => {
let body = "";
res.on("data", (d) => (body += d));
res.on("end", () => resolve({ status: res.statusCode, body }));
});
req.on("error", reject);
req.on("timeout", () => { req.destroy(); reject(new Error("timeout")); });
req.end();
});
}
describe("test-01: Gateway Startup Baseline", () => {
it("01.01 - gateway config exists", () => {
const { config } = loadConfig();
assert.ok(config, "config should be loaded");
assert.ok(config.gateway, "gateway section should exist");
});
it("01.02 - gateway bind port is defined", () => {
const { gatewayPort } = loadConfig();
assert.ok(gatewayPort > 0 && gatewayPort < 65536, `port ${gatewayPort} must be valid`);
});
it("01.03 - gateway is reachable via HTTP", async () => {
const { gatewayPort } = loadConfig();
const result = await httpGet("127.0.0.1", gatewayPort, "/");
assert.ok(result.status >= 200 && result.status < 400,
`gateway HTTP must respond with 2xx/3xx, got ${result.status}`);
});
it("01.04 - gateway status reports running", () => {
const out = execSync("openclaw status --json 2>/dev/null", { timeout: 15000, encoding: "utf8" }).trim();
assert.ok(out.length > 0, "openclaw status must produce output");
try {
const s = JSON.parse(out);
assert.ok(s, "status must be valid JSON");
} catch {
assert.ok(!out.toLowerCase().includes("error"), "status must not report error");
}
});
it("01.05 - gateway process is not crashing (baseline snapshot)", () => {
const out = execSync("openclaw status 2>&1", { timeout: 15000, encoding: "utf8" }).trim();
const isRunning = out.includes("running") || out.includes("active") || out.includes("reachable");
console.log("[BASELINE] gateway status snapshot:", out.substring(0, 300));
assert.ok(isRunning, "gateway must be running");
});
it("01.06 - memory index is accessible", () => {
const out = execSync("openclaw memory status --json 2>/dev/null", { timeout: 15000, encoding: "utf8" }).trim();
const s = JSON.parse(out);
assert.ok(Array.isArray(s) && s.length > 0, "at least one agent memory entry");
const main = s.find((e) => e.agentId === "main");
assert.ok(main, "main agent must have memory");
console.log("[BASELINE] memory backend: %s, files: %d, chunks: %d",
main.status.backend, main.status.files, main.status.chunks);
});
it("01.07 - gateway auth mode recorded", () => {
const { config } = loadConfig();
const mode = config?.gateway?.auth?.mode;
console.log("[BASELINE] gateway auth mode:", mode);
assert.ok(mode, "gateway auth mode must be defined");
});
});
@@ -0,0 +1,83 @@
/**
* PR-A Baseline Test 02: Session Creation
* Verifies: sessions can be created, read, and have persistent state
* Freezes: session creation contract
*/
import { describe, it } from "node:test";
import assert from "node:assert";
import { execSync } from "node:child_process";
import { existsSync, readFileSync, readdirSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
const AGENTS_HOME = join(homedir(), ".openclaw");
const SESSIONS_DIR = join(AGENTS_HOME, "agents", "main", "sessions");
describe("test-02: Session Creation Baseline", () => {
it("02.01 - sessions directory exists", () => {
const exists = existsSync(SESSIONS_DIR);
console.log("[BASELINE] sessions dir:", SESSIONS_DIR);
console.log("[BASELINE] sessions dir exists:", exists);
// Directory might not exist if no sessions created yet — that's valid baseline
if (!exists) {
console.log("[BASELINE] No sessions directory — no sessions created yet (valid baseline)");
}
assert.ok(true, "baseline frozen: sessions dir check");
});
it("02.02 - can list existing sessions", () => {
const out = execSync("openclaw status --json 2>/dev/null", {
timeout: 15000,
encoding: "utf8",
}).trim();
try {
const s = JSON.parse(out);
console.log("[BASELINE] sessions count:", s.sessionCount ?? "unknown");
assert.ok(typeof s === "object", "status must be an object");
} catch {
// Text output is fine
assert.ok(out.length > 0, "status must produce output");
}
});
it("02.03 - session store directory structure recorded", () => {
if (existsSync(SESSIONS_DIR)) {
const files = readdirSync(SESSIONS_DIR).filter(
(f) => f.endsWith(".json") || f.endsWith(".md")
);
console.log("[BASELINE] session files count:", files.length);
console.log("[BASELINE] session file types:",
[...new Set(files.map(f => f.slice(f.lastIndexOf('.'))))].join(", "));
assert.ok(Array.isArray(files), "session files must be listable");
} else {
console.log("[BASELINE] No session files to inspect (valid baseline)");
}
assert.ok(true, "baseline frozen: session dir structure");
});
it("02.04 - workspace files are accessible (session context)", () => {
const workspaceDir = join(AGENTS_HOME, "workspace");
const keyFiles = ["AGENTS.md", "SOUL.md", "MEMORY.md"];
for (const f of keyFiles) {
const path = join(workspaceDir, f);
const exists = existsSync(path);
const size = exists ? readFileSync(path, "utf8").length : 0;
console.log(`[BASELINE] workspace/${f}: exists=${exists}, size=${size}`);
}
assert.ok(existsSync(join(workspaceDir, "AGENTS.md")), "AGENTS.md must exist");
assert.ok(existsSync(join(workspaceDir, "MEMORY.md")), "MEMORY.md must exist");
});
it("02.05 - session write lock mechanism exists", () => {
// Check if proper-lockfile is available (used for session locking)
try {
require.resolve("proper-lockfile");
console.log("[BASELINE] proper-lockfile: available (session locking)");
assert.ok(true, "session locking library available");
} catch {
console.log("[BASELINE] proper-lockfile: not resolvable (may be bundled)");
assert.ok(true, "baseline frozen: lockfile check");
}
});
});
@@ -0,0 +1,108 @@
/**
* PR-A Baseline Test 03: memory_search Current Behavior
* Verifies: memory_search tool exists, has stable schema, returns stable format
* Freezes: memory_search contract
*/
import { describe, it } from "node:test";
import assert from "node:assert";
import { execSync } from "node:child_process";
describe("test-03: memory_search Baseline", () => {
it("03.01 - memory_search CLI returns JSON", () => {
const out = execSync(
'openclaw memory search "hello world" --json 2>/dev/null',
{ timeout: 15000, encoding: "utf8" }
).trim();
assert.ok(out.length > 0, "memory search must produce output");
try {
const result = JSON.parse(out);
assert.ok(typeof result === "object", "must be JSON object");
console.log("[BASELINE] memory_search result keys:", Object.keys(result).join(", "));
console.log("[BASELINE] memory_search results count:",
result.results?.length ?? "N/A");
} catch (e) {
console.log("[BASELINE] memory_search output (not JSON):", out.substring(0, 200));
assert.ok(!out.toLowerCase().includes("error"), "must not error");
}
});
it("03.02 - memory_search returns results array", () => {
const out = execSync(
'openclaw memory search "AGENTS.md" --json 2>/dev/null',
{ timeout: 15000, encoding: "utf8" }
).trim();
try {
const result = JSON.parse(out);
const results = result.results || [];
console.log("[BASELINE] search 'AGENTS.md' results:", results.length);
if (results.length > 0) {
const first = results[0];
console.log("[BASELINE] first result keys:", Object.keys(first).join(", "));
console.log("[BASELINE] first result file:", first.file || first.path || "N/A");
console.log("[BASELINE] first result score:", first.score ?? "N/A");
}
assert.ok(Array.isArray(results), "results must be array");
} catch {
console.log("[BASELINE] search output raw:", out.substring(0, 300));
}
assert.ok(true, "baseline frozen: search results shape");
});
it("03.03 - memory_search schema stable (empty query)", () => {
const out = execSync(
'openclaw memory search "___nonexistent_xyzzy___" --json 2>/dev/null',
{ timeout: 15000, encoding: "utf8" }
).trim();
try {
const result = JSON.parse(out);
const results = result.results || [];
console.log("[BASELINE] empty search results:", results.length);
// Empty results should not error
} catch {
console.log("[BASELINE] empty search raw:", out.substring(0, 200));
}
assert.ok(true, "baseline frozen: empty search behavior");
});
it("03.04 - memory_search handles special characters", () => {
const queries = [
"中文测试",
"test-123",
"hello/world",
"a.b.c",
];
for (const q of queries) {
const out = execSync(
`openclaw memory search "${q}" --json 2>/dev/null`,
{ timeout: 15000, encoding: "utf8" }
).trim();
try {
JSON.parse(out);
console.log(`[BASELINE] search "${q}": OK (valid JSON)`);
} catch {
console.log(`[BASELINE] search "${q}": non-JSON output`);
}
assert.ok(!out.toLowerCase().includes("fatal"), `query "${q}" must not crash`);
}
});
it("03.05 - memory_search contract: result object shape", () => {
const out = execSync(
'openclaw memory search "architecture" --json 2>/dev/null',
{ timeout: 15000, encoding: "utf8" }
).trim();
try {
const result = JSON.parse(out);
// Freeze the top-level keys
const topKeys = Object.keys(result).sort();
console.log("[BASELINE] memory_search response keys:", topKeys.join(", "));
// There must be a 'results' key
assert.ok("results" in result || topKeys.length > 0,
"must have results key or be non-empty object");
} catch {
console.log("[BASELINE] raw response:", out.substring(0, 300));
}
assert.ok(true, "baseline frozen: contract shape");
});
});
+71
View File
@@ -0,0 +1,71 @@
/**
* PR-A Baseline Test 04: memory_get Current Behavior
* Verifies: memory_get tool exists, can read files, stable error format
* Freezes: memory_get contract
*/
import { describe, it } from "node:test";
import assert from "node:assert";
import { existsSync, readFileSync, statSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
const WORKSPACE = join(homedir(), ".openclaw", "workspace");
describe("test-04: memory_get Baseline", () => {
it("04.01 - MEMORY.md exists and is readable", () => {
const path = join(WORKSPACE, "MEMORY.md");
assert.ok(existsSync(path), "MEMORY.md must exist");
const content = readFileSync(path, "utf8");
const lines = content.split("\n").length;
const size = content.length;
console.log("[BASELINE] MEMORY.md: size=%d bytes, lines=%d", size, lines);
assert.ok(size > 0, "MEMORY.md must not be empty");
});
it("04.02 - daily memory files exist", () => {
const dailyDir = join(WORKSPACE, "memory");
const today = new Date().toISOString().slice(0, 10);
const dailyFile = join(dailyDir, `${today}.md`);
console.log("[BASELINE] today:", today);
console.log("[BASELINE] daily file:", dailyFile);
console.log("[BASELINE] daily file exists:", existsSync(dailyFile));
assert.ok(existsSync(dailyDir), "memory/ directory must exist");
});
it("04.03 - workspace files measurable", () => {
const files = ["AGENTS.md", "SOUL.md", "MEMORY.md", "USER.md", "TOOLS.md"];
for (const f of files) {
const path = join(WORKSPACE, f);
if (existsSync(path)) {
const stat = statSync(path);
console.log(`[BASELINE] ${f}: size=${stat.size}, mtime=${stat.mtime.toISOString()}`);
} else {
console.log(`[BASELINE] ${f}: NOT FOUND`);
}
}
assert.ok(true, "baseline frozen: workspace file inventory");
});
it("04.04 - memory_get for nonexistent file returns stable error", () => {
// memory_get behavior for missing file: should not crash, should return structured error
const nonexistent = "___nonexistent_file_xyzzy___.md";
const path = join(WORKSPACE, nonexistent);
assert.ok(!existsSync(path), "test file must not exist");
console.log("[BASELINE] nonexistent file check: path=", path);
// This just verifies the file doesn't exist — the tool behavior
// when requesting a missing file would be tested via the actual tool API
assert.ok(true, "baseline frozen: missing file expectation");
});
it("04.05 - memory file encoding is UTF-8", () => {
const path = join(WORKSPACE, "MEMORY.md");
const buf = readFileSync(path);
// Check for BOM (should not be present)
const hasBOM = buf[0] === 0xEF && buf[1] === 0xBB && buf[2] === 0xBF;
console.log("[BASELINE] MEMORY.md has BOM:", hasBOM);
// Read as utf8 should succeed
const content = readFileSync(path, "utf8");
assert.ok(content.length > 0, "MEMORY.md must decode as UTF-8");
});
});
+94
View File
@@ -0,0 +1,94 @@
/**
* PR-A Baseline Test 05: exec Tool Current Behavior
* Verifies: shell command execution returns stdout/stderr/exitCode correctly
* Freezes: exec tool contract
*/
import { describe, it } from "node:test";
import assert from "node:assert";
import { execSync, spawnSync } from "node:child_process";
import { homedir } from "node:os";
import { join } from "node:path";
const GATEWAY_URL = "http://127.0.0.1:18789";
describe("test-05: exec Tool Baseline", () => {
it("05.01 - local shell execution works (node child_process)", () => {
const result = spawnSync("echo", ["hello"], {
encoding: "utf8",
timeout: 5000,
});
console.log("[BASELINE] echo hello stdout:", JSON.stringify(result.stdout.trim()));
console.log("[BASELINE] echo hello stderr:", JSON.stringify(result.stderr));
console.log("[BASELINE] echo hello status:", result.status);
assert.equal(result.stdout.trim(), "hello", "echo must output hello");
assert.equal(result.status, 0, "exit code must be 0");
});
it("05.02 - shell error exit codes are preserved", () => {
const result = spawnSync("sh", ["-c", "exit 42"], {
encoding: "utf8",
timeout: 5000,
});
console.log("[BASELINE] exit 42 status:", result.status);
assert.equal(result.status, 42, "exit code must be preserved exactly");
});
it("05.03 - shell stderr is captured separately", () => {
const result = spawnSync("sh", ["-c", "echo stdout-text && echo stderr-text >&2"], {
encoding: "utf8",
timeout: 5000,
});
console.log("[BASELINE] stdout:", JSON.stringify(result.stdout.trim()));
console.log("[BASELINE] stderr:", JSON.stringify(result.stderr.trim()));
assert.ok(result.stdout.includes("stdout-text"), "stdout must contain message");
assert.ok(result.stderr.includes("stderr-text"), "stderr must contain message");
});
it("05.04 - shell output encoding is UTF-8", () => {
const result = spawnSync("sh", ["-c", "echo 你好世界"], {
encoding: "utf8",
timeout: 5000,
});
console.log("[BASELINE] UTF-8 output:", JSON.stringify(result.stdout.trim()));
assert.ok(result.stdout.includes("你好世界"), "UTF-8 must be preserved");
});
it("05.05 - shell timeout kills process", () => {
const start = Date.now();
const result = spawnSync("sleep", ["10"], {
encoding: "utf8",
timeout: 2000, // 2 second timeout
});
const elapsed = Date.now() - start;
console.log("[BASELINE] sleep 10 timeout: elapsed=%dms, killed=%s",
elapsed, result.signal || "none");
// Process should be killed by timeout
assert.ok(result.signal === "SIGTERM" || result.status !== 0 || elapsed < 10000,
"long-running process must be terminated by timeout");
});
it("05.06 - exec tool: binary output handling", () => {
// Create a null-byte test
const result = spawnSync("printf", ["\\x00hello\\x00"], {
encoding: "buffer",
timeout: 5000,
});
console.log("[BASELINE] binary stdout length:", result.stdout.length);
console.log("[BASELINE] binary stdout bytes:",
Array.from(result.stdout.slice(0, 10)).map(b => '0x' + b.toString(16)).join(' '));
assert.ok(result.stdout.includes(0x68), "output must contain 'h' (0x68)");
});
it("05.07 - exec tool: large output handled", () => {
// Generate 10KB of output
const result = spawnSync("sh", ["-c", "yes head | head -1000"], {
encoding: "utf8",
timeout: 5000,
maxBuffer: 1024 * 1024,
});
const lines = result.stdout.trim().split("\n").length;
console.log("[BASELINE] large output: lines=%d, bytes=%d", lines, result.stdout.length);
assert.ok(lines > 100, "large output must be captured");
});
});
@@ -0,0 +1,85 @@
/**
* PR-A Baseline Test 06: Agent Complete Reply
* Verifies: agent can produce a reply via openclaw CLI
* Freezes: agent reply contract
*
* Uses openclaw agent CLI to send a test message and verify reply structure.
*/
import { describe, it } from "node:test";
import assert from "node:assert";
import { execSync } from "node:child_process";
describe("test-06: Agent Reply Baseline", () => {
it("06.01 - agent CLI exists and shows help", () => {
const out = execSync("openclaw agent --help 2>&1", {
timeout: 10000,
encoding: "utf8",
}).trim();
console.log("[BASELINE] agent help first 300 chars:", out.substring(0, 300));
assert.ok(out.includes("agent") || out.includes("turn"),
"agent CLI must exist and show help");
});
it("06.02 - agent run command structure recorded", () => {
// Freeze the CLI interface shape
const out = execSync("openclaw agent --help 2>&1", {
timeout: 10000,
encoding: "utf8",
});
const hasMessage = out.includes("message") || out.includes("prompt") || out.includes("text");
const hasTimeout = out.includes("timeout") || out.includes("Time");
const hasModel = out.includes("model") || out.includes("Model");
console.log("[BASELINE] agent has --message param:", hasMessage);
console.log("[BASELINE] agent has --timeout param:", hasTimeout);
console.log("[BASELINE] agent has --model param:", hasModel);
assert.ok(true, "baseline frozen: agent CLI interface shape");
});
it("06.03 - gateway agent endpoint is documented", () => {
// Check the gateway protocol docs for agent method
const docPath = "/opt/homebrew/lib/node_modules/openclaw/docs/gateway/protocol.md";
try {
const doc = execSync(`head -200 "${docPath}" 2>/dev/null`, {
timeout: 5000,
encoding: "utf8",
});
console.log("[BASELINE] protocol docs exist:", doc.length > 0);
} catch {
console.log("[BASELINE] protocol docs: not directly readable (npm install)");
}
assert.ok(true, "baseline frozen: agent endpoint documentation");
});
it("06.04 - session/agent persistence directory exists", () => {
const out = execSync("openclaw status --json 2>/dev/null", {
timeout: 10000,
encoding: "utf8",
}).trim();
try {
const s = JSON.parse(out);
console.log("[BASELINE] agent info:", JSON.stringify({
agents: s.agents,
sessions: s.sessionCount,
defaultAgent: s.defaultAgent,
}, null, 2));
assert.ok(typeof s === "object", "status must be object");
} catch {
assert.ok(out.length > 0, "status must produce output");
}
});
it("06.05 - model providers are configured", () => {
try {
const configPath = homedir() + "/.openclaw/openclaw.json";
const config = JSON.parse(readFileSync(configPath, "utf8"));
const providers = config?.models?.providers ?? {};
const providerIds = Object.keys(providers);
console.log("[BASELINE] configured model providers:", providerIds.join(", "));
assert.ok(providerIds.length > 0, "at least one model provider must be configured");
} catch (e) {
console.log("[BASELINE] config read error:", e.message);
assert.ok(true, "baseline frozen: provider config existence");
}
});
});
@@ -0,0 +1,101 @@
/**
* PR-A Baseline Test 07: MCP Tool Discovery
* Verifies: MCP integration exists, tools can be discovered
* Freezes: MCP tool discovery contract
*/
import { describe, it } from "node:test";
import assert from "node:assert";
import { existsSync, readFileSync, readdirSync } from "node:fs";
import { join } from "node:path";
const OPENCLAW_HOME = "/opt/homebrew/lib/node_modules/openclaw";
const EXTENSIONS_DIR = join(OPENCLAW_HOME, "dist", "extensions");
const MCP_DIR = join(OPENCLAW_HOME, "dist", "mcp");
describe("test-07: MCP Tool Discovery Baseline", () => {
it("07.01 - MCP SDK is a dependency", () => {
const pkgPath = join(OPENCLAW_HOME, "package.json");
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
const mcpDep = pkg.dependencies?.["@modelcontextprotocol/sdk"];
console.log("[BASELINE] MCP SDK version:", mcpDep);
assert.ok(mcpDep, "@modelcontextprotocol/sdk must be a dependency");
});
it("07.02 - MCP module exists in dist", () => {
const exists = existsSync(MCP_DIR);
console.log("[BASELINE] MCP dir exists:", exists);
if (exists) {
const files = readdirSync(MCP_DIR);
console.log("[BASELINE] MCP dir files:", files.join(", "));
}
assert.ok(exists || existsSync(EXTENSIONS_DIR),
"MCP or extensions directory must exist");
});
it("07.03 - MCP API module exports recorded", () => {
const apiPath = join(MCP_DIR, "api.js");
if (existsSync(apiPath)) {
const size = readFileSync(apiPath, "utf8").length;
console.log("[BASELINE] MCP api.js size:", size);
assert.ok(size > 100, "MCP api.js must be substantial");
} else {
console.log("[BASELINE] MCP api.js not at expected path (checking alternative)");
// Check plugin-tools-serve
const servePath = join(MCP_DIR, "plugin-tools-serve.js");
if (existsSync(servePath)) {
console.log("[BASELINE] MCP plugin-tools-serve.js: exists");
}
}
assert.ok(true, "baseline frozen: MCP module existence");
});
it("07.04 - MCP index exports recorded", () => {
const indexPath = join(MCP_DIR, "index.js");
if (existsSync(indexPath)) {
const content = readFileSync(indexPath, "utf8");
const exports = content.match(/export\s+(?:const|function|class|default)\s+(\w+)/g) || [];
console.log("[BASELINE] MCP index exports:", exports.map(e => e.split(/\s+/)[2]).join(", "));
assert.ok(exports.length > 0, "MCP index must have exports");
} else {
console.log("[BASELINE] MCP index.js: not found at expected path");
}
assert.ok(true, "baseline frozen: MCP exports");
});
it("07.05 - MCP protocol SDK version checked", () => {
// Find actual MCP SDK
try {
const mcpSdkPath = require.resolve("@modelcontextprotocol/sdk/package.json", {
paths: [OPENCLAW_HOME],
});
const mcpPkg = JSON.parse(readFileSync(mcpSdkPath, "utf8"));
console.log("[BASELINE] MCP SDK actual version:", mcpPkg.version);
console.log("[BASELINE] MCP SDK location:", mcpSdkPath);
assert.ok(mcpPkg.version, "MCP SDK must have version");
} catch (e) {
console.log("[BASELINE] MCP SDK not resolvable:", e.message);
// SDK might be bundled differently in production
}
assert.ok(true, "baseline frozen: MCP SDK check");
});
it("07.06 - codex-mcp-projection module exists", () => {
// Check plugin-sdk exports
const sdkPath = join(OPENCLAW_HOME, "dist", "plugin-sdk", "index.js");
if (existsSync(sdkPath)) {
const content = readFileSync(sdkPath, "utf8");
const hasMCP = content.includes("codex-mcp-projection") || content.includes("mcp");
console.log("[BASELINE] plugin-sdk index contains MCP reference:", hasMCP);
}
// Check dist for mcp-related files
try {
const result = execSync(
`find "${OPENCLAW_HOME}/dist" -name "*mcp*" -o -name "*MCP*" 2>/dev/null | head -10`,
{ timeout: 5000, encoding: "utf8" }
);
console.log("[BASELINE] dist MCP-related files:\n" + (result.trim() || "(none found)"));
} catch {}
assert.ok(true, "baseline frozen: MCP projection check");
});
});
+109
View File
@@ -0,0 +1,109 @@
/**
* PR-A Baseline Test 08: Config Loading
* Verifies: config loads correctly, invalid config is rejected
* Freezes: config loading contract
*/
import { describe, it } from "node:test";
import assert from "node:assert";
import { execSync } from "node:child_process";
import { existsSync, readFileSync, writeFileSync, unlinkSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
const CONFIG_PATH = join(homedir(), ".openclaw", "openclaw.json");
const TEMP_INVALID_CONFIG = join(homedir(), ".openclaw", "openclaw-invalid-test.json");
describe("test-08: Config Loading Baseline", () => {
it("08.01 - config file exists and is valid JSON", () => {
assert.ok(existsSync(CONFIG_PATH), "openclaw.json must exist");
const content = readFileSync(CONFIG_PATH, "utf8");
let parsed;
try {
parsed = JSON.parse(content);
} catch (e) {
assert.fail(`config must be valid JSON: ${e.message}`);
}
console.log("[BASELINE] config top-level keys:", Object.keys(parsed).join(", "));
assert.ok(typeof parsed === "object", "config must be object");
});
it("08.02 - config sections recorded", () => {
const config = JSON.parse(readFileSync(CONFIG_PATH, "utf8"));
const sections = {
gateway: !!config.gateway,
agents: !!config.agents,
models: !!config.models,
plugins: !!config.plugins,
channels: !!config.channels,
tools: !!config.tools,
diagnostics: !!config.diagnostics,
};
console.log("[BASELINE] config sections present:", JSON.stringify(sections));
assert.ok(sections.gateway, "gateway section must exist");
assert.ok(sections.models, "models section should exist");
});
it("08.03 - config validate CLI works", () => {
const out = execSync("openclaw config get gateway 2>&1", {
timeout: 10000,
encoding: "utf8",
}).trim();
console.log("[BASELINE] config get gateway:", out.substring(0, 200));
// Should not error
assert.ok(!out.toLowerCase().includes("error") || out.includes("Error"),
"config get must return data or clear error");
});
it("08.04 - invalid JSON config is rejected", () => {
// Create a temporary invalid config for testing rejection behavior
const invalidContent = "{ this is not valid json {{{";
try {
// Don't actually create it on the real config path
// Instead use openclaw config validate with a test file
writeFileSync(TEMP_INVALID_CONFIG, invalidContent, "utf8");
// Test that openclaw rejects it
try {
execSync(`OPENCLAW_CONFIG_PATH="${TEMP_INVALID_CONFIG}" openclaw config get gateway 2>&1`, {
timeout: 10000,
encoding: "utf8",
});
} catch (e) {
console.log("[BASELINE] invalid config rejection:", e.stderr?.substring(0, 200) || e.message?.substring(0, 200));
// Error on invalid config is expected behavior
assert.ok(e.stderr || e.message, "invalid config must produce error");
}
} finally {
try { unlinkSync(TEMP_INVALID_CONFIG); } catch {}
}
});
it("08.05 - config with unknown keys loads without crash", () => {
const config = JSON.parse(readFileSync(CONFIG_PATH, "utf8"));
// Check if unknown keys cause silent failure
// In practice, extra keys should be silently ignored or warned
console.log("[BASELINE] config key count:", Object.keys(config).length);
assert.ok(Object.keys(config).length > 0, "config must have sections");
});
it("08.06 - config dot-path get works", () => {
const paths = [
"gateway.bind",
"gateway.auth.mode",
"gateway.port",
];
for (const p of paths) {
try {
const out = execSync(`openclaw config get "${p}" 2>&1`, {
timeout: 10000,
encoding: "utf8",
}).trim();
console.log(`[BASELINE] config get ${p}:`, out.substring(0, 100));
} catch (e) {
console.log(`[BASELINE] config get ${p}: not found or error`);
}
}
assert.ok(true, "baseline frozen: dot-path get");
});
});
@@ -0,0 +1,115 @@
/**
* PR-A Baseline Test 09: Multi-Session Concurrency
* Verifies: multiple sessions don't interfere with each other
* Freezes: session isolation contract
*/
import { describe, it } from "node:test";
import assert from "node:assert";
import { existsSync, readdirSync, readFileSync, writeFileSync, unlinkSync, rmdirSync, statSync, mkdirSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
import { randomUUID } from "node:crypto";
const WORKSPACE_FOR_TEST = join(homedir(), ".openclaw", "workspace");
const TEMP_DIR = join(WORKSPACE_FOR_TEST, "test", "baseline", "tmp");
import { mkdirSync as _mkdirSync } from "node:fs";
try { _mkdirSync(TEMP_DIR, { recursive: true }); } catch {}
const AGENTS_HOME = join(homedir(), ".openclaw");
describe("test-09: Multi-Session Concurrency Baseline", () => {
it("09.01 - concurrent file writes don't corrupt", () => {
const files = [];
const count = 10;
// Write 10 files concurrently (simulated)
for (let i = 0; i < count; i++) {
const path = join(TEMP_DIR, `concurrent-${i}.txt`);
writeFileSync(path, `session-${i}-data-${randomUUID()}`, "utf8");
files.push(path);
}
// Verify all files intact
for (let i = 0; i < count; i++) {
assert.ok(existsSync(files[i]), `file ${i} must exist`);
const content = readFileSync(files[i], "utf8");
assert.ok(content.startsWith(`session-${i}`), `file ${i} must have correct content`);
}
// Cleanup
for (const f of files) {
try { unlinkSync(f); } catch {}
}
console.log("[BASELINE] concurrent writes: OK (%d files)", count);
});
it("09.02 - session data isolation verified (separate dirs)", () => {
// Create two isolated session directories
const sessionA = join(TEMP_DIR, "session-a");
const sessionB = join(TEMP_DIR, "session-b");
try { mkdirSync(sessionA, { recursive: true }); } catch {}
try { mkdirSync(sessionB, { recursive: true }); } catch {}
// Write different data to each
writeFileSync(join(sessionA, "state.json"), JSON.stringify({ id: "a", value: 1 }));
writeFileSync(join(sessionB, "state.json"), JSON.stringify({ id: "b", value: 2 }));
// Read back and verify no cross-contamination
const dataA = JSON.parse(readFileSync(join(sessionA, "state.json"), "utf8"));
const dataB = JSON.parse(readFileSync(join(sessionB, "state.json"), "utf8"));
assert.equal(dataA.id, "a", "session A must be isolated");
assert.equal(dataB.id, "b", "session B must be isolated");
assert.notEqual(dataA.value, dataB.value, "session values must differ");
// Cleanup
try { unlinkSync(join(sessionA, "state.json")); } catch {}
try { unlinkSync(join(sessionB, "state.json")); } catch {}
try { rmdirSync(sessionA); } catch {}
try { rmdirSync(sessionB); } catch {}
console.log("[BASELINE] session isolation: OK");
});
it("09.03 - session lock prevents concurrent writes to same file", () => {
// OpenClaw uses proper-lockfile for session write locking
// Check that the locking library exists
try {
require.resolve("proper-lockfile");
console.log("[BASELINE] session lock via proper-lockfile: available");
assert.ok(true, "session locking mechanism available");
} catch {
console.log("[BASELINE] proper-lockfile not directly importable (may be bundled)");
assert.ok(true, "baseline frozen: lock mechanism check");
}
});
it("09.04 - agent sessions directory isolation check", () => {
const sessionsDir = join(AGENTS_HOME, "agents", "main", "sessions");
if (existsSync(sessionsDir)) {
const dirs = readdirSync(sessionsDir, { withFileTypes: true })
.filter(d => d.isDirectory());
console.log("[BASELINE] agent sessions subdirs:", dirs.length);
console.log("[BASELINE] session dir names:", dirs.map(d => d.name).slice(0, 5).join(", "));
assert.ok(Array.isArray(dirs), "session dirs must be listable");
} else {
console.log("[BASELINE] agent sessions dir: not found (valid baseline)");
}
assert.ok(true, "baseline frozen: session dirs inventory");
});
it("09.05 - concurrent memory operations don't corrupt index", () => {
// The memory index is SQLite-based — check that multiple reads work
const memoryDb = join(AGENTS_HOME, "memory", "main.sqlite");
if (existsSync(memoryDb)) {
const stat = statSync(memoryDb);
console.log("[BASELINE] memory DB: size=%d, exists=%s", stat.size, true);
// SQLite handles concurrent reads correctly via WAL mode
assert.ok(stat.size > 0, "memory DB must have content");
} else {
console.log("[BASELINE] memory DB not found at expected path");
}
assert.ok(true, "baseline frozen: memory DB check");
});
});
@@ -0,0 +1,90 @@
/**
* PR-A Baseline Test 10: Session Crash Recovery
* Verifies: session state survives restart/reload scenarios
* Freezes: session persistence contract
*/
import { describe, it } from "node:test";
import assert from "node:assert";
import { existsSync, readFileSync, writeFileSync, unlinkSync, statSync, mkdirSync, readdirSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
import { randomUUID } from "node:crypto";
const WORKSPACE = join(homedir(), ".openclaw", "workspace");
const TEMP_DIR = join(WORKSPACE, "test", "baseline", "tmp");
try { mkdirSync(TEMP_DIR, { recursive: true }); } catch {}
describe("test-10: Session Crash Recovery Baseline", () => {
it("10.01 - written data survives simulated crash (no fsync)", () => {
const path = join(TEMP_DIR, "crash-test.json");
const data = { id: randomUUID(), state: "running", timestamp: Date.now() };
writeFileSync(path, JSON.stringify(data), "utf8");
const recovered = JSON.parse(readFileSync(path, "utf8"));
assert.equal(recovered.id, data.id, "data must survive 'crash'");
assert.equal(recovered.state, "running", "state must be preserved");
try { unlinkSync(path); } catch {}
console.log("[BASELINE] crash recovery: data survives write");
});
it("10.02 - partial writes don't produce valid JSON (atomicity check)", () => {
const path = join(TEMP_DIR, "partial-crash.json");
writeFileSync(path, '{"id":"test","state":"runn', "utf8");
try {
JSON.parse(readFileSync(path, "utf8"));
assert.fail("partial JSON should not parse");
} catch (e) {
console.log("[BASELINE] partial write detected:", e.message.substring(0, 80));
assert.ok(e instanceof SyntaxError, "partial write must cause parse error");
}
try { unlinkSync(path); } catch {}
});
it("10.03 - session state file format is JSON", () => {
const sessionsDir = join(homedir(), ".openclaw", "agents", "main", "sessions");
if (existsSync(sessionsDir)) {
const files = readdirSync(sessionsDir);
const jsonFiles = files.filter(f => f.endsWith(".json"));
console.log("[BASELINE] session JSON files count:", jsonFiles.length);
if (jsonFiles.length > 0) {
for (const f of jsonFiles.slice(0, 3)) {
try {
const content = readFileSync(join(sessionsDir, f), "utf8");
JSON.parse(content);
console.log(`[BASELINE] ${f}: valid JSON, size=${content.length}`);
} catch (e) {
console.log(`[BASELINE] ${f}: invalid JSON — ${e.message.substring(0, 80)}`);
}
}
}
}
assert.ok(true, "baseline frozen: session file format");
});
it("10.04 - memory index survives process restart simulation", () => {
const memoryDb = join(homedir(), ".openclaw", "memory", "main.sqlite");
if (existsSync(memoryDb)) {
const stat1 = statSync(memoryDb);
console.log("[BASELINE] memory DB before 'restart': size=%d, mtime=%s",
stat1.size, stat1.mtime.toISOString());
const stat2 = statSync(memoryDb);
assert.equal(stat2.size, stat1.size, "memory DB must survive re-read");
} else {
console.log("[BASELINE] no memory DB to check (valid baseline)");
}
assert.ok(true, "baseline frozen: memory index survival");
});
it("10.05 - workspace files survive across reads (persistence check)", () => {
const criticalFiles = ["MEMORY.md", "AGENTS.md"];
for (const f of criticalFiles) {
const path = join(WORKSPACE, f);
if (existsSync(path)) {
const content1 = readFileSync(path, "utf8");
const content2 = readFileSync(path, "utf8");
assert.equal(content1.length, content2.length,
`${f} must be identical across reads`);
console.log(`[BASELINE] ${f}: persistent read OK, len=${content1.length}`);
}
}
});
});
+110
View File
@@ -0,0 +1,110 @@
/**
* PR-A Baseline Test 11: Compaction Trigger
* Verifies: compaction mechanism exists in the codebase
* Freezes: compaction contract
*/
import { describe, it } from "node:test";
import assert from "node:assert";
import { existsSync, readFileSync, readdirSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
const OPENCLAW_HOME = "/opt/homebrew/lib/node_modules/openclaw";
const DIST_DIR = join(OPENCLAW_HOME, "dist");
const DOCS_DIR = join(OPENCLAW_HOME, "docs");
describe("test-11: Compaction Baseline", () => {
it("11.01 - compaction module exists in dist", () => {
// Look for compaction-related files
const compactionPaths = [
join(DIST_DIR, "bundled", "compaction-notifier"),
join(DIST_DIR, "commitments"),
];
let found = false;
for (const p of compactionPaths) {
if (existsSync(p)) {
console.log("[BASELINE] found:", p);
const files = readdirSync(p);
console.log("[BASELINE] contents:", files.join(", "));
found = true;
}
}
// Also check for compaction in main dist files
const indexJs = join(DIST_DIR, "index.js");
if (existsSync(indexJs)) {
const content = readFileSync(indexJs, "utf8");
const hasCompaction = content.includes("compaction") || content.includes("Compaction");
console.log("[BASELINE] main index.js contains 'compaction':", hasCompaction);
if (hasCompaction) found = true;
}
assert.ok(found, "compaction module must exist somewhere in dist");
});
it("11.02 - compaction documentation exists", () => {
const docPath = join(DOCS_DIR, "concepts", "compaction.md");
assert.ok(existsSync(docPath), "compaction docs must exist");
const content = readFileSync(docPath, "utf8");
console.log("[BASELINE] compaction docs size:", content.length);
const hasConfig = content.includes("config") || content.includes("Config");
const hasReserve = content.includes("reserve") || content.includes("Reserve");
const hasThreshold = content.includes("threshold") || content.includes("budget");
console.log("[BASELINE] compaction docs covers config:", hasConfig);
console.log("[BASELINE] compaction docs covers reserve:", hasReserve);
console.log("[BASELINE] compaction docs covers threshold:", hasThreshold);
assert.ok(content.length > 100, "compaction docs must be substantial");
});
it("11.03 - compaction-notifier bundled module", () => {
const notifierPath = join(DIST_DIR, "bundled", "compaction-notifier");
if (existsSync(notifierPath)) {
const files = readdirSync(notifierPath);
console.log("[BASELINE] compaction-notifier files:", files.join(", "));
// Should have at least handler and metadata
const hasHandler = files.some(f => f.includes("handler") || f.includes("HOOK"));
console.log("[BASELINE] has handler:", hasHandler);
assert.ok(files.length > 0, "compaction-notifier must have files");
} else {
console.log("[BASELINE] compaction-notifier not at expected path");
}
assert.ok(true, "baseline frozen: compaction notifier check");
});
it("11.04 - compaction config schema recorded", () => {
// Check config schema for compaction settings
const configPath = join(homedir(), ".openclaw", "openclaw.json");
const config = JSON.parse(readFileSync(configPath, "utf8"));
const hasCompactionConfig =
config?.agents?.defaults?.compaction !== undefined ||
config?.compaction !== undefined;
console.log("[BASELINE] explicit compaction config:", hasCompactionConfig);
// Check docs for compaction parameter names
const docContent = readFileSync(
join(DOCS_DIR, "concepts", "compaction.md"), "utf8"
);
const mentions = [
"reserveTokens", "reserve", "threshold", "budget",
"memoryFlush", "autoCompact", "auto-compact"
];
for (const m of mentions) {
if (docContent.includes(m)) {
console.log(`[BASELINE] compaction param "${m}": documented`);
}
}
assert.ok(true, "baseline frozen: compaction config schema");
});
it("11.05 - memory flush before compaction is documented", () => {
const docContent = readFileSync(
join(DOCS_DIR, "concepts", "compaction.md"), "utf8"
);
const hasMemoryFlush = docContent.includes("memoryFlush") ||
docContent.includes("memory flush") ||
docContent.includes("Memory Flush");
console.log("[BASELINE] memory flush documented:", hasMemoryFlush);
assert.ok(hasMemoryFlush, "memory flush before compaction must be documented");
});
});
@@ -0,0 +1,149 @@
/**
* PR-A Baseline Test 12: Active Memory Plugin
* Verifies: active-memory plugin exists, loads, has hook mechanism
* Freezes: active-memory plugin contract
*/
import { describe, it } from "node:test";
import assert from "node:assert";
import { existsSync, readFileSync, readdirSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
const OPENCLAW_HOME = "/opt/homebrew/lib/node_modules/openclaw";
const ACTIVE_MEM_DIR = join(OPENCLAW_HOME, "dist", "extensions", "active-memory");
const MEMORY_CORE_DIR = join(OPENCLAW_HOME, "dist", "extensions", "memory-core");
describe("test-12: Active Memory Plugin Baseline", () => {
it("12.01 - active-memory plugin directory exists", () => {
const exists = existsSync(ACTIVE_MEM_DIR);
console.log("[BASELINE] active-memory dir:", ACTIVE_MEM_DIR);
console.log("[BASELINE] active-memory dir exists:", exists);
if (exists) {
const files = readdirSync(ACTIVE_MEM_DIR);
console.log("[BASELINE] active-memory files:", files.join(", "));
}
assert.ok(exists, "active-memory plugin directory must exist");
});
it("12.02 - active-memory plugin.json has contracts", () => {
const pluginPath = join(ACTIVE_MEM_DIR, "openclaw.plugin.json");
if (existsSync(pluginPath)) {
const plugin = JSON.parse(readFileSync(pluginPath, "utf8"));
console.log("[BASELINE] active-memory plugin id:", plugin.id);
console.log("[BASELINE] active-memory onStartup:", plugin.activation?.onStartup);
console.log("[BASELINE] active-memory name:", plugin.name);
// Check config schema keys
if (plugin.configSchema?.properties) {
const keys = Object.keys(plugin.configSchema.properties);
console.log("[BASELINE] active-memory config keys:", keys.join(", "));
console.log("[BASELINE] active-memory config key count:", keys.length);
// Key config fields that must exist
assert.ok(keys.includes("enabled"), "must have 'enabled' config");
assert.ok(keys.includes("timeoutMs"), "must have 'timeoutMs' config");
assert.ok(keys.includes("queryMode"), "must have 'queryMode' config");
}
} else {
console.log("[BASELINE] active-memory plugin.json not found");
}
assert.ok(true, "baseline frozen: plugin contract");
});
it("12.03 - memory-core plugin also exists", () => {
const exists = existsSync(MEMORY_CORE_DIR);
console.log("[BASELINE] memory-core dir exists:", exists);
if (exists) {
const pluginPath = join(MEMORY_CORE_DIR, "openclaw.plugin.json");
if (existsSync(pluginPath)) {
const plugin = JSON.parse(readFileSync(pluginPath, "utf8"));
console.log("[BASELINE] memory-core plugin id:", plugin.id);
console.log("[BASELINE] memory-core kind:", plugin.kind);
console.log("[BASELINE] memory-core contracts:",
JSON.stringify(plugin.contracts));
console.log("[BASELINE] memory-core has dreaming:",
!!plugin.configSchema?.properties?.dreaming);
// Tool contracts are critical
const tools = plugin.contracts?.tools || [];
console.log("[BASELINE] memory-core tools:", tools.join(", "));
assert.ok(tools.includes("memory_search"), "must register memory_search");
assert.ok(tools.includes("memory_get"), "must register memory_get");
// Dreaming phases
const phases = plugin.configSchema?.properties?.dreaming?.properties?.phases?.properties;
if (phases) {
const phaseNames = Object.keys(phases);
console.log("[BASELINE] dreaming phases:", phaseNames.join(", "));
// Freeze: current phase count (light, deep, rem = 3)
console.log("[BASELINE] dreaming phase count:", phaseNames.length);
}
}
}
assert.ok(exists, "memory-core plugin directory must exist");
});
it("12.04 - active-memory hook mechanism verified", () => {
// active-memory uses before_agent_reply hook
const pluginPath = join(ACTIVE_MEM_DIR, "openclaw.plugin.json");
if (existsSync(pluginPath)) {
const plugin = JSON.parse(readFileSync(pluginPath, "utf8"));
// Check if hook is declared in plugin metadata
const hasHooks = plugin.hooks !== undefined ||
plugin.activation?.onStartup === true;
console.log("[BASELINE] active-memory has hook declarations:", hasHooks);
// Config reveals hook behavior
const mode = plugin.configSchema?.properties?.queryMode;
if (mode) {
console.log("[BASELINE] queryMode options:", mode.enum?.join(", ") || "unknown");
}
}
// Check that the actual code module loads
const indexJs = join(ACTIVE_MEM_DIR, "index.js");
if (existsSync(indexJs)) {
const size = readFileSync(indexJs, "utf8").length;
console.log("[BASELINE] active-memory index.js size:", size);
assert.ok(size > 100, "active-memory code must be substantial");
}
assert.ok(true, "baseline frozen: active-memory hook mechanism");
});
it("12.05 - circuit breaker config exists", () => {
const pluginPath = join(ACTIVE_MEM_DIR, "openclaw.plugin.json");
if (existsSync(pluginPath)) {
const plugin = JSON.parse(readFileSync(pluginPath, "utf8"));
const props = plugin.configSchema?.properties || {};
const hasCircuitBreaker =
props.circuitBreakerMaxTimeouts !== undefined &&
props.circuitBreakerCooldownMs !== undefined;
console.log("[BASELINE] circuit breaker config:", hasCircuitBreaker);
if (hasCircuitBreaker) {
console.log("[BASELINE] circuitBreakerMaxTimeouts min:",
props.circuitBreakerMaxTimeouts.minimum);
console.log("[BASELINE] circuitBreakerCooldownMs min:",
props.circuitBreakerCooldownMs.minimum);
}
}
assert.ok(true, "baseline frozen: circuit breaker config");
});
it("12.06 - block mode currently available (blocking path exists)", () => {
// Active memory has a blocking mode that runs before agent reply
// This test freezes the fact that it exists (not whether it's enabled)
const pluginPath = join(ACTIVE_MEM_DIR, "openclaw.plugin.json");
if (existsSync(pluginPath)) {
const plugin = JSON.parse(readFileSync(pluginPath, "utf8"));
const promptStyle = plugin.configSchema?.properties?.promptStyle;
if (promptStyle) {
console.log("[BASELINE] promptStyle options:", promptStyle.enum?.join(", "));
assert.ok(promptStyle.enum.length >= 4, "must have multiple prompt styles");
}
}
assert.ok(true, "baseline frozen: active memory blocking behavior exists");
});
});