pi-loopflows 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.2 - 2026-06-22
4
+
5
+ - Tighten README positioning around loopflows as LEGO-like subagent workflows.
6
+ - Remove the dedicated Launch Control README section while keeping it listed as a bundled workflow.
7
+
8
+ ## 0.1.1 - 2026-06-22
9
+
10
+ - Polish product README and usage guidance for public release.
11
+ - Add bundled `build-review` loopflow for lightweight implementation feedback loops.
12
+ - Add bundled `plan-review` loopflow for plan quality gates before implementation.
13
+ - Expand loopflows skill instructions.
14
+ - Clarify adapter/backend direction for future compatible executors.
15
+
3
16
  ## 0.1.0 - 2026-06-22
4
17
 
5
18
  - Initial release.
package/README.md CHANGED
@@ -1,12 +1,24 @@
1
1
  # pi-loopflows
2
2
 
3
- Deterministic loop workflows for Pi subagents.
3
+ Build deterministic AI workflows out of Pi subagents.
4
4
 
5
- A **loopflow** describes agent work as a process instead of a single prompt: steps, gates, feedback loops, stop conditions, and saved evidence. It lets you connect Pi subagents like building blocks: gather context, plan, build, review, loop back for fixes, and audit the result.
5
+ Think of **loopflows** as LEGO for subagents. You take small specialist agents, connect them into a process, add gates where decisions matter, and let the workflow move forward, branch, loop back, or stop based on explicit results. Instead of one giant prompt, you get a reusable structure for how agents collaborate: steps, feedback loops, stop rules, and saved evidence.
6
6
 
7
- ## Why
7
+ ## Why loopflows
8
8
 
9
- Normal chains are linear. Real work is not. A reviewer may request changes, a builder may need another pass, or a gate may block because evidence is missing. `pi-loopflows` adds that missing control flow while keeping the agents focused on their roles.
9
+ Linear chains are useful, but real work is not always linear. A reviewer can request changes. A validator can reject missing evidence. A planner can reveal that the task is blocked. A builder may need several focused passes before the result is safe to accept.
10
+
11
+ Loopflows make that control flow explicit:
12
+
13
+ ```text
14
+ step → step → gate
15
+
16
+ approved → continue
17
+ changes_requested → loop back
18
+ blocked → stop
19
+ ```
20
+
21
+ The philosophy is simple: AI should work through a process, not just produce a confident answer. A loopflow defines who does the work, who checks it, what counts as success, how many attempts are allowed, where evidence is saved, and when the run must stop instead of guessing.
10
22
 
11
23
  ## Install
12
24
 
@@ -14,19 +26,19 @@ Normal chains are linear. Real work is not. A reviewer may request changes, a bu
14
26
  pi install npm:pi-loopflows
15
27
  ```
16
28
 
17
- Or from GitHub:
29
+ `pi-loopflows` uses Pi subagent definitions as its first backend. Install `pi-subagents` if you have not already:
18
30
 
19
31
  ```bash
20
- pi install https://github.com/nik1t7n/pi-loopflows
32
+ pi install npm:pi-subagents
21
33
  ```
22
34
 
23
- Reload Pi after installing:
35
+ Then reload Pi:
24
36
 
25
37
  ```text
26
38
  /reload
27
39
  ```
28
40
 
29
- ## What it adds
41
+ ## What you get
30
42
 
31
43
  ### Tool
32
44
 
@@ -45,35 +57,55 @@ loopflow_run({
45
57
  /loopflow launch-control -- Implement this approved backend plan
46
58
  ```
47
59
 
48
- ### Bundled loopflow
60
+ ### Built-in loopflows
49
61
 
50
- `launch-control`:
62
+ - `launch-control` — plan-as-contract implementation loop with builder/reviewer feedback and final audit.
63
+ - `build-review` — small generic build → review → fix loop for scoped implementation tasks.
64
+ - `plan-review` — planning loop that lets a reviewer reject vague or unsafe plans before implementation.
51
65
 
52
- ```text
53
- context-builder
54
- planner
55
- → loop max 3:
56
- worker
57
- reviewer gate
58
- approved -> continue
59
- changes_requested -> repeat
60
- blocked -> stop
61
- final audit
62
- ```
66
+ ## Loopflows as a constructor
67
+
68
+ Think of loopflows as LEGO for agent processes. A loopflow can use any available Pi subagent role:
69
+
70
+ - `context-builder`
71
+ - `scout`
72
+ - `researcher`
73
+ - `planner`
74
+ - `worker`
75
+ - `reviewer`
76
+ - `oracle`
77
+ - your own custom agents
78
+
79
+ You decide:
80
+
81
+ - which agent runs first;
82
+ - what each agent receives;
83
+ - which output is saved;
84
+ - which step is a gate;
85
+ - what statuses mean pass, retry, or stop;
86
+ - how many loop iterations are allowed;
87
+ - where artifacts go;
88
+ - what final audit should prove.
89
+
90
+ Today, the backend runs Pi-compatible subagents. The engine is intentionally built behind an adapter boundary, so future versions can add other compatible backends — Codex CLI, OpenCode, ACP workers, remote agents, or custom executors — without changing the loopflow concept.
63
91
 
64
92
  ## Loopflow files
65
93
 
66
- Loopflows are JSON files named `*.loopflow.json`.
94
+ Loopflows are JSON files named:
95
+
96
+ ```text
97
+ *.loopflow.json
98
+ ```
67
99
 
68
100
  Discovery locations:
69
101
 
70
- - bundled package `loopflows/`
71
- - user: `~/.pi/agent/loopflows/`
72
- - project: `.pi/loopflows/`
102
+ - bundled package loopflows;
103
+ - user loopflows: `~/.pi/agent/loopflows/`;
104
+ - project loopflows: `.pi/loopflows/`.
73
105
 
74
- Project loopflows can override or add workflows for a repo.
106
+ Project loopflows are the easiest way to customize behavior for one repo.
75
107
 
76
- ## Minimal shape
108
+ ## Minimal example
77
109
 
78
110
  ```json
79
111
  {
@@ -114,14 +146,39 @@ Project loopflows can override or add workflows for a repo.
114
146
 
115
147
  ## Template variables
116
148
 
117
- - `{task}` — original user task
118
- - `{previous}` — previous step output
119
- - `{outputs.stepId}` — output from a named step
120
- - `{outputs.stepId.status}` — parsed gate status
121
- - `{outputs.stepId.json}` — parsed gate JSON
122
- - `{loop.iteration}` — current loop iteration
123
- - `{artifactsDir}` — current run artifact directory
124
- - `{params.name}` — runtime params passed to `loopflow_run`
149
+ - `{task}` — original user task.
150
+ - `{previous}` — previous step output.
151
+ - `{outputs.stepId}` — output from a named step.
152
+ - `{outputs.stepId.output}` — same as above, explicit form.
153
+ - `{outputs.stepId.status}` — parsed gate status.
154
+ - `{outputs.stepId.json}` — parsed gate JSON.
155
+ - `{loop.iteration}` — current loop iteration.
156
+ - `{artifactsDir}` — current run artifact directory.
157
+ - `{params.name}` — runtime params passed to `loopflow_run`.
158
+
159
+ ## Gate contract
160
+
161
+ Gate steps should return JSON. A typical reviewer gate returns:
162
+
163
+ ```json
164
+ {
165
+ "status": "approved",
166
+ "summary": "The implementation satisfies the plan.",
167
+ "findings": [],
168
+ "validation_gaps": [],
169
+ "requires_user_decision": false
170
+ }
171
+ ```
172
+
173
+ Common statuses:
174
+
175
+ - `approved` — move forward.
176
+ - `changes_requested` — loop back for another pass.
177
+ - `blocked` — stop; user or environment action is required.
178
+ - `complete` — final audit passed.
179
+ - `incomplete` — final audit failed.
180
+
181
+ Each loopflow decides which statuses pass, retry, or stop.
125
182
 
126
183
  ## Artifacts
127
184
 
@@ -131,7 +188,7 @@ Every run writes evidence to:
131
188
  <cwd>/.pi/loopflows/runs/<timestamp>-<workflow>/
132
189
  ```
133
190
 
134
- Typical files:
191
+ Typical artifacts:
135
192
 
136
193
  ```text
137
194
  task.md
@@ -144,30 +201,92 @@ final-audit.json
144
201
  summary.md
145
202
  ```
146
203
 
204
+ This makes loopflows inspectable. You can see what each agent claimed, what the gate decided, and why the run stopped or passed.
205
+
206
+ ## Customization patterns
207
+
208
+ ### Make Launch Control stricter
209
+
210
+ Copy the bundled file:
211
+
212
+ ```bash
213
+ mkdir -p .pi/loopflows
214
+ cp ~/.pi/agent/npm/node_modules/pi-loopflows/loopflows/launch-control.loopflow.json \
215
+ .pi/loopflows/launch-control.loopflow.json
216
+ ```
217
+
218
+ Then edit the project copy. Common changes:
219
+
220
+ - increase `maxIterations`;
221
+ - change `reviewer` to a custom security reviewer;
222
+ - add stricter validation language;
223
+ - add a docs or migration audit step;
224
+ - change stop statuses;
225
+ - make the final audit require `complete` only.
226
+
227
+ ### Create a lightweight workflow
228
+
229
+ Use `build-review` for small implementation tasks where full Launch Control is too formal.
230
+
231
+ ```text
232
+ /loopflow build-review -- Add validation to the import endpoint
233
+ ```
234
+
235
+ ### Review a plan before coding
236
+
237
+ Use `plan-review` when you want a plan to be checked before a worker touches files.
238
+
239
+ ```text
240
+ /loopflow plan-review -- Plan the database migration for workspace roles
241
+ ```
242
+
147
243
  ## Backend design
148
244
 
149
- The engine uses an executor adapter boundary:
245
+ The runtime uses an executor adapter boundary:
150
246
 
151
247
  ```ts
152
248
  runAgent(agent, task, options) -> StepResult
153
249
  ```
154
250
 
155
- Current backend: Pi subprocess agents compatible with `pi-subagents` agent definitions.
251
+ Current backend:
156
252
 
157
- Future backends can support Codex CLI, OpenCode, ACP-based workers, remote workers, or other agent runtimes without changing loopflow definitions.
253
+ - Pi subprocess agents compatible with `pi-subagents` agent definitions.
158
254
 
159
- ## Requirements
255
+ Future-compatible backend ideas:
160
256
 
161
- - Pi coding agent
162
- - `pi-subagents` installed for the bundled agent roles:
257
+ - Codex CLI workers;
258
+ - OpenCode workers;
259
+ - ACP-compatible agents;
260
+ - remote worker pools;
261
+ - project-specific executors.
163
262
 
164
- ```bash
165
- pi install npm:pi-subagents
263
+ The point is that loopflows describe the process. The backend decides how each agent is actually executed.
264
+
265
+ ## When to use loopflows vs chains
266
+
267
+ Use normal Pi subagent chains when the process is linear:
268
+
269
+ ```text
270
+ scout → planner → worker
166
271
  ```
167
272
 
273
+ Use loopflows when a step can send work backward or stop the process:
274
+
275
+ ```text
276
+ worker → reviewer → worker → reviewer
277
+ ```
278
+
279
+ If you need a feedback loop, a quality gate, a max iteration limit, or saved evidence, use a loopflow.
280
+
168
281
  ## Status
169
282
 
170
- Early but usable. The core model is intentionally small: steps, loops, gates, artifacts, and adapters.
283
+ `pi-loopflows` is early, but designed as a real product surface rather than a one-off script. The core model is intentionally small:
284
+
285
+ ```text
286
+ steps + loops + gates + artifacts + adapters
287
+ ```
288
+
289
+ That is enough to build useful workflows without turning the extension into a giant orchestration platform.
171
290
 
172
291
  ## License
173
292
 
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "build-review",
3
+ "version": "1.0.0",
4
+ "description": "Generic scoped implementation loop: plan, build, independent review, repeat fixes until approved or blocked.",
5
+ "backend": "pi-subprocess",
6
+ "defaults": {
7
+ "agentScope": "both"
8
+ },
9
+ "steps": [
10
+ {
11
+ "id": "plan",
12
+ "agent": "planner",
13
+ "output": "plan.md",
14
+ "task": "Create a concise implementation plan for this task:\n\n{task}\n\nInclude acceptance criteria, likely files, validation commands, non-goals, and stop conditions. Do not edit files."
15
+ },
16
+ {
17
+ "loop": {
18
+ "id": "build-review",
19
+ "maxIterations": 3,
20
+ "gateStep": "review",
21
+ "passStatuses": ["approved"],
22
+ "retryStatuses": ["changes_requested"],
23
+ "stopStatuses": ["blocked"],
24
+ "onExhausted": "stop",
25
+ "body": [
26
+ {
27
+ "id": "build",
28
+ "agent": "worker",
29
+ "output": "build-{loop.iteration}.md",
30
+ "task": "Implement or fix iteration {loop.iteration}.\n\nTask:\n{task}\n\nPlan:\n{outputs.plan}\n\nPrevious review, if any:\n{outputs.review.output}\n\nIf this is iteration 1, implement the planned change. If this is a later iteration, apply only required reviewer fixes. Use the real project stack. Do not add mocks, demos, fake validation, or hidden fallbacks unless explicitly requested. Run focused validation and report changed files, commands with exit codes, evidence, blockers, and remaining risks."
31
+ },
32
+ {
33
+ "id": "review",
34
+ "agent": "reviewer",
35
+ "output": "review-{loop.iteration}.json",
36
+ "gate": {
37
+ "type": "json-status",
38
+ "passStatuses": ["approved"],
39
+ "retryStatuses": ["changes_requested"],
40
+ "stopStatuses": ["blocked"]
41
+ },
42
+ "task": "Review iteration {loop.iteration}. Do not edit project/source files.\n\nTask:\n{task}\n\nPlan:\n{outputs.plan}\n\nBuilder report:\n{outputs.build.output}\n\nReturn ONLY valid JSON:\n{\n \"status\": \"approved\" | \"changes_requested\" | \"blocked\",\n \"summary\": \"short verdict\",\n \"findings\": [{\"severity\": \"blocker|required|optional\", \"file\": \"path or null\", \"issue\": \"specific issue\", \"required_fix\": \"specific fix or null\"}],\n \"validation_gaps\": [\"gap\"],\n \"requires_user_decision\": false\n}\n\nApprove only if the implementation and evidence satisfy the plan. Request changes for required fixable issues. Block for missing credentials, missing decisions, unsafe scope, or stale plan."
43
+ }
44
+ ]
45
+ }
46
+ }
47
+ ]
48
+ }
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "plan-review",
3
+ "version": "1.0.0",
4
+ "description": "Planning loop: gather context, draft a plan, review the plan, and revise until approved or blocked before implementation.",
5
+ "backend": "pi-subprocess",
6
+ "defaults": {
7
+ "agentScope": "both"
8
+ },
9
+ "steps": [
10
+ {
11
+ "id": "context",
12
+ "agent": "context-builder",
13
+ "output": "context.md",
14
+ "task": "Build planning context for this task:\n\n{task}\n\nInspect the repository enough to identify relevant files, constraints, validation commands, risks, and unknowns. Do not edit files."
15
+ },
16
+ {
17
+ "loop": {
18
+ "id": "plan-review",
19
+ "maxIterations": 2,
20
+ "gateStep": "review",
21
+ "passStatuses": ["approved"],
22
+ "retryStatuses": ["changes_requested"],
23
+ "stopStatuses": ["blocked"],
24
+ "onExhausted": "stop",
25
+ "body": [
26
+ {
27
+ "id": "plan",
28
+ "agent": "planner",
29
+ "output": "plan-{loop.iteration}.md",
30
+ "task": "Draft or revise implementation plan iteration {loop.iteration}.\n\nTask:\n{task}\n\nContext:\n{outputs.context}\n\nPrevious review, if any:\n{outputs.review.output}\n\nReturn a practical implementation plan with scope, non-goals, acceptance criteria, likely files, validation commands, risks, and open questions. Do not edit files."
31
+ },
32
+ {
33
+ "id": "review",
34
+ "agent": "reviewer",
35
+ "output": "plan-review-{loop.iteration}.json",
36
+ "gate": {
37
+ "type": "json-status",
38
+ "passStatuses": ["approved"],
39
+ "retryStatuses": ["changes_requested"],
40
+ "stopStatuses": ["blocked"]
41
+ },
42
+ "task": "Review this implementation plan before any code is written. Do not edit files.\n\nTask:\n{task}\n\nContext:\n{outputs.context}\n\nPlan:\n{outputs.plan}\n\nReturn ONLY valid JSON:\n{\n \"status\": \"approved\" | \"changes_requested\" | \"blocked\",\n \"summary\": \"short verdict\",\n \"findings\": [{\"severity\": \"blocker|required|optional\", \"issue\": \"specific issue\", \"required_fix\": \"specific plan change or null\"}],\n \"missing_acceptance_criteria\": [\"criterion\"],\n \"requires_user_decision\": false\n}\n\nApprove only if the plan is specific, scoped, testable, and safe to hand to a worker. Request changes for vague scope, missing validation, or unclear acceptance criteria. Block when user/product decisions or credentials are required."
43
+ }
44
+ ]
45
+ }
46
+ }
47
+ ]
48
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-loopflows",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Deterministic loop workflows for Pi subagents: steps, gates, feedback loops, and artifacts.",
5
5
  "license": "MIT",
6
6
  "author": "Nikita Nosov <20nik.nosov21@gmail.com>",
@@ -26,6 +26,7 @@
26
26
  "extensions",
27
27
  "loopflows",
28
28
  "skills",
29
+ "scripts",
29
30
  "README.md",
30
31
  "LICENSE",
31
32
  "CHANGELOG.md"
@@ -36,8 +37,7 @@
36
37
  ],
37
38
  "skills": [
38
39
  "./skills"
39
- ],
40
- "image": "https://raw.githubusercontent.com/nik1t7n/pi-loopflows/main/assets/pi-loopflows.png"
40
+ ]
41
41
  },
42
42
  "peerDependencies": {
43
43
  "@earendil-works/pi-coding-agent": "*",
@@ -51,6 +51,8 @@
51
51
  },
52
52
  "scripts": {
53
53
  "typecheck": "tsc --noEmit",
54
- "pack:check": "npm pack --dry-run"
54
+ "pack:check": "npm pack --dry-run",
55
+ "validate": "node scripts/validate.mjs",
56
+ "prepublishOnly": "npm run validate && npm run typecheck && npm run pack:check"
55
57
  }
56
58
  }
@@ -0,0 +1,71 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ const root = path.resolve(new URL('..', import.meta.url).pathname);
5
+ const loopflowsDir = path.join(root, 'loopflows');
6
+ const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
7
+
8
+ const errors = [];
9
+
10
+ function assert(condition, message) {
11
+ if (!condition) errors.push(message);
12
+ }
13
+
14
+ assert(pkg.name === 'pi-loopflows', 'package name must be pi-loopflows');
15
+ assert(pkg.keywords?.includes('pi-package'), 'package must include pi-package keyword');
16
+ assert(pkg.pi?.extensions?.includes('./extensions'), 'package pi manifest must expose extensions');
17
+ assert(pkg.pi?.skills?.includes('./skills'), 'package pi manifest must expose skills');
18
+
19
+ const files = fs.readdirSync(loopflowsDir).filter((file) => file.endsWith('.loopflow.json'));
20
+ assert(files.length >= 3, 'expected bundled launch-control, build-review, and plan-review loopflows');
21
+
22
+ for (const file of files) {
23
+ const full = path.join(loopflowsDir, file);
24
+ let wf;
25
+ try {
26
+ wf = JSON.parse(fs.readFileSync(full, 'utf8'));
27
+ } catch (error) {
28
+ errors.push(`${file}: invalid JSON: ${error.message}`);
29
+ continue;
30
+ }
31
+
32
+ assert(typeof wf.name === 'string' && wf.name.length > 0, `${file}: missing name`);
33
+ assert(typeof wf.description === 'string' && wf.description.length > 0, `${file}: missing description`);
34
+ assert(Array.isArray(wf.steps) && wf.steps.length > 0, `${file}: steps must be a non-empty array`);
35
+
36
+ const topLevelIds = new Set();
37
+ for (const [index, node] of wf.steps.entries()) {
38
+ if (node.loop) {
39
+ const loop = node.loop;
40
+ assert(typeof loop.id === 'string' && loop.id.length > 0, `${file}: loop ${index} missing id`);
41
+ assert(Number.isInteger(loop.maxIterations) && loop.maxIterations > 0, `${file}: loop ${loop.id} maxIterations must be positive integer`);
42
+ assert(Array.isArray(loop.body) && loop.body.length > 0, `${file}: loop ${loop.id} body must be non-empty`);
43
+ assert(typeof loop.gateStep === 'string' && loop.gateStep.length > 0, `${file}: loop ${loop.id} missing gateStep`);
44
+ const bodyIds = new Set(loop.body.map((step) => step.id));
45
+ assert(bodyIds.has(loop.gateStep), `${file}: loop ${loop.id} gateStep not present in body`);
46
+ for (const step of loop.body) validateStep(file, step, `loop ${loop.id}`);
47
+ } else {
48
+ validateStep(file, node, `step ${index}`);
49
+ if (node.id) {
50
+ assert(!topLevelIds.has(node.id), `${file}: duplicate top-level step id ${node.id}`);
51
+ topLevelIds.add(node.id);
52
+ }
53
+ }
54
+ }
55
+ }
56
+
57
+ function validateStep(file, step, label) {
58
+ assert(typeof step.id === 'string' && step.id.length > 0, `${file}: ${label} missing id`);
59
+ assert(typeof step.agent === 'string' && step.agent.length > 0, `${file}: ${label} missing agent`);
60
+ assert(typeof step.task === 'string' && step.task.length > 0, `${file}: ${label} missing task`);
61
+ if (step.gate) {
62
+ assert(step.task.includes('JSON') || step.task.includes('json'), `${file}: gate step ${step.id} should explicitly request JSON`);
63
+ }
64
+ }
65
+
66
+ if (errors.length) {
67
+ console.error(errors.map((e) => `- ${e}`).join('\n'));
68
+ process.exit(1);
69
+ }
70
+
71
+ console.log(`Validated ${files.length} loopflows for ${pkg.name}@${pkg.version}`);
@@ -1,19 +1,19 @@
1
1
  ---
2
2
  name: loopflows
3
- description: Use when the user wants deterministic multi-agent workflows, feedback loops between builder/reviewer agents, launch-control style implementation gates, or repeatable Pi subagent processes with max iterations, gates, stop conditions, and artifacts.
3
+ description: Use when the user wants deterministic multi-agent workflows, feedback loops between builder/reviewer agents, launch-control style implementation gates, repeatable Pi subagent processes, or custom workflow construction with max iterations, gates, stop conditions, and artifacts.
4
4
  ---
5
5
 
6
6
  # Loopflows
7
7
 
8
- Use `loopflow_run` for deterministic agent workflows that need real control flow instead of a linear chain.
8
+ Use `loopflow_run` when a task needs process control, not just a linear chain.
9
9
 
10
- Prefer loopflows when work needs:
10
+ A loopflow is a reusable workflow made from subagent steps, gates, and loops. Use it when work should be checked, sent back for fixes, capped by max iterations, or stopped when evidence is missing.
11
11
 
12
- - a builder/reviewer feedback loop;
13
- - explicit pass/retry/stop gates;
14
- - max iteration limits;
15
- - saved evidence artifacts;
16
- - launch-control style plan build review fix → audit flow.
12
+ ## Built-in loopflows
13
+
14
+ - `launch-control` strict plan-as-contract flow: context → plan → build/review loop → final audit.
15
+ - `build-review` lightweight implementation loop for scoped changes.
16
+ - `plan-review` review and revise a plan before implementation starts.
17
17
 
18
18
  ## Commands
19
19
 
@@ -38,3 +38,7 @@ loopflow_run({ workflow: "launch-control", task: "...", maxIterations: 3 })
38
38
  ## Rule of thumb
39
39
 
40
40
  Use `pi-subagents` chains for simple linear handoffs. Use `pi-loopflows` when a gate can send work backward for fixes or stop the run.
41
+
42
+ ## Customization
43
+
44
+ Loopflows are `.loopflow.json` files. Copy bundled workflows into `.pi/loopflows/` to customize them for a project: change agents, prompts, max iterations, pass/retry/stop statuses, or final audit rules.