---
name: create-loop
description: Use when asked to create an automation loop or automate a recurring task with an FSM.
allowed-tools:
  - Bash(mkdir:*, test:*, ll-loop:*)
metadata:
  short-description: Use when asked to create an automation loop or automate a recurring task with an
---

# Create Loop

Interactive command for creating new automation loop configurations. This command guides you through:
1. Choosing a structural loop pattern (fix until clean, maintain constraints, drive a metric, run a sequence, or harness a skill/prompt)
2. Gathering type-specific parameters
3. Naming the loop
4. Generating and previewing FSM YAML
5. Saving and validating
6. Optional test iteration to verify the loop works

## Allowed Tools

Use these tools during the workflow:
- `AskUserQuestion` - For interactive prompts
- `Write` - To save the loop configuration
- `Bash` - To run validation and create directories
- `Read` - To check for existing loops

## Workflow

### Step -1: Natural Language Pre-fill (when args provided)

**If `args` is non-empty**, parse the natural language description before doing anything else. Skip this step entirely when `args` is empty or absent.

#### Inference Rules

Read the description and infer the following fields:

**Loop type** — map keywords to types:
- "fix", "clean", "until passing", "lint", "type check", "test" → `fix-until-clean`
- "maintain", "keep", "enforce", "constraint", "guard" → `maintain-constraints`
- "reduce", "increase", "drive", "metric", "count", "score", "coverage" → `drive-metric`
- "sequence", "steps", "pipeline", "stage", "ordered" → `run-sequence`
- "harness", "wrap", "skill", "prompt", "iterate", "refine" → `harness`
- "bandit", "explore", "exploit", "A/B", "strategy" → `rl-bandit`
- "generate", "score", "RLHF", "quality", "candidate" → `rl-rlhf`
- "policy", "act", "observe", "reward", "agent" → `rl-policy`
- "optimize", "meta", "improve loop", "improve skill", "improve command" → `meta-optimize`
- "route", "dispatch", "compose", "orchestrate", "supervisor", "router" → `orch-router`

**Key parameters** — extract as many as possible from the description:
- Check/fix command (e.g., "run pytest", "run mypy", "run ruff")
- Target skill or prompt name
- Metric name and direction (reduce/increase) and target value
- Step names for sequences
- Max iterations (e.g., "up to 10 times", "max 5 iterations")
- Loop name hint (e.g., "call it X", "name it X")

**Suggested loop name** — derive from inferred type and targets (same rules as Step 3).

#### Confirmation Display

Present a structured summary of inferred values in text (not a tool call), then use AskUserQuestion:

```
I understood your description as:

  Loop type:      <inferred type label>
  <param key>:    <inferred value>
  <param key>:    <inferred value>
  ...
  Suggested name: <suggested-name>

Anything I couldn't confidently infer will be asked next.
```

```yaml
questions:
  - question: "Does this match what you want?"
    header: "Confirm intent"
    multiSelect: false
    options:
      - label: "Yes, generate the loop (Recommended)"
        description: "Use inferred values — skip the wizard and go straight to YAML preview"
      - label: "Let me adjust first"
        description: "Walk through the guided questions with inferred values as defaults"
```

#### Routing

- **"Yes, generate the loop"** — skip Steps 0–3, proceed directly to **Step 4** with all inferred values already populated. For any parameter that could not be confidently inferred, use the type-appropriate defaults from [loop-types.md](loop-types.md).
- **"Let me adjust first"** — proceed to **Step 0**, but pre-select inferred values as the default answer in each subsequent `AskUserQuestion` call (highlight the inferred option or pre-fill the text). The user can override any of them.

---

### Step 0: Creation Mode

Use AskUserQuestion to determine whether to use a template or build from scratch:

```yaml
questions:
  - question: "How would you like to create your loop?"
    header: "Creation mode"
    multiSelect: false
    options:
      - label: "Start from template (Recommended)"
        description: "Choose a pre-built loop for common tasks"
      - label: "Build from scratch"
        description: "Configure a new loop from scratch using the guided wizard"
```

**If "Start from template"**: Read [templates.md](templates.md) for template selection and customization flow (Steps 0.1-0.2), then skip to Step 4.
**If "Build from scratch"**: Skip to Step 1 (Loop Type Selection)

---

### Step 1: Loop Type Selection (Custom Mode Only)

