name: apo-opro
description: |
  OPRO-style prompt optimization (APO technique): maintains a running history of
  previous candidates and their scores, proposes improved variants informed by
  past weaknesses, evaluates each candidate, and iterates until the score target
  is reached or max_iterations is exceeded. History accumulates across iterations
  to guide proposals away from known failure modes.
initial: init_history
max_iterations: 25
timeout: 3600
on_handoff: spawn
context:
  prompt_file: system.md
  eval_criteria: "clarity, specificity, and effectiveness"
  target_score: 90
states:
  init_history:
    action: echo "No previous candidates."
    action_type: shell
    capture: score_history
    next: propose_candidate
  propose_candidate:
    action_type: prompt
    timeout: 300
    action: |
      Read the current prompt from ${context.prompt_file}.

      Past candidates and scores (most recent last):
      ${captured.score_history.output}

      You are a prompt optimizer. Propose an improved prompt variant that avoids the
      weaknesses visible in the history above. If there is no history yet, propose a
      first candidate based on the prompt file alone.

      Output the full improved prompt text only — no preamble, no explanation,
      no markdown fences. Just the raw prompt text.
    capture: candidate
    on_blocked: done
    next: evaluate_candidate
  evaluate_candidate:
    action_type: prompt
    timeout: 180
    action: |
      Evaluate this prompt candidate against the criteria: ${context.eval_criteria}

      CANDIDATE:
      ${captured.candidate.output}

      Respond with:
      1. A score from 0 to 100
      2. Specific strengths (1-3 bullets)
      3. Specific weaknesses and how to address them (1-3 bullets)

      If the score is >= ${context.target_score}, end your response with exactly:
      CONVERGED

      Otherwise end with exactly:
      CONTINUE
    capture: eval_result
    on_blocked: done
    next: update_history
  update_history:
    action_type: prompt
    timeout: 120
    action: |
      Append this entry to the score history and output the full updated history.

      Previous history:
      ${captured.score_history.output}

      New entry — extract the score from the evaluation below and write a one-line
      summary of the main weakness identified:
      ${captured.eval_result.output}

      Output the complete updated history (all previous entries plus the new one),
      with one entry per line in the format: Score: <N> | <one-line summary>
    capture: score_history
    on_blocked: done
    next: route_convergence
  route_convergence:
    evaluate:
      type: output_contains
      source: "${captured.eval_result.output}"
      pattern: "CONVERGED"
    on_yes: done
    on_no: propose_candidate
  done:
    terminal: true
