234429737a
Copies 6 omo-codex components (rules, comment-checker, lsp, ultrawork, ultragoal, start-work-continuation) into the CC plugin tree and applies a declarative patch manifest: relax model/turn_id validators, CLAUDE_PLUGIN_ROOT/ DATA env fallbacks, .codex-plugin->.claude-plugin, rules matcher widened to Write|Edit|MultiEdit, start-work-continuation claude: session prefix. ultragoal copied verbatim (deep refactor is a later task). --check detects vendor drift. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
88 lines
3.2 KiB
JavaScript
88 lines
3.2 KiB
JavaScript
import { spawnSync } from "node:child_process";
|
|
import { readFile, writeFile } from "node:fs/promises";
|
|
import assert from "node:assert/strict";
|
|
import { dirname, join } from "node:path";
|
|
import { test } from "node:test";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
import { HANDLED_COMPONENTS, PATCH_MANIFEST, syncComponents } from "./sync-components.mjs";
|
|
|
|
const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
|
|
const SCRIPT_PATH = join(SCRIPT_DIR, "sync-components.mjs");
|
|
const PLUGIN_ROOT = dirname(SCRIPT_DIR);
|
|
const DRIFT_FILE = join(PLUGIN_ROOT, "components", "lsp", "src", "codex-hook.ts");
|
|
|
|
function runCli(args) {
|
|
return spawnSync(process.execPath, [SCRIPT_PATH, ...args], { encoding: "utf8" });
|
|
}
|
|
|
|
test("sync then --check is GREEN (exit 0)", () => {
|
|
const sync = runCli([]);
|
|
assert.equal(sync.status, 0, `sync failed: ${sync.stderr}`);
|
|
|
|
const check = runCli(["--check"]);
|
|
assert.equal(check.status, 0, `--check should be green after sync but got: ${check.stderr}`);
|
|
assert.match(check.stdout, /in sync/);
|
|
});
|
|
|
|
test("--check is RED (nonzero) after hand-drift, then re-sync restores GREEN", async () => {
|
|
runCli([]);
|
|
|
|
const original = await readFile(DRIFT_FILE, "utf8");
|
|
try {
|
|
await writeFile(DRIFT_FILE, `${original}\n// drift\n`);
|
|
const drifted = runCli(["--check"]);
|
|
assert.notEqual(drifted.status, 0, "--check must fail after hand-drift");
|
|
assert.match(drifted.stderr, /out of sync/);
|
|
assert.match(drifted.stderr, /lsp\/src\/codex-hook\.ts/);
|
|
} finally {
|
|
// Re-sync to restore the vendored tree regardless of assertion outcome.
|
|
const restore = runCli([]);
|
|
assert.equal(restore.status, 0, `restore sync failed: ${restore.stderr}`);
|
|
}
|
|
|
|
const check = runCli(["--check"]);
|
|
assert.equal(check.status, 0, `--check should be green again after re-sync: ${check.stderr}`);
|
|
});
|
|
|
|
test("sync is idempotent (running twice yields no drift)", () => {
|
|
assert.equal(runCli([]).status, 0);
|
|
assert.equal(runCli([]).status, 0);
|
|
assert.equal(runCli(["--check"]).status, 0);
|
|
});
|
|
|
|
test("a single component can be synced and check passes", () => {
|
|
const sync = runCli(["rules"]);
|
|
assert.equal(sync.status, 0, sync.stderr);
|
|
assert.match(sync.stdout, /rules/);
|
|
// Re-sync all so the rest of the suite/state is whole.
|
|
assert.equal(runCli([]).status, 0);
|
|
assert.equal(runCli(["--check"]).status, 0);
|
|
});
|
|
|
|
test("unknown component is rejected", () => {
|
|
const result = runCli(["does-not-exist"]);
|
|
assert.notEqual(result.status, 0);
|
|
assert.match(result.stderr, /unknown component/);
|
|
});
|
|
|
|
test("every required replacement in the manifest matches the source", async () => {
|
|
const matched = [];
|
|
await syncComponents({ check: true, components: HANDLED_COMPONENTS });
|
|
// syncComponents records matches via its internal collector; re-derive by
|
|
// running a check pass and asserting no required replacement is unmatched.
|
|
const result = await syncComponents({ check: true });
|
|
for (const entry of result.matched) {
|
|
if (entry.required) {
|
|
assert.equal(
|
|
entry.matched,
|
|
true,
|
|
`required replacement did not match: ${entry.component}/${entry.file} :: ${entry.find}`,
|
|
);
|
|
}
|
|
}
|
|
assert.ok(result.matched.length >= PATCH_MANIFEST.length, "expected manifest replacements to be exercised");
|
|
// matched local kept for clarity; not otherwise used.
|
|
void matched;
|
|
});
|