# template: new-dispatch-model
# version: 1
# description: Wire a new AI model into Recoil's dispatch matrix
# touches: pipeline, config, execution
# mandatory_final_phase: audit_dispatch.py

parameters:
  - name: model_id
    type: string
    pattern: "^[a-z0-9-]+$"
    description: "Model identifier (e.g., 'kling-2.0', 'seedance-1.0')"
  - name: provider
    type: enum
    values: [fal, replicate, google, openai, anthropic]
    description: "API provider"
  - name: modalities
    type: list_enum
    values: [t2v, i2v, t2i, r2v, r2v_multi, v2v, keyframe]
    min: 1
    description: "Which modalities this model supports"
  - name: adapter_method
    type: enum
    values: [existing, new]
    description: "Use an existing provider adapter or create a new one"
  - name: cinema_support
    type: enum
    values: [full, compressed, none]
    description: "Cinema mode support level (none = unsupported)"

phases:
  - name: config-registration
    engine: claude
    description: "Add model `{{ model_id }}` to model_profiles.json with provider=`{{ provider }}`, modalities=`{{ modalities }}`, cinema_support=`{{ cinema_support }}`. Add the same model to provider_strategy.json under the `{{ provider }}` provider section. Add to PROMPT_BIBLE.yaml under the {{ provider }} provider's prompt conventions section."
    files_modify:
      - recoil/config/model_profiles.json
      - recoil/config/provider_strategy.json
      - recoil/config/PROMPT_BIBLE.yaml
    validation: |
      python3 -c 'import json; json.load(open("recoil/config/model_profiles.json"))' && \
      python3 -c 'import json; json.load(open("recoil/config/provider_strategy.json"))' && \
      python3 -c 'import yaml; yaml.safe_load(open("recoil/config/PROMPT_BIBLE.yaml").read())' && \
      grep -q '{{ model_id }}' recoil/config/model_profiles.json && \
      grep -q '{{ provider }}' recoil/config/model_profiles.json && \
      grep -q '{{ cinema_support }}' recoil/config/model_profiles.json && \
      echo "config-registration OK"

  - name: adapter-wire
    engine: claude
    depends_on: [config-registration]
    description: "Add `{{ model_id }}` to the BUILDERS table in recoil/pipeline/lib/prompt_engine.py. Create one builder function per declared modality in `{{ modalities }}` (e.g., if modalities is `t2v, i2v` then create both a t2v builder and an i2v builder, keyed by their modality in the BUILDERS table). Adapter method is `{{ adapter_method }}`: if `new`, also create or extend the provider adapter at recoil/pipeline/adapters/{{ provider }}_adapter.py; if `existing`, reuse the current `{{ provider }}` adapter as-is. Do not modify any other model's builders."
    files_modify:
      - recoil/pipeline/lib/prompt_engine.py
    validation: |
      python3 -c 'import ast; ast.parse(open("recoil/pipeline/lib/prompt_engine.py").read())' && \
      grep -q '{{ model_id }}' recoil/pipeline/lib/prompt_engine.py && \
      echo "adapter-wire OK"

  - name: tests
    engine: claude
    depends_on: [adapter-wire]
    description: "Write unit tests for the new builder function"
    files_create:
      - "recoil/tests/test_{{ model_id_snake }}.py"
    validation: |
      PYTHONPATH=. pytest "recoil/tests/test_{{ model_id_snake }}.py" -x --tb=short && \
      echo "tests OK"

  - name: dispatch-audit
    mandatory: true
    description: "Run the dispatch audit to verify all modality x model paths"
    validation: |
      PYTHONPATH=. python3 recoil/pipeline/tools/audit_dispatch.py && \
      echo "dispatch-audit OK"

gates:
  pre_build:
    - description: "Model must not already exist in config"
      command: |
        python3 -c "import json; d=json.load(open('recoil/config/model_profiles.json')); assert '{{ model_id }}' not in d, 'model already exists in model_profiles.json'"
  post_build:
    - command: "PYTHONPATH=. python3 recoil/pipeline/tools/audit_dispatch.py"
    - command: "PYTHONPATH=. pytest recoil/tests/ -x --tb=short -q"
