Normalize Codex command templates to the scripts-based schema and auto-upgrade generated commands.
This commit is contained in:
@@ -70,48 +70,154 @@ CLAUDE_LOCAL_PATH = Path.home() / ".claude" / "local" / "claude"
|
|||||||
|
|
||||||
# Embedded fallback command templates for Codex (used only if packaged templates are unavailable)
|
# Embedded fallback command templates for Codex (used only if packaged templates are unavailable)
|
||||||
CODEX_CMD_SPECIFY = """---
|
CODEX_CMD_SPECIFY = """---
|
||||||
name: specify
|
description: Create or update the feature specification from a natural language feature description.
|
||||||
description: "Start a new feature by creating a specification and feature branch."
|
scripts:
|
||||||
|
sh: scripts/bash/create-new-feature.sh --json "{ARGS}"
|
||||||
|
ps: scripts/powershell/create-new-feature.ps1 -Json "{ARGS}"
|
||||||
---
|
---
|
||||||
|
|
||||||
Start a new feature by creating a specification and feature branch.
|
|
||||||
|
|
||||||
Given the feature description provided as an argument, do this:
|
Given the feature description provided as an argument, do this:
|
||||||
|
|
||||||
1. Run the script `scripts/create-new-feature.sh --json "{ARGS}"` from the repo root and parse its JSON for BRANCH_NAME and SPEC_FILE. All future paths must be absolute.
|
1. Run the script `{SCRIPT}` from repo root and parse its JSON output for BRANCH_NAME and SPEC_FILE. All file paths must be absolute.
|
||||||
2. Load `templates/spec-template.md` and create the initial specification at SPEC_FILE, filling in the placeholders with concrete details derived from the arguments while preserving headings/order.
|
2. Load `templates/spec-template.md` to understand required sections.
|
||||||
3. Report completion with the new branch name and spec file path.
|
3. Write the specification to SPEC_FILE using the template structure, replacing placeholders with concrete details derived from the feature description (arguments) while preserving section order and headings.
|
||||||
|
4. Report completion with branch name, spec file path, and readiness for the next phase.
|
||||||
|
|
||||||
|
Note: The script creates and checks out the new branch and initializes the spec file before writing.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
CODEX_CMD_PLAN = """---
|
CODEX_CMD_PLAN = """---
|
||||||
name: plan
|
description: Execute the implementation planning workflow using the plan template to generate design artifacts.
|
||||||
description: "Plan how to implement the specified feature."
|
scripts:
|
||||||
|
sh: scripts/bash/setup-plan.sh --json
|
||||||
|
ps: scripts/powershell/setup-plan.ps1 -Json
|
||||||
---
|
---
|
||||||
|
|
||||||
Plan how to implement the specified feature.
|
|
||||||
|
|
||||||
Given the implementation details provided as an argument, do this:
|
Given the implementation details provided as an argument, do this:
|
||||||
|
|
||||||
1. Run `scripts/setup-plan.sh --json` from the repo root and parse JSON for FEATURE_SPEC, IMPL_PLAN, SPECS_DIR, BRANCH. Use absolute paths in all steps.
|
1. Run `{SCRIPT}` from the repo root and parse JSON for FEATURE_SPEC, IMPL_PLAN, SPECS_DIR, BRANCH. All future file paths must be absolute.
|
||||||
2. Read the feature specification (FEATURE_SPEC) and `memory/constitution.md`.
|
2. Read and analyze the feature specification to understand:
|
||||||
3. Copy `templates/plan-template.md` to IMPL_PLAN if not already present and fill in all sections using the specification and {ARGS} as Technical Context.
|
- The feature requirements and user stories
|
||||||
4. Ensure the plan includes phases and produces research.md, data-model.md (if needed), contracts/, quickstart.md as appropriate.
|
- Functional and non-functional requirements
|
||||||
5. Report results with BRANCH and generated artifact paths.
|
- Success criteria and acceptance criteria
|
||||||
|
- Any technical constraints or dependencies mentioned
|
||||||
|
|
||||||
|
3. Read the constitution at `memory/constitution.md` to understand constitutional requirements.
|
||||||
|
|
||||||
|
4. Execute the implementation plan template:
|
||||||
|
- Load `templates/plan-template.md` (already copied to IMPL_PLAN path)
|
||||||
|
- Set Input path to FEATURE_SPEC
|
||||||
|
- Run the Execution Flow (main) function steps 1-9
|
||||||
|
- The template is self-contained and executable
|
||||||
|
- Follow error handling and gate checks as specified
|
||||||
|
- Let the template guide artifact generation in $SPECS_DIR:
|
||||||
|
* Phase 0 generates research.md
|
||||||
|
* Phase 1 generates data-model.md, contracts/, quickstart.md
|
||||||
|
* Phase 2 generates tasks.md
|
||||||
|
- Incorporate user-provided details from arguments into Technical Context: {ARGS}
|
||||||
|
- Update Progress Tracking as you complete each phase
|
||||||
|
|
||||||
|
5. Verify execution completed:
|
||||||
|
- Check Progress Tracking shows all phases complete
|
||||||
|
- Ensure all required artifacts were generated
|
||||||
|
- Confirm no ERROR states in execution
|
||||||
|
|
||||||
|
6. Report results with branch name, file paths, and generated artifacts.
|
||||||
|
|
||||||
|
Use absolute paths with the repository root for all file operations to avoid path issues.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
CODEX_CMD_TASKS = """---
|
CODEX_CMD_TASKS = """---
|
||||||
name: tasks
|
description: Generate an actionable, dependency-ordered tasks.md for the feature based on available design artifacts.
|
||||||
description: "Break down the plan into executable tasks."
|
scripts:
|
||||||
|
sh: scripts/bash/check-task-prerequisites.sh --json
|
||||||
|
ps: scripts/powershell/check-task-prerequisites.ps1 -Json
|
||||||
---
|
---
|
||||||
|
|
||||||
Break down the plan into executable tasks.
|
Given the context provided as an argument, do this:
|
||||||
|
|
||||||
1. Run `scripts/check-task-prerequisites.sh --json` and parse FEATURE_DIR and AVAILABLE_DOCS.
|
1. Run `{SCRIPT}` from repo root and parse FEATURE_DIR and AVAILABLE_DOCS list. All paths must be absolute.
|
||||||
2. Read plan.md and any available docs to derive concrete tasks.
|
2. Load and analyze available design documents:
|
||||||
3. Use `templates/tasks-template.md` as the base, generating numbered tasks (T001, T002, …) with clear file paths and dependency notes. Mark tasks that can run in parallel with [P].
|
- Always read plan.md for tech stack and libraries
|
||||||
4. Write the result to FEATURE_DIR/tasks.md.
|
- IF EXISTS: Read data-model.md for entities
|
||||||
|
- IF EXISTS: Read contracts/ for API endpoints
|
||||||
|
- IF EXISTS: Read research.md for technical decisions
|
||||||
|
- IF EXISTS: Read quickstart.md for test scenarios
|
||||||
|
|
||||||
|
Note: Not all projects have all documents. For example:
|
||||||
|
- CLI tools might not have contracts/
|
||||||
|
- Simple libraries might not need data-model.md
|
||||||
|
- Generate tasks based on what's available
|
||||||
|
|
||||||
|
3. Generate tasks following the template:
|
||||||
|
- Use `templates/tasks-template.md` as the base
|
||||||
|
- Replace example tasks with actual tasks based on:
|
||||||
|
* **Setup tasks**: Project init, dependencies, linting
|
||||||
|
* **Test tasks [P]**: One per contract, one per integration scenario
|
||||||
|
* **Core tasks**: One per entity, service, CLI command, endpoint
|
||||||
|
* **Integration tasks**: DB connections, middleware, logging
|
||||||
|
* **Polish tasks [P]**: Unit tests, performance, docs
|
||||||
|
|
||||||
|
4. Task generation rules:
|
||||||
|
- Each contract file → contract test task marked [P]
|
||||||
|
- Each entity in data-model → model creation task marked [P]
|
||||||
|
- Each endpoint → implementation task (not parallel if shared files)
|
||||||
|
- Each user story → integration test marked [P]
|
||||||
|
- Different files = can be parallel [P]
|
||||||
|
- Same file = sequential (no [P])
|
||||||
|
|
||||||
|
5. Order tasks by dependencies:
|
||||||
|
- Setup before everything
|
||||||
|
- Tests before implementation (TDD)
|
||||||
|
- Models before services
|
||||||
|
- Services before endpoints
|
||||||
|
- Core before integration
|
||||||
|
- Everything before polish
|
||||||
|
|
||||||
|
6. Include parallel execution examples:
|
||||||
|
- Group [P] tasks that can run together
|
||||||
|
- Show actual Task agent commands
|
||||||
|
|
||||||
|
7. Create FEATURE_DIR/tasks.md with:
|
||||||
|
- Correct feature name from implementation plan
|
||||||
|
- Numbered tasks (T001, T002, etc.)
|
||||||
|
- Clear file paths for each task
|
||||||
|
- Dependency notes
|
||||||
|
- Parallel execution guidance
|
||||||
|
|
||||||
|
Context for task generation: {ARGS}
|
||||||
|
|
||||||
|
The tasks.md should be immediately executable - each task must be specific enough that an LLM can complete it without additional context.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
# Utility to ensure Codex command templates use the modern schema (with scripts mapping)
|
||||||
|
def ensure_codex_command_templates_current(commands_dir: Path) -> None:
|
||||||
|
expected = {
|
||||||
|
"specify.md": CODEX_CMD_SPECIFY,
|
||||||
|
"plan.md": CODEX_CMD_PLAN,
|
||||||
|
"tasks.md": CODEX_CMD_TASKS,
|
||||||
|
}
|
||||||
|
|
||||||
|
def needs_upgrade(content: str) -> bool:
|
||||||
|
# Old templates lacked the scripts: mapping and {SCRIPT} placeholder
|
||||||
|
return "scripts:" not in content or "{SCRIPT}" not in content
|
||||||
|
|
||||||
|
for filename, template_text in expected.items():
|
||||||
|
target_file = commands_dir / filename
|
||||||
|
if target_file.exists():
|
||||||
|
try:
|
||||||
|
current = target_file.read_text(encoding="utf-8")
|
||||||
|
except Exception:
|
||||||
|
target_file.write_text(template_text, encoding="utf-8")
|
||||||
|
else:
|
||||||
|
if needs_upgrade(current):
|
||||||
|
target_file.write_text(template_text, encoding="utf-8")
|
||||||
|
else:
|
||||||
|
target_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
target_file.write_text(template_text, encoding="utf-8")
|
||||||
|
|
||||||
|
|
||||||
# ASCII Art Banner
|
# ASCII Art Banner
|
||||||
BANNER = """
|
BANNER = """
|
||||||
███████╗██████╗ ███████╗ ██████╗██╗███████╗██╗ ██╗
|
███████╗██████╗ ███████╗ ██████╗██╗███████╗██╗ ██╗
|
||||||
@@ -972,6 +1078,7 @@ def init(
|
|||||||
# Ensure scripts are executable (POSIX)
|
# Ensure scripts are executable (POSIX)
|
||||||
ensure_executable_scripts(project_path, tracker=tracker)
|
ensure_executable_scripts(project_path, tracker=tracker)
|
||||||
|
|
||||||
|
# Codex only: if commands/ is missing, copy from template (with embedded fallback)
|
||||||
if selected_ai == "codex":
|
if selected_ai == "codex":
|
||||||
tracker.start("commands")
|
tracker.start("commands")
|
||||||
try:
|
try:
|
||||||
@@ -985,13 +1092,20 @@ def init(
|
|||||||
break
|
break
|
||||||
if commands_src is not None:
|
if commands_src is not None:
|
||||||
shutil.copytree(commands_src, target_cmds, dirs_exist_ok=True)
|
shutil.copytree(commands_src, target_cmds, dirs_exist_ok=True)
|
||||||
|
ensure_codex_command_templates_current(target_cmds)
|
||||||
tracker.complete("commands", "added")
|
tracker.complete("commands", "added")
|
||||||
else:
|
else:
|
||||||
target_cmds.mkdir(parents=True, exist_ok=True)
|
template_commands = project_path / ".specify" / "templates" / "commands"
|
||||||
(target_cmds / "specify.md").write_text(CODEX_CMD_SPECIFY, encoding="utf-8")
|
if template_commands.exists():
|
||||||
(target_cmds / "plan.md").write_text(CODEX_CMD_PLAN, encoding="utf-8")
|
shutil.copytree(template_commands, target_cmds, dirs_exist_ok=True)
|
||||||
(target_cmds / "tasks.md").write_text(CODEX_CMD_TASKS, encoding="utf-8")
|
ensure_codex_command_templates_current(target_cmds)
|
||||||
tracker.complete("commands", "bootstrapped")
|
tracker.complete("commands", "added from template")
|
||||||
|
else:
|
||||||
|
target_cmds.mkdir(parents=True, exist_ok=True)
|
||||||
|
(target_cmds / "specify.md").write_text(CODEX_CMD_SPECIFY, encoding="utf-8")
|
||||||
|
(target_cmds / "plan.md").write_text(CODEX_CMD_PLAN, encoding="utf-8")
|
||||||
|
(target_cmds / "tasks.md").write_text(CODEX_CMD_TASKS, encoding="utf-8")
|
||||||
|
tracker.complete("commands", "bootstrapped minimal")
|
||||||
else:
|
else:
|
||||||
tracker.skip("commands", "already present")
|
tracker.skip("commands", "already present")
|
||||||
except Exception as codex_error:
|
except Exception as codex_error:
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ Given the implementation details provided as an argument, do this:
|
|||||||
- Success criteria and acceptance criteria
|
- Success criteria and acceptance criteria
|
||||||
- Any technical constraints or dependencies mentioned
|
- Any technical constraints or dependencies mentioned
|
||||||
|
|
||||||
3. Read the constitution at `/memory/constitution.md` to understand constitutional requirements.
|
3. Read the constitution at `memory/constitution.md` to understand constitutional requirements.
|
||||||
|
|
||||||
4. Execute the implementation plan template:
|
4. Execute the implementation plan template:
|
||||||
- Load `/templates/plan-template.md` (already copied to IMPL_PLAN path)
|
- Load `templates/plan-template.md` (already copied to IMPL_PLAN path)
|
||||||
- Set Input path to FEATURE_SPEC
|
- Set Input path to FEATURE_SPEC
|
||||||
- Run the Execution Flow (main) function steps 1-9
|
- Run the Execution Flow (main) function steps 1-9
|
||||||
- The template is self-contained and executable
|
- The template is self-contained and executable
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ Given the context provided as an argument, do this:
|
|||||||
- Generate tasks based on what's available
|
- Generate tasks based on what's available
|
||||||
|
|
||||||
3. Generate tasks following the template:
|
3. Generate tasks following the template:
|
||||||
- Use `/templates/tasks-template.md` as the base
|
- Use `templates/tasks-template.md` as the base
|
||||||
- Replace example tasks with actual tasks based on:
|
- Replace example tasks with actual tasks based on:
|
||||||
* **Setup tasks**: Project init, dependencies, linting
|
* **Setup tasks**: Project init, dependencies, linting
|
||||||
* **Test tasks [P]**: One per contract, one per integration scenario
|
* **Test tasks [P]**: One per contract, one per integration scenario
|
||||||
|
|||||||
Reference in New Issue
Block a user