Skip to content
Back to skills

Compiled Loop Example

ASecurity

A worked example of a compiled loop. From a written statement of what a product is for, it runs /discover-intent then /discover-domains on one branch and ends with proposed business intents and a seeded domain, checked by a checker the config picks. Not a real loop — /create-loop copies its shape, and the loop linter's tests check it.

  • 3 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 7, 2026
businesspythongobashnode

Security analysis

A100/100

Pro scans all 19 files and shows the line behind each finding

Scanned November 7, 2026

npx -y skills add intent-driven-ai/garura --skill compiled-loop-example --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Compiled Loop Example?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Compiled Loop Example
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/intent-driven-ai-compiled-loop-example/badge)](https://www.skillsdirectory.com/skills/intent-driven-ai-compiled-loop-example)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: sample-loop
description: >
  A worked example of a compiled loop. From a written statement of what a product is for, it
  runs /discover-intent then /discover-domains on one branch and ends with proposed business intents and a seeded
  domain, checked by a checker the config picks. Not a real loop — /create-loop copies its
  shape, and the loop linter's tests check it.
user-invocable: true
kind: loop
position: both
---

# sample-loop

From a written statement, run `/discover-intent` then `/discover-domains` as one loop: one issue, one branch,
questions first, no stop for the plays' approvals, a checker at the end, and one pull request.

**Pipeline position: both.** The loop opens its change (`start-change`) and lands it (the end
sequence). The plays inside open nothing (loop contract, step 3).

## Compiled From

This loop was compiled from the sample-loop ICE (`reference/ice.md`) by create-loop.
Intent defines constraints (C1–C4) and failure conditions (F1–F4); the expectation defines
success scenarios (S1–S2), a Done means (D1–D4, baked to `stop-condition.yaml`), and one
recovery entry per failure condition. To modify this loop, update `reference/ice.md` and
recompile with `/edit-loop`.
Do NOT edit this file manually — it is a compiled artifact.

## Role

You are the loop. You run the plays below in rounds, in any order (ADR 043), and do no work of your own
(ADR 029 §2): every rule lives in the plays. You ask the loop's questions first, hand every
play the same contract, check each play's done check, commit its run files, have the checker
judge the result, and land the change. Each play runs as a sub-agent (or headless, by config)
and dispatches its own agents and judges.

**Forbidden:** doing a play's work yourself; answering a question nothing in memory or the
person's answers supports; starting a play before the one before it proved done; ending done
without the checker's pass.

## Pre-flight

| Check | Constraint | Action on Failure |
|-------|-----------|-------------------|
| Config, the plays installed, each accepts a loop contract, runner and checker known (`loop_preflight.py`) | C3 | Hard halt |
| A written statement is given | C2 | Ask for it (gather, not a halt) |

## Task DAG

```
[T1] Open the change (start-change)        blockedBy: []
[T2] Questions first                        blockedBy: [T1]
[T3] Write the loop contract               blockedBy: [T2]
[T4] Round n: run /discover-intent                   blockedBy: [T3]
[T5] Round n: run /discover-domains                   blockedBy: [T3]
[T5b] After the round: done, again or ask    blockedBy: [T4, T5]   (again: back to T4, round n+1)
[T5c] The knowledge step                  blockedBy: [T5b] (only on ask)
[T5d] Brief the person; record the reply   blockedBy: [T5c] (then back to T4)
[T6] The checker                            blockedBy: [T5b]
[E1] commit-change                          blockedBy: [T6]
[E2] propose-change                         blockedBy: [E1]
[E3] check-change                          blockedBy: [E2]
[E4] merge-change                           blockedBy: [E3]
[T7] Scenario Validation                    blockedBy: [E4]
[T8] Close                                  blockedBy: [T7]
```

## Workflow

Run the Shared Loop Run with this loop's values:

```bash
# --- Shared Loop Run (shared; see ../_shared/loop-run.md) ---
loop=sample-loop
plays=discover-intent,discover-domains
questions=who_asks -> answers.discover-intent.who_asks; proof -> answers.discover-intent.proof
runner_key=loops.sample-loop.runner
checker_key=loops.sample-loop.checker
end=commit-change, propose-change, check-change, merge-change (merge pinned)
max_rounds_key=loops.sample-loop.max_rounds
# --- end Shared Loop Run ---
```

### Phase: Open

**Step 1 — Open the change** · Owner: `start-change` · Depends on: pre-flight
Run R2 of the shared run.
**SE-1 (F1/C1):** `start-change.json` names one issue and one branch; every file the run writes
is under `{stm_base}<issue>/`.

### Phase: Questions

**Step 2 — Questions first** · Owner: loop · Depends on: Step 1
Run R3: ask "Who asks for this product?" and "How will we know it worked?". The loop reads
no memory itself; write the answers to `answers.json` and their source (`from: person`) to
`answers-sources.json`.
**SE-2 (F2/C2):** `answers.json` exists before `contract.json`, and every answer names its
source.

**Step 3 — Write the loop contract** · Owner: loop (script) · Depends on: Step 2
Run R4 with the statement as `inputs.discover-intent.statement`.

### Phase: Plays, in rounds

The plays run in rounds until the loop's job is done (R5, C3). A question one play cannot
answer goes to the loop, not to the person: the play records it in `open-<play>.json` and
finishes what it can (C2).

**Step 4 — Round n: run /discover-intent** · Owner: `discover-intent` · Depends on: Step 3 (or Step 5b, 5d)
Run R5 for `discover-intent`. A later round: it reads what `/discover-domains` wrote and fills what it left open.

**Step 5 — Round n: run /discover-domains** · Owner: `discover-domains` · Depends on: Step 3 (or Step 5b, 5d)
Run R5 for `discover-domains` with the statement as `inputs.discover-domains.goal` — never another play's output
(ADR 043).

**Step 5b — After the round: done, again or ask** · Owner: loop (script) · Depends on: Steps 4 and 5
Run R5 steps 7–8: `product-os-keeper` runs `find-model-gaps` and `link-model-gaps`, the round
is committed once, then `round_state.py` (with `--gaps` and `--close-report`, `--max-rounds`
from `loops.sample-loop.max_rounds`). `done` → Step 6. `again` → Step 4, round n+1, only the
plays named in `next`. `ask` → Step 5c.

**Step 5c — The knowledge step** · Owner: loop · Depends on: Step 5b
Run R5c: group the open questions, dispatch `knowledge-builder` once (it answers what the
sources show and what memory holds, through the memory tool; raises knowledge pages as memory
updates waiting for the person; drafts our proposed answer, with its basis and context, for
what only the person can confirm; and writes the brief), then `check_knowledge.py`.

**Step 5d — Brief the person; record the reply** · Owner: loop · Depends on: Step 5c
Run R5b: show the brief, record the reply (`from: person`), then Step 4, round n+1.
**SE-3 (F3/C3):** `discover-intent-done.json` and `discover-domains-done.json` read `done: true`; no play's
contract input names another play's output; `round-<n>-commit.json` shows no leftover; the last
`rounds.json` reads `gaps_left: 0`.

### Phase: Check

**Step 6 — The checker** · Owner: checker · Depends on: Step 5b (`done`)
Run R6.
**SE-4 (F4/C4):** `check.yaml` reads `verdict: pass` from a checker that is not the loop's own
model; a reject halted the loop.

### Phase: End sequence (injected — D2 position: both)

**Step E1 — commit-change** · Owner: `commit-change` · blockedBy: Step 6
**Step E2 — propose-change** · Owner: `propose-change` · blockedBy: E1
**Step E3 — check-change** · Owner: `check-change` · blockedBy: E2
**Step E4 — merge-change** · Owner: `merge-change` · blockedBy: E3

### Phase: Scenario Validation

**Step 7 — Scenario evals** · Owner: loop · Depends on: Step E4
- **SCE-1 (S1 — product owner):** `contract.json`, `discover-intent-done.json`, `discover-domains-done.json` and
  `check.yaml` (`verdict: pass`) exist under the issue; one pull request carries the change.
- **SCE-2 (S2 — product owner):** `/discover-domains`'s question was in `open-discover-domains.json`, the knowledge
  step ran for that round, the person's answer is in the issue's short-term memory with
  `from: person`, and `discover-domains-done.json` reads `done: true`.

### Phase: Evidence & Close

**Step 8 — Close** · Owner: loop · Depends on: Step 7

```bash
# --- Standard Play Close (shared; see ../_shared/play-close.md) ---
# Run the close in ../_shared/play-close.md (R8 of the shared loop run). The loop writes the
# one delivery report for the run. Its Next line comes from the Next-line map.
#   evidence_base="${stm_base}${issue}/evidence/sample-loop/"   ; slug="#${issue}"
session_stamp=$(python3 scripts/session_stamp.py --phase close \
    --marker "${stm_base}${issue}/status/session-stamp-sample-loop.json")
python3 scripts/check_stop_condition.py --manifest "<loop-dir>/stop-condition.yaml" \
    --base "<working>/" --out "${stm_base}${issue}/status/stop-condition-sample-loop.yaml"
sc_exit=$?   # 0 held · 1 unmet · 2 error
# --- end Standard Play Close ---
```

## Scenario Validation

| Scenario | Persona | Eval |
|----------|---------|------|
| S1 — statement to seeded domain | product owner | SCE-1 |
| S2 — a question no play answers | product owner | SCE-2 |

## Recovery

| For | Trigger | Direction | Handoff |
|-----|---------|-----------|---------|
| F1 | a write outside the issue, or a second issue or branch | move the record under the loop's issue and run on the contract's branch | autonomous |
| F2 | a play ran before the questions, answered from nothing, or the person was asked what a play or memory answers | ask the loop's own questions first; send an unanswered question to the loop (`open-<play>.json`), run the knowledge step, brief the person on what is left, then run the next round | human |
| F3 | a play took another's output, an unclean tree, or done with a node not linked | halt; re-run the play on the statement alone; commit the round; run the gap skills and the plays they give work to | human |
| F4 | the loop would end done with no checker pass | run the checker; a reject halts the loop | autonomous |

## Pause and Resume

The loop's run lives under its issue (`{stm_base}<issue>/context/sample-loop/<run-ts>/`). On
entry, find the last run folder and its last `round-<n>.json`: in the current round, skip every
play whose `<play>-done.json` reads `done: true` and whose run files are committed, and continue
from the first play not done.

## Compilation Metadata

| Field | Value |
|-------|-------|
| fingerprint | sha256:c16942eb14108a8a6b97dc62094b2ec4bce71d7bf8bc95aae8ef84be7834a966 (of `reference/ice.md`) |
| compiled_by | create-loop |
| kind | loop |
| pipeline_position | both |
| plays | discover-intent, discover-domains |
| stop_condition | stop-condition.yaml (D1–D4) |
| scripts | 13 (loop_preflight.py, write_loop_contract.py, check_loop_contract.py, run_play_headless.py, check_play_done.py, commit_run_files.py, round_state.py, loop_status.py, prepare_check.py, run_checker_codex.py, record_check.py, session_stamp.py, check_stop_condition.py) |
| step_evals | 4 (SE-1…SE-4) |
| scenario_evals | 2 (SCE-1…SCE-2) |
| recovery_entries | 4 (one per failure condition; 2 autonomous / 2 human) |

Files in this skill

  • SKILL.md10.5 KB
  • reference/ice.md5 KB
  • scripts/check_knowledge.py15.5 KB
  • scripts/check_loop_contract.py4.3 KB
  • scripts/check_play_done.py2.4 KB
  • scripts/check_stop_condition.py5 KB
  • scripts/commit_run_files.py4.2 KB
  • scripts/group_questions.py6.5 KB
  • scripts/loop_preflight.py7.4 KB
  • scripts/loop_status.py2.7 KB
  • scripts/prepare_check.py6.4 KB
  • scripts/record_check.py4.4 KB
  • scripts/record_review.py6.5 KB
  • scripts/round_state.py8.5 KB
  • scripts/run_checker_codex.py3.1 KB
  • scripts/run_play_headless.py3.5 KB
  • scripts/session_stamp.py4.8 KB
  • scripts/write_loop_contract.py3.4 KB
  • stop-condition.yaml618 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.