b68b6be2ff
sync-skills aggregates 4 component skills + 10 shared; 6 harness-tool skills get
the Claude Code Harness Tool Compatibility block; start-work's embedded Codex
section is demoted. Root hooks.json uses ${CLAUDE_PLUGIN_ROOT}, widens PostToolUse
to Write|Edit|MultiEdit, and registers no create_goal PreToolUse (D4). Plugin
aggregate test pins hooks/skills/mcp shape.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
54 lines
2.6 KiB
JavaScript
54 lines
2.6 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { readdirSync, readFileSync } from "node:fs";
|
|
import { dirname, join } from "node:path";
|
|
import { test } from "node:test";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const PLUGIN_ROOT = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
|
|
test("hooks.json is valid JSON and Claude-Code shaped", () => {
|
|
const raw = readFileSync(join(PLUGIN_ROOT, "hooks", "hooks.json"), "utf8");
|
|
const parsed = JSON.parse(raw);
|
|
assert.ok(parsed.hooks, "has top-level hooks key");
|
|
const events = Object.keys(parsed.hooks);
|
|
for (const event of ["SessionStart", "UserPromptSubmit", "PostToolUse", "PostCompact", "Stop", "SubagentStop"]) {
|
|
assert.ok(events.includes(event), `aggregate registers ${event}`);
|
|
}
|
|
assert.ok(!events.includes("PreToolUse"), "no PreToolUse block (ultragoal create_goal guard not registered)");
|
|
assert.ok(raw.includes("${CLAUDE_PLUGIN_ROOT}"), "hook commands use ${CLAUDE_PLUGIN_ROOT}");
|
|
assert.ok(!/\$\{PLUGIN_ROOT\}/.test(raw), "no bare ${PLUGIN_ROOT} left");
|
|
assert.ok(!raw.includes("create_goal"), "no create_goal matcher in the aggregate");
|
|
});
|
|
|
|
test("14 skills are aggregated", () => {
|
|
const skills = readdirSync(join(PLUGIN_ROOT, "skills"), { withFileTypes: true })
|
|
.filter((entry) => entry.isDirectory())
|
|
.map((entry) => entry.name);
|
|
assert.equal(skills.length, 14, `expected 14 skills, got ${skills.length}: ${skills.join(", ")}`);
|
|
});
|
|
|
|
test("harness-tool skills carry the Claude Code compatibility block", () => {
|
|
const expected = ["init-deep", "planing-prometheustic", "refactor", "remove-ai-slops", "review-work", "start-work"];
|
|
for (const skill of expected) {
|
|
const body = readFileSync(join(PLUGIN_ROOT, "skills", skill, "SKILL.md"), "utf8");
|
|
assert.ok(
|
|
body.includes("## Claude Code Harness Tool Compatibility"),
|
|
`${skill} carries the Claude Code Harness Tool Compatibility block`,
|
|
);
|
|
}
|
|
const startWork = readFileSync(join(PLUGIN_ROOT, "skills", "start-work", "SKILL.md"), "utf8");
|
|
assert.ok(
|
|
!/^## Codex Harness Tool Compatibility/m.test(startWork),
|
|
"start-work's embedded Codex compatibility heading is demoted, not authoritative",
|
|
);
|
|
});
|
|
|
|
test(".mcp.json references ${CLAUDE_PLUGIN_ROOT} with no parent-relative paths", () => {
|
|
const raw = readFileSync(join(PLUGIN_ROOT, ".mcp.json"), "utf8");
|
|
const parsed = JSON.parse(raw);
|
|
assert.ok(parsed.mcpServers.ast_grep, "ast_grep MCP server declared");
|
|
assert.ok(parsed.mcpServers.lsp, "lsp MCP server declared");
|
|
assert.ok(raw.includes("${CLAUDE_PLUGIN_ROOT}"), ".mcp.json uses ${CLAUDE_PLUGIN_ROOT}");
|
|
assert.ok(!raw.includes("../"), ".mcp.json has no parent-relative paths");
|
|
});
|