feat: fix skill transformation pipeline across all targets (#334)
This commit is contained in:
@@ -248,6 +248,35 @@ Task compound-engineering:review:security-reviewer(code_diff)`,
|
||||
expect(parsed.body).not.toContain("Task compound-engineering:")
|
||||
})
|
||||
|
||||
test("transforms zero-argument Task calls", () => {
|
||||
const plugin: ClaudePlugin = {
|
||||
...fixturePlugin,
|
||||
commands: [
|
||||
{
|
||||
name: "review",
|
||||
description: "Review code",
|
||||
body: `- Task compound-engineering:review:code-simplicity-reviewer()`,
|
||||
sourcePath: "/tmp/plugin/commands/review.md",
|
||||
},
|
||||
],
|
||||
agents: [],
|
||||
skills: [],
|
||||
}
|
||||
|
||||
const bundle = convertClaudeToCodex(plugin, {
|
||||
agentMode: "subagent",
|
||||
inferTemperature: false,
|
||||
permissions: "none",
|
||||
})
|
||||
|
||||
const commandSkill = bundle.generatedSkills.find((s) => s.name === "review")
|
||||
expect(commandSkill).toBeDefined()
|
||||
const parsed = parseFrontmatter(commandSkill!.content)
|
||||
expect(parsed.body).toContain("Use the $code-simplicity-reviewer skill")
|
||||
expect(parsed.body).not.toContain("compound-engineering:")
|
||||
expect(parsed.body).not.toContain("skill to:")
|
||||
})
|
||||
|
||||
test("transforms slash commands to prompts syntax", () => {
|
||||
const plugin: ClaudePlugin = {
|
||||
...fixturePlugin,
|
||||
|
||||
@@ -177,6 +177,7 @@ Run these research agents:
|
||||
Also run bare agents:
|
||||
|
||||
- Task best-practices-researcher(topic)
|
||||
- Task compound-engineering:review:code-simplicity-reviewer()
|
||||
`,
|
||||
)
|
||||
|
||||
@@ -205,6 +206,10 @@ Also run bare agents:
|
||||
// Bare Task calls should still be rewritten
|
||||
expect(installedSkill).toContain("Use the $best-practices-researcher skill to: topic")
|
||||
expect(installedSkill).not.toContain("Task best-practices-researcher")
|
||||
|
||||
// Zero-arg Task calls should be rewritten without trailing "to:"
|
||||
expect(installedSkill).toContain("Use the $code-simplicity-reviewer skill")
|
||||
expect(installedSkill).not.toContain("code-simplicity-reviewer skill to:")
|
||||
})
|
||||
|
||||
test("preserves unknown slash text in copied SKILL.md files", async () => {
|
||||
|
||||
@@ -444,6 +444,27 @@ Task best-practices-researcher(topic)`
|
||||
expect(result).not.toContain("Task repo-research-analyst(")
|
||||
})
|
||||
|
||||
test("transforms namespaced Task agent calls using final segment", () => {
|
||||
const input = `Run agents:
|
||||
|
||||
- Task compound-engineering:research:repo-research-analyst(feature_description)
|
||||
- Task compound-engineering:review:security-reviewer(code_diff)`
|
||||
|
||||
const result = transformContentForCopilot(input)
|
||||
expect(result).toContain("Use the repo-research-analyst skill to: feature_description")
|
||||
expect(result).toContain("Use the security-reviewer skill to: code_diff")
|
||||
expect(result).not.toContain("compound-engineering:")
|
||||
})
|
||||
|
||||
test("transforms zero-argument Task calls", () => {
|
||||
const input = `- Task compound-engineering:review:code-simplicity-reviewer()`
|
||||
|
||||
const result = transformContentForCopilot(input)
|
||||
expect(result).toContain("Use the code-simplicity-reviewer skill")
|
||||
expect(result).not.toContain("compound-engineering:")
|
||||
expect(result).not.toContain("skill to:")
|
||||
})
|
||||
|
||||
test("replaces colons with hyphens in slash commands", () => {
|
||||
const input = `1. Run /deepen-plan to enhance
|
||||
2. Start /workflows:work to implement
|
||||
|
||||
@@ -165,6 +165,44 @@ describe("writeCopilotBundle", () => {
|
||||
expect(backupFiles.length).toBeGreaterThanOrEqual(1)
|
||||
})
|
||||
|
||||
test("transforms Task calls in copied SKILL.md files", async () => {
|
||||
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "copilot-skill-transform-"))
|
||||
const sourceSkillDir = path.join(tempRoot, "source-skill")
|
||||
await fs.mkdir(sourceSkillDir, { recursive: true })
|
||||
await fs.writeFile(
|
||||
path.join(sourceSkillDir, "SKILL.md"),
|
||||
`---
|
||||
name: ce:plan
|
||||
description: Planning workflow
|
||||
---
|
||||
|
||||
Run these research agents:
|
||||
|
||||
- Task compound-engineering:research:repo-research-analyst(feature_description)
|
||||
- Task compound-engineering:research:learnings-researcher(feature_description)
|
||||
- Task compound-engineering:review:code-simplicity-reviewer()
|
||||
`,
|
||||
)
|
||||
|
||||
const bundle: CopilotBundle = {
|
||||
agents: [],
|
||||
generatedSkills: [],
|
||||
skillDirs: [{ name: "ce:plan", sourceDir: sourceSkillDir }],
|
||||
}
|
||||
|
||||
await writeCopilotBundle(tempRoot, bundle)
|
||||
|
||||
const installedSkill = await fs.readFile(
|
||||
path.join(tempRoot, ".github", "skills", "ce:plan", "SKILL.md"),
|
||||
"utf8",
|
||||
)
|
||||
|
||||
expect(installedSkill).toContain("Use the repo-research-analyst skill to: feature_description")
|
||||
expect(installedSkill).toContain("Use the learnings-researcher skill to: feature_description")
|
||||
expect(installedSkill).toContain("Use the code-simplicity-reviewer skill")
|
||||
expect(installedSkill).not.toContain("Task compound-engineering:")
|
||||
})
|
||||
|
||||
test("creates skill directories with SKILL.md", async () => {
|
||||
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "copilot-genskill-"))
|
||||
const bundle: CopilotBundle = {
|
||||
|
||||
@@ -148,6 +148,63 @@ Task best-practices-researcher(topic)`,
|
||||
expect(parsed.body).not.toContain("Task repo-research-analyst(")
|
||||
})
|
||||
|
||||
test("transforms namespaced Task agent calls using final segment", () => {
|
||||
const plugin: ClaudePlugin = {
|
||||
...fixturePlugin,
|
||||
commands: [
|
||||
{
|
||||
name: "plan",
|
||||
description: "Planning with namespaced agents",
|
||||
body: `Run agents:
|
||||
|
||||
- Task compound-engineering:research:repo-research-analyst(feature_description)
|
||||
- Task compound-engineering:review:security-reviewer(code_diff)`,
|
||||
sourcePath: "/tmp/plugin/commands/plan.md",
|
||||
},
|
||||
],
|
||||
agents: [],
|
||||
skills: [],
|
||||
}
|
||||
|
||||
const bundle = convertClaudeToDroid(plugin, {
|
||||
agentMode: "subagent",
|
||||
inferTemperature: false,
|
||||
permissions: "none",
|
||||
})
|
||||
|
||||
const parsed = parseFrontmatter(bundle.commands[0].content)
|
||||
expect(parsed.body).toContain("Task repo-research-analyst: feature_description")
|
||||
expect(parsed.body).toContain("Task security-reviewer: code_diff")
|
||||
expect(parsed.body).not.toContain("compound-engineering:")
|
||||
})
|
||||
|
||||
test("transforms zero-argument Task calls", () => {
|
||||
const plugin: ClaudePlugin = {
|
||||
...fixturePlugin,
|
||||
commands: [
|
||||
{
|
||||
name: "review",
|
||||
description: "Review code",
|
||||
body: `- Task compound-engineering:review:code-simplicity-reviewer()`,
|
||||
sourcePath: "/tmp/plugin/commands/review.md",
|
||||
},
|
||||
],
|
||||
agents: [],
|
||||
skills: [],
|
||||
}
|
||||
|
||||
const bundle = convertClaudeToDroid(plugin, {
|
||||
agentMode: "subagent",
|
||||
inferTemperature: false,
|
||||
permissions: "none",
|
||||
})
|
||||
|
||||
const parsed = parseFrontmatter(bundle.commands[0].content)
|
||||
expect(parsed.body).toContain("Task code-simplicity-reviewer")
|
||||
expect(parsed.body).not.toContain("compound-engineering:")
|
||||
expect(parsed.body).not.toContain("()")
|
||||
})
|
||||
|
||||
test("transforms slash commands by flattening namespaces", () => {
|
||||
const plugin: ClaudePlugin = {
|
||||
...fixturePlugin,
|
||||
|
||||
@@ -47,6 +47,44 @@ describe("writeDroidBundle", () => {
|
||||
expect(droidContent).toContain("Droid content")
|
||||
})
|
||||
|
||||
test("transforms Task calls in copied SKILL.md files", async () => {
|
||||
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "droid-skill-transform-"))
|
||||
const sourceSkillDir = path.join(tempRoot, "source-skill")
|
||||
await fs.mkdir(sourceSkillDir, { recursive: true })
|
||||
await fs.writeFile(
|
||||
path.join(sourceSkillDir, "SKILL.md"),
|
||||
`---
|
||||
name: ce:plan
|
||||
description: Planning workflow
|
||||
---
|
||||
|
||||
Run these research agents:
|
||||
|
||||
- Task compound-engineering:research:repo-research-analyst(feature_description)
|
||||
- Task compound-engineering:research:learnings-researcher(feature_description)
|
||||
- Task compound-engineering:review:code-simplicity-reviewer()
|
||||
`,
|
||||
)
|
||||
|
||||
const bundle: DroidBundle = {
|
||||
commands: [],
|
||||
droids: [],
|
||||
skillDirs: [{ name: "ce:plan", sourceDir: sourceSkillDir }],
|
||||
}
|
||||
|
||||
await writeDroidBundle(tempRoot, bundle)
|
||||
|
||||
const installedSkill = await fs.readFile(
|
||||
path.join(tempRoot, ".factory", "skills", "ce:plan", "SKILL.md"),
|
||||
"utf8",
|
||||
)
|
||||
|
||||
expect(installedSkill).toContain("Task repo-research-analyst: feature_description")
|
||||
expect(installedSkill).toContain("Task learnings-researcher: feature_description")
|
||||
expect(installedSkill).toContain("Task code-simplicity-reviewer")
|
||||
expect(installedSkill).not.toContain("Task compound-engineering:")
|
||||
})
|
||||
|
||||
test("writes directly into a .factory output root", async () => {
|
||||
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "droid-home-"))
|
||||
const factoryRoot = path.join(tempRoot, ".factory")
|
||||
|
||||
@@ -338,6 +338,27 @@ Task best-practices-researcher(topic)`
|
||||
expect(result).not.toContain("Task repo-research-analyst")
|
||||
})
|
||||
|
||||
test("transforms namespaced Task agent calls using final segment", () => {
|
||||
const input = `Run agents:
|
||||
|
||||
- Task compound-engineering:research:repo-research-analyst(feature_description)
|
||||
- Task compound-engineering:review:security-reviewer(code_diff)`
|
||||
|
||||
const result = transformContentForGemini(input)
|
||||
expect(result).toContain("Use the repo-research-analyst skill to: feature_description")
|
||||
expect(result).toContain("Use the security-reviewer skill to: code_diff")
|
||||
expect(result).not.toContain("compound-engineering:")
|
||||
})
|
||||
|
||||
test("transforms zero-argument Task calls", () => {
|
||||
const input = `- Task compound-engineering:review:code-simplicity-reviewer()`
|
||||
|
||||
const result = transformContentForGemini(input)
|
||||
expect(result).toContain("Use the code-simplicity-reviewer skill")
|
||||
expect(result).not.toContain("compound-engineering:")
|
||||
expect(result).not.toContain("skill to:")
|
||||
})
|
||||
|
||||
test("transforms @agent references to skill references", () => {
|
||||
const result = transformContentForGemini("Ask @security-sentinel for a review.")
|
||||
expect(result).toContain("the security-sentinel skill")
|
||||
|
||||
@@ -66,6 +66,44 @@ describe("writeGeminiBundle", () => {
|
||||
expect(settingsContent.mcpServers.playwright.command).toBe("npx")
|
||||
})
|
||||
|
||||
test("transforms Task calls in copied SKILL.md files", async () => {
|
||||
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "gemini-skill-transform-"))
|
||||
const sourceSkillDir = path.join(tempRoot, "source-skill")
|
||||
await fs.mkdir(sourceSkillDir, { recursive: true })
|
||||
await fs.writeFile(
|
||||
path.join(sourceSkillDir, "SKILL.md"),
|
||||
`---
|
||||
name: ce:plan
|
||||
description: Planning workflow
|
||||
---
|
||||
|
||||
Run these research agents:
|
||||
|
||||
- Task compound-engineering:research:repo-research-analyst(feature_description)
|
||||
- Task compound-engineering:research:learnings-researcher(feature_description)
|
||||
- Task compound-engineering:review:code-simplicity-reviewer()
|
||||
`,
|
||||
)
|
||||
|
||||
const bundle: GeminiBundle = {
|
||||
generatedSkills: [],
|
||||
skillDirs: [{ name: "ce:plan", sourceDir: sourceSkillDir }],
|
||||
commands: [],
|
||||
}
|
||||
|
||||
await writeGeminiBundle(tempRoot, bundle)
|
||||
|
||||
const installedSkill = await fs.readFile(
|
||||
path.join(tempRoot, ".gemini", "skills", "ce:plan", "SKILL.md"),
|
||||
"utf8",
|
||||
)
|
||||
|
||||
expect(installedSkill).toContain("Use the repo-research-analyst skill to: feature_description")
|
||||
expect(installedSkill).toContain("Use the learnings-researcher skill to: feature_description")
|
||||
expect(installedSkill).toContain("Use the code-simplicity-reviewer skill")
|
||||
expect(installedSkill).not.toContain("Task compound-engineering:")
|
||||
})
|
||||
|
||||
test("namespaced commands create subdirectories", async () => {
|
||||
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "gemini-ns-"))
|
||||
const bundle: GeminiBundle = {
|
||||
|
||||
@@ -391,6 +391,27 @@ Task best-practices-researcher(topic)`
|
||||
expect(result).not.toContain("Task repo-research-analyst")
|
||||
})
|
||||
|
||||
test("transforms namespaced Task agent calls using final segment", () => {
|
||||
const input = `Run agents:
|
||||
|
||||
- Task compound-engineering:research:repo-research-analyst(feature_description)
|
||||
- Task compound-engineering:review:security-reviewer(code_diff)`
|
||||
|
||||
const result = transformContentForKiro(input)
|
||||
expect(result).toContain("Use the use_subagent tool to delegate to the repo-research-analyst agent: feature_description")
|
||||
expect(result).toContain("Use the use_subagent tool to delegate to the security-reviewer agent: code_diff")
|
||||
expect(result).not.toContain("compound-engineering:")
|
||||
})
|
||||
|
||||
test("transforms zero-argument Task calls", () => {
|
||||
const input = `- Task compound-engineering:review:code-simplicity-reviewer()`
|
||||
|
||||
const result = transformContentForKiro(input)
|
||||
expect(result).toContain("Use the use_subagent tool to delegate to the code-simplicity-reviewer agent")
|
||||
expect(result).not.toContain("compound-engineering:")
|
||||
expect(result).not.toContain("code-simplicity-reviewer agent:")
|
||||
})
|
||||
|
||||
test("transforms @agent references for known agents only", () => {
|
||||
const result = transformContentForKiro("Ask @security-sentinel for a review.", ["security-sentinel"])
|
||||
expect(result).toContain("the security-sentinel agent")
|
||||
|
||||
@@ -99,6 +99,43 @@ describe("writeKiroBundle", () => {
|
||||
expect(mcpContent.mcpServers.playwright.command).toBe("npx")
|
||||
})
|
||||
|
||||
test("transforms Task calls in copied SKILL.md files", async () => {
|
||||
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "kiro-skill-transform-"))
|
||||
const sourceSkillDir = path.join(tempRoot, "source-skill")
|
||||
await fs.mkdir(sourceSkillDir, { recursive: true })
|
||||
await fs.writeFile(
|
||||
path.join(sourceSkillDir, "SKILL.md"),
|
||||
`---
|
||||
name: ce:plan
|
||||
description: Planning workflow
|
||||
---
|
||||
|
||||
Run these research agents:
|
||||
|
||||
- Task compound-engineering:research:repo-research-analyst(feature_description)
|
||||
- Task compound-engineering:research:learnings-researcher(feature_description)
|
||||
- Task compound-engineering:review:code-simplicity-reviewer()
|
||||
`,
|
||||
)
|
||||
|
||||
const bundle: KiroBundle = {
|
||||
...emptyBundle,
|
||||
skillDirs: [{ name: "ce:plan", sourceDir: sourceSkillDir }],
|
||||
}
|
||||
|
||||
await writeKiroBundle(tempRoot, bundle)
|
||||
|
||||
const installedSkill = await fs.readFile(
|
||||
path.join(tempRoot, ".kiro", "skills", "ce:plan", "SKILL.md"),
|
||||
"utf8",
|
||||
)
|
||||
|
||||
expect(installedSkill).toContain("Use the use_subagent tool to delegate to the repo-research-analyst agent: feature_description")
|
||||
expect(installedSkill).toContain("Use the use_subagent tool to delegate to the learnings-researcher agent: feature_description")
|
||||
expect(installedSkill).toContain("Use the use_subagent tool to delegate to the code-simplicity-reviewer agent")
|
||||
expect(installedSkill).not.toContain("Task compound-engineering:")
|
||||
})
|
||||
|
||||
test("does not double-nest when output root is .kiro", async () => {
|
||||
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "kiro-home-"))
|
||||
const kiroRoot = path.join(tempRoot, ".kiro")
|
||||
|
||||
@@ -85,6 +85,70 @@ describe("convertClaudeToPi", () => {
|
||||
expect(parsedPrompt.body).toContain("file-based todos (todos/ + /skill:file-todos)")
|
||||
})
|
||||
|
||||
test("transforms namespaced Task agent calls using final segment", () => {
|
||||
const plugin: ClaudePlugin = {
|
||||
root: "/tmp/plugin",
|
||||
manifest: { name: "fixture", version: "1.0.0" },
|
||||
agents: [],
|
||||
commands: [
|
||||
{
|
||||
name: "plan",
|
||||
description: "Planning with namespaced agents",
|
||||
body: [
|
||||
"Run agents:",
|
||||
"- Task compound-engineering:research:repo-research-analyst(feature_description)",
|
||||
"- Task compound-engineering:review:security-reviewer(code_diff)",
|
||||
].join("\n"),
|
||||
sourcePath: "/tmp/plugin/commands/plan.md",
|
||||
},
|
||||
],
|
||||
skills: [],
|
||||
hooks: undefined,
|
||||
mcpServers: undefined,
|
||||
}
|
||||
|
||||
const bundle = convertClaudeToPi(plugin, {
|
||||
agentMode: "subagent",
|
||||
inferTemperature: false,
|
||||
permissions: "none",
|
||||
})
|
||||
|
||||
const parsedPrompt = parseFrontmatter(bundle.prompts[0].content)
|
||||
expect(parsedPrompt.body).toContain('Run subagent with agent="repo-research-analyst" and task="feature_description".')
|
||||
expect(parsedPrompt.body).toContain('Run subagent with agent="security-reviewer" and task="code_diff".')
|
||||
expect(parsedPrompt.body).not.toContain("compound-engineering:")
|
||||
})
|
||||
|
||||
test("transforms zero-argument Task calls", () => {
|
||||
const plugin: ClaudePlugin = {
|
||||
root: "/tmp/plugin",
|
||||
manifest: { name: "fixture", version: "1.0.0" },
|
||||
agents: [],
|
||||
commands: [
|
||||
{
|
||||
name: "review",
|
||||
description: "Review code",
|
||||
body: "- Task compound-engineering:review:code-simplicity-reviewer()",
|
||||
sourcePath: "/tmp/plugin/commands/review.md",
|
||||
},
|
||||
],
|
||||
skills: [],
|
||||
hooks: undefined,
|
||||
mcpServers: undefined,
|
||||
}
|
||||
|
||||
const bundle = convertClaudeToPi(plugin, {
|
||||
agentMode: "subagent",
|
||||
inferTemperature: false,
|
||||
permissions: "none",
|
||||
})
|
||||
|
||||
const parsedPrompt = parseFrontmatter(bundle.prompts[0].content)
|
||||
expect(parsedPrompt.body).toContain('Run subagent with agent="code-simplicity-reviewer".')
|
||||
expect(parsedPrompt.body).not.toContain("compound-engineering:")
|
||||
expect(parsedPrompt.body).not.toContain("()")
|
||||
})
|
||||
|
||||
test("appends MCPorter compatibility note when command references MCP", () => {
|
||||
const plugin: ClaudePlugin = {
|
||||
root: "/tmp/plugin",
|
||||
|
||||
@@ -50,6 +50,46 @@ describe("writePiBundle", () => {
|
||||
expect(agentsContent).toContain("MCPorter")
|
||||
})
|
||||
|
||||
test("transforms Task calls in copied SKILL.md files", async () => {
|
||||
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "pi-skill-transform-"))
|
||||
const outputRoot = path.join(tempRoot, ".pi")
|
||||
const sourceSkillDir = path.join(tempRoot, "source-skill")
|
||||
await fs.mkdir(sourceSkillDir, { recursive: true })
|
||||
await fs.writeFile(
|
||||
path.join(sourceSkillDir, "SKILL.md"),
|
||||
`---
|
||||
name: ce:plan
|
||||
description: Planning workflow
|
||||
---
|
||||
|
||||
Run these research agents:
|
||||
|
||||
- Task compound-engineering:research:repo-research-analyst(feature_description)
|
||||
- Task compound-engineering:research:learnings-researcher(feature_description)
|
||||
- Task compound-engineering:review:code-simplicity-reviewer()
|
||||
`,
|
||||
)
|
||||
|
||||
const bundle: PiBundle = {
|
||||
prompts: [],
|
||||
skillDirs: [{ name: "ce:plan", sourceDir: sourceSkillDir }],
|
||||
generatedSkills: [],
|
||||
extensions: [],
|
||||
}
|
||||
|
||||
await writePiBundle(outputRoot, bundle)
|
||||
|
||||
const installedSkill = await fs.readFile(
|
||||
path.join(outputRoot, "skills", "ce:plan", "SKILL.md"),
|
||||
"utf8",
|
||||
)
|
||||
|
||||
expect(installedSkill).toContain('Run subagent with agent="repo-research-analyst" and task="feature_description".')
|
||||
expect(installedSkill).toContain('Run subagent with agent="learnings-researcher" and task="feature_description".')
|
||||
expect(installedSkill).toContain('Run subagent with agent="code-simplicity-reviewer".')
|
||||
expect(installedSkill).not.toContain("Task compound-engineering:")
|
||||
})
|
||||
|
||||
test("writes to ~/.pi/agent style roots without nesting under .pi", async () => {
|
||||
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "pi-agent-root-"))
|
||||
const outputRoot = path.join(tempRoot, "agent")
|
||||
|
||||
@@ -508,6 +508,27 @@ Task best-practices-researcher(topic)`
|
||||
expect(result).not.toContain("Task repo-research-analyst")
|
||||
})
|
||||
|
||||
test("transforms namespaced Task agent calls using final segment", () => {
|
||||
const input = `Run agents:
|
||||
|
||||
- Task compound-engineering:research:repo-research-analyst(feature_description)
|
||||
- Task compound-engineering:review:security-reviewer(code_diff)`
|
||||
|
||||
const result = transformContentForWindsurf(input)
|
||||
expect(result).toContain("Use the @repo-research-analyst skill: feature_description")
|
||||
expect(result).toContain("Use the @security-reviewer skill: code_diff")
|
||||
expect(result).not.toContain("compound-engineering:")
|
||||
})
|
||||
|
||||
test("transforms zero-argument Task calls", () => {
|
||||
const input = `- Task compound-engineering:review:code-simplicity-reviewer()`
|
||||
|
||||
const result = transformContentForWindsurf(input)
|
||||
expect(result).toContain("Use the @code-simplicity-reviewer skill")
|
||||
expect(result).not.toContain("compound-engineering:")
|
||||
expect(result).not.toContain("code-simplicity-reviewer skill:")
|
||||
})
|
||||
|
||||
test("keeps @agent references as-is for known agents (Windsurf skill invocation syntax)", () => {
|
||||
const result = transformContentForWindsurf("Ask @security-sentinel for a review.", ["security-sentinel"])
|
||||
expect(result).toContain("@security-sentinel")
|
||||
|
||||
@@ -85,6 +85,43 @@ describe("writeWindsurfBundle", () => {
|
||||
expect(mcpContent.mcpServers.local).toEqual({ command: "echo", args: ["hello"] })
|
||||
})
|
||||
|
||||
test("transforms Task calls in copied SKILL.md files", async () => {
|
||||
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "windsurf-skill-transform-"))
|
||||
const sourceSkillDir = path.join(tempRoot, "source-skill")
|
||||
await fs.mkdir(sourceSkillDir, { recursive: true })
|
||||
await fs.writeFile(
|
||||
path.join(sourceSkillDir, "SKILL.md"),
|
||||
`---
|
||||
name: ce:plan
|
||||
description: Planning workflow
|
||||
---
|
||||
|
||||
Run these research agents:
|
||||
|
||||
- Task compound-engineering:research:repo-research-analyst(feature_description)
|
||||
- Task compound-engineering:research:learnings-researcher(feature_description)
|
||||
- Task compound-engineering:review:code-simplicity-reviewer()
|
||||
`,
|
||||
)
|
||||
|
||||
const bundle: WindsurfBundle = {
|
||||
...emptyBundle,
|
||||
skillDirs: [{ name: "ce:plan", sourceDir: sourceSkillDir }],
|
||||
}
|
||||
|
||||
await writeWindsurfBundle(tempRoot, bundle)
|
||||
|
||||
const installedSkill = await fs.readFile(
|
||||
path.join(tempRoot, "skills", "ce:plan", "SKILL.md"),
|
||||
"utf8",
|
||||
)
|
||||
|
||||
expect(installedSkill).toContain("Use the @repo-research-analyst skill: feature_description")
|
||||
expect(installedSkill).toContain("Use the @learnings-researcher skill: feature_description")
|
||||
expect(installedSkill).toContain("Use the @code-simplicity-reviewer skill")
|
||||
expect(installedSkill).not.toContain("Task compound-engineering:")
|
||||
})
|
||||
|
||||
test("writes directly into outputRoot without nesting", async () => {
|
||||
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "windsurf-direct-"))
|
||||
const bundle: WindsurfBundle = {
|
||||
|
||||
Reference in New Issue
Block a user