Complete Discovery
ASecurityThe Discovery loop — product to intent (ADR 029 §6, ADR 043). Give it a working prototype (a file, a project folder or a link) and a short write-up of it, and it reads the prototype once and runs /discover-intent, /discover-domains and /discover-capabilities on that one reading, each writing its own kind — business intents, domains, capabilities and features — on one issue and one branch. After each round it has the model's gaps found and closed, and gives the work still missing to the play t...
- 3 stars
- 0 votes
- 0 copies
- 0 views
- Added November 7, 2026
Security analysis
100/100Pro scans all 20 files and shows the line behind each finding
npx -y skills add intent-driven-ai/garura --skill complete-discovery --agent claude-codeAre you the author of Complete Discovery?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/intent-driven-ai-complete-discovery)---
name: complete-discovery
description: >
The Discovery loop — product to intent (ADR 029 §6, ADR 043). Give it a working prototype (a
file, a project folder or a link) and a short write-up of it, and it reads the prototype once
and runs /discover-intent, /discover-domains and /discover-capabilities on that one reading, each writing its own kind —
business intents, domains, capabilities and features — on one issue and one branch.
After each round it has the model's gaps found and closed, and gives the work still missing
to the play that does it, until everything is linked. It asks first what it can, asks the
person only what none of its plays, memory or approved research answers, has a checker the
config picks judge the result, records its evidence, and ends at the pull request where the
person types confirm or drop for each intent. Use when someone shares a working prototype and wants the product model built from
it — "discovery", "start from this prototype", "run the Discovery loop".
user-invocable: true
kind: loop
position: both
---
# discovery
From a working prototype and its write-up to business intents the person has decided and a
linked product model — as one loop: one issue, one branch, questions and the write-up first,
one reading of the prototype for every play, no stop for the plays' approvals, the loop closed
by the gap skills, a checker at the end, 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 discovery ICE (`reference/ice.md`) by create-loop (#613) and
recompiled by edit-loop (#689, ADR 043). Intent defines constraints (C1–C8) and failure
conditions (F1–F8); the expectation defines success scenarios (S1–S4), a Done means (D1–D8,
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 `/discover-intent`, `/discover-domains` and `/discover-capabilities` and do no work of your own
(ADR 029 §2): every rule about intents and the product model lives in the plays and skills.
You check the prototype, ask what you can first and get the write-up, have the
`prototype-reader` read the prototype once, hand every play the same contract with that one
capture, check each play's done check, have `product-os-keeper` find and close the model's
gaps after each round, commit the round, run only the plays the gaps give work to, have the
checker judge the result, record the person's typed decision on each intent, 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 or a skill's work yourself; answering a question nothing in
memory or the person's answers supports; writing the write-up yourself; handing a play another
play's output as its input; ending done with a node not linked or a screen uncovered, or
without the checker's pass; confirming, dropping or otherwise changing an intent in the model.
## Pre-flight
| Check | Constraint | Action on Failure |
|-------|-----------|-------------------|
| Config, the three plays installed and each accepts a loop contract, the knowledge step's skills installed, runner and checker known (`loop_preflight.py`) | C4 | Hard halt |
| A working prototype is given — ask where it is and, for a file or folder, how it starts | C2 | Ask the person (gather, not a halt) |
| The write-up is given, in its five parts | C2 | Ask the person (gather, not a halt); never write it yourself |
| The prototype runs (`check_prototype.py`) | C2 | Hard halt, before anything is opened |
```bash
git branch --show-current
python3 scripts/loop_preflight.py --config .garura/core/config.yaml --loop complete-discovery \
--skills-root .. --plays discover-intent,discover-domains,discover-capabilities \
--branch "$(git branch --show-current)" --out <pre>/preflight.json
python3 scripts/check_prototype.py --prototype "<where it is>" [--start "<how it starts>"] \
--out <pre>/prototype.json
```
`<pre>` is a scratch folder (`mktemp -d`): no issue exists yet. After Step 1 its files move
into the loop's working folder `{stm_base}<issue>/context/discovery/<run-ts>/` (`<working>`).
## Task DAG
```
[T1] Open the change (start-change) blockedBy: []
[T2] Questions first blockedBy: [T1]
[T3] Write the loop contract blockedBy: [T2]
[T3b] Read the prototype once (prototype-reader) blockedBy: [T3]
[T4] Round n: run /discover-intent (if given work) blockedBy: [T3b]
[T5] Round n: run /discover-domains (if given work) blockedBy: [T3b]
[T6] Round n: run /discover-capabilities (if given work) blockedBy: [T3b]
[T6a] After the round: find and close the gaps blockedBy: [T4, T5, T6]
[T6b] After the round: done, again or ask blockedBy: [T6a] (again: back to T4, round n+1, only the plays given work)
[T6c] The knowledge step (knowledge-builder) blockedBy: [T6b] (only on ask)
[T6d] Brief the person; record the reply blockedBy: [T6c] (then back to T4)
[T7] The checker blockedBy: [T6b]
[E1] commit-change blockedBy: [T7]
[E2] propose-change blockedBy: [E1]
[T8] The person decides each intent blockedBy: [E2]
[E3] check-change blockedBy: [T8]
[E4] merge-change blockedBy: [E3]
[T9] Scenario Validation blockedBy: [E4]
[T10] Close blockedBy: [T9]
```
Mark each task in progress before its step and completed right after its eval passes. No
runtime reordering. On resume, skip completed and reset in-progress to pending.
## Workflow
Run the Shared Loop Run with this loop's values:
```bash
# --- Shared Loop Run (shared; see ../_shared/loop-run.md) ---
loop=complete-discovery
plays=discover-intent,discover-domains,discover-capabilities
questions=prototype -> inputs.discover-intent.argument; how it starts -> prototype.json (asked at pre-flight, C2); for a link, may the walk change data -> answers.discover-intent.may_change_data
documents=the write-up, five parts (C2) -> <working>/write-up.md, handed to every play with the capture
source=the prototype, read once by prototype-reader (R4b) -> inputs.<play>.capture
runner_key=loops.complete-discovery.runner
checker_key=loops.complete-discovery.checker
end=commit-change, propose-change, the person types confirm or drop per intent (recorded; the model untouched), check-change, merge-change (merge pinned)
max_rounds_key=loops.complete-discovery.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: one issue, one branch. Move `<pre>`'s files into `<working>`.
**SE-1 (F2/C2):** `prototype.json` reads `runs: true`, and was written before `start-change`
ran — no issue or branch exists for a prototype that does not run.
**SE-2 (F1/C1):** `start-change.json` names one issue and one branch; every file the loop and
its plays write is under `{stm_base}<issue>/`; no play's run record names another issue.
### Phase: Questions
**Step 2 — Questions first** · Owner: loop · Depends on: Step 1
Run R3. The prototype and how it starts were asked at pre-flight. For a link, also ask whether
the walk may press buttons that change data on it (pay, delete, submit) — `true` only on the
person's yes — as `answers.discover-intent.may_change_data`. Get the write-up (C2): when the person did
not give it with the prototype, ask for it in its five parts and wait for the typed reply; save
it exactly as given to `<working>/write-up.md`. Write the answers to `answers.json`, and their
sources (`from: person`, the write-up under `documents`) to `answers-sources.json`.
**SE-3 (F3/C3):** `answers.json`, `answers-sources.json` and `write-up.md` exist before
`contract.json`; every answer and the write-up name their source; no play's capture was walked
by the play itself.
**Step 3 — Write the loop contract** · Owner: loop (script) · Depends on: Step 2
Run R4 with `inputs.discover-intent.argument` = the prototype.
**Step 3b — Read the prototype once** · Owner: loop · Depends on: Step 3
Run R4b: capture the prototype and the write-up once, each as a Source (`/discover-intent`'s capture
script, laid beside the loop), then dispatch `prototype-reader` once to walk it, planning
from the write-up's walkthrough. Hand the capture — both source manifests, the write-up, the
journeys with their main sections, the view texts — to every play as `inputs.<play>.capture`,
and run R4 again. No play captures or walks the prototype again.
### Phase: Plays, in rounds
The plays run in rounds until the loop's job is done (R5, C4). Each reads the one capture and
the write-up, writes its own kind, and takes no other play's output as its input. 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 (C5). Round 1 runs all three, in turn; a later round
runs only the plays `round-<n>.json` names in `next`, each on its `targets`.
**Step 4 — Round n: run /discover-intent** · Owner: `discover-intent` · Depends on: Step 3b (or Step 6b, 6d)
Run R5 for `discover-intent` on the capture: it writes business intents only, as `proposed`, naming
each gap as an open question.
**Step 5 — Round n: run /discover-domains** · Owner: `discover-domains` · Depends on: Step 3b (or Step 6b, 6d)
Run R5 for `discover-domains` on the capture and the write-up: it writes domains only, found by research.
**Step 6 — Round n: run /discover-capabilities** · Owner: `discover-capabilities` · Depends on: Step 3b (or Step 6b, 6d)
Run R5 for `discover-capabilities` on the capture (`inputs.discover-capabilities.capture`; on a later round its
`inputs.discover-capabilities.targets`): it writes capabilities and features with their ICE.
**Step 6a — After the round: find and close the gaps** · Owner: loop · Depends on: Steps 4, 5 and 6
Run R5 step 7: dispatch `product-os-keeper` to run `find-model-gaps`, then `link-model-gaps`,
over the whole model. Then commit the round once (`commit_run_files.py --play round-<n>
--also <product_base>product-os`).
**Step 6b — After the round: done, again or ask** · Owner: loop (script) · Depends on: Step 6a
Run R5 step 8 (`round_state.py` with `--gaps` and `--close-report`, `--max-rounds` from
`loops.complete-discovery.max_rounds`). `done` → Step 7. `again` → Step 4, round n+1, only the plays named
in `next`. `ask` → Step 6c.
**Step 6c — The knowledge step** · Owner: loop · Depends on: Step 6b
Run R5c (ADR 059): `group_questions.py` merges the questions asked again; one `knowledge-builder`
dispatch answers what the prototype shows (quoted) and what memory holds (through the memory
tool, traced), closes the rest — knowledge pages it raises as memory updates waiting for the
person, our proposed answer with its basis and context, notes for the prototype, settled for
what the context answers — and has the brief written: what we understood, what we built (each
proposed business intent, the domains, the capabilities and features), a few gaps each with its
context and our proposed answer, the knowledge pages with our recommendation, a pointer to the
prototype notes. `check_knowledge.py` checks all three records.
**Step 6d — Brief the person; record the reply** · Owner: loop · Depends on: Step 6c
Run R5b: show the brief, wait for the reply, record it with `record_review.py`
(`from: person`), then Step 4, round n+1.
**SE-4 (F4/C4):** each play that ran has its `<play>-done.json` reading `done: true`; no
play's contract input names another play's output; each play wrote only its own kind;
`round-<n>-commit.json` shows no leftover; and the last `rounds.json` reads `gaps_left: 0` —
every node linked, no duplicate left, no screen uncovered.
**SE-5 (F5/C5):** the memory tool's `citations --issue <issue> --check` lists no problems, and
every memory update the plays applied was approved by a person; the person was asked only in a
round whose `round-<n>.json` reads `ask`, never after a round that read `again`, and only after
the knowledge step ran for that round (its `knowledge-check.json` reads `ok: true`); the person saw
the brief, never a bare question; each answer is in the issue's short-term memory with
`from: person` (`person-answers-round-<n>.json`).
### Phase: Check
**Step 7 — The checker** · Owner: checker · Depends on: Step 6b
Run R6 with `checker_key` (default: a sub-agent on `sonnet`).
**SE-6 (F6/C6):** `check.yaml` reads `verdict: pass`, from a checker whose model is not the
session's; a reject halted the loop before any pull request.
### Phase: End (stand-in until Argus, the review tool — C7)
**Step E1 — commit-change** · Owner: `commit-change` · blockedBy: Step 7
**Step E2 — propose-change** · Owner: `propose-change` · blockedBy: E1
**Step 8 — The person decides each intent** · Owner: loop · Depends on: E2
Show each intent `/discover-intent` saved (its `intent-manifest.json`), one at a time, exactly as it
reads, with its ICE under it, and ask the person to type **confirm** or **drop** (with any
words of their own). Never use `AskUserQuestion`. Write their exact words to
`<working>/replies.json`, then:
```bash
python3 scripts/record_confirmation.py --manifest <intent run>/intent-manifest.json \
--replies <working>/replies.json --by "<git user>" --at <date> \
--out <working>/confirmation.yaml
```
The intents stay `proposed` in the model; Argus's review step writes the approval later (#650).
**SE-7 (F7/C7):** `record_confirmation.py` exited 0: `confirmation.yaml` reads `by: person`,
holds one decision per saved intent in the person's own words, and every intent page still
reads `Stage: proposed`.
**Step E3 — check-change** · Owner: `check-change` · blockedBy: Step 8
**Step E4 — merge-change** · Owner: `merge-change` · blockedBy: E3
### Phase: Scenario Validation
**Step 9 — Scenario evals** · Owner: loop · Depends on: Step E4
- **SCE-1 (S1 — business owner, a prototype link):** `contract.json`, the three done files
reading `done: true`, `check.yaml` reading `verdict: pass` and `confirmation.yaml` exist under
the issue; every intent page still reads `proposed`; the pull request merged.
- **SCE-2 (S2 — business owner, no working prototype):** `prototype.json` reads `runs: false`,
no new branch exists, and the loop closed HALTED with `exit_reason: preflight`.
- **SCE-3 (S3 — business owner, gaps closed round by round):** `round-1.json` reads `again`
with `next` naming the plays and their targets, the last `rounds.json` reads `gaps_left: 0`
and `open_left: 0`, any brief came only after a `round-<n>.json` that reads `ask`
(`knowledge-check.json` reads `ok: true`), and each answer is in the issue's short-term memory
with `from: person`.
- **SCE-4 (S4 — business owner, a checker reject):** `check.yaml` reads `verdict: reject` with
a reason per failed criterion, and no pull request exists for the branch.
### Phase: Evidence & Close
**Step 10 — Close** · Owner: loop · Depends on: Step 9
**SE-8 (F8/C8):** an evidence file exists under `{stm_base}<issue>/evidence/discovery/`
(`evidence.plays.complete-discovery: true` in the config), naming every play's result, the contract, the
answers and the checker's verdict.
```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/discovery/" ; slug="#${issue}"
session_stamp=$(python3 scripts/session_stamp.py --phase close \
--marker "${stm_base}${issue}/status/session-stamp-discovery.json")
python3 scripts/check_stop_condition.py --manifest "<loop-dir>/stop-condition.yaml" \
--base "<working>/" --out "${stm_base}${issue}/status/stop-condition-discovery.yaml"
sc_exit=$? # 0 held · 1 unmet · 2 error
# --- end Standard Play Close ---
```
## Scenario Validation
| Scenario | Persona | Eval |
|----------|---------|------|
| S1 — a prototype link | business owner | SCE-1 |
| S2 — no working prototype | business owner | SCE-2 |
| S3 — gaps closed round by round | business owner | SCE-3 |
| S4 — a checker reject | business owner | SCE-4 |
## 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; run on the contract's branch | autonomous |
| F2 | no prototype, or one that does not run | halt before opening; ask the person for a working prototype | human |
| F3 | a play ran before the questions or the write-up, an answer or the write-up has no source, or a play walked the prototype again | stop; get the write-up and ask the questions, record each source, read the prototype once, re-run the play on the capture | autonomous |
| F4 | a play took another's output or wrote another's kind, an unclean tree, or done with gaps left | halt; re-run the play on the capture alone, writing only its kind; commit the round; run the gap skills and the plays they give work to | autonomous |
| F5 | an answer from the model alone, a stop for a question the loop could still answer, or a bare question put to the person | strip the answer, or go on round the loop; brief the person only on what no play answers (the knowledge step's brief: our proposed answer with its context); re-run the play | human |
| F6 | done without the checker's pass | run the checker; a reject halts the loop | autonomous |
| F7 | the loop changed an intent's state, or recorded a decision without the person's word | undo the change to the intent page; ask the person and record their own words | human |
| F8 | no evidence record | write the evidence before closing; the close stays HALTED until it exists | autonomous |
## Pause and Resume
The loop's run lives under its issue (`{stm_base}<issue>/context/discovery/<run-ts>/`). On
entry, find the last run folder and the last `round-<n>.json`: reuse the capture and the
write-up, skip every play of the round whose `<play>-done.json` reads `done: true` and whose
run files are committed, and continue from the first step not done. A run halted at
a question resumes the same play with the person's answer (shared run, R5 step 3).
## Compilation Metadata
| Field | Value |
|-------|-------|
| fingerprint | sha256:2ed346c270bfc2e3d8ccae2197e4fba49818100a780629e6b34a9e9f396483b0 (of `reference/ice.md`) |
| compiled_by | edit-loop (#920, ADR 059: the knowledge step is one step run by one agent); edit-loop (#689, ADR 043: one reading, one kind per play, the gap skills close the loop); create-loop (#613) |
| kind | loop |
| pipeline_position | both |
| plays | discover-intent, discover-domains, discover-capabilities |
| stop_condition | stop-condition.yaml (D1–D8) |
| scripts | 15 (13 shared: 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; 2 own: check_prototype.py, record_confirmation.py) |
| step_evals | 8 (SE-1…SE-8) |
| scenario_evals | 4 (SCE-1…SCE-4) |
| recovery_entries | 8 (one per failure condition; 5 autonomous / 3 human) |
Files in this skill
- SKILL.md
- reference/ice.md
- scripts/check_knowledge.py
- scripts/check_loop_contract.py
- scripts/check_play_done.py
- scripts/check_prototype.py
- scripts/check_stop_condition.py
- scripts/commit_run_files.py
- scripts/group_questions.py
- scripts/loop_preflight.py
- scripts/loop_status.py
- scripts/prepare_check.py
- scripts/record_check.py
- scripts/record_confirmation.py
- scripts/record_review.py
- scripts/round_state.py
- scripts/run_checker_codex.py
- scripts/run_play_headless.py
- scripts/session_stamp.py
- scripts/test_discovery_scripts.py
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.