Skip to content

feat: add Codex CLI as delivery provider#101

Merged
azalio merged 5 commits intomainfrom
codex-plan
Apr 22, 2026
Merged

feat: add Codex CLI as delivery provider#101
azalio merged 5 commits intomainfrom
codex-plan

Conversation

@azalio
Copy link
Copy Markdown
Owner

@azalio azalio commented Apr 20, 2026

Summary

  • Add --provider codex flag to mapify init that installs .codex/ layout (skills, TOML agents, hooks) for OpenAI Codex CLI
  • Introduce BaseProvider ABC with ClaudeProvider and CodexProvider implementations for clean provider isolation
  • Fix workflow-gate step-ID translation bug where subtask_phases values weren't translated to phase names
  • Make check, doctor, upgrade commands provider-aware via _detect_provider()

Key changes

  • New files: delivery/providers.py, delivery/codex_copier.py, .codex/ templates
  • Refactored: init() now uses ClaudeProvider.install() for the claude path
  • Fixed: get_project_health() no longer reports false missing paths for codex projects
  • Tests: 28 new tests (21 AC, 3 step-ID translation, 4 edge cases)
  • Docs: CHANGELOG [Unreleased] + USAGE.md Codex section

Test plan

  • pytest tests/test_mapify_cli.py tests/test_template_sync.py tests/test_workflow_gate.py — 163 passed, 1 skipped
  • ruff check — all clean
  • Template sync verified (10 codex files byte-identical)
  • Manual: mapify init /tmp/test --provider codex --no-git produces valid .codex/ layout
  • Manual: mapify doctor on codex project shows correct status

Add BaseProvider/CodexProvider abstraction so `mapify init . --provider codex`
installs .codex/ layout (skills, TOML agents, hooks) for OpenAI Codex CLI.

- Provider-aware get_project_health(), check, doctor, upgrade commands
- Workflow gate step-ID translation (STEP_ID_TO_PHASE dict)
- ClaudeProvider wired into init() replacing direct function calls
- 28 new tests (21 AC + 3 step-ID + 4 edge cases)
- Template sync for .codex/ ↔ templates/codex/
- CHANGELOG and USAGE.md updated
Copilot AI review requested due to automatic review settings April 20, 2026 14:19
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an OpenAI Codex CLI delivery provider to MAP Framework, making initialization and diagnostics provider-aware while fixing a workflow-gate phase-translation bug.

Changes:

  • Introduces provider abstraction (BaseProvider) with ClaudeProvider + CodexProvider, and adds --provider codex to mapify init.
  • Adds .codex/ templates (skills, TOML agents, hooks/config) plus sync/verification tests to ensure template parity.
  • Fixes workflow-gate handling of subtask_phases step IDs by translating step IDs to phase names before comparing to EDITING_PHASES.

Reviewed changes

Copilot reviewed 39 out of 39 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/test_workflow_gate.py Adds regression tests for step-id → phase translation in subtask_phases.
tests/test_template_sync.py Adds Codex template synchronization/parity checks between .codex/ and templates/codex/.
tests/test_mapify_cli.py Adds functional tests for Codex provider init/doctor/upgrade and provider detection edge cases.
src/mapify_cli/templates/map/scripts/map_step_runner.py Formatting-only refactors in MAP runtime script.
src/mapify_cli/templates/map/scripts/map_orchestrator.py Formatting-only refactors in MAP orchestrator template.
src/mapify_cli/templates/map/scripts/diagnostics.py Formatting-only refactor in diagnostics template.
src/mapify_cli/templates/hooks/workflow-gate.py Adds STEP_ID_TO_PHASE mapping and translates subtask_phases values before phase comparison.
src/mapify_cli/templates/codex/skills/map-plan/SKILL.md Adds Codex $map-plan skill template (planning/decomposition workflow).
src/mapify_cli/templates/codex/skills/map-fast/SKILL.md Adds Codex $map-fast skill template (lightweight workflow).
src/mapify_cli/templates/codex/skills/map-check/SKILL.md Adds Codex $map-check skill template (verification gates).
src/mapify_cli/templates/codex/hooks/workflow-gate.py Adds Codex hook script template (workflow enforcement + constraints).
src/mapify_cli/templates/codex/hooks.json Adds Codex hook registration config.
src/mapify_cli/templates/codex/config.toml Adds Codex project configuration template.
src/mapify_cli/templates/codex/agents/researcher.toml Adds Codex agent TOML for researcher.
src/mapify_cli/templates/codex/agents/decomposer.toml Adds Codex agent TOML for decomposer.
src/mapify_cli/templates/codex/agents/monitor.toml Adds Codex agent TOML for monitor.
src/mapify_cli/templates/codex/AGENTS.md Adds Codex agent/skill index documentation.
src/mapify_cli/delivery/providers.py Adds BaseProvider ABC plus ClaudeProvider/CodexProvider implementations.
src/mapify_cli/delivery/codex_copier.py Adds Codex template copier that installs .codex/ + root AGENTS.md + optional .map/scripts/.
src/mapify_cli/delivery/init.py Re-exports provider abstractions for external import.
src/mapify_cli/cli_ui.py Updates tagline to be provider-agnostic.
src/mapify_cli/init.py Adds --provider to init; provider detection; provider-aware check/doctor/upgrade; updates project health paths.
scripts/sync-templates.sh Extends template sync script to copy .codex/ into templates/codex/.
docs/USAGE.md Documents Codex provider usage and provider auto-detection behavior.
CHANGELOG.md Adds Unreleased notes for Codex provider + provider abstraction + gate fix.
.codex/skills/map-plan/SKILL.md Adds repo-local Codex skill source for sync to templates.
.codex/skills/map-fast/SKILL.md Adds repo-local Codex skill source for sync to templates.
.codex/skills/map-check/SKILL.md Adds repo-local Codex skill source for sync to templates.
.codex/hooks/workflow-gate.py Adds repo-local Codex hook source for sync to templates.
.codex/hooks.json Adds repo-local Codex hooks config source for sync to templates.
.codex/config.toml Adds repo-local Codex config source for sync to templates.
.codex/agents/researcher.toml Adds repo-local Codex agent TOML source for sync to templates.
.codex/agents/decomposer.toml Adds repo-local Codex agent TOML source for sync to templates.
.codex/agents/monitor.toml Adds repo-local Codex agent TOML source for sync to templates.
.codex/AGENTS.md Adds repo-local Codex AGENTS.md source for sync to templates.
.claude/rules/learned/testing-strategies.md Adds learned rule emphasizing filesystem-side-effect assertions for install tests.
.claude/rules/learned/security-patterns.md Adds learned security rule about blocklist-before-allowlist ordering.
.claude/rules/learned/architecture-patterns.md Adds learned rule about provider install scope isolation.
.claude/hooks/workflow-gate.py Mirrors step-id → phase translation fix in Claude hook source.
Comments suppressed due to low confidence (1)

