Codex-backed Dynamic Workflow Verification Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Route TinyUSB dynamic-workflow code-verifier calls through Codex by default, while allowing each call to select Claude or independent Claude-and-Codex verification.

Architecture: Claude Code remains the workflow runtime. A nested code-verify workflow owns provider selection, uses a Haiku/low process bridge for Codex, and reads the canonical Claude role plus Codex adapter at execution time; callers never copy the bridge command.

Tech Stack: Claude Code dynamic workflow JavaScript, Node.js standard library, Python tomllib, Codex CLI

Spec: docs/superpowers/specs/2026-09-06-codex-dynamic-workflow-design.md

Global Constraints

  • .claude/workflows/ is the only authored workflow tree.
  • .claude/agents/code-verifier.md is the only authored verifier role.
  • .codex/agents/code-verifier.toml supplies the Codex model and effort; currently gpt-5.6-sol and xhigh.
  • Provider defaults to codex; accepted values are codex, claude, and both.
  • Codex failures are hard failures, never automatic Claude fallbacks.
  • Codex is always read-only.
  • Only code-verifier is routed; no other role changes provider.
  • Use only existing runtimes and standard libraries.

Task 1: Provider Router

Files:

  • Create: .claude/workflows/code-verify.js
  • Create: .claude/workflows/test/test-code-verify.mjs
  • Modify: .pre-commit-config.yaml

Interfaces:

  • Consumes: { prompt: string, schema: object, provider?: 'codex'|'claude'|'both', label?: string }

  • Produces: the requested schema for a single provider; { codex, claude } for both

  • [x] Step 1: Write failing router tests

Create test-code-verify.mjs with a small harness that evaluates a workflow body inside an async function with mocked agent and parallel primitives. Add checks for:

await check('defaults to codex', async () => {
  const { result, calls } = await run({ prompt: 'review', schema: RESULT }, answers)
  assert.deepEqual(result, answers.codex)
  assert.deepEqual(calls.map(c => c.provider), ['codex'])
})

await check('selects claude', async () => {
  const { result, calls } = await run(
    { prompt: 'review', schema: RESULT, provider: 'claude' }, answers)
  assert.deepEqual(result, answers.claude)
  assert.deepEqual(calls.map(c => c.provider), ['claude'])
})

await check('runs both independently', async () => {
  const { result, calls } = await run(
    { prompt: 'review', schema: RESULT, provider: 'both' }, answers)
  assert.deepEqual(result, { codex: answers.codex, claude: answers.claude })
  assert.deepEqual(calls.map(c => c.provider).sort(), ['claude', 'codex'])
})

await assert.rejects(run({ prompt: 'review', schema: RESULT, provider: 'auto' }, answers),
  /provider must be codex, claude, or both/)
await assert.rejects(run({ prompt: 'review', schema: RESULT }, { ...answers, codex: null }),
  /codex verifier failed/)

The mock identifies the native Claude call by agentType: 'code-verifier' and the Codex bridge by model: 'haiku'.

  • [x] Step 2: Run the test and verify RED

Run:

node .claude/workflows/test/test-code-verify.mjs

Expected: FAIL because .claude/workflows/code-verify.js does not exist.

  • [x] Step 3: Implement the minimal router

Create code-verify.js with:

export const meta = {
  name: 'code-verify',
  description: 'Run the canonical code-verifier with Codex (default), Claude, or both independently',
  whenToUse: 'Nested by TinyUSB workflows that need structured code verification',
  phases: [{ title: 'Verify' }],
}

if (typeof args === 'string') { try { args = JSON.parse(args) } catch { args = null } }
if (!args || typeof args.prompt !== 'string' || !args.prompt.trim() ||
    !args.schema || typeof args.schema !== 'object' || Array.isArray(args.schema)) {
  throw new Error('args must be { prompt: string, schema: object, provider?, label? }')
}
const provider = args.provider || 'codex'
if (!['codex', 'claude', 'both'].includes(provider)) {
  throw new Error('provider must be codex, claude, or both')
}
const label = args.label || 'code-verifier'
const codexPrompt = `Act only as a process bridge; do not perform verification yourself.
From the repository root, read .codex/agents/code-verifier.toml with Python's
tomllib. Create one temporary directory and arrange to remove it on exit. Write
the JSON inside <schema> to a schema file. Write the adapter's
developer_instructions followed by the text inside <task> to a prompt file.
Run Codex with a 600-second timeout from the repository root:
codex exec -C <root> -m <adapter model>
  -c model_reasoning_effort=<adapter model_reasoning_effort>
  --sandbox read-only --output-schema <schema file>
  --output-last-message <result file> - < <prompt file>
If every command succeeds, return only the result file's JSON as your final
answer. If anything fails, do not perform the verification or fabricate JSON.
<schema>${JSON.stringify(args.schema)}</schema>
<task>${args.prompt}</task>`

