refactor(tests): update fixtures for flat agents layout

Update sourcePath fixtures and expected Codex agent names across the
test suite to reflect agents now living directly under
plugins/compound-engineering/agents/ with no category subfolders:

- tests/codex-converter.test.ts: flip the namespaced-Task test to the
  flat layout with bare ce-<agent> expected names. Add a new test that
  pins the nested-layout fallback: any third-party plugin still using
  agents/<category>/<name>.md passed through convertClaudeToCodex must
  continue to produce <category>-ce-<agent> Codex agent names.
- tests/pi-writer.test.ts, tests/review-skill-contract.test.ts,
  tests/legacy-cleanup.test.ts, tests/pipeline-review-contract.test.ts,
  tests/kiro-writer.test.ts: strip the <category>/ segment from every
  hardcoded plugins/compound-engineering/agents/* path. Several of
  these (legacy-cleanup.test.ts in particular) perform live filesystem
  reads and would throw ENOENT if left pointing at the old nested
  locations.
- tests/review-skill-contract.test.ts: update the
  stack-specific-reviewers contract test to assert bare ce-<agent>
  references in SKILL.md / persona-catalog.md, matching the new
  convention.

Also simplify cleanupLegacyAgentSkillDirs: the `agent.name.includes("-ce-")`
branch relied on compound names like review-ce-foo to extract a legacy
ce-<final> variant. Every current agent now starts with ce- with no
embedded -ce-, so that branch produced nonsense entries (ce-ce-<name>)
and swept nothing. Remove the dead branch; keep the primary
legacySkillNames.add(sanitizePathName(agent.name)) which still catches
stale skill directories under ~/.codex/skills/<plugin>/<agent-name>/.

bun test passes with 830 tests green. bun run release:validate reports
no drift: compound-engineering at 50 agents, 45 skills, 0 MCP servers.

Per docs/plans/2026-04-21-001-refactor-flatten-agents-directory-plan.md
Unit 5.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trevin Chow
2026-04-21 02:04:18 -07:00
parent 99284a64c6
commit 25f1c8b975
7 changed files with 73 additions and 35 deletions
-2
View File
@@ -299,9 +299,7 @@ async function cleanupLegacyAgentSkillDirs(
const currentSkillSet = new Set(currentSkills)
const legacySkillNames = new Set<string>()
for (const agent of bundle.agents ?? []) {
const finalSegment = agent.name.includes("-ce-") ? agent.name.split("-ce-").pop() : agent.name
legacySkillNames.add(sanitizePathName(agent.name))
if (finalSegment) legacySkillNames.add(`ce-${sanitizePathName(finalSegment)}`)
}
for (const name of getLegacyCodexArtifacts({
pluginName,
+49 -9
View File
@@ -326,14 +326,59 @@ Task compound-engineering:review:ce-security-reviewer(code_diff)`,
name: "ce-repo-research-analyst",
description: "Repo research",
body: "Research repositories.",
sourcePath: "/tmp/plugin/agents/research/ce-repo-research-analyst.agent.md",
sourcePath: "/tmp/plugin/agents/ce-repo-research-analyst.agent.md",
},
{
name: "ce-learnings-researcher",
description: "Learning research",
body: "Search learnings.",
sourcePath: "/tmp/plugin/agents/research/ce-learnings-researcher.agent.md",
sourcePath: "/tmp/plugin/agents/ce-learnings-researcher.agent.md",
},
{
name: "ce-security-reviewer",
description: "Security review",
body: "Review security.",
sourcePath: "/tmp/plugin/agents/ce-security-reviewer.agent.md",
},
],
skills: [],
}
const bundle = convertClaudeToCodex(plugin, {
agentMode: "subagent",
inferTemperature: false,
permissions: "none",
codexIncludeSkills: true,
})
const commandSkill = bundle.generatedSkills.find((s) => s.name === "plan")
expect(commandSkill).toBeDefined()
const parsed = parseFrontmatter(commandSkill!.content)
expect(parsed.body).toContain("Spawn the custom agent `ce-repo-research-analyst` with task: feature_description")
expect(parsed.body).toContain("Spawn the custom agent `ce-learnings-researcher` with task: feature_description")
expect(parsed.body).toContain("Spawn the custom agent `ce-security-reviewer` with task: code_diff")
// Original namespaced Task syntax should not remain
expect(parsed.body).not.toContain("Task compound-engineering:")
})
test("retains <category>-<agent> naming for nested-layout plugins (dead-code fallback)", () => {
// This test pins the behavior of getAgentCategory() for any third-party
// plugin that still uses agents/<category>/<name>.md layout. The
// compound-engineering plugin itself is flat, but the converter must keep
// working for other plugins passed through the CLI.
const plugin: ClaudePlugin = {
...fixturePlugin,
commands: [
{
name: "plan",
description: "Planning with agents from a nested-layout plugin",
body: `- Task compound-engineering:review:ce-security-reviewer(code_diff)`,
sourcePath: "/tmp/plugin/commands/plan.md",
},
],
agents: [
{
name: "ce-security-reviewer",
description: "Security review",
@@ -355,12 +400,7 @@ Task compound-engineering:review:ce-security-reviewer(code_diff)`,
expect(commandSkill).toBeDefined()
const parsed = parseFrontmatter(commandSkill!.content)
expect(parsed.body).toContain("Spawn the custom agent `research-ce-repo-research-analyst` with task: feature_description")
expect(parsed.body).toContain("Spawn the custom agent `research-ce-learnings-researcher` with task: feature_description")
expect(parsed.body).toContain("Spawn the custom agent `review-ce-security-reviewer` with task: code_diff")
// Original namespaced Task syntax should not remain
expect(parsed.body).not.toContain("Task compound-engineering:")
})
test("transforms zero-argument Task calls", () => {
@@ -379,7 +419,7 @@ Task compound-engineering:review:ce-security-reviewer(code_diff)`,
name: "ce-code-simplicity-reviewer",
description: "Simplicity review",
body: "Review simplicity.",
sourcePath: "/tmp/plugin/agents/review/ce-code-simplicity-reviewer.agent.md",
sourcePath: "/tmp/plugin/agents/ce-code-simplicity-reviewer.agent.md",
},
],
skills: [],
@@ -395,7 +435,7 @@ Task compound-engineering:review:ce-security-reviewer(code_diff)`,
const commandSkill = bundle.generatedSkills.find((s) => s.name === "review")
expect(commandSkill).toBeDefined()
const parsed = parseFrontmatter(commandSkill!.content)
expect(parsed.body).toContain("Spawn the custom agent `review-ce-code-simplicity-reviewer`")
expect(parsed.body).toContain("Spawn the custom agent `ce-code-simplicity-reviewer`")
expect(parsed.body).not.toContain("compound-engineering:")
expect(parsed.body).not.toContain("skill to:")
})
+1 -1
View File
@@ -38,7 +38,7 @@ describe("writeKiroBundle", () => {
const kiroRoot = path.join(tempRoot, ".kiro")
await fs.mkdir(path.join(kiroRoot, "agents", "prompts"), { recursive: true })
const sessionHistorianDescription = await pluginDescription(
"plugins/compound-engineering/agents/research/ce-session-historian.agent.md",
"plugins/compound-engineering/agents/ce-session-historian.agent.md",
)
await fs.writeFile(
+9 -9
View File
@@ -257,14 +257,14 @@ describe("cleanupStaleAgents", () => {
path.join(root, "adversarial-reviewer.md"),
agentContent(
"adversarial-reviewer",
await pluginDescription("plugins/compound-engineering/agents/review/ce-adversarial-reviewer.agent.md"),
await pluginDescription("plugins/compound-engineering/agents/ce-adversarial-reviewer.agent.md"),
),
)
await createFile(
path.join(root, "learnings-researcher.md"),
agentContent(
"learnings-researcher",
await pluginDescription("plugins/compound-engineering/agents/research/ce-learnings-researcher.agent.md"),
await pluginDescription("plugins/compound-engineering/agents/ce-learnings-researcher.agent.md"),
),
)
@@ -281,14 +281,14 @@ describe("cleanupStaleAgents", () => {
path.join(root, "security-sentinel.agent.md"),
agentContent(
"security-sentinel",
await pluginDescription("plugins/compound-engineering/agents/review/ce-security-sentinel.agent.md"),
await pluginDescription("plugins/compound-engineering/agents/ce-security-sentinel.agent.md"),
),
)
await createFile(
path.join(root, "performance-oracle.agent.md"),
agentContent(
"performance-oracle",
await pluginDescription("plugins/compound-engineering/agents/review/ce-performance-oracle.agent.md"),
await pluginDescription("plugins/compound-engineering/agents/ce-performance-oracle.agent.md"),
),
)
@@ -304,14 +304,14 @@ describe("cleanupStaleAgents", () => {
path.join(root, "slack-researcher.json"),
kiroAgentConfigContent(
"slack-researcher",
await pluginDescription("plugins/compound-engineering/agents/research/ce-slack-researcher.agent.md"),
await pluginDescription("plugins/compound-engineering/agents/ce-slack-researcher.agent.md"),
),
)
await createFile(
path.join(root, "session-historian.json"),
kiroAgentConfigContent(
"session-historian",
await pluginDescription("plugins/compound-engineering/agents/research/ce-session-historian.agent.md"),
await pluginDescription("plugins/compound-engineering/agents/ce-session-historian.agent.md"),
),
)
await createFile(
@@ -336,14 +336,14 @@ describe("cleanupStaleAgents", () => {
path.join(root, "code-simplicity-reviewer"),
skillContent(
"code-simplicity-reviewer",
await pluginDescription("plugins/compound-engineering/agents/review/ce-code-simplicity-reviewer.agent.md"),
await pluginDescription("plugins/compound-engineering/agents/ce-code-simplicity-reviewer.agent.md"),
),
)
await createDir(
path.join(root, "repo-research-analyst"),
skillContent(
"repo-research-analyst",
await pluginDescription("plugins/compound-engineering/agents/research/ce-repo-research-analyst.agent.md"),
await pluginDescription("plugins/compound-engineering/agents/ce-repo-research-analyst.agent.md"),
),
)
@@ -618,7 +618,7 @@ describe("idempotency", () => {
path.join(root, "adversarial-reviewer.md"),
agentContent(
"adversarial-reviewer",
await pluginDescription("plugins/compound-engineering/agents/review/ce-adversarial-reviewer.agent.md"),
await pluginDescription("plugins/compound-engineering/agents/ce-adversarial-reviewer.agent.md"),
),
)
+1 -1
View File
@@ -32,7 +32,7 @@ describe("writePiBundle", () => {
const outputRoot = path.join(tempRoot, ".pi")
const sessionHistorianDescription = await pluginDescription(
"plugins/compound-engineering/agents/research/ce-session-historian.agent.md",
"plugins/compound-engineering/agents/ce-session-historian.agent.md",
)
await fs.mkdir(path.join(outputRoot, "skills", "session-historian"), { recursive: true })
+1 -1
View File
@@ -597,7 +597,7 @@ describe("ce-compound frontmatter schema expansion contract", () => {
describe("ce-learnings-researcher domain-agnostic contract", () => {
test("agent prompt frames as domain-agnostic not bug-focused", async () => {
const agent = await readRepoFile(
"plugins/compound-engineering/agents/research/ce-learnings-researcher.agent.md"
"plugins/compound-engineering/agents/ce-learnings-researcher.agent.md"
)
// Domain-agnostic identity framing
+12 -12
View File
@@ -205,11 +205,11 @@ describe("ce-code-review contract", () => {
)
for (const agent of [
"review:ce-dhh-rails-reviewer",
"review:ce-kieran-rails-reviewer",
"review:ce-kieran-python-reviewer",
"review:ce-kieran-typescript-reviewer",
"review:ce-julik-frontend-races-reviewer",
"ce-dhh-rails-reviewer",
"ce-kieran-rails-reviewer",
"ce-kieran-python-reviewer",
"ce-kieran-typescript-reviewer",
"ce-julik-frontend-races-reviewer",
]) {
expect(content).toContain(agent)
expect(catalog).toContain(agent)
@@ -222,23 +222,23 @@ describe("ce-code-review contract", () => {
test("stack-specific reviewer agents follow the structured findings contract", async () => {
const reviewers = [
{
path: "plugins/compound-engineering/agents/review/ce-dhh-rails-reviewer.agent.md",
path: "plugins/compound-engineering/agents/ce-dhh-rails-reviewer.agent.md",
reviewer: "dhh-rails",
},
{
path: "plugins/compound-engineering/agents/review/ce-kieran-rails-reviewer.agent.md",
path: "plugins/compound-engineering/agents/ce-kieran-rails-reviewer.agent.md",
reviewer: "kieran-rails",
},
{
path: "plugins/compound-engineering/agents/review/ce-kieran-python-reviewer.agent.md",
path: "plugins/compound-engineering/agents/ce-kieran-python-reviewer.agent.md",
reviewer: "kieran-python",
},
{
path: "plugins/compound-engineering/agents/review/ce-kieran-typescript-reviewer.agent.md",
path: "plugins/compound-engineering/agents/ce-kieran-typescript-reviewer.agent.md",
reviewer: "kieran-typescript",
},
{
path: "plugins/compound-engineering/agents/review/ce-julik-frontend-races-reviewer.agent.md",
path: "plugins/compound-engineering/agents/ce-julik-frontend-races-reviewer.agent.md",
reviewer: "julik-frontend-races",
},
]
@@ -262,7 +262,7 @@ describe("ce-code-review contract", () => {
test("leaves data-migration-expert as the unstructured review format", async () => {
const content = await readRepoFile(
"plugins/compound-engineering/agents/review/ce-data-migration-expert.agent.md",
"plugins/compound-engineering/agents/ce-data-migration-expert.agent.md",
)
expect(content).toContain("## Reviewer Checklist")
@@ -304,7 +304,7 @@ describe("ce-code-review contract", () => {
describe("testing-reviewer contract", () => {
test("includes behavioral-changes-with-no-test-additions check", async () => {
const content = await readRepoFile("plugins/compound-engineering/agents/review/ce-testing-reviewer.agent.md")
const content = await readRepoFile("plugins/compound-engineering/agents/ce-testing-reviewer.agent.md")
// New check exists in "What you're hunting for" section
expect(content).toContain("Behavioral changes with no test additions")