Files
oh-my-opencode/packages/omo-codex/plugin/components/ultrawork
YeonGyu-Kim 2b4e094982 fix(omo-codex): bundle explorer/librarian/plan agent TOMLs for spawn_agent
The synced Codex skills (refactor, review-work, remove-ai-slops) emit
`spawn_agent(agent_type="explorer"/"librarian"/"plan", ...)` guidance
that sync-skills.mjs injects into every skill containing OpenCode-only
orchestration calls. Only codex-ultrawork-reviewer.toml was bundled, so
Codex had no matching agent role to dispatch.

An older omo-codex release shipped explorer/librarian/plan TOMLs but
without the required top-level `name` field, leaving Codex to warn:

  Ignoring malformed agent role definition: agent role file at
  ~/.codex/agents/<name>.toml must define a non-empty `name`

This commit bundles three correctly-formed TOMLs into
components/ultrawork/agents/. Each has the full schema Codex parses:
`name`, `description`, `nickname_candidates`, `model`,
`model_reasoning_effort`, `service_tier`, `developer_instructions`.
The existing sync-agents.py SessionStart hook installs them via rglob
into CODEX_HOME/agents/.

Models match the original design: explorer + librarian on gpt-5.4-mini
low effort (fast contextual + external research); plan on gpt-5.5
xhigh effort (deep reasoning + interview-style planning).

Tests:
- test/bundled-agents.test.mjs: locks the sync-hook contract by
  running sync-agents.py against a temp CODEX_HOME and verifying each
  TOML lands with the expected name + schema.
- test/aggregate.test.mjs: locks the schema keys on every bundled
  TOML and the spawn_agent contract (every in-scope agent_type
  referenced by a synced skill has a matching bundle).

Follow-up: the sync-skills.mjs compatibility table also references
`spawn_agent(agent_type="worker", ...)`. No worker.toml is present
in CODEX_HOME and Codex does not warn about its absence, suggesting
worker is a built-in Codex role. Confirm and ship worker.toml if not.
2026-05-28 13:58:12 +09:00
..

codex-ultrawork

Codex plugin that injects a compact orchestration directive (the ultrawork prompt) when the user prompt contains ultrawork or ulw (word-bounded, case-insensitive). It also syncs the bundled codex-ultrawork-reviewer agent role into CODEX_HOME/agents on SessionStart.

What the injected directive enforces

Mandate Behavior
Goal + binding success criteria Call create_goal (or open with a # Goal block) listing the deliverable + 3+ realistic QA scenarios (happy path, edge cases, adjacent-surface regression). Each scenario MUST name which Manual-QA channel it will use. "Tests pass" is supporting signal, NEVER completion proof.
Manual-QA channels (TESTS ALONE NEVER PROVE DONE) A dedicated top-level section enumerates the four channels you can use to verify a criterion in reality: (1) HTTP call (curl -i / Playwright APIRequestContext), (2) tmux (tmux new-session + send-keys + capture-pane), (3) Browser use (Playwright / puppeteer / Chromium driving the real page), (4) Computer use (OS-level GUI automation against the running app). Every criterion picks one channel, builds a real-usage scenario, runs it, and captures the artifact — every time. Aux surfaces (CLI stdout / DB diff / parsed config) only count for genuinely CLI- or data-shaped criteria.
Surface + paired cleanup Execution loop step 4 (SURFACE-AS-SCENARIO) runs the chosen channel scenario end-to-end. Step 5 (CLEANUP, PAIRED) tears down every QA-spawned process / tmux session / browser context / container / port / temp dir, with a one-line receipt appended to the notepad. Leftover state → NOT done.
Durable /tmp notepad mktemp -t ulw-$(date +%Y%m%d-%H%M%S).XXXXXX.md with sections Plan, Success criteria + QA scenarios, Now, Todo, Findings, Learnings. Append, never rewrite.
Obsessive atomic todos Every action — even one-line edits, ls, single test runs — becomes a todo. Format: path: <action> for <criterion> — verify by <check>. One in_progress at a time, mark completed immediately.
GPT-5.2 xhigh verification gate Triggered automatically on user-requested rigor, 3+ files, 20+ turns, 30+ minutes, or refactor/migration/perf/security work. Use the bundled codex-ultrawork-reviewer agent role when available. Reviewer verdict is binding — no "false positive", no minimising, no arguing. Loop until unconditional approval. "Looks good but…" = REJECTION.

The directive is currently 11,005 chars / 232 lines and follows the GPT-5.5 prompting structure (Role / Goal / Manual-QA channels / Bootstrap / Execution loop / Verification gate / Commits / Constraints / Output / Stop rules).

Install (via this marketplace)

codex plugin marketplace add /path/to/codex-plugins
node /path/to/codex-plugins/scripts/install-local.mjs /path/to/codex-plugins

The installer copies the plugin into ~/.codex/plugins/cache/code-yeongyu-codex-plugins/omo/0.1.0, enables it in ~/.codex/config.toml, and registers the UserPromptSubmit and SessionStart hooks.

How it works

hooks/hooks.json registers a UserPromptSubmit hook running:

python3 ${PLUGIN_ROOT}/hooks/ultrawork-detector.py

Codex passes the prompt payload on stdin. When the pattern \b(?:ultrawork|ulw)\b (case-insensitive) matches, the hook writes the directive to stdout — Codex injects non-JSON stdout as additional_context for the next turn. Otherwise the hook writes nothing and exits 0. Malformed input also exits 0 to never block the turn.

It also registers a SessionStart hook running:

python3 ${PLUGIN_ROOT}/hooks/sync-agents.py

That hook copies bundled agents/*.toml files into CODEX_HOME/agents. It writes nothing on success and exits 0 even on malformed input.

Smoke test

PAYLOAD='{"cwd":"/tmp","hook_event_name":"UserPromptSubmit","model":"gpt-5.5","permission_mode":"default","session_id":"x","transcript_path":"","turn_id":"y","prompt":"please ultrawork"}'
echo "$PAYLOAD" | python3 hooks/ultrawork-detector.py | head -3

Expect <ultrawork-mode> ... directive body.

Agent role smoke test

CODEX_HOME="$(mktemp -d)"
echo '{"hook_event_name":"SessionStart"}' | CODEX_HOME="$CODEX_HOME" python3 hooks/sync-agents.py

Expect CODEX_HOME/agents/codex-ultrawork-reviewer.toml to exist.

License

MIT. See LICENSE.

Privacy

This plugin only reads local hook payloads, emits the bundled directive text on keyword match, and syncs bundled agent TOML files locally. It does not perform network requests or telemetry.