diff --git a/README.md b/README.md index 458c39fb..52c39720 100644 --- a/README.md +++ b/README.md @@ -249,6 +249,15 @@ Then check in with: /codex:result ``` +### Orchestration: Plan → Tasks → Execute → Review + +Use this when Claude should plan/review and Codex should execute: + +1. **Plan** in the main Claude thread: define architecture, constraints, edge cases, and target files. +2. **Tasks**: split work into small tasks with explicit acceptance criteria. +3. **Execute** with `/codex:rescue` (prefer `--background` for long tasks), then track with `/codex:status` and collect with `/codex:result`. Use `/codex:rescue --resume` for follow-ups in the same Codex thread. +4. **Review** the resulting diff locally and/or with `/codex:review` or `/codex:adversarial-review`; if needed, send targeted fixes back through `/codex:rescue --resume` and loop until it passes. + ## Codex Integration The Codex plugin wraps the [Codex app server](https://developers.openai.com/codex/app-server). It uses the global `codex` binary installed in your environment and [applies the same configuration](https://developers.openai.com/codex/config-basic). diff --git a/plugins/codex/skills/codex-orchestration/SKILL.md b/plugins/codex/skills/codex-orchestration/SKILL.md new file mode 100644 index 00000000..ab77b0d2 --- /dev/null +++ b/plugins/codex/skills/codex-orchestration/SKILL.md @@ -0,0 +1,41 @@ +--- +name: codex-orchestration +description: Claude-led orchestration loop for Plan → Tasks → Execute → Review using existing /codex commands +user-invocable: true +--- + +# Codex Orchestration + +Use this skill in the main Claude thread when Claude should act as planner/reviewer and Codex should act as executor. + +Role rules: +- Claude plans and reviews, but does not write production code in this mode. +- Codex executes edits, but does not decide architecture or product design. +- `codex:codex-rescue` stays a single-shot forwarder, not an orchestrator. + +## PLAN + +- Analyze the request and define architecture decisions, target files, constraints, and edge cases. +- Capture project invariants that must hold (for example, rules in `CLAUDE.md` when present). +- Produce a precise implementation brief with clear non-goals. + +## TASKS + +- Split the brief into small, bounded tasks. +- Give each task explicit acceptance criteria. +- Keep each task independently reviewable. + +## EXECUTE + +- Delegate each task with `/codex:rescue` (write-capable by default). +- Prefer `/codex:rescue --background` for long-running or open-ended work. +- Track background jobs with `/codex:status` and collect outputs with `/codex:result`. +- Send follow-ups in the same Codex thread using `/codex:rescue --resume` when the direction is iterative. + +## REVIEW + +- Review the produced diff against the implementation brief. +- Validate with local checks (for example typecheck/tests) and confirm constraints still hold. +- Optionally run `/codex:review` for read-only review or `/codex:adversarial-review` to challenge tradeoffs. +- If issues are found, send specific corrections with `/codex:rescue --resume`. +- Repeat the Execute/Review loop until review passes. diff --git a/tests/orchestration.test.mjs b/tests/orchestration.test.mjs new file mode 100644 index 00000000..0e0f391b --- /dev/null +++ b/tests/orchestration.test.mjs @@ -0,0 +1,34 @@ +import fs from "node:fs"; +import path from "node:path"; +import test from "node:test"; +import assert from "node:assert/strict"; +import { fileURLToPath } from "node:url"; + +const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const ORCHESTRATION_SKILL = path.join( + ROOT, + "plugins", + "codex", + "skills", + "codex-orchestration", + "SKILL.md" +); + +test("orchestration skill exists and documents Plan → Tasks → Execute → Review with rescue forwarder constraint", () => { + assert.equal(fs.existsSync(ORCHESTRATION_SKILL), true); + + const source = fs.readFileSync(ORCHESTRATION_SKILL, "utf8"); + assert.match(source, /^name:\s*codex-orchestration$/m); + assert.match(source, /^user-invocable:\s*true$/m); + assert.match(source, /^## PLAN$/m); + assert.match(source, /^## TASKS$/m); + assert.match(source, /^## EXECUTE$/m); + assert.match(source, /^## REVIEW$/m); + assert.match(source, /\/codex:rescue/); + assert.match(source, /\/codex:status/); + assert.match(source, /\/codex:result/); + assert.match(source, /\/codex:review/); + assert.match(source, /\/codex:adversarial-review/); + assert.match(source, /\/codex:rescue --resume/); + assert.match(source, /single-shot forwarder, not an orchestrator/i); +});