Conversation
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
There was a problem hiding this comment.
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) withClaudeProvider+CodexProvider, and adds--provider codextomapify init. - Adds
.codex/templates (skills, TOML agents, hooks/config) plus sync/verification tests to ensure template parity. - Fixes workflow-gate handling of
subtask_phasesstep IDs by translating step IDs to phase names before comparing toEDITING_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 forrequired_paths, but it still hard-codesagents_dir,commands_dir, andinternal_mcp_pathto.claude/*even whendetected == "codex". This makesinstalled_agents/installed_commandsandhas_internal_mcpinaccurate 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.
| 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) |
There was a problem hiding this comment.
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).
| 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)") |
There was a problem hiding this comment.
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.
| """ | ||
| 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 | ||
|
|
There was a problem hiding this comment.
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.
…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).
There was a problem hiding this comment.
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.
| 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) |
There was a problem hiding this comment.
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.
| # 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/" | ||
|
|
There was a problem hiding this comment.
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.
| """ | ||
| 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 | ||
|
|
There was a problem hiding this comment.
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.
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.
Summary
--provider codexflag tomapify initthat installs.codex/layout (skills, TOML agents, hooks) for OpenAI Codex CLIBaseProviderABC withClaudeProviderandCodexProviderimplementations for clean provider isolationsubtask_phasesvalues weren't translated to phase namescheck,doctor,upgradecommands provider-aware via_detect_provider()Key changes
delivery/providers.py,delivery/codex_copier.py,.codex/templatesinit()now usesClaudeProvider.install()for the claude pathget_project_health()no longer reports false missing paths for codex projectsTest plan
pytest tests/test_mapify_cli.py tests/test_template_sync.py tests/test_workflow_gate.py— 163 passed, 1 skippedruff check— all cleanmapify init /tmp/test --provider codex --no-gitproduces valid .codex/ layoutmapify doctoron codex project shows correct status