diff --git a/packages/omo-codex/plugin/scripts/sync-skills.mjs b/packages/omo-codex/plugin/scripts/sync-skills.mjs index 62c36a307..6ba2923a2 100644 --- a/packages/omo-codex/plugin/scripts/sync-skills.mjs +++ b/packages/omo-codex/plugin/scripts/sync-skills.mjs @@ -1,10 +1,11 @@ #!/usr/bin/env node -import { cp, mkdir, readdir, rm } from "node:fs/promises"; +import { cp, mkdir, readdir, readFile, rm, writeFile } from "node:fs/promises"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; const root = dirname(dirname(fileURLToPath(import.meta.url))); const sharedSkillsRoot = join(root, "..", "..", "shared-skills", "skills"); +const skillsRoot = join(root, "skills"); const skillSources = [ ["comment-checker", "components/comment-checker/skills/comment-checker"], ["lsp", "components/lsp/skills/lsp"], @@ -12,11 +13,53 @@ const skillSources = [ ["ultragoal", "components/ultragoal/skills/ultragoal"], ]; -await rm(join(root, "skills"), { recursive: true, force: true }); -await mkdir(join(root, "skills"), { recursive: true }); +const opencodeOnlyOrchestrationPattern = /\b(?:call_omo_agent|background_output|team_[a-z_]+|task)\s*\(/; + +const codexHarnessToolCompatibility = `## Codex Harness Tool Compatibility + +This skill may include examples copied from the OpenCode harness. In Codex, do not call OpenCode-only tools such as \`call_omo_agent(...)\`, \`task(...)\`, \`background_output(...)\`, or \`team_*(...)\` literally. Translate those examples to Codex native tools: + +| OpenCode example | Codex tool to use | +| --- | --- | +| \`call_omo_agent(subagent_type="explore", ...)\` | \`spawn_agent(agent_type="explorer", task_name="...", message="...")\` | +| \`call_omo_agent(subagent_type="librarian", ...)\` | \`spawn_agent(agent_type="librarian", task_name="...", message="...")\` | +| \`task(subagent_type="plan", ...)\` | \`spawn_agent(agent_type="plan", task_name="...", message="...")\` | +| \`task(subagent_type="oracle", ...)\` for final verification | \`spawn_agent(agent_type="codex-ultrawork-reviewer", task_name="...", message="...")\` | +| \`task(category="...", ...)\` for implementation or QA | \`spawn_agent(agent_type="worker", task_name="...", message="...")\` | +| \`background_output(task_id="...")\` | \`wait_agent(...)\` to wait for subagent completion and mailbox updates | +| \`team_*(...)\` | Use Codex native subagents plus \`send_message\`, \`followup_task\`, \`wait_agent\`, and \`close_agent\` | + +When translating \`load_skills=[...]\`, include the requested skill names in the spawned agent's \`message\`. If a code block below conflicts with this section, this section wins. + +`; + +function insertCodexCompatibilityGuidance(content) { + if (!opencodeOnlyOrchestrationPattern.test(content)) return content; + if (content.includes("## Codex Harness Tool Compatibility")) return content; + + const frontmatterMatch = content.match(/^---\n[\s\S]*?\n---\n+/); + if (!frontmatterMatch) { + return `${codexHarnessToolCompatibility}${content}`; + } + + return `${frontmatterMatch[0]}${codexHarnessToolCompatibility}${content.slice(frontmatterMatch[0].length)}`; +} + +async function adaptSkillForCodex(skillName) { + const skillPath = join(skillsRoot, skillName, "SKILL.md"); + const content = await readFile(skillPath, "utf8"); + const adapted = insertCodexCompatibilityGuidance(content); + if (adapted !== content) { + await writeFile(skillPath, adapted, "utf8"); + } +} + +await rm(skillsRoot, { recursive: true, force: true }); +await mkdir(skillsRoot, { recursive: true }); for (const [name, source] of skillSources) { - await cp(join(root, source), join(root, "skills", name), { recursive: true }); + await cp(join(root, source), join(skillsRoot, name), { recursive: true }); + await adaptSkillForCodex(name); } const sharedSkillEntries = await readdir(sharedSkillsRoot, { withFileTypes: true }); @@ -26,5 +69,6 @@ const sharedSkillNames = sharedSkillEntries .sort(); for (const skillName of sharedSkillNames) { - await cp(join(sharedSkillsRoot, skillName), join(root, "skills", skillName), { recursive: true }); + await cp(join(sharedSkillsRoot, skillName), join(skillsRoot, skillName), { recursive: true }); + await adaptSkillForCodex(skillName); } diff --git a/packages/omo-codex/plugin/skills/refactor/SKILL.md b/packages/omo-codex/plugin/skills/refactor/SKILL.md index 50cac0609..9fcbdd6b7 100644 --- a/packages/omo-codex/plugin/skills/refactor/SKILL.md +++ b/packages/omo-codex/plugin/skills/refactor/SKILL.md @@ -3,6 +3,22 @@ name: refactor description: "Intelligent refactor command. Triggers: refactor, refactoring, cleanup, restructure, extract, simplify, modernize." --- +## Codex Harness Tool Compatibility + +This skill may include examples copied from the OpenCode harness. In Codex, do not call OpenCode-only tools such as `call_omo_agent(...)`, `task(...)`, `background_output(...)`, or `team_*(...)` literally. Translate those examples to Codex native tools: + +| OpenCode example | Codex tool to use | +| --- | --- | +| `call_omo_agent(subagent_type="explore", ...)` | `spawn_agent(agent_type="explorer", task_name="...", message="...")` | +| `call_omo_agent(subagent_type="librarian", ...)` | `spawn_agent(agent_type="librarian", task_name="...", message="...")` | +| `task(subagent_type="plan", ...)` | `spawn_agent(agent_type="plan", task_name="...", message="...")` | +| `task(subagent_type="oracle", ...)` for final verification | `spawn_agent(agent_type="codex-ultrawork-reviewer", task_name="...", message="...")` | +| `task(category="...", ...)` for implementation or QA | `spawn_agent(agent_type="worker", task_name="...", message="...")` | +| `background_output(task_id="...")` | `wait_agent(...)` to wait for subagent completion and mailbox updates | +| `team_*(...)` | Use Codex native subagents plus `send_message`, `followup_task`, `wait_agent`, and `close_agent` | + +When translating `load_skills=[...]`, include the requested skill names in the spawned agent's `message`. If a code block below conflicts with this section, this section wins. + export const REFACTOR_TEMPLATE = `# Intelligent Refactor Command ## Usage diff --git a/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md b/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md index 5102d44bf..453b2e597 100644 --- a/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +++ b/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md @@ -3,6 +3,22 @@ name: remove-ai-slops description: Remove AI-generated code smells (slop) from branch changes or an explicit file list. Locks behavior with regression tests FIRST, then runs categorized cleanup via parallel `deep` agents in batches of 5, then verifies with quality gates. Covers 10 slop categories including performance equivalences, excessive complexity (object annotations, if/elif variant chains), and oversized modules (250+ pure LOC with mandatory modular refactoring). MUST USE when the user asks to "remove slop", "clean AI code", "deslop", "AI 코드 정리", "AI 슬롭 제거", or wants to clean up AI-generated patterns from recent changes. Triggers - "remove ai slops", "clean ai code", "deslop", "cleanup AI generated", "AI 슬롭 제거", "AI 코드 정리해줘", "슬롭 빼라", "ai-slop 정리". --- +## Codex Harness Tool Compatibility + +This skill may include examples copied from the OpenCode harness. In Codex, do not call OpenCode-only tools such as `call_omo_agent(...)`, `task(...)`, `background_output(...)`, or `team_*(...)` literally. Translate those examples to Codex native tools: + +| OpenCode example | Codex tool to use | +| --- | --- | +| `call_omo_agent(subagent_type="explore", ...)` | `spawn_agent(agent_type="explorer", task_name="...", message="...")` | +| `call_omo_agent(subagent_type="librarian", ...)` | `spawn_agent(agent_type="librarian", task_name="...", message="...")` | +| `task(subagent_type="plan", ...)` | `spawn_agent(agent_type="plan", task_name="...", message="...")` | +| `task(subagent_type="oracle", ...)` for final verification | `spawn_agent(agent_type="codex-ultrawork-reviewer", task_name="...", message="...")` | +| `task(category="...", ...)` for implementation or QA | `spawn_agent(agent_type="worker", task_name="...", message="...")` | +| `background_output(task_id="...")` | `wait_agent(...)` to wait for subagent completion and mailbox updates | +| `team_*(...)` | Use Codex native subagents plus `send_message`, `followup_task`, `wait_agent`, and `close_agent` | + +When translating `load_skills=[...]`, include the requested skill names in the spawned agent's `message`. If a code block below conflicts with this section, this section wins. + # Remove AI Slops Skill ## Inputs diff --git a/packages/omo-codex/plugin/skills/review-work/SKILL.md b/packages/omo-codex/plugin/skills/review-work/SKILL.md index 8dd521d7c..759b2c59a 100644 --- a/packages/omo-codex/plugin/skills/review-work/SKILL.md +++ b/packages/omo-codex/plugin/skills/review-work/SKILL.md @@ -2,6 +2,22 @@ name: review-work description: "Post-implementation review orchestrator. Launches 5 parallel background sub-agents: Oracle (goal/constraint verification), Oracle (code quality), Oracle (security), unspecified-high (hands-on QA execution), unspecified-high (context mining from GitHub/git/Slack/Notion). All must pass for review to pass. MUST USE after completing any significant implementation work. Triggers: 'review work', 'review my work', 'review changes', 'QA my work', 'verify implementation', 'check my work', 'validate changes', 'post-implementation review'." --- +## Codex Harness Tool Compatibility + +This skill may include examples copied from the OpenCode harness. In Codex, do not call OpenCode-only tools such as `call_omo_agent(...)`, `task(...)`, `background_output(...)`, or `team_*(...)` literally. Translate those examples to Codex native tools: + +| OpenCode example | Codex tool to use | +| --- | --- | +| `call_omo_agent(subagent_type="explore", ...)` | `spawn_agent(agent_type="explorer", task_name="...", message="...")` | +| `call_omo_agent(subagent_type="librarian", ...)` | `spawn_agent(agent_type="librarian", task_name="...", message="...")` | +| `task(subagent_type="plan", ...)` | `spawn_agent(agent_type="plan", task_name="...", message="...")` | +| `task(subagent_type="oracle", ...)` for final verification | `spawn_agent(agent_type="codex-ultrawork-reviewer", task_name="...", message="...")` | +| `task(category="...", ...)` for implementation or QA | `spawn_agent(agent_type="worker", task_name="...", message="...")` | +| `background_output(task_id="...")` | `wait_agent(...)` to wait for subagent completion and mailbox updates | +| `team_*(...)` | Use Codex native subagents plus `send_message`, `followup_task`, `wait_agent`, and `close_agent` | + +When translating `load_skills=[...]`, include the requested skill names in the spawned agent's `message`. If a code block below conflicts with this section, this section wins. + # Review Work - 5-Agent Parallel Review Orchestrator Launch 5 specialized sub-agents in parallel to review completed implementation work from every angle. All 5 must pass for the review to pass. If even ONE fails, the review fails. diff --git a/packages/omo-codex/plugin/test/sync-skills.test.mjs b/packages/omo-codex/plugin/test/sync-skills.test.mjs index 8dae8b4d4..7ff99f058 100644 --- a/packages/omo-codex/plugin/test/sync-skills.test.mjs +++ b/packages/omo-codex/plugin/test/sync-skills.test.mjs @@ -37,3 +37,28 @@ test("#given synced aggregate Codex skills #when inspected #then component and s assert.match(content, /^---\n/); } }); + +test("#given synced aggregate Codex skills #when they contain OpenCode orchestration examples #then Codex tool compatibility guidance is injected", async () => { + // given + const skillsRoot = join(root, "skills"); + const opencodeOnlyToolPattern = /\b(?:call_omo_agent|background_output|team_[a-z_]+|task)\s*\(/; + + // when + const skillNames = (await readdir(skillsRoot, { withFileTypes: true })) + .filter((entry) => entry.isDirectory()) + .map((entry) => entry.name) + .sort(); + + // then + for (const skillName of skillNames) { + const content = await readFile(join(skillsRoot, skillName, "SKILL.md"), "utf8"); + if (!opencodeOnlyToolPattern.test(content)) continue; + + const compatibilityIndex = content.indexOf("## Codex Harness Tool Compatibility"); + assert.notEqual(compatibilityIndex, -1, `${skillName} is missing Codex compatibility guidance`); + assert.ok( + compatibilityIndex < content.search(opencodeOnlyToolPattern), + `${skillName} must explain Codex tool translation before OpenCode-only examples`, + ); + } +});