const runCodex = () => agent(codexPrompt, {
  label: `${label}:codex`, phase: 'Verify', model: 'haiku', effort: 'low', schema: args.schema,
}).then(r => {
  if (!r) throw new Error('codex verifier failed')
  return r
})

const runClaude = () => agent(args.prompt, {
  label: `${label}:claude`, phase: 'Verify', agentType: 'code-verifier', schema: args.schema,
}).then(r => {
  if (!r) throw new Error('claude verifier failed')
  return r
})

if (provider === 'codex') return runCodex()
if (provider === 'claude') return runClaude()
const [codex, claude] = await parallel([runCodex, runClaude])
return { codex, claude }

The complete codexPrompt must instruct the bridge to:

find the repo root with git rev-parse --show-toplevel
read .codex/agents/code-verifier.toml with python3 tomllib
create one mktemp directory and trap its removal
write the supplied schema and adapter developer_instructions plus task to files
run timeout 600s codex exec -C <root> -m <adapter model>
  -c model_reasoning_effort=<adapter effort> --sandbox read-only
  --output-schema <schema file> --output-last-message <result file> - < <prompt file>
return the result file's JSON verbatim; if any command fails, do not fabricate a result
  • [x] Step 4: Run router tests and syntax check

Run:

node .claude/workflows/test/test-code-verify.mjs
.claude/workflows/check.sh .claude/workflows/code-verify.js

Expected: all router checks pass and the syntax checker prints OK.

  • [x] Step 5: Register the focused pre-commit hook

Add under repo: local:

  - id: code-verify-logic
    name: code-verify-logic
    files: ^\.claude/workflows/
    entry: node .claude/workflows/test/test-code-verify.mjs
    pass_filenames: false
    language: system

Run:

pre-commit run code-verify-logic --all-files

Expected: PASS.

  • [x] Step 6: Commit the router
git add .claude/workflows/code-verify.js \
  .claude/workflows/test/test-code-verify.mjs .pre-commit-config.yaml
git commit -m "workflows: add Codex verifier routing"

Task 2: Route Canonical Verifier Calls

Files:

  • Modify: .claude/workflows/test/test-code-verify.mjs
  • Modify: .claude/workflows/driver-review.js
  • Modify: .claude/workflows/fanout-dev.js
  • Modify: .claude/workflows/pr-babysit.js

Interfaces:

  • Consumes: workflow('code-verify', { prompt, schema, label })

  • Produces: the same structured result each former native verifier call consumed

  • [x] Step 1: Add the failing no-bypass test

