-
Preflight. Run command -v codex via Bash. If it errors, stop and tell the user to install the OpenAI Codex CLI (npm i -g @openai/codex or equivalent) and authenticate.
-
Capture the target. Treat the user's argument as an opaque string <T>. Derive a filesystem-safe slug <S> (replace /, :, .., #, spaces with _) for use in tmp filenames.
-
Build the Codex prompt. Read .claude/skills/spec-compliance/SKILL.md and append a final line ARGUMENTS: <T>. Write the combined text to /tmp/dual-spec-compliance-prompt-<S>.md.
-
Launch Codex in the background. Use Bash with run_in_background: true. Pipe the prompt via stdin — the spec-compliance skill starts with --- (YAML frontmatter), which codex's arg parser treats as a flag separator and rejects with exit 2 if passed positionally:
cat /tmp/dual-spec-compliance-prompt-<S>.md | \
codex exec --skip-git-repo-check --sandbox read-only --full-auto - \
> /tmp/dual-spec-compliance-codex-<S>.md 2>&1
--full-auto is required for non-interactive background use (otherwise codex blocks on approval prompts). --sandbox read-only keeps codex from touching the working tree. You'll be notified when it finishes. Do not poll.
-
In parallel, run spec-compliance yourself by following .claude/skills/spec-compliance/SKILL.md for target <T>. Resolve every <!-- pdf|paper|spec|code[…]: … --> directive, fetch URLs via WebFetch, read PDFs via Read, and produce the full report (template and all). Hold it in memory; do not print it yet.
-
When the background task completes, read /tmp/dual-spec-compliance-codex-<S>.md. If it's empty or errored, skip to step 8 and note the dual leg failed — don't suppress your own findings to fit the template.
-
Merge. Walk both reports finding-by-finding. Two findings match if they cite the same file.go:line (±a few lines) and target the same reference anchor (same paper §/figure, same spec MUST clause, same upstream function), or describe the same root cause attributed to the same reference in different words. A finding cited against KOS15 §3.2 and one cited against RFC9180 §4.1 are not matches even if they touch the same line — they're describing different obligations. Preserve each finding's original severity tag ([deviation vs. <ref>], [missing vs. <ref>], [addition vs. <ref|all references>], [question vs. <ref>]) and original wording — do not paraphrase. For agreed-by-both findings:
- Prefer the more specific reference anchor if the two diverge in precision (
KOS15 §3.2 Thm 3 cond. (1) over KOS15 §3).
- If the kinds disagree (e.g. one says
[deviation], the other says [question]), cite both: [deviation vs. KOS15 §3.2 — Claude] / [question vs. KOS15 §3.2 — Codex].
- Keep the
_Impact:_ sub-bullet from whichever side has the more concrete property-at-stake (soundness / ZK / interop / round-trip). If both have one, keep both, attributed.
-
Print the merged report in this exact order:
## Dual spec-compliance — `<T>`
**References (union):**
- `<short-name-A>` (paper) — <role>. Locator: `<status>` (Claude) / `<status>` (Codex)
- `<short-name-B>` (spec) — <role>. Locator: `<status>` (Claude) / `<status>` (Codex)
- `<short-name-C>` (code) — <role>. Locator: `<status>` (Claude) / `<status>` (Codex)
_(If the two agents disagree on which references exist, list the union and note the disagreement on the affected rows.)_
**In-repo spec:** <synthesised; note disagreement if any>
**Acknowledged drift (from README):** <one-liner each, or "none">
### Reference ↔ Reference consistency
- `<short-name-A>` ↔ in-repo spec: <verdict — note disagreement between Claude and Codex if any>
- `<short-name-B>` ↔ `<short-name-C>` (where they overlap): <…>
### Findings unique to Claude
- **[deviation vs. KOS15 §3.2]** `file.go:42` — …
- _Impact:_ …
### Findings unique to Codex
- **[missing vs. RFC9180 §4.1 (MUST)]** `file.go:99` — …
- _Impact:_ …
### Findings agreed by both
- **[deviation vs. bitcoin/base58.cpp:DecodeBase58]** `base58.go:88` — …
- _Impact (Claude):_ …
- _Impact (Codex):_ …
### Summary
**Counts (union):** N deviation, N missing, N addition, N question.
**Per-reference coverage:** `<short-name-A>` (paper): N findings; `<short-name-B>` (spec): N; `<short-name-C>` (code): N.
**Highest-risk:** `path:line` (vs. `<short-name>` §X) — <property at stake>.
---
### Raw — Claude
<verbatim Claude spec-compliance output>
### Raw — Codex
<verbatim Codex spec-compliance output>
If a bucket is empty, write _None._ rather than omitting the header — the user wants to see at a glance whether each agent found something the other missed. Order findings within each bucket as spec-compliance prescribes: deviations first, then missing, then additions, then questions; within each kind, order by reference short-name (alphabetical), then file path, then line.