Plugin-first E2E workflow
Structured workflow (v2.4 lineage) This reference follows the retained Plugin / source Legacy runtime and may include later fixes; it is not a frozen v2.4.0 snapshot. npm 3.x Web does not expose these structured APIs. Original v2.4.0 docs and migration · Current Web guide.
This page records the implementation audit and the acceptance path for a user who installs only the Codex Plugin. The Plugin is the product surface; the npm CLI remains a standalone Runtime, compatibility, and debugging surface.
Plugin-only Runtime and architecture audit
The current implementation has one canonical Runtime source:
| Surface | Actual implementation |
|---|---|
| Plugin manifest | .codex-plugin/plugin.json, with skills: "./skills/" |
| Five Skills | coordinate-agents, coordinate-setup, coordinate-task, coordinate-review, coordinate-recover |
| Canonical executable | bin/coordinate-agents-legacy.mjs |
| Plugin Skill resolver | skills/coordinate-agents/scripts/runtime-entry.mjs |
| Task persistence | skills/coordinate-agents/scripts/task-runtime.mjs under .agent-bus/tasks/ |
| Execution Session | skills/coordinate-agents/scripts/session-manager.mjs, session-service.mjs, and session-host.mjs under .agent-bus/sessions/ |
| PTY backend | skills/coordinate-agents/scripts/pty-runtime.mjs, preferring node-pty with bounded owned-stdio compatibility fallback |
| JSON contract | skills/coordinate-agents/scripts/runtime-contract.mjs |
| Machine configuration | skills/coordinate-agents/scripts/user-config.mjs at ~/.coordinate-agents/config.json |
| Project orchestration | .agent-bus/config.json, inboxes, state, leases, and the existing Agent Bus scripts |
| Adapter registry | skills/coordinate-agents/adapters/index.mjs; public shape validation is frozen separately in Adapter Contract v1 |
| Task execution | task dispatch uses the Session Manager to validate, open/reuse, write, observe, and persist sessionId; legacy launch remains a compatibility path |
| npm payload | package.json.files includes .codex-plugin, skills, and bin |
The resolver is intentionally not a second Runtime. It starts the same bin/coordinate-agents-legacy.mjs with process.execPath and an argument array. A Plugin Skill uses:
node "<skill-dir>/../coordinate-agents/scripts/runtime-entry.mjs" <command> ...The active Skill supplies the concrete absolute directory. The resolver checks, in order, the active Plugin ancestor, a canonical package resolution, a local personal marketplace source, the Codex cached Git marketplace layout, and known npm package roots. It never requires coordinate-agents to be on PATH. The cached layout is expected to be equivalent to:
<CODEX_HOME>/plugins/cache/<marketplace>/coordinate-agents/<version>/
├── .codex-plugin/plugin.json
├── bin/coordinate-agents-legacy.mjs
├── lib/
│ ├── cli/parse-args.mjs
│ ├── commands/
│ └── cli-core.mjs
└── skills/The canonical bin is intentionally a thin executable and compatibility export surface. Argument parsing and top-level command execution live under lib/, while the public Runtime functions remain import-compatible through the bin.
The resolver uses safe child-process argument arrays, so the Plugin path and Implementer commands remain usable on Windows with spaces in the Plugin root, absolute .exe paths, and .cmd/.bat wrappers. All five Skills use this one invocation convention.
Setup transaction
coordinate-setup separates discovery from configuration:
- Discover reports executable facts and inferred Adapter candidates without mutating user or project configuration.
- Configure accepts the chosen Agent identity and executable, infers a known Adapter where possible, and validates the Adapter contract.
generic-cliis onlyREADYwhen its argument template contains{prompt}; executable detection alone is not a compatibility claim. - The transaction writes the machine-specific command/args to
~/.coordinate-agents/config.json, ensures the project Agent registration, assignsworkflow.implementer, and leaves an absolute machine command out of.agent-bus/config.jsonunless the project already has an explicit override. - It runs the final Adapter compatibility and executable checks and returns a JSON
doctor.ok: trueresult. Failure rolls back the configuration changes.
For example, choosing a custom Antigravity wrapper preserves the identity and Adapter while selecting the wrapper as the executable:
node "<skill-dir>/../coordinate-agents/scripts/runtime-entry.mjs" setup configure --agent antigravity --command agy-proxy --adapter antigravity-cli --root "<repository>" --jsonThe result contains agent.id: "antigravity", agent.adapter: "antigravity-cli", agent.command: "agy-proxy", agent.commandSource: "user", project.registered: true, and workflow.implementer: "antigravity".
The same setup response includes the additive adapters registry snapshot. When a trusted local Contract v1 module is registered, discovery reports its identity and capabilities without launching it; a configured external Agent adds only its Contract-defined detection facts. MCP calls the same Runtime operations, so selecting that adapter preserves the exact command precedence and the canonical Task/persistent-Session lifecycle without adding a second tool catalog.
Task dispatch
Task creation remains separate from dispatch so Codex can hold a conversation, clarify requirements, and approve a complete specification. task dispatch owns the whole handoff:
Task
→ validate state and non-empty specification
→ resolve workflow.implementer and Agent config
→ resolve Adapter and final command
→ executable check
→ Agent Bus IMPLEMENT message
→ Execution Session Manager open/reuse
→ one persistent PTY activation and bounded input/output
→ Task WAITING_IMPLEMENTER or REVIEWINGWhen the executable check fails, dispatch changes the Task to ERROR, records the canonical EXECUTABLE_NOT_FOUND, records the Agent ERROR state when possible, and does not send IMPLEMENT or start a child process. A non-zero Implementer exit becomes AGENT_EXIT_NONZERO, preserves bounded output in the existing error artifact, and stops the activation. There is no fallback, auto retry, second Planner, or Autopilot.
An IMPLEMENTATION_DONE Bus message addressed to the Task Planner is promoted by the Task Runtime into implementationCommit, bounded evidence, updatedAt, and REVIEWING. The Bus remains durable transport; the Task is the product-facing state source.
The Task stores the returned sessionId but does not own the process. A healthy Session is keyed by repository root, Agent identity, and effective executable. When review records CHANGES_REQUESTED, the next explicit dispatch writes the new specification and feedback into the same healthy PTY context. An exited or failed Session is a recovery fact; replacement happens only on an explicit dispatch and never through an infinite retry loop. recover inspect reports Session facts without restarting, replaying input, or controlling the Codex App Terminal UI.
Task state mapping
| Task status | Agent Bus / operation meaning |
|---|---|
CREATED | Conversation/task record exists; no Implementer launch |
PLANNING | Codex is still clarifying the requirement |
SPEC_READY | Approved non-empty specification is persisted; dispatch is allowed |
IMPLEMENTING | IMPLEMENT was sent and the bounded activation is running |
WAITING_IMPLEMENTER | Activation ended without completion evidence; no automatic retry |
REVIEWING | IMPLEMENTATION_DONE was synchronized with commit/evidence |
CHANGES_REQUESTED | Review feedback is persisted and the next round is explicit |
APPROVED | Review approved; this is not release authorization |
ERROR | Executable, transport, spawn, or runtime failure; lastError is canonical |
STOPPED | User/runtime stopped the Task; resume is explicit |
CREATED, PLANNING, SPEC_READY, and CHANGES_REQUESTED can dispatch. IMPLEMENTING and WAITING_IMPLEMENTER reject another dispatch with TASK_ALREADY_RUNNING; APPROVED rejects dispatch; ERROR requires task resume before dispatch. CHANGES_REQUESTED increments round, and the next IMPLEMENT includes the approved specification, feedback, round, and previous commit/evidence reference.
task review --decision REVIEW_APPROVED maps REVIEWING to APPROVED. task review --decision CHANGES_REQUESTED --feedback "..." maps it to CHANGES_REQUESTED and sends the feedback through the Bus. Neither decision authorizes push, merge, tag, publish, deploy, or any other release action; the exact user gate RELEASE_APPROVED remains required.
Plugin-only acceptance gates
The automated test/plugin-e2e.test.mjs fixture materializes a Plugin root in a path containing spaces and runs with an empty executable PATH. It verifies:
- cached Plugin Runtime resolution and one-document JSON output;
- discovery-compatible
setup configure; - user config, project registration, Implementer assignment, and command precedence;
agy-proxy→antigravity+antigravity-cliwithout falling back toagy;- generic Adapter incompatibility as
UNSUPPORTED_CAPABILITY; - Task create → dispatch →
IMPLEMENT→ fixture completion →REVIEWING; CHANGES_REQUESTEDround increment and explicit redispatch;REVIEW_APPROVED→APPROVEDand release-gate separation;- missing executable failure without Bus handoff or launch;
- non-zero fixture exit as
AGENT_EXIT_NONZERO, Task/AgentERROR, and explicit resume. - Session open/status/inspect/write/read/close, bounded output, root/Agent isolation, and same-Session review rework.
- MCP setup discovery/configuration and external-adapter Task/Session coverage are exercised separately by
test/mcp-server.test.mjsusing an explicitly registered local Contract v1 fixture.
The same fixture covers Windows .cmd wrappers and POSIX executable wrappers according to the host platform. No MCP server, lifecycle Hook, Autopilot, parallel Implementer, external daemon, database, Codex Terminal UI automation, or third-party adapter loading is needed for this closure. Separately, trusted local Contract v1 modules may now be loaded only through an explicit adapter register <local-file> operation. The three built-in adapters are created through their public Contract v1 descriptors and pass the same deterministic conformance runner used by external adapters. The Runtime continues to own executable, process, Session, Task, and release behavior; the Session Host exists only after an explicit Task/Session operation.