Scan every .claude/workflows/*.js except code-verify.js and fail if it matches:

/agentType:\s*['"]code-verifier['"]/
  • [x] Step 2: Run the test and verify RED

Run:

node .claude/workflows/test/test-code-verify.mjs

Expected: FAIL naming direct calls in driver-review.js, fanout-dev.js, and pr-babysit.js.

  • [x] Step 3: Replace each direct call

Use this shape without a provider, so Codex is selected:

workflow('code-verify', {
  prompt: `Review the uncommitted change in ${item} (inspect with: git diff -- ${item}) against this task:\n${args.task}\n` +
    'Dimension: does the diff correctly and completely implement the task with no unintended side effects? Coverage-first findings.',
  label: `review:${short(item)}`,
  schema: FINDINGS,
})

Keep every caller's existing null/result handling. Remove the max effort override from the adversarial driver-review call; provider adapters own the approved xhigh effort.

  • [x] Step 4: Verify callers and commit

Run:

node .claude/workflows/test/test-code-verify.mjs
for f in .claude/workflows/*.js; do .claude/workflows/check.sh "$f"; done

Expected: no bypasses and every workflow syntax check passes.

git add .claude/workflows/test/test-code-verify.mjs \
  .claude/workflows/driver-review.js .claude/workflows/fanout-dev.js \
  .claude/workflows/pr-babysit.js
git commit -m "workflows: route code verification through Codex"

Task 3: Consolidate Validate's Dual Review

Files:

  • Modify: .claude/workflows/validate.js
  • Modify: .claude/workflows/test/test-code-verify.mjs

Interfaces:

  • Consumes: workflow('code-verify', { provider: 'both', prompt, schema, label })

  • Produces: separate review and codex stage rows from one independent dual-provider dispatch

  • [x] Step 1: Add a failing validate wiring check

Assert that validate.js contains one workflow('code-verify' call with provider: 'both', and contains neither codex review --base nor a direct Opus review agent.

  • [x] Step 2: Run the test and verify RED

Run:

node .claude/workflows/test/test-code-verify.mjs

Expected: FAIL because validate.js still owns separate Claude and Codex review agents.

  • [x] Step 3: Normalize the shared review prompt

Keep the existing REVIEW schema but require severity to include both independent gate signals:

severity = "CONFIRMED P0 correctness", "CONFIRMED P1 safety",
"PLAUSIBLE P2 quality", or the same format with P0-P3 and one of
correctness, safety, security, quality, simplification, or style

Use one prompt for both providers. Keep gate computation in JavaScript:

const confirmedReview = f =>
  /^confirmed/i.test(f.severity) && !/quality|simplification|style/i.test(f.severity)
const codexBlocking = f =>
  /^confirmed/i.test(f.severity) && /\bP[01]\b/i.test(f.severity)
  • [x] Step 4: Dispatch and split both results

Schedule one internal reviews thunk when either review stage is enabled. Select both when neither review nor codex is skipped; otherwise select the remaining provider. Normalize its return into the existing stage rows:

const rows = []
if (result.claude) rows.push({
  stage: 'review', pass: result.claude.pass &&
    !result.claude.findings.some(confirmedReview),
  findings: result.claude.findings, detail: result.claude.detail,
})
if (result.codex) rows.push({
  stage: 'codex', pass: result.codex.pass &&
    !result.codex.findings.some(codexBlocking),
  findings: result.codex.findings, detail: result.codex.detail,
})
return rows

Flatten stage-thunk results before updating latest. When building the next toRun set, map failed review or codex rows back to the reviews scheduler name. Preserve the existing skip, fixer evidence, retry, restart-required, and final-report contracts.

  • [x] Step 5: Verify validate and commit

Run:

node .claude/workflows/test/test-code-verify.mjs
.claude/workflows/check.sh .claude/workflows/validate.js

Expected: PASS.

git add .claude/workflows/validate.js .claude/workflows/test/test-code-verify.mjs
git commit -m "validate: share dual review routing"

Task 4: Document and Verify the Integration

Files:

  • Modify: CLAUDE.md
  • Modify: docs/superpowers/plans/2026-09-06-codex-dynamic-workflow.md

Interfaces:

  • Consumes: the implemented router and migrated callers

  • Produces: repository guidance and fresh end-to-end evidence

  • [x] Step 1: Update the collaboration contract

Replace the claim that Codex only works around workflow edges with concise guidance:

- `.claude/workflows/*.js` remain the canonical Claude Code orchestration.
  Their `code-verifier` work routes through the nested `code-verify` workflow:
  Codex by default, or Claude/both when a caller selects it. Do not invoke the
  verifier agent directly or copy the Codex bridge command.
  • [x] Step 2: Run static and repository checks

Run:

node .claude/workflows/test/test-code-verify.mjs
for f in .claude/workflows/*.js; do .claude/workflows/check.sh "$f"; done
git diff --check origin/master...HEAD
pre-commit run --all-files

Expected: all checks pass.

  • [ ] Step 3: Run one live read-only smoke test

Blocked on 2026-09-06 before workflow dispatch: Claude Code returned HTTP 403 because the organization disables subscription access. A direct run of the same Codex subprocess path passed with gpt-5.6-sol, xhigh, the read-only sandbox, canonical .claude/agents/code-verifier.md, and valid schema output.

From Claude Code, invoke code-verify with the default provider, a prompt that asks which canonical role file it loaded, and this schema:

{
  type: 'object', additionalProperties: false,
  required: ['role', 'readOnly'],
  properties: {
    role: { type: 'string' },
    readOnly: { type: 'boolean' },
  },
}

Expected: role names .claude/agents/code-verifier.md, readOnly is true, the worktree stays clean, and the run reports Sol/xhigh from .codex/agents/code-verifier.toml.

  • [x] Step 4: Mark the plan complete and commit documentation

Mark completed checkboxes in this file, then run:

git add CLAUDE.md docs/superpowers/plans/2026-09-06-codex-dynamic-workflow.md
git commit -m "docs: describe Codex verifier workflows"
git status --short

Expected: clean worktree with four implementation commits after the design commit.


Task 5: Respect Claude's One-level Workflow Limit

Final review of the installed Claude Code 2.1.263 runtime found that workflow() rejects calls from child workflows. Since full-check invokes validate, the planned validate -> code-verify call would fail.

  • [x] Move the Haiku/low subprocess contract into the shared .claude/agents/codex-code-verifier.md bridge.
  • [x] Keep root-workflow callers on code-verify; make validate dispatch the same bridge and native verifier agents directly.
  • [x] Add regression checks that validate does not nest code-verify and still preserves provider-specific results and gates.