If user selected "Build from scratch" in Step 0, use this flow.

Use AskUserQuestion with a single-select to determine the loop type:

```yaml
questions:
  - question: "What kind of automation loop do you want to create?"
    header: "Loop type"
    multiSelect: false
    options:
      - label: "Fix until clean (Recommended)"
        description: "Run a check and fix issues until it passes. Pattern: evaluate → fix → done"
      - label: "Maintain constraints"
        description: "Keep multiple conditions true in a chain. Pattern: check-fix pairs chained to terminal"
      - label: "Drive a metric toward a target"
        description: "Measure a value and apply fixes until it reaches goal. Best for: reducing error counts, coverage"
      - label: "Run a sequence of steps"
        description: "Execute steps in order, repeat until condition met. Best for: multi-stage builds"
      - label: "Harness a skill or prompt"
        description: "Wrap a skill/prompt with plan-evaluate-iterate. Auto-generates evaluation from project context."
      - label: "Specialist role pipeline"
        description: "Decompose a task into Plan -> Research -> Implement -> Report specialist roles. Best for deep refactors, multi-file features, and cross-cutting changes."
      - label: "RL: Bandit (explore vs exploit)"
        description: "Epsilon-greedy bandit loop — alternate explore/exploit rounds, routing on reward convergence. Best for: A/B strategy selection, prompt optimization, hyperparameter search."
      - label: "RL: RLHF-style (generate → score → refine)"
        description: "Generate candidate output, score quality, refine until quality target is met. Best for: iterative content improvement, prompt refinement, answer quality loops."
      - label: "RL: Policy iteration (act → observe → improve)"
        description: "Agent acts, observes reward, improves policy toward a target. Best for: environment interaction, agent training simulations, adaptive automation."
      - label: "Optimize a harness (meta-loop)"
        description: "Iteratively improve a loop YAML, skill, agent, or command using an external scorer. Generates diagnosis-first scaffolding required for meta-loops (SHOR-compliant)."
      - label: "Orch: Router (dynamic dispatch)"
        description: "Classify a goal and dispatch to the best-fit existing loop. Pattern: classify → score → dispatch → review → done"
      - label: "Orch: Composer (goal → DAG)"
        description: "Decompose a goal into a sequence of sub-loops run via depends_on. Maps to loop-composer built-in loop."
      - label: "Orch: Supervisor (adaptive re-plan)"
        description: "Run a loop, reassess on failure, re-plan the sub-loop sequence. Maps to loop-composer-adaptive built-in loop."
      - label: "Orch: Cluster (multi-goal fan-out)"
        description: "Orchestrate a list of goals (sprint, EPIC, backlog slice) as batches with cross-batch context propagation. Maps to goal-cluster built-in loop."
```

**Type Mapping:**
- "Fix until clean" -> `fix-until-clean` type (states: evaluate, fix, done)
- "Maintain constraints" -> `maintain-constraints` type (check/fix pairs + terminal)
- "Drive a metric toward a target" -> `drive-metric` type (states: measure, apply, done)
- "Run a sequence of steps" -> `run-sequence` type (step_0...step_N, check_done, done)
- "Harness a skill or prompt" -> `harness` type (states: discover, execute, check_concrete, check_semantic, check_invariants, advance, done)
- "Specialist role pipeline" -> `specialist-pipeline` type (states: plan, research, implement, report, done)
- **Sub-loop composition** — not a wizard type; use `loop:` field in YAML to invoke other loops as child FSMs (see [reference.md](reference.md))
- "RL: Bandit (explore vs exploit)" -> `rl-bandit` type (states: explore, exploit, reward, done)
- "RL: RLHF-style (generate → score → refine)" -> `rl-rlhf` type (states: generate, score, refine, done)
- "RL: Policy iteration (act → observe → improve)" -> `rl-policy` type (states: act, observe, score, improve, done)
- "Optimize a harness (meta-loop)" -> `meta-optimize` type (states: diagnose, baseline, propose, apply, score, gate, commit_or_revert, done)
- "Orch: Router (dynamic dispatch)" -> `orch-router` type (states: classify, score, dispatch, review, done)
- "Orch: Composer (goal → DAG)" -> `loop-composer` built-in loop (run via `ll-loop run loop-composer --input "..."`)
- "Orch: Supervisor (adaptive re-plan)" -> `loop-composer-adaptive` built-in loop (run via `ll-loop run loop-composer-adaptive --input "..."`)
- "Orch: Cluster (multi-goal fan-out)" -> `goal-cluster` built-in loop (run via `ll-loop run goal-cluster --input "goal1\ngoal2\n..."` or `--input "EPIC-NNN"`)

### Step 2: Type-Specific Questions

Based on the selected loop type, read [loop-types.md](loop-types.md) for the detailed question flow and FSM YAML generation for each type.

---

### Step 3: Loop Name

After gathering type-specific parameters, ask for the loop name:

```yaml
questions:
  - question: "What should this loop be called?"
    header: "Loop name"
    multiSelect: false
    options:
      - label: "<auto-suggested-name>"
        description: "Based on your selections"
      - label: "Custom name"
        description: "Enter your own name"
```

**Auto-suggest names based on loop type:**
- Fix until clean: `fix-<targets>` (e.g., `fix-types-and-lint`)
- Maintain constraints: `<constraint-names>-guardian` (e.g., `tests-types-lint-guardian`)
- Drive a metric: `reduce-<metric>` or `increase-<metric>` (e.g., `reduce-lint-errors`)
- Run a sequence: `<step-summary>-loop` (e.g., `fix-test-check-loop`)
- Harness a skill/prompt: `harness-<skill-name>` or `<skill-name>-loop` (e.g., `harness-refine-issue`)

### Step 4: Preview and Confirm

Generate and display the FSM YAML.

**Generate FSM YAML:**

Read [loop-types.md](loop-types.md) for the FSM YAML template for the selected loop type. Generate the complete FSM YAML based on the parameters gathered in Step 2.

Also generate a summary preview showing:
1. States in execution order (use -> between states)
2. Transitions for each non-terminal state
3. Terminal states marked with `[terminal]`
4. Initial state and max_steps from the configuration

**Routing graph check (before presenting to user):**

Scan the generated routing graph for infinite cycles. If any non-terminal state A routes to state B (via `on_no`, `on_error`, or `next:`), and state B routes unconditionally back to A, warn the user inline:

> ⚠️ Routing cycle detected: `<A>` → `<B>` → `<A>`. If the condition that triggers `on_no`/`on_error` is persistent (e.g. a required tool is unavailable), this cycle runs until `max_steps` is exhausted. Consider routing failures forward to a recovery or terminal state instead.

The most common case: a `generate` state with `next: evaluate` and an `evaluate` state with `on_no: generate` is a cycle when Playwright or another external capture tool is absent. The fix is `on_no: score` (degrade to LLM evaluation) rather than `on_no: generate`.

Also warn if the generated YAML includes a `terminal: true` failure state that has an `action:` field — the action is silently skipped by the executor (`_finish("terminal")` fires before any action runs). The correct pattern is a two-state `diagnose → failed` split: a non-terminal `diagnose` state with the diagnostic action and `next: failed`, followed by a bare `failed: terminal: true` state with no action.

**Display format:**

```
Here's your loop configuration:

## FSM YAML
```yaml
<generated-yaml>
```

## Summary
States: <state1> -> <state2> -> ... -> <terminal>
Transitions:
  <state1>: <verdict>-><target>, <verdict>-><target>
  <state2>: next-><target>
  ...
  <terminal>: [terminal]
Initial: <initial-state>
Max steps: <max_steps>
Evaluator: <type> [<details>]  # Only shown if non-default evaluator configured

This will create: {{config.loops.loops_dir}}/<name>.yaml
```

Use AskUserQuestion:
```yaml
questions:
  - question: "Save this loop configuration?"
    header: "Confirm"
    multiSelect: false
    options:
      - label: "Yes, save and validate"
        description: "Save to {{config.loops.loops_dir}}/<name>.yaml and run validation"
      - label: "No, start over"
        description: "Discard and restart the wizard"
```

### Step 5: Save and Validate

If confirmed:

1. **Create directory if needed:**
   ```bash
   mkdir -p {{config.loops.loops_dir}}
   ```

2. **Check for existing file:**
   ```bash
   test -f {{config.loops.loops_dir}}/<name>.yaml && echo "EXISTS" || echo "OK"
   ```

   If exists, ask:
   ```yaml
   questions:
     - question: "A loop with this name already exists. Overwrite?"
       header: "Overwrite"
       multiSelect: false
       options:
         - label: "Yes, overwrite"
           description: "Replace the existing loop configuration"
         - label: "No, choose different name"
           description: "Go back and pick a new name"
   ```

3. **Write the file** using the Write tool:
   - Path: `{{config.loops.loops_dir}}/<name>.yaml`
   - Content: The generated YAML

4. **Validate** using ll-loop CLI:
   ```bash
   ll-loop validate <name>
   ```

5. **Offer test iteration** (after validation succeeds):

   Use AskUserQuestion:
   ```yaml
   questions:
     - question: "Would you like to run a test iteration to verify the loop works?"
       header: "Test run"
       multiSelect: false
       options:
         - label: "Yes, run one iteration (Recommended)"
           description: "Execute check command and verify evaluation works"
         - label: "No, I'll test manually"
           description: "Skip test iteration"
   ```

   If "Yes, run one iteration":
   ```bash
   ll-loop test <name>
   ```

   Display the test output directly. Example output:

   ```
   ## Test Iteration: my-loop

   State: check
   Action: {{config.project.type_cmd}} {{config.project.src_dir}}

   Exit code: 1
   Output:
   Found 3 errors in 1 file (checked 5 source files)

   Evaluator: exit_code (default)
   Verdict: FAILURE

   Would transition: check -> fix

   Loop appears to be configured correctly
   ```

   The test command validates your loop configuration by running one iteration:
   - Shows the state and action being tested
   - Displays exit code and output (truncated if long)
   - Reports evaluator type and verdict
   - Indicates what transition would occur

   Continue to the success report regardless of test result.

6. **Report results:**

   On success (no test issues):
   ```
   Loop created successfully!

   File: {{config.loops.loops_dir}}/<name>.yaml
   States: <list-of-states>
   Initial: <initial-state>
   Max iterations: <max>

   Run now with: ll-loop <name>
   Tip: Run /ll:review-loop <name> to audit quality and best practices.
   ```

   On success with test issues (test ran but found problems):
   ```
   Loop created successfully!

   File: {{config.loops.loops_dir}}/<name>.yaml
   States: <list-of-states>
   Initial: <initial-state>
   Max iterations: <max>

   Note: Test iteration found issues - see output above.
   You may want to review the configuration before running.

   Run now with: ll-loop <name>
   Tip: Run /ll:review-loop <name> to audit quality and best practices.
   ```

   On validation failure:
   ```
   Loop saved but validation failed:
   <error-message>

   Please fix the configuration at {{config.loops.loops_dir}}/<name>.yaml
   ```

## Additional Resources

- For pre-built loop templates, see [templates.md](templates.md)
- For loop type question flows and FSM YAML generation, see [loop-types.md](loop-types.md)
- For quick reference tables and advanced configuration, see [reference.md](reference.md)

**Note on `from:` inheritance**: A new loop that closely matches an existing one can declare `from: <parent-loop-name>` at the top level instead of duplicating the full state graph. Inheritance is resolved before validation and diagram generation, so the validator and `/ll:review-loop` always see the materialized loop. See `docs/guides/LOOPS_GUIDE.md#loop-template-inheritance-via-from` for merge rules.

## Examples

```bash
# Start the interactive wizard
/ll:create-loop

# Pass a natural language description to skip most wizard questions
/ll:create-loop run mypy and ruff until they both pass
/ll:create-loop reduce lint errors to zero using ruff check, max 8 iterations
/ll:create-loop harness the refine-issue skill and iterate until the issue is implementation-ready
/ll:create-loop maintain tests passing and types clean, call it quality-guardian
/ll:create-loop poll GitHub CI every 5 minutes and retry on failure, max 20 iterations
```

When args are provided, the skill infers loop type and parameters from the description, shows a
confirmation summary, and — if confirmed — jumps straight to the YAML preview (Step 4), skipping
the guided wizard entirely.

---

## Integration

This command creates FSM loop configurations that can be executed with the `ll-loop` CLI.

Works well with:
- `ll-loop <name>` - Execute the created loop
- `ll-loop validate <name>` - Validate loop configuration
- `/ll:check-code` - Often used as a fix action in loops
- `/ll:manage-issue` - Used for complex bug fixes in loops