src/mapify_cli/init.py:317

  • get_project_health() now detects the provider for required_paths, but it still hard-codes agents_dir, commands_dir, and internal_mcp_path to .claude/* even when detected == "codex". This makes installed_agents/installed_commands and has_internal_mcp inaccurate for Codex projects and can lead to confusing diagnostics if these fields are used elsewhere later. Consider making these paths provider-aware (or returning provider-specific keys) so the health payload is self-consistent.
    agents_dir = project_path / ".claude" / "agents"
    commands_dir = project_path / ".claude" / "commands"
    mcp_json_path = project_path / ".mcp.json"
    internal_mcp_path = project_path / ".claude" / "mcp_config.json"

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +142 to +146
claude_md = project_path / "CLAUDE.md"
if claude_md.exists() and not claude_md.is_symlink():
agents_md_dst.symlink_to("CLAUDE.md")
else:
shutil.copy2(agents_md_src, agents_md_dst)
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agents_md_dst.symlink_to("CLAUDE.md") can raise OSError on platforms without symlink support/permissions (notably Windows) and will make mapify init --provider codex fail even though a regular file copy would work. Consider wrapping the symlink creation in try/except and falling back to copying AGENTS.md when symlinks are unavailable (and/or gating symlink creation behind an OS capability check).

Copilot uses AI. Check for mistakes.
Comment on lines +1048 to +1056
codex_dir = project_path / ".codex"
codex_checks = {
".codex/config.toml": codex_dir / "config.toml",
".codex/skills": codex_dir / "skills",
".codex/agents": codex_dir / "agents",
}
codex_missing = [n for n, p in codex_checks.items() if not p.exists()]
if not codex_missing:
tracker.complete("project", "all core paths present (codex)")
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In doctor(), the Codex branch validates only .codex/{config.toml,skills,agents} but omits .map/scripts, which get_project_health() treats as required for Codex projects. As a result, doctor can report “all core paths present (codex)” even when the MAP runtime scripts are missing. Consider adding .map/scripts to codex_checks (or reusing health["missing_paths"] for Codex too) so diagnostics are consistent.

Copilot uses AI. Check for mistakes.
Comment on lines +2 to +13
"""
Claude Code PreToolUse Hook: Workflow Enforcement Gate

Blocks Edit/Write/MultiEdit outside of Actor-related phases.
Uses step_state.json (orchestrator canonical state) as single source of truth.

ENFORCEMENT:
- Edit allowed during phases: ACTOR, APPLY, TEST_WRITER
- Edit blocked during all other phases (DECOMPOSE, MONITOR, PREDICTOR, etc.)
- Fail-open: missing or unreadable step_state.json → allow
- Always allows: .map/ artifacts, ~/.claude/ memory, non-editing tools

Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Codex hook template still identifies itself as a “Claude Code PreToolUse Hook” and references ~/.claude/ memory paths. Since this file is shipped under templates/codex/ and installed into .codex/, the docstring/comments should be updated to accurately describe Codex (and, if applicable, Codex-specific exempt paths). Also ensure the corresponding .codex/hooks/workflow-gate.py stays byte-identical to satisfy the template sync tests.

Copilot uses AI. Check for mistakes.
…der interop

Decomposer (833 lines): full JSON schema, AAG contract format, complexity
scoring, re-decomposition mode — matching map_orchestrator.py contract.

Monitor (852 lines): 11-dimension quality model, BUILD GATE, decision rules,
full JSON output schema — matching map_orchestrator.py contract.

Researcher (75 lines): structured findings format, search strategy, 1500-token
budget, read-only enforcement.

Also remove allow_network=false from config.toml (use Codex defaults).
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 39 out of 39 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

src/mapify_cli/init.py:318

  • get_project_health() switches required_paths based on the detected provider, but it still hard-codes agents_dir/commands_dir/internal_mcp_path to .claude/*, which makes installed_agents/installed_commands/has_internal_mcp misleading (and potentially wrong) for codex projects. Consider branching these paths (or returning provider-specific health fields) when detected == "codex" so codex projects report installed templates and MCP status from .codex/ (or explicitly omit those metrics).
    agents_dir = project_path / ".claude" / "agents"
    commands_dir = project_path / ".claude" / "commands"
    mcp_json_path = project_path / ".mcp.json"
    internal_mcp_path = project_path / ".claude" / "mcp_config.json"
    branch_artifact_files = [

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +142 to +146
claude_md = project_path / "CLAUDE.md"
if claude_md.exists() and not claude_md.is_symlink():
agents_md_dst.symlink_to("CLAUDE.md")
else:
shutil.copy2(agents_md_src, agents_md_dst)
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating AGENTS.md as a symlink to CLAUDE.md can raise OSError/PermissionError (notably on Windows or restricted filesystems), which would fail mapify init --provider codex. Wrap the symlink creation in try/except and fall back to copying the template (or copying CLAUDE.md contents) if symlinks aren’t permitted.

Copilot uses AI. Check for mistakes.
Comment thread scripts/sync-templates.sh Outdated
Comment on lines +56 to +60
# Config + hooks
cp -a .codex/config.toml "$templates_root/codex/"
cp -a .codex/hooks.json "$templates_root/codex/"
find .codex/hooks -maxdepth 1 -type f | xargs -I{} cp -a {} "$templates_root/codex/hooks/"

Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With set -euo pipefail, the unconditional .codex/* copies will cause this script to exit if any of those files/dirs are absent. In particular, find .codex/hooks ... will error if .codex/hooks doesn’t exist, and the pipeline will fail the whole sync. Add explicit [[ -f ... ]] / [[ -d ... ]] guards (and consider using rsync for hooks too) so partial/bootstrapping codex layouts don’t break sync-templates.sh.

Copilot uses AI. Check for mistakes.
Comment on lines +2 to +13
"""
Claude Code PreToolUse Hook: Workflow Enforcement Gate

Blocks Edit/Write/MultiEdit outside of Actor-related phases.
Uses step_state.json (orchestrator canonical state) as single source of truth.

ENFORCEMENT:
- Edit allowed during phases: ACTOR, APPLY, TEST_WRITER
- Edit blocked during all other phases (DECOMPOSE, MONITOR, PREDICTOR, etc.)
- Fail-open: missing or unreadable step_state.json → allow
- Always allows: .map/ artifacts, ~/.claude/ memory, non-editing tools

Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Codex workflow-gate template’s docstring still says “Claude Code PreToolUse Hook” and mentions “~/.claude/ memory”, which is confusing/misleading for Codex users. Update the header/docs to refer to Codex (or make it provider-neutral) so users don’t assume it only applies to Claude paths.

Copilot uses AI. Check for mistakes.
azalio added 3 commits April 20, 2026 17:57
Tests using os.chdir(tmp_path) were leaking the changed CWD to
subsequent test files, breaking workflow-context-injector tests that
use relative path .claude/hooks/. Add autouse conftest fixture.
- Symlink fallback: try/except OSError on AGENTS.md symlink creation,
  fall back to file copy on platforms without symlink support
- doctor() codex: add .map/scripts to codex_checks for consistent diagnostics
- workflow-gate.py: update docstring to provider-agnostic language
- sync-templates.sh: add [[ -f ]] / [[ -d ]] guards for partial codex layouts
Codex CLI expects developer_instructions as a plain string, not a
[developer_instructions] table. Change from:
  [developer_instructions]
  content = """..."""
To:
  developer_instructions = """..."""

Also register agents in config.toml [agents.*] sections and add
CI test (TestCodexAgentTomlFormat) that validates TOML parsing and
developer_instructions type to prevent regression.
@azalio azalio merged commit 8e3f2e1 into main Apr 22, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants