feature-flow-cli 0.14.0__tar.gz → 0.23.0__tar.gz
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.
- {feature_flow_cli-0.14.0/feature_flow_cli.egg-info → feature_flow_cli-0.23.0}/PKG-INFO +99 -15
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/README.md +98 -14
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/adapters/codex/feature-flow/SKILL.md +12 -12
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/adapters/codex/feature-flow/agents/openai.yaml +1 -1
- feature_flow_cli-0.23.0/agents/flow-architect.md +52 -0
- feature_flow_cli-0.23.0/agents/flow-designer.md +52 -0
- feature_flow_cli-0.23.0/agents/flow-po.md +52 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/agents/flow-scout.md +25 -0
- feature_flow_cli-0.23.0/agents/flow-skeptic.md +55 -0
- feature_flow_cli-0.23.0/agents/flow-tester.md +24 -0
- feature_flow_cli-0.23.0/agents/plan-reviewer.md +45 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/agents/ticket-builder.md +2 -2
- feature_flow_cli-0.23.0/agents/ticket-reviewer.md +41 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/__init__.py +1 -1
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/cli.py +20 -2
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/codehash.py +1 -1
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/command.py +10 -2
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/conductor.py +627 -71
- feature_flow_cli-0.23.0/feature_flow/evaluate.py +436 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/floorguard.py +4 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/git.py +10 -0
- feature_flow_cli-0.23.0/feature_flow/importer.py +222 -0
- feature_flow_cli-0.23.0/feature_flow/profiles.py +43 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/prompts.py +38 -4
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/proof.py +19 -10
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/report.py +1 -1
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/scouts.py +1 -1
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/state.py +1 -1
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/status.py +8 -2
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0/feature_flow_cli.egg-info}/PKG-INFO +99 -15
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow_cli.egg-info/SOURCES.txt +8 -0
- feature_flow_cli-0.23.0/guides/brainstorm.md +67 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/guides/brief.md +6 -1
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/guides/build.md +4 -1
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/guides/plan-review.md +3 -1
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/guides/plan.md +7 -4
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/guides/replan.md +1 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/guides/review-single.md +3 -1
- feature_flow_cli-0.23.0/guides/templates/brainstorm.md +50 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/guides/templates/commands.md +4 -1
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/guides/templates/spec.md +4 -3
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/guides/templates/ticket.md +1 -0
- feature_flow_cli-0.23.0/guides/test.md +56 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/scripts/flow-trust.py +15 -9
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/skills/feature-flow/SKILL.md +14 -14
- feature_flow_cli-0.14.0/agents/flow-architect.md +0 -27
- feature_flow_cli-0.14.0/agents/flow-designer.md +0 -27
- feature_flow_cli-0.14.0/agents/flow-po.md +0 -27
- feature_flow_cli-0.14.0/agents/plan-reviewer.md +0 -20
- feature_flow_cli-0.14.0/agents/ticket-reviewer.md +0 -16
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/LICENSE +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/MANIFEST.in +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/agents/feature-planner.md +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/agents/flow-web.md +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/__main__.py +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/checks.py +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/gate.py +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/install.py +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/lanes.py +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/proc.py +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/released.py +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/suggest.py +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/tickets.py +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/uninstall.py +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow/view.py +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow_cli.egg-info/dependency_links.txt +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow_cli.egg-info/entry_points.txt +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/feature_flow_cli.egg-info/top_level.txt +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/guides/debug.md +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/guides/review-feature.md +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/guides/review-quality.md +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/guides/review.md +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/guides/show.md +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/guides/templates/learnings.md +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/guides/templates/map.md +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/guides/templates/ui-mockup.md +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/install.py +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/install.sh +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/pyproject.toml +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/scripts/floor-guard.py +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/scripts/flow-status.py +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/scripts/flow-view.html +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/scripts/flow-view.py +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/scripts/flow.py +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/scripts/gate.py +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/setup.cfg +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/skills/architect-review/SKILL.md +0 -0
- {feature_flow_cli-0.14.0 → feature_flow_cli-0.23.0}/skills/automation-design/SKILL.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: feature-flow-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.23.0
|
|
4
4
|
Summary: A ticket-graph workflow for coding agents: installs the feature-flow skill into a repo
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/hamilton-sky/feature-flow
|
|
@@ -45,13 +45,22 @@ python3 install.py /path/to/your/repo --agent all # both, side by side
|
|
|
45
45
|
# `bash install.sh ...` still works on Linux and macOS: it only runs install.py
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
+
As a Claude Code plugin, with nothing written into your repo (this repo is its own marketplace):
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
/plugin marketplace add hamilton-sky/feature-flow
|
|
52
|
+
/plugin install feature-flow@feature-flow
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The plugin carries the skills, the roles (named `feature-flow:ticket-builder` and so on), the conductor, the scripts and the guides, and the skill runs the conductor from the plugin's folder. A repo with its own install still uses that one. Claude Code cloud sessions (claude.ai/code) do not install plugins, so for them install into the repo and commit `.claude/`, `scripts/` and `.feature-flow/` as below. The plugin path is new and has not had a real run yet.
|
|
56
|
+
|
|
48
57
|
Without a clone, the same installer runs from [PyPI](https://pypi.org/project/feature-flow-cli/):
|
|
49
58
|
|
|
50
59
|
```bash
|
|
51
60
|
uvx feature-flow-cli install /path/to/your/repo --agent all # or: pipx run feature-flow-cli install ...
|
|
52
61
|
```
|
|
53
62
|
|
|
54
|
-
The package puts a `feature-flow` command on your PATH with `install`, `uninstall`, `status <feature>`, `view <feature>`, `reset <feature>` and `
|
|
63
|
+
The package puts a `feature-flow` command on your PATH with `install`, `uninstall`, `status <feature>`, `view <feature>`, `reset <feature>`, `report <feature>` and `eval <feature>`. It installs the same files, byte for byte, as `install.py` from a clone.
|
|
55
64
|
|
|
56
65
|
The installer lists what it wrote in `.feature-flow/installed.txt`, with each file's hash in `.feature-flow/installed.sha256`. Commit those files (`git add --pathspec-from-file=.feature-flow/installed.txt`); until you do, the flow does not count them as uncommitted changes. Installing a newer version over an older one updates every file nobody edited since it was installed, and keeps (and names) the ones you changed; `--force` replaces those too.
|
|
57
66
|
|
|
@@ -96,6 +105,10 @@ The Claude Code skill is `skills/feature-flow/`. The Codex skill is written by h
|
|
|
96
105
|
## How a ticket flows
|
|
97
106
|
|
|
98
107
|
```
|
|
108
|
+
tester subagent (once, before the first ticket, when commands.md
|
|
109
|
+
has Acceptance:): writes acceptance tests from spec.md only
|
|
110
|
+
│
|
|
111
|
+
▼
|
|
99
112
|
smoke command (script): is the base healthy? no ─► stop, spend nothing
|
|
100
113
|
│ yes
|
|
101
114
|
▼
|
|
@@ -116,23 +129,22 @@ The Claude Code skill is `skills/feature-flow/`. The Codex skill is written by h
|
|
|
116
129
|
commit that failed Test before the code fail ─┤
|
|
117
130
|
│ pass │
|
|
118
131
|
▼ │
|
|
119
|
-
|
|
120
|
-
+ diff,
|
|
121
|
-
|
|
122
|
-
▼ │
|
|
123
|
-
quality review: a second fresh reviewer subagent FAIL ─┤
|
|
124
|
-
(a level 1 or 2 ticket gets one combined review instead
|
|
125
|
-
of these two; see "Ticket levels" below)
|
|
132
|
+
review: one fresh reviewer subagent, sees only the ticket │
|
|
133
|
+
+ diff: the spec checklist, then the code's quality; at level 3 │
|
|
134
|
+
it also probes every input as a hostile caller FAIL ─┤
|
|
126
135
|
│ PASS ▼
|
|
127
136
|
▼ findings written into the ticket,
|
|
128
137
|
next ticket reopened, built again (rounds by level);
|
|
129
138
|
the builder's prompt then carries
|
|
130
139
|
a root-cause debugging guide
|
|
140
|
+
|
|
141
|
+
every ticket resolved: the acceptance tests run (script) fail ─► fix ticket, built and
|
|
142
|
+
reviewed like any other
|
|
131
143
|
```
|
|
132
144
|
|
|
133
|
-
`scripts/flow.py` is the conductor. The session asks it `next`, and it answers with one line: `BUILD`, `REVIEW`, `DONE`, `STOP` or `HANDOFF`. It prints the full prompt for each subagent from runtime-neutral guides, so the session never writes one itself.
|
|
145
|
+
`scripts/flow.py` is the conductor. The session asks it `next`, and it answers with one line: `TEST`, `BUILD`, `REVIEW`, `ASK`, `DONE`, `STOP` or `HANDOFF`. It prints the full prompt for each subagent from runtime-neutral guides, so the session never writes one itself.
|
|
134
146
|
|
|
135
|
-
**What the script checks and what it trusts.** The conductor verifies the build from the repo: the ticket file must say `resolved`, the tree must be clean and committed, and it runs the gate and the floor guard itself. It also runs the `check` block under each ticket's Done when and compares the exit code and printed text, and for a `Test first: yes` ticket it proves the red test commit itself: it checks out the test-only commit, runs Test, and requires it to fail before the code. A failure of either goes back to the builder before any reviewer is started. It also checks that the reviewer changed no tracked file and made no commit. The review verdicts are different: each reviewer's reply
|
|
147
|
+
**What the script checks and what it trusts.** The conductor verifies the build from the repo: the ticket file must say `resolved`, the tree must be clean and committed, and it runs the gate and the floor guard itself. It also runs the `check` block under each ticket's Done when and compares the exit code and printed text (a check with a `needs <what>` line, such as `needs network`, that fails is deferred instead: the reviewer is told it is not met, and it goes to `followups.md`), and for a `Test first: yes` ticket it proves the red test commit itself: it checks out the test-only commit, runs Test, and requires it to fail before the code. A failure of either goes back to the builder before any reviewer is started. It also checks that the reviewer changed no tracked file and made no commit (an edit is put back and the review given to a fresh reviewer, see Read only roles below). The review verdicts are different: each reviewer's reply is relayed by the session, which saves it to a file and hands it to `flow.py verdict`. The script reads `REVIEW: PASS` or `REVIEW: FAIL` from that reply; it cannot prove the session passed it on unedited. A ticket with a `Level:` line moves on after one PASS verdict. A ticket with no level (a plan from before 0.9.0) needs two, a spec review and then a quality review, unless the conductor judged it small. The size is measured from the repo (`git diff` against the commit the ticket started from), never taken from the builder.
|
|
136
148
|
|
|
137
149
|
**The gate: full or quick.** The gate runs Build, Test and Lint after every ticket. With an optional `Quick:` line in `commands.md` (a faster subset of `Test`), it runs Build, Quick and Lint after the tickets in the middle of a plan, and the full Build, Test and Lint after the last ticket, before a handoff, and under `FLOW_GATE_FULL=1`. A plan without `Quick:` runs the full gate every time. The test-first proof still runs the full `Test` command.
|
|
138
150
|
|
|
@@ -141,12 +153,12 @@ The Claude Code skill is `skills/feature-flow/`. The Codex skill is written by h
|
|
|
141
153
|
| | Level 1 (light) | Level 2 (standard) | Level 3 (boundary) |
|
|
142
154
|
|---|---|---|---|
|
|
143
155
|
| For | tests, docs, prompt text, spikes, the acceptance ticket | ordinary feature code | auth, tokens, permissions, money and run limits, data loss, the flow's own code, anything a hostile caller reaches |
|
|
144
|
-
| Reviews | one combined review | one combined review, spec checklist first |
|
|
156
|
+
| Reviews | one combined review | one combined review, spec checklist first | one combined review that also probes every input as a hostile caller |
|
|
145
157
|
| Rework rounds | 1, then the run stops for you | 2; from round 3 only a `blocker` sends it back, majors go to `plans/<feature>/followups.md` and the ticket passes | `FLOW_MAX_REVIEW_ROUNDS` (3), then the run stops for you |
|
|
146
158
|
|
|
147
159
|
The gate does not depend on the level: it still runs Quick mid-plan and the full Test on the last ticket and before a handoff. Nobody but you can lower a level. The conductor reads `Level:` from the ticket as it was at the base commit, so a builder's edit does nothing (and the floor guard fails it). It raises the level from what it measures, never lowers it: `Review: full`, `Type: convert` and `Floor: allow flow-edit` make a ticket level 3, so does a diff that touches a path on the optional `Sensitive:` line of `commands.md` (frozen by the floor guard), and a level 1 diff over the small limits becomes level 2. A reviewer can raise it with a line `LEVEL: 3` above the verdict; a raise to 3 during a combined review adds a quality review. The log records `LEVEL-1`, `LEVEL-2` or `LEVEL-3` for each review round, and `feature-flow report` shows it.
|
|
148
160
|
|
|
149
|
-
**
|
|
161
|
+
**One review at level 3 too (0.23.0).** Before 0.23.0 a level 3 ticket got a spec review and then a separate quality review. In the first field run (two features, 19 separate spec reviews), every real catch came from the quality review: the spec review re-ran the Done when checks the conductor had already run and passed, and found nothing they had missed. So a level 3 ticket now gets one review, which does the spec checklist (marking bullets the conductor's check block covered as `MET (conductor)` instead of running them again) and then the quality review with the hostile caller probe. That saves a fresh reviewer per level 3 ticket. A reviewer that raises a ticket to level 3 in a combined review still adds a quality review after it, since it did not probe the change as level 3.
|
|
150
162
|
|
|
151
163
|
**One review for a small ticket (no level).** A ticket with no `Level:` line, from a plan written before 0.9.0, keeps the 0.8.0 rules. A ticket whose built diff is 3 files and 60 changed lines at most (the plan folder left out), and whose `check` block ran and passed, gets one combined review instead of the spec and quality reviews. The conductor measures the diff itself. `Review: full` in the ticket (as it was at the start), `Type: convert`, no `check` block, or `FLOW_GATE=off` keep both reviews. Every other conductor check still runs on every ticket.
|
|
152
164
|
|
|
@@ -164,8 +176,9 @@ The gate does not depend on the level: it still runs Quick mid-plan and the full
|
|
|
164
176
|
| `ticket-reviewer` | Read, Glob, Grep, Bash (no Edit, no Write) | Reviews one ticket by the review guide in its prompt and ends with `REVIEW: PASS` or `REVIEW: FAIL`. |
|
|
165
177
|
| `feature-planner` | Read, Glob, Grep, Bash, Write, Edit, WebSearch, WebFetch | Plans one feature from the approved brief by the plan guide, writes only the draft, cites outside sources, and ends with `PLAN: READY` or `PLAN: QUESTIONS`. |
|
|
166
178
|
| `plan-reviewer` | Read, Glob, Grep, Bash (no Edit, no Write) | Checks the draft against the brief by the plan review guide and ends with `PLAN-REVIEW: PASS` or `PLAN-REVIEW: FAIL`. |
|
|
179
|
+
| `flow-tester` | Read, Glob, Grep, Edit, Write, Bash | Writes the feature's acceptance tests from `spec.md` alone, before the build, by the test guide. Never reads the tickets. |
|
|
167
180
|
|
|
168
|
-
|
|
181
|
+
**Read only roles.** The reviewers, the consultants (`flow-architect`, `flow-designer`, `flow-po`) and `flow-scout` have no Edit or Write tool, and in Claude Code a `PreToolUse` hook in their role file blocks shell commands that change files or the repository: git commands that write (`commit`, `add`, `stash`, `checkout`, `reset` and the like), `sed -i`, `rm`, `mv`, `cp`, `touch`, `tee` and output redirected into a file other than `/dev/null` or `/tmp/`. The hook reads the command's text, so a program that writes files itself (a test runner updating snapshots, a script) still gets through, and Claude Code ignores hooks in a plugin's agents. A Codex subagent cannot be limited at all: Codex gives every child its parent's sandbox. So the conductor is the backstop everywhere: when a reviewer or consultant leaves a tracked file changed, it saves the change as `.feature-flow/state/edit-<feature>-<NN>.patch`, puts the files back, throws that answer away and hands the same review to a fresh reviewer, with a note saying why (`EDIT-UNDONE` in the log). A second edit in a row stops the run, and so does a commit, which it cannot undo safely. A planner's draft reaches `plans/` only through `plan-accept`. On Codex the planner can research the web only if web search is on; otherwise it plans from the code and says so. The Codex planning path has not been run by hand.
|
|
169
182
|
|
|
170
183
|
The guides in `guides/` (installed to `.feature-flow/guides/`) hold the protocol: how to build, review, write the brief, plan, review a plan and show. The skill holds only what differs per agent.
|
|
171
184
|
|
|
@@ -178,6 +191,7 @@ plans/
|
|
|
178
191
|
├── map.md destination, the bar, decisions so far (workers append only)
|
|
179
192
|
├── commands.md build, test, lint, smoke commands (frozen once approved)
|
|
180
193
|
├── learnings.md traps workers found (workers append only)
|
|
194
|
+
├── brainstorm.md the options weighed and the one picked (only after a brainstorm)
|
|
181
195
|
└── tasks/
|
|
182
196
|
├── 01-types.md
|
|
183
197
|
├── 02-service.md
|
|
@@ -273,7 +287,7 @@ Before a planner, builder or reviewer starts, the session can spawn cheap helper
|
|
|
273
287
|
| a level 1 ticket | none |
|
|
274
288
|
| a build below level 3 (first attempt) | one builder scout on the ticket and its `Touches:` |
|
|
275
289
|
| a level 3 build (first attempt) | two builder scouts: the code it changes, and what depends on it |
|
|
276
|
-
| a level 3 ticket's
|
|
290
|
+
| a level 3 ticket's first review | one reviewer scout on the conventions the diff must follow |
|
|
277
291
|
| the feature review (fast path) | one reviewer scout |
|
|
278
292
|
|
|
279
293
|
`scouts [lane]` lists `SCOUT <k> <agent> <reply file>` lines (or `NONE`) and clears the last ones' replies; `scout-prompt <k> [lane]` prints one scout's prompt. The session saves each reply into its file, and the phase's `prompt` adds them under `## Scout findings (unverified)`, cut to 60 lines each. A reply saved for one phase never reaches another. Retries and later rounds get no scouts. `FLOW_SCOUTS=off` turns them off.
|
|
@@ -288,12 +302,23 @@ A builder, reviewer or planner that hits a question it should not decide alone a
|
|
|
288
302
|
- **The planner** starts each open question with `architect:`, `designer:`, `po:` or `user:`. The session runs `consult-prompt <role> <question file>` for the first three, adds the answers to the brief under `Consulted:`, kept apart from your `Decided:` lines, and plans again.
|
|
289
303
|
- **What still comes to you.** Any question the asker marks `user`, any answer a consultant ends with `ANSWER: USER` (it changes what you get, so its options come to you), and a third consultant question on one ticket all stop the run with the question, written into the ticket under `## Ask: user`. You answer under `## Consulted (user)` at the end of the ticket, commit, and run `next`. A reviewer's question for you reopens the ticket, so its builder builds again with your answer.
|
|
290
304
|
|
|
305
|
+
## Acceptance tests (the tester)
|
|
306
|
+
|
|
307
|
+
A builder writes its own tests, so they tend to check what it built rather than what was asked. With an `Acceptance:` line in `commands.md` (the planner writes one for any feature a test can reach from outside), a separate tester writes the feature's acceptance tests before any of it is built, from the product owner's words alone.
|
|
308
|
+
|
|
309
|
+
- **Before the first ticket**, `next` hands out `TEST <plan folder> <sha>`. A fresh `flow-tester` reads `spec.md` (its bar, stories and acceptance criteria, edge cases and interfaces), `map.md`, `commands.md` and the existing code's conventions, never the tickets, and commits tests under `plans/<feature>/acceptance/` that only the `Acceptance:` command runs. The conductor then checks its work: the commits change nothing outside that folder, the gate still passes with the tests in place, and the tests fail now, since nothing is built yet (`TEST-WRITTEN` in the log). Otherwise a fresh tester gets the job again, with a note saying what was wrong. It has no lane, even when lanes run.
|
|
310
|
+
- **Builders cannot change them.** The tests sit inside the plan folder, so the floor guard fails any builder's change there (`acceptance-edit`), and no `Floor:` line allows it. A builder may run them to see where the feature stands.
|
|
311
|
+
- **Once every ticket is resolved**, the conductor runs the `Acceptance:` command itself (`ACCEPT-PASS` or `ACCEPT-FAIL`). A failure becomes a new ticket, `NN-acceptance-fixes-<round>.md`, with the failing output in it, built and reviewed like any other; then the tests run again. After `FLOW_MAX_REVIEW_ROUNDS` failed rounds the run stops for you. With the fast path, the tests run before the feature review.
|
|
312
|
+
- **A disputed test.** The tester can be wrong too, most often where the spec is vague. A fix ticket's builder that is sure a test asks for something `spec.md` does not say asks the product owner with `## Ask: po`. `flow-po` rules from `spec.md` alone with `RULING: TEST WRONG` or `RULING: CODE WRONG` (`RULING-TEST` or `RULING-CODE` in the log). The builder leaves a test ruled wrong failing and finishes the rest; once the ticket is resolved, a tester changes exactly the tests ruled wrong, as the rulings say, and the tests run again. The usual limit on questions holds, so a third one goes to you.
|
|
313
|
+
- **No `Acceptance:` line, no tester**: a plan written before 0.23.0 runs as before.
|
|
314
|
+
|
|
291
315
|
## The fast path
|
|
292
316
|
|
|
293
317
|
`/feature-flow <feature> fast` trades per-ticket reviews for speed. The planner gets `Pace: fast` in the brief and writes a short plan of fewer, larger tickets, and the plan reviewer is skipped. With `FLOW_FAST=1` on `start`, a ticket below level 3 (one with no `Level:` line too) that passes the gate, the floor guard and its Done when checks passes at once (`REVIEW-DEFERRED` in the log). With `FLOW_GATE=off` nothing would check it, so every ticket keeps its review. A level 3 ticket, or one that touches a `Sensitive:` path, still gets its own reviews.
|
|
294
318
|
|
|
295
319
|
- **The feature review.** Once every ticket is resolved, `next` hands out `REVIEW <plan folder> all <sha>`: one fresh reviewer reads the deferred tickets as they were planned and the whole diff from the oldest deferred ticket's base to HEAD, with `guides/review-feature.md`. It has no lane, even when lanes run.
|
|
296
320
|
- **A failed feature review** becomes a new ticket, `NN-feature-review-fixes-<round>.md`, with the findings in it. A builder fixes it, and the feature is reviewed again. After `FLOW_MAX_REVIEW_ROUNDS` failed rounds the run stops for you.
|
|
321
|
+
- **Batches.** In fast mode one builder takes up to 5 ready tickets at once (`BATCH <n>` in the log), when each is level 1 or 2, has a `Touches:` line, and touches nothing another ticket of the batch or a `Sensitive:` path touches. The `BUILD` line names the first ticket and the prompt lists the rest. The builder finishes them one at a time, each with its own commits. The conductor then checks each ticket on its own commits: the gate once at the end (and, if it fails there, at each ticket's last commit, to find the first one that broke it), then the floor guard, the footprint, Done when and test first with HEAD at that ticket's last commit. A ticket that passes is deferred to the feature review like any other. One that fails, or that the builder never finished, goes back to open with its findings and is built alone (`BATCH-FAIL`), never in a batch again. That saves a builder and its context for every ticket but the first. A mistake in one ticket can still carry into the later ones of the batch, which is why only small, separate tickets are batched. Lanes, `FLOW_RELAY` and `FLOW_GATE=off` turn batches off, and so does `FLOW_BATCH=1` (`FLOW_BATCH=<n>` sets the size, at most 5).
|
|
297
322
|
- **Mid-run.** `fast on` and `fast off` (through the runner, like `next`) switch it between phases. Asking the session to go faster runs `fast on`. Asking again while fast is on offers the re-plan below. Tickets already passed without a review still get the feature review, whichever way it is switched.
|
|
298
323
|
- **The cost.** A mistake in an early ticket is found at the end, when later tickets may have built on it. Use it for small or low-risk features. `reset` keeps the list of deferred tickets, so they still get the feature review.
|
|
299
324
|
|
|
@@ -305,6 +330,58 @@ A builder, reviewer or planner that hits a question it should not decide alone a
|
|
|
305
330
|
- **Still over, a re-plan offer.** Once fast mode has finished a ticket and the run is still over (or at once, if fast mode was already on), the run stops once with the minutes spent, the tickets left, and an offer to re-plan. If one ticket took more than half the time over several attempts, the stop names it as stuck, since that is a stuck ticket, not a slow plan. `next` goes on as planned, and a new `budget` earns a new offer.
|
|
306
331
|
- **The re-plan needs your yes.** On your yes, between tickets, `replan-prompt` hands the `feature-planner` the open tickets with `guides/replan.md`. It folds them into fewer, larger tickets with the same bar: every Done when item and check moves into the ticket that takes over, folded tickets become `Status: parked (folded into NN)`, and resolved tickets stay as they are. The session shows you the change and commits it only on a second yes. The next `next` stops if the re-plan changed a resolved ticket. Nothing is ever cut without you.
|
|
307
332
|
|
|
333
|
+
## Recording a run (eval)
|
|
334
|
+
|
|
335
|
+
Every finished run can leave a record of what it cost and what it caught, so a trial on your own repo gives an answer, not an impression. On `DONE` the skill runs `python3 scripts/flow-status.py <feature> --eval` (or run `feature-flow eval <feature>` yourself) and asks you a few questions.
|
|
336
|
+
|
|
337
|
+
- **`plans/<feature>/eval.json`**: tickets, builds, reviews and rework; tickets settled when the plan was approved and never built; every catch by the check that made it (gate, floor guard, Done when, test first, footprint, reviewer, feature review); the follow-ups in `followups.md` and the deferred checks; who drove the run (`driver`: `person` or `agent`); where the run needed its driver (stops, questions, handoffs, resets); active minutes; and tokens.
|
|
338
|
+
- **`plans/<feature>/followups.md`**: what the run left for later, committed as it goes: the `minor` findings of every passing review, the findings a level 2 ticket passed with after its full rounds, and each `needs` check (below) that could not pass on this host.
|
|
339
|
+
- **Tokens** come from Claude Code's own session transcripts (`~/.claude/projects/`, or `CLAUDE_CONFIG_DIR`), never from the agent: every message of the sessions and subagents that worked in this repo during the run, each counted once, by model and, without lanes, split per ticket by time. Codex sessions are not read yet.
|
|
340
|
+
- **`plans/<feature>/eval-verdict.md`**: a form for you. Was the plan right, how many fixes you made by hand, would you use it again, and for each catch whether it was real or a false alarm. Run `--eval` again and your answers land in `eval.json`. The false-alarm count is the only way to tell whether the checks are worth their cost.
|
|
341
|
+
- **Later:** `feature-flow eval <feature> --later`, a week or two on, lists the commits since the run whose subject says fix, revert, bug or regression on the paths each ticket's `Touches:` names: the defects the run let through.
|
|
342
|
+
|
|
343
|
+
Both files sit in the plan folder, so they are committed with it and survive a cloud session. Nothing is sent anywhere; attach `eval.json` to a field-run issue if you want to share it. Run logs from before 0.15.0 have no dates, so they give no tokens.
|
|
344
|
+
|
|
345
|
+
## Profiles
|
|
346
|
+
|
|
347
|
+
Most settings below never need touching. One word picks a sensible set:
|
|
348
|
+
|
|
349
|
+
| Profile | Sets | For |
|
|
350
|
+
|---|---|---|
|
|
351
|
+
| `careful` | `FLOW_GATE_FULL=1`, `FLOW_FAST=0`, `FLOW_SMALL_LINES=0`, `FLOW_TICKETS_PER_SESSION=3` | code where a wrong "done" is expensive: the full gate and an own review for every ticket |
|
|
352
|
+
| `normal` | nothing: the defaults | everyday features |
|
|
353
|
+
| `fast` | `FLOW_FAST=1`, `FLOW_SCOUTS=off`, `FLOW_TICKETS_PER_SESSION=6` | small, low-risk features: one feature review at the end |
|
|
354
|
+
|
|
355
|
+
Pick one with `/feature-flow <feature> careful` (or `fast`), `FLOW_PROFILE=<name>` on `start`, or a `Profile:` line in the plan's `commands.md`, approved with the plan. A profile fills only settings you did not set: `FLOW_PROFILE=fast FLOW_SCOUTS=on` keeps the scouts. The log records `PROFILE-<NAME>` at the start. A level 3 or `Sensitive:` ticket keeps its own reviews in every profile.
|
|
356
|
+
|
|
357
|
+
The long `python3 -I -c ...` line the skill uses to call the conductor stays as it is: it is how the skill checks `flow-trust.py` against the sha256 it pins before running it, and a shorter wrapper would be one more file nothing checks. The session copies it from the skill; you never type it.
|
|
358
|
+
|
|
359
|
+
## Brainstorm before planning
|
|
360
|
+
|
|
361
|
+
When an idea is still fuzzy, the session can brainstorm it with you before it writes the brief: `/feature-flow <feature> brainstorm`, always in `careful`, and offered on its own when there is no bar yet or there are two real ways to build it. It asks you up to three questions, one at a time, sends a scout to see how the code does the nearest thing today, then lays out two or three options, each with a mermaid diagram, its pros and cons, its size and its risky areas, and recommends one. Your pick and the brief share one yes.
|
|
362
|
+
|
|
363
|
+
Six read only helpers work for the session during a brainstorm: a code scout, a web scout, the architect, designer and product owner, and `flow-skeptic`, who attacks each finished option so the session that wrote the options is not the one that judges them. Each gets its prompt from `brainstorm-prompt <helper> <question file>`, which counts them: `normal` allows 2 scouts, 1 web, 2 consultants and 1 skeptic per brainstorm, `careful` 3, 2, 3 and 1, and `FLOW_SCOUTS=off` no scouts. Helpers never write the brainstorm and never ask you anything; the session does both.
|
|
364
|
+
|
|
365
|
+
The result is `brainstorm.md` ([template](guides/templates/brainstorm.md)), committed with the plan. The planner follows its chosen option and copies its diagram into `spec.md`, the plan reviewer fails a plan that builds a rejected option or leaves a risky area below level 3, and a re-plan keeps the choice. It is skipped in `fast`, for an import, and with `auto`; with `agent`, the driving agent picks, the file says `Picked by: agent`, and the eval records it.
|
|
366
|
+
|
|
367
|
+
## Starting from Spec Kit or OpenSpec
|
|
368
|
+
|
|
369
|
+
If you already plan with [GitHub Spec Kit](https://github.com/github/spec-kit) or [OpenSpec](https://github.com/Fission-AI/OpenSpec), feature-flow can build what they planned:
|
|
370
|
+
|
|
371
|
+
```bash
|
|
372
|
+
feature-flow import specs/001-photo-albums albums # a Spec Kit feature folder (or its tasks.md)
|
|
373
|
+
feature-flow import openspec/changes/add-auth auth # an OpenSpec change folder
|
|
374
|
+
python3 scripts/flow-status.py albums --import specs/001-photo-albums # the same, from a repo install
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Or ask the session to plan `albums` from `specs/001-photo-albums`. Either way it writes `plans/<feature>/`, never over an existing plan (`--dry-run` shows what it would write):
|
|
378
|
+
|
|
379
|
+
- **One ticket per phase or section**, its tasks as the Done when items, so thirty small tasks become five tickets with real reviews, not thirty.
|
|
380
|
+
- **Order:** each section waits for the one before. Spec Kit's user story phases (`[US1]`, `[US2]`) wait only for the phases before the first story, so with lanes they are built side by side, and the polish phase waits for every story.
|
|
381
|
+
- **Touches:** the paths the tasks name, when every task in the section names one.
|
|
382
|
+
- **spec.md** carries the source's `spec.md` and `plan.md` (Spec Kit) or `proposal.md` and `design.md` (OpenSpec).
|
|
383
|
+
- **What you add:** the commands (`commands.md` is the template), a `check` block per ticket and the levels. `flow-status.py <feature> --lint` says what is missing. The skill does this with you, then asks for a yes before it commits the plan.
|
|
384
|
+
|
|
308
385
|
## Long features and handoff
|
|
309
386
|
|
|
310
387
|
A session's context fills up, so the flow moves to a fresh session every few tickets. After `FLOW_TICKETS_PER_SESSION` tickets (default 4) pass review, `next` prints a `HANDOFF` line instead of the next ticket, for example `HANDOFF /feature-flow csv-export 3f9c0a1b2c3d4e5f.0a1b2c3d4e5f6a7b` (the last word is the runner's digest, which lets the new session check that the flow's files did not change in between). The session stops and tells you to open a new session and type that line. The new session picks up exactly where the last one stopped. Set `FLOW_TICKETS_PER_SESSION=0` to never hand off.
|
|
@@ -313,6 +390,8 @@ A session's context fills up, so the flow moves to a fresh session every few tic
|
|
|
313
390
|
- **Resuming after a closed session.** If a session ended without `HANDOFF` (you closed it, it crashed, it ran out of budget), the feature is still owned by it, and a new session stops and says so. Once you are sure the old session is gone, answer yes when the new session asks, or start it with `FLOW_TAKEOVER=1`. With `auto` the skill never takes over on its own.
|
|
314
391
|
- **Stuck on a ticket.** `python3 scripts/flow.py <feature> reset` (or `feature-flow reset <feature>`) reopens a ticket left `claimed` or `in-progress`, commits that, and clears the conductor's run state, so the next `/feature-flow <feature>` starts clean from the ticket files. `reset <NN>` reopens that one ticket, even a resolved one, to build it again. While a session owns the feature it needs `FLOW_TAKEOVER=1`. A mistyped command or feature name gets a `did you mean` hint.
|
|
315
392
|
- **Relay mode.** `FLOW_RELAY=1` hands off after every build and every review, so each phase gets a session of its own.
|
|
393
|
+
- **When an agent drives.** An orchestrating agent (another Claude session driving the skill for you) has no context to refresh, so handoffs are pure overhead. `/feature-flow <feature> agent` runs `start` with `FLOW_DRIVER=agent`: no `HANDOFF` unless `FLOW_TICKETS_PER_SESSION` is set by hand, builders skip the "continue in a fresh session" line (they leave it out whenever the flow runs them), and the eval records that an agent drove the run, so its stops, handoffs and resets are not read as your time. `next` runs the gate and the checks before it answers, which can take minutes: a caller with a 2 minute tool timeout should give it 10 minutes or more, or run it in the background.
|
|
394
|
+
- **Argument mistakes say what to do.** `verdict` without its file, `--after-build` in the wrong place (the runner now accepts it anywhere), a `next` after a REVIEW with no `verdict` in between (it used to hand out the same review again; now it changes nothing and says to run `verdict` first), a digest from another feature (the runner says to pass `FLOW_TRUST=new` on a feature's first call), and a commit made between a review and its `next` (the stop says how to take it out and make it again later).
|
|
316
395
|
- **Nobody needs to watch.** With `auto` the skill asks nothing, and a Claude Code cloud session keeps working while you are away. You only come back to type the `HANDOFF` line.
|
|
317
396
|
|
|
318
397
|
The state lives in `.feature-flow/state/` (the state, a log of every step, and the last review reply). That folder ignores itself, so it never shows up in `git status`, and a normal Codex session can write it, which it cannot do under `.git`.
|
|
@@ -329,6 +408,8 @@ python3 scripts/flow-status.py <feature> --counts one line of counts
|
|
|
329
408
|
python3 scripts/flow-status.py <feature> --check cycles, missing blockers, missing Done when, unordered mentions
|
|
330
409
|
python3 scripts/flow-status.py <feature> --lint --check plus: a check block (or `Check: none <why>`) on every ticket, a Test command
|
|
331
410
|
feature-flow report <feature> what a run did, from its log: builds, reviews, failed checks, stops
|
|
411
|
+
feature-flow import <spec-kit or openspec folder> <feature> start plans/<feature>/ from their task list
|
|
412
|
+
feature-flow eval <feature> [--later] record the run in plans/<feature>/eval.json, with your verdict (also: flow-status.py <feature> --eval)
|
|
332
413
|
python3 scripts/flow-status.py <feature> --mermaid the ticket graph, coloured by status (add "plain" for none)
|
|
333
414
|
python3 scripts/flow-status.py <feature> --json every ticket with status, blockers and readiness
|
|
334
415
|
python3 scripts/flow-view.py <feature> [--watch] the animated graph page, opened in your browser
|
|
@@ -344,11 +425,14 @@ The commands in `commands.md` run through `bash -c` on Linux and macOS and throu
|
|
|
344
425
|
|
|
345
426
|
| Variable | Default | Meaning |
|
|
346
427
|
|---|---|---|
|
|
428
|
+
| `FLOW_PROFILE` | unset | `careful`, `normal` or `fast`: fills the settings in this table that are not set; a `Profile:` line in `commands.md` does the same |
|
|
347
429
|
| `FLOW_TICKETS_PER_SESSION` | `4` | tickets per session before `HANDOFF`; `0` never hands off |
|
|
348
430
|
| `FLOW_RELAY` | `0` | `1` hands off after every build and every review |
|
|
431
|
+
| `FLOW_DRIVER` | `person` | read by `start`: `agent` when another agent drives the run: no handoffs (unless `FLOW_TICKETS_PER_SESSION` is set), and the eval says so |
|
|
349
432
|
| `FLOW_LANES` | `1` | read by `start`: `2` to `4` builds tickets with disjoint `Touches:` side by side in worktrees (not with `FLOW_RELAY`) |
|
|
350
433
|
| `FLOW_FAST` | unset | read by `start`: `1` defers the reviews of tickets below level 3 to one feature review at the end, `0` turns it off; unset keeps the run's setting |
|
|
351
434
|
| `FLOW_BUDGET` | unset | read by `start`: minutes of active work before fast mode turns on, then a re-plan offer; `off` drops it |
|
|
435
|
+
| `FLOW_BATCH` | `5` | fast mode: most small tickets one builder takes at once; `1` turns batches off |
|
|
352
436
|
| `FLOW_SCOUTS` | `on` | `off` lists no scouts before any phase |
|
|
353
437
|
| `FLOW_TAKEOVER` | unset | `1` lets `start` take a feature over from a session that is gone |
|
|
354
438
|
| `FLOW_MAX_RETRIES` | `2` | builds or reviews per step before the run stops |
|
|
@@ -26,13 +26,22 @@ python3 install.py /path/to/your/repo --agent all # both, side by side
|
|
|
26
26
|
# `bash install.sh ...` still works on Linux and macOS: it only runs install.py
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
+
As a Claude Code plugin, with nothing written into your repo (this repo is its own marketplace):
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
/plugin marketplace add hamilton-sky/feature-flow
|
|
33
|
+
/plugin install feature-flow@feature-flow
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The plugin carries the skills, the roles (named `feature-flow:ticket-builder` and so on), the conductor, the scripts and the guides, and the skill runs the conductor from the plugin's folder. A repo with its own install still uses that one. Claude Code cloud sessions (claude.ai/code) do not install plugins, so for them install into the repo and commit `.claude/`, `scripts/` and `.feature-flow/` as below. The plugin path is new and has not had a real run yet.
|
|
37
|
+
|
|
29
38
|
Without a clone, the same installer runs from [PyPI](https://pypi.org/project/feature-flow-cli/):
|
|
30
39
|
|
|
31
40
|
```bash
|
|
32
41
|
uvx feature-flow-cli install /path/to/your/repo --agent all # or: pipx run feature-flow-cli install ...
|
|
33
42
|
```
|
|
34
43
|
|
|
35
|
-
The package puts a `feature-flow` command on your PATH with `install`, `uninstall`, `status <feature>`, `view <feature>`, `reset <feature>` and `
|
|
44
|
+
The package puts a `feature-flow` command on your PATH with `install`, `uninstall`, `status <feature>`, `view <feature>`, `reset <feature>`, `report <feature>` and `eval <feature>`. It installs the same files, byte for byte, as `install.py` from a clone.
|
|
36
45
|
|
|
37
46
|
The installer lists what it wrote in `.feature-flow/installed.txt`, with each file's hash in `.feature-flow/installed.sha256`. Commit those files (`git add --pathspec-from-file=.feature-flow/installed.txt`); until you do, the flow does not count them as uncommitted changes. Installing a newer version over an older one updates every file nobody edited since it was installed, and keeps (and names) the ones you changed; `--force` replaces those too.
|
|
38
47
|
|
|
@@ -77,6 +86,10 @@ The Claude Code skill is `skills/feature-flow/`. The Codex skill is written by h
|
|
|
77
86
|
## How a ticket flows
|
|
78
87
|
|
|
79
88
|
```
|
|
89
|
+
tester subagent (once, before the first ticket, when commands.md
|
|
90
|
+
has Acceptance:): writes acceptance tests from spec.md only
|
|
91
|
+
│
|
|
92
|
+
▼
|
|
80
93
|
smoke command (script): is the base healthy? no ─► stop, spend nothing
|
|
81
94
|
│ yes
|
|
82
95
|
▼
|
|
@@ -97,23 +110,22 @@ The Claude Code skill is `skills/feature-flow/`. The Codex skill is written by h
|
|
|
97
110
|
commit that failed Test before the code fail ─┤
|
|
98
111
|
│ pass │
|
|
99
112
|
▼ │
|
|
100
|
-
|
|
101
|
-
+ diff,
|
|
102
|
-
|
|
103
|
-
▼ │
|
|
104
|
-
quality review: a second fresh reviewer subagent FAIL ─┤
|
|
105
|
-
(a level 1 or 2 ticket gets one combined review instead
|
|
106
|
-
of these two; see "Ticket levels" below)
|
|
113
|
+
review: one fresh reviewer subagent, sees only the ticket │
|
|
114
|
+
+ diff: the spec checklist, then the code's quality; at level 3 │
|
|
115
|
+
it also probes every input as a hostile caller FAIL ─┤
|
|
107
116
|
│ PASS ▼
|
|
108
117
|
▼ findings written into the ticket,
|
|
109
118
|
next ticket reopened, built again (rounds by level);
|
|
110
119
|
the builder's prompt then carries
|
|
111
120
|
a root-cause debugging guide
|
|
121
|
+
|
|
122
|
+
every ticket resolved: the acceptance tests run (script) fail ─► fix ticket, built and
|
|
123
|
+
reviewed like any other
|
|
112
124
|
```
|
|
113
125
|
|
|
114
|
-
`scripts/flow.py` is the conductor. The session asks it `next`, and it answers with one line: `BUILD`, `REVIEW`, `DONE`, `STOP` or `HANDOFF`. It prints the full prompt for each subagent from runtime-neutral guides, so the session never writes one itself.
|
|
126
|
+
`scripts/flow.py` is the conductor. The session asks it `next`, and it answers with one line: `TEST`, `BUILD`, `REVIEW`, `ASK`, `DONE`, `STOP` or `HANDOFF`. It prints the full prompt for each subagent from runtime-neutral guides, so the session never writes one itself.
|
|
115
127
|
|
|
116
|
-
**What the script checks and what it trusts.** The conductor verifies the build from the repo: the ticket file must say `resolved`, the tree must be clean and committed, and it runs the gate and the floor guard itself. It also runs the `check` block under each ticket's Done when and compares the exit code and printed text, and for a `Test first: yes` ticket it proves the red test commit itself: it checks out the test-only commit, runs Test, and requires it to fail before the code. A failure of either goes back to the builder before any reviewer is started. It also checks that the reviewer changed no tracked file and made no commit. The review verdicts are different: each reviewer's reply
|
|
128
|
+
**What the script checks and what it trusts.** The conductor verifies the build from the repo: the ticket file must say `resolved`, the tree must be clean and committed, and it runs the gate and the floor guard itself. It also runs the `check` block under each ticket's Done when and compares the exit code and printed text (a check with a `needs <what>` line, such as `needs network`, that fails is deferred instead: the reviewer is told it is not met, and it goes to `followups.md`), and for a `Test first: yes` ticket it proves the red test commit itself: it checks out the test-only commit, runs Test, and requires it to fail before the code. A failure of either goes back to the builder before any reviewer is started. It also checks that the reviewer changed no tracked file and made no commit (an edit is put back and the review given to a fresh reviewer, see Read only roles below). The review verdicts are different: each reviewer's reply is relayed by the session, which saves it to a file and hands it to `flow.py verdict`. The script reads `REVIEW: PASS` or `REVIEW: FAIL` from that reply; it cannot prove the session passed it on unedited. A ticket with a `Level:` line moves on after one PASS verdict. A ticket with no level (a plan from before 0.9.0) needs two, a spec review and then a quality review, unless the conductor judged it small. The size is measured from the repo (`git diff` against the commit the ticket started from), never taken from the builder.
|
|
117
129
|
|
|
118
130
|
**The gate: full or quick.** The gate runs Build, Test and Lint after every ticket. With an optional `Quick:` line in `commands.md` (a faster subset of `Test`), it runs Build, Quick and Lint after the tickets in the middle of a plan, and the full Build, Test and Lint after the last ticket, before a handoff, and under `FLOW_GATE_FULL=1`. A plan without `Quick:` runs the full gate every time. The test-first proof still runs the full `Test` command.
|
|
119
131
|
|
|
@@ -122,12 +134,12 @@ The Claude Code skill is `skills/feature-flow/`. The Codex skill is written by h
|
|
|
122
134
|
| | Level 1 (light) | Level 2 (standard) | Level 3 (boundary) |
|
|
123
135
|
|---|---|---|---|
|
|
124
136
|
| For | tests, docs, prompt text, spikes, the acceptance ticket | ordinary feature code | auth, tokens, permissions, money and run limits, data loss, the flow's own code, anything a hostile caller reaches |
|
|
125
|
-
| Reviews | one combined review | one combined review, spec checklist first |
|
|
137
|
+
| Reviews | one combined review | one combined review, spec checklist first | one combined review that also probes every input as a hostile caller |
|
|
126
138
|
| Rework rounds | 1, then the run stops for you | 2; from round 3 only a `blocker` sends it back, majors go to `plans/<feature>/followups.md` and the ticket passes | `FLOW_MAX_REVIEW_ROUNDS` (3), then the run stops for you |
|
|
127
139
|
|
|
128
140
|
The gate does not depend on the level: it still runs Quick mid-plan and the full Test on the last ticket and before a handoff. Nobody but you can lower a level. The conductor reads `Level:` from the ticket as it was at the base commit, so a builder's edit does nothing (and the floor guard fails it). It raises the level from what it measures, never lowers it: `Review: full`, `Type: convert` and `Floor: allow flow-edit` make a ticket level 3, so does a diff that touches a path on the optional `Sensitive:` line of `commands.md` (frozen by the floor guard), and a level 1 diff over the small limits becomes level 2. A reviewer can raise it with a line `LEVEL: 3` above the verdict; a raise to 3 during a combined review adds a quality review. The log records `LEVEL-1`, `LEVEL-2` or `LEVEL-3` for each review round, and `feature-flow report` shows it.
|
|
129
141
|
|
|
130
|
-
**
|
|
142
|
+
**One review at level 3 too (0.23.0).** Before 0.23.0 a level 3 ticket got a spec review and then a separate quality review. In the first field run (two features, 19 separate spec reviews), every real catch came from the quality review: the spec review re-ran the Done when checks the conductor had already run and passed, and found nothing they had missed. So a level 3 ticket now gets one review, which does the spec checklist (marking bullets the conductor's check block covered as `MET (conductor)` instead of running them again) and then the quality review with the hostile caller probe. That saves a fresh reviewer per level 3 ticket. A reviewer that raises a ticket to level 3 in a combined review still adds a quality review after it, since it did not probe the change as level 3.
|
|
131
143
|
|
|
132
144
|
**One review for a small ticket (no level).** A ticket with no `Level:` line, from a plan written before 0.9.0, keeps the 0.8.0 rules. A ticket whose built diff is 3 files and 60 changed lines at most (the plan folder left out), and whose `check` block ran and passed, gets one combined review instead of the spec and quality reviews. The conductor measures the diff itself. `Review: full` in the ticket (as it was at the start), `Type: convert`, no `check` block, or `FLOW_GATE=off` keep both reviews. Every other conductor check still runs on every ticket.
|
|
133
145
|
|
|
@@ -145,8 +157,9 @@ The gate does not depend on the level: it still runs Quick mid-plan and the full
|
|
|
145
157
|
| `ticket-reviewer` | Read, Glob, Grep, Bash (no Edit, no Write) | Reviews one ticket by the review guide in its prompt and ends with `REVIEW: PASS` or `REVIEW: FAIL`. |
|
|
146
158
|
| `feature-planner` | Read, Glob, Grep, Bash, Write, Edit, WebSearch, WebFetch | Plans one feature from the approved brief by the plan guide, writes only the draft, cites outside sources, and ends with `PLAN: READY` or `PLAN: QUESTIONS`. |
|
|
147
159
|
| `plan-reviewer` | Read, Glob, Grep, Bash (no Edit, no Write) | Checks the draft against the brief by the plan review guide and ends with `PLAN-REVIEW: PASS` or `PLAN-REVIEW: FAIL`. |
|
|
160
|
+
| `flow-tester` | Read, Glob, Grep, Edit, Write, Bash | Writes the feature's acceptance tests from `spec.md` alone, before the build, by the test guide. Never reads the tickets. |
|
|
148
161
|
|
|
149
|
-
|
|
162
|
+
**Read only roles.** The reviewers, the consultants (`flow-architect`, `flow-designer`, `flow-po`) and `flow-scout` have no Edit or Write tool, and in Claude Code a `PreToolUse` hook in their role file blocks shell commands that change files or the repository: git commands that write (`commit`, `add`, `stash`, `checkout`, `reset` and the like), `sed -i`, `rm`, `mv`, `cp`, `touch`, `tee` and output redirected into a file other than `/dev/null` or `/tmp/`. The hook reads the command's text, so a program that writes files itself (a test runner updating snapshots, a script) still gets through, and Claude Code ignores hooks in a plugin's agents. A Codex subagent cannot be limited at all: Codex gives every child its parent's sandbox. So the conductor is the backstop everywhere: when a reviewer or consultant leaves a tracked file changed, it saves the change as `.feature-flow/state/edit-<feature>-<NN>.patch`, puts the files back, throws that answer away and hands the same review to a fresh reviewer, with a note saying why (`EDIT-UNDONE` in the log). A second edit in a row stops the run, and so does a commit, which it cannot undo safely. A planner's draft reaches `plans/` only through `plan-accept`. On Codex the planner can research the web only if web search is on; otherwise it plans from the code and says so. The Codex planning path has not been run by hand.
|
|
150
163
|
|
|
151
164
|
The guides in `guides/` (installed to `.feature-flow/guides/`) hold the protocol: how to build, review, write the brief, plan, review a plan and show. The skill holds only what differs per agent.
|
|
152
165
|
|
|
@@ -159,6 +172,7 @@ plans/
|
|
|
159
172
|
├── map.md destination, the bar, decisions so far (workers append only)
|
|
160
173
|
├── commands.md build, test, lint, smoke commands (frozen once approved)
|
|
161
174
|
├── learnings.md traps workers found (workers append only)
|
|
175
|
+
├── brainstorm.md the options weighed and the one picked (only after a brainstorm)
|
|
162
176
|
└── tasks/
|
|
163
177
|
├── 01-types.md
|
|
164
178
|
├── 02-service.md
|
|
@@ -254,7 +268,7 @@ Before a planner, builder or reviewer starts, the session can spawn cheap helper
|
|
|
254
268
|
| a level 1 ticket | none |
|
|
255
269
|
| a build below level 3 (first attempt) | one builder scout on the ticket and its `Touches:` |
|
|
256
270
|
| a level 3 build (first attempt) | two builder scouts: the code it changes, and what depends on it |
|
|
257
|
-
| a level 3 ticket's
|
|
271
|
+
| a level 3 ticket's first review | one reviewer scout on the conventions the diff must follow |
|
|
258
272
|
| the feature review (fast path) | one reviewer scout |
|
|
259
273
|
|
|
260
274
|
`scouts [lane]` lists `SCOUT <k> <agent> <reply file>` lines (or `NONE`) and clears the last ones' replies; `scout-prompt <k> [lane]` prints one scout's prompt. The session saves each reply into its file, and the phase's `prompt` adds them under `## Scout findings (unverified)`, cut to 60 lines each. A reply saved for one phase never reaches another. Retries and later rounds get no scouts. `FLOW_SCOUTS=off` turns them off.
|
|
@@ -269,12 +283,23 @@ A builder, reviewer or planner that hits a question it should not decide alone a
|
|
|
269
283
|
- **The planner** starts each open question with `architect:`, `designer:`, `po:` or `user:`. The session runs `consult-prompt <role> <question file>` for the first three, adds the answers to the brief under `Consulted:`, kept apart from your `Decided:` lines, and plans again.
|
|
270
284
|
- **What still comes to you.** Any question the asker marks `user`, any answer a consultant ends with `ANSWER: USER` (it changes what you get, so its options come to you), and a third consultant question on one ticket all stop the run with the question, written into the ticket under `## Ask: user`. You answer under `## Consulted (user)` at the end of the ticket, commit, and run `next`. A reviewer's question for you reopens the ticket, so its builder builds again with your answer.
|
|
271
285
|
|
|
286
|
+
## Acceptance tests (the tester)
|
|
287
|
+
|
|
288
|
+
A builder writes its own tests, so they tend to check what it built rather than what was asked. With an `Acceptance:` line in `commands.md` (the planner writes one for any feature a test can reach from outside), a separate tester writes the feature's acceptance tests before any of it is built, from the product owner's words alone.
|
|
289
|
+
|
|
290
|
+
- **Before the first ticket**, `next` hands out `TEST <plan folder> <sha>`. A fresh `flow-tester` reads `spec.md` (its bar, stories and acceptance criteria, edge cases and interfaces), `map.md`, `commands.md` and the existing code's conventions, never the tickets, and commits tests under `plans/<feature>/acceptance/` that only the `Acceptance:` command runs. The conductor then checks its work: the commits change nothing outside that folder, the gate still passes with the tests in place, and the tests fail now, since nothing is built yet (`TEST-WRITTEN` in the log). Otherwise a fresh tester gets the job again, with a note saying what was wrong. It has no lane, even when lanes run.
|
|
291
|
+
- **Builders cannot change them.** The tests sit inside the plan folder, so the floor guard fails any builder's change there (`acceptance-edit`), and no `Floor:` line allows it. A builder may run them to see where the feature stands.
|
|
292
|
+
- **Once every ticket is resolved**, the conductor runs the `Acceptance:` command itself (`ACCEPT-PASS` or `ACCEPT-FAIL`). A failure becomes a new ticket, `NN-acceptance-fixes-<round>.md`, with the failing output in it, built and reviewed like any other; then the tests run again. After `FLOW_MAX_REVIEW_ROUNDS` failed rounds the run stops for you. With the fast path, the tests run before the feature review.
|
|
293
|
+
- **A disputed test.** The tester can be wrong too, most often where the spec is vague. A fix ticket's builder that is sure a test asks for something `spec.md` does not say asks the product owner with `## Ask: po`. `flow-po` rules from `spec.md` alone with `RULING: TEST WRONG` or `RULING: CODE WRONG` (`RULING-TEST` or `RULING-CODE` in the log). The builder leaves a test ruled wrong failing and finishes the rest; once the ticket is resolved, a tester changes exactly the tests ruled wrong, as the rulings say, and the tests run again. The usual limit on questions holds, so a third one goes to you.
|
|
294
|
+
- **No `Acceptance:` line, no tester**: a plan written before 0.23.0 runs as before.
|
|
295
|
+
|
|
272
296
|
## The fast path
|
|
273
297
|
|
|
274
298
|
`/feature-flow <feature> fast` trades per-ticket reviews for speed. The planner gets `Pace: fast` in the brief and writes a short plan of fewer, larger tickets, and the plan reviewer is skipped. With `FLOW_FAST=1` on `start`, a ticket below level 3 (one with no `Level:` line too) that passes the gate, the floor guard and its Done when checks passes at once (`REVIEW-DEFERRED` in the log). With `FLOW_GATE=off` nothing would check it, so every ticket keeps its review. A level 3 ticket, or one that touches a `Sensitive:` path, still gets its own reviews.
|
|
275
299
|
|
|
276
300
|
- **The feature review.** Once every ticket is resolved, `next` hands out `REVIEW <plan folder> all <sha>`: one fresh reviewer reads the deferred tickets as they were planned and the whole diff from the oldest deferred ticket's base to HEAD, with `guides/review-feature.md`. It has no lane, even when lanes run.
|
|
277
301
|
- **A failed feature review** becomes a new ticket, `NN-feature-review-fixes-<round>.md`, with the findings in it. A builder fixes it, and the feature is reviewed again. After `FLOW_MAX_REVIEW_ROUNDS` failed rounds the run stops for you.
|
|
302
|
+
- **Batches.** In fast mode one builder takes up to 5 ready tickets at once (`BATCH <n>` in the log), when each is level 1 or 2, has a `Touches:` line, and touches nothing another ticket of the batch or a `Sensitive:` path touches. The `BUILD` line names the first ticket and the prompt lists the rest. The builder finishes them one at a time, each with its own commits. The conductor then checks each ticket on its own commits: the gate once at the end (and, if it fails there, at each ticket's last commit, to find the first one that broke it), then the floor guard, the footprint, Done when and test first with HEAD at that ticket's last commit. A ticket that passes is deferred to the feature review like any other. One that fails, or that the builder never finished, goes back to open with its findings and is built alone (`BATCH-FAIL`), never in a batch again. That saves a builder and its context for every ticket but the first. A mistake in one ticket can still carry into the later ones of the batch, which is why only small, separate tickets are batched. Lanes, `FLOW_RELAY` and `FLOW_GATE=off` turn batches off, and so does `FLOW_BATCH=1` (`FLOW_BATCH=<n>` sets the size, at most 5).
|
|
278
303
|
- **Mid-run.** `fast on` and `fast off` (through the runner, like `next`) switch it between phases. Asking the session to go faster runs `fast on`. Asking again while fast is on offers the re-plan below. Tickets already passed without a review still get the feature review, whichever way it is switched.
|
|
279
304
|
- **The cost.** A mistake in an early ticket is found at the end, when later tickets may have built on it. Use it for small or low-risk features. `reset` keeps the list of deferred tickets, so they still get the feature review.
|
|
280
305
|
|
|
@@ -286,6 +311,58 @@ A builder, reviewer or planner that hits a question it should not decide alone a
|
|
|
286
311
|
- **Still over, a re-plan offer.** Once fast mode has finished a ticket and the run is still over (or at once, if fast mode was already on), the run stops once with the minutes spent, the tickets left, and an offer to re-plan. If one ticket took more than half the time over several attempts, the stop names it as stuck, since that is a stuck ticket, not a slow plan. `next` goes on as planned, and a new `budget` earns a new offer.
|
|
287
312
|
- **The re-plan needs your yes.** On your yes, between tickets, `replan-prompt` hands the `feature-planner` the open tickets with `guides/replan.md`. It folds them into fewer, larger tickets with the same bar: every Done when item and check moves into the ticket that takes over, folded tickets become `Status: parked (folded into NN)`, and resolved tickets stay as they are. The session shows you the change and commits it only on a second yes. The next `next` stops if the re-plan changed a resolved ticket. Nothing is ever cut without you.
|
|
288
313
|
|
|
314
|
+
## Recording a run (eval)
|
|
315
|
+
|
|
316
|
+
Every finished run can leave a record of what it cost and what it caught, so a trial on your own repo gives an answer, not an impression. On `DONE` the skill runs `python3 scripts/flow-status.py <feature> --eval` (or run `feature-flow eval <feature>` yourself) and asks you a few questions.
|
|
317
|
+
|
|
318
|
+
- **`plans/<feature>/eval.json`**: tickets, builds, reviews and rework; tickets settled when the plan was approved and never built; every catch by the check that made it (gate, floor guard, Done when, test first, footprint, reviewer, feature review); the follow-ups in `followups.md` and the deferred checks; who drove the run (`driver`: `person` or `agent`); where the run needed its driver (stops, questions, handoffs, resets); active minutes; and tokens.
|
|
319
|
+
- **`plans/<feature>/followups.md`**: what the run left for later, committed as it goes: the `minor` findings of every passing review, the findings a level 2 ticket passed with after its full rounds, and each `needs` check (below) that could not pass on this host.
|
|
320
|
+
- **Tokens** come from Claude Code's own session transcripts (`~/.claude/projects/`, or `CLAUDE_CONFIG_DIR`), never from the agent: every message of the sessions and subagents that worked in this repo during the run, each counted once, by model and, without lanes, split per ticket by time. Codex sessions are not read yet.
|
|
321
|
+
- **`plans/<feature>/eval-verdict.md`**: a form for you. Was the plan right, how many fixes you made by hand, would you use it again, and for each catch whether it was real or a false alarm. Run `--eval` again and your answers land in `eval.json`. The false-alarm count is the only way to tell whether the checks are worth their cost.
|
|
322
|
+
- **Later:** `feature-flow eval <feature> --later`, a week or two on, lists the commits since the run whose subject says fix, revert, bug or regression on the paths each ticket's `Touches:` names: the defects the run let through.
|
|
323
|
+
|
|
324
|
+
Both files sit in the plan folder, so they are committed with it and survive a cloud session. Nothing is sent anywhere; attach `eval.json` to a field-run issue if you want to share it. Run logs from before 0.15.0 have no dates, so they give no tokens.
|
|
325
|
+
|
|
326
|
+
## Profiles
|
|
327
|
+
|
|
328
|
+
Most settings below never need touching. One word picks a sensible set:
|
|
329
|
+
|
|
330
|
+
| Profile | Sets | For |
|
|
331
|
+
|---|---|---|
|
|
332
|
+
| `careful` | `FLOW_GATE_FULL=1`, `FLOW_FAST=0`, `FLOW_SMALL_LINES=0`, `FLOW_TICKETS_PER_SESSION=3` | code where a wrong "done" is expensive: the full gate and an own review for every ticket |
|
|
333
|
+
| `normal` | nothing: the defaults | everyday features |
|
|
334
|
+
| `fast` | `FLOW_FAST=1`, `FLOW_SCOUTS=off`, `FLOW_TICKETS_PER_SESSION=6` | small, low-risk features: one feature review at the end |
|
|
335
|
+
|
|
336
|
+
Pick one with `/feature-flow <feature> careful` (or `fast`), `FLOW_PROFILE=<name>` on `start`, or a `Profile:` line in the plan's `commands.md`, approved with the plan. A profile fills only settings you did not set: `FLOW_PROFILE=fast FLOW_SCOUTS=on` keeps the scouts. The log records `PROFILE-<NAME>` at the start. A level 3 or `Sensitive:` ticket keeps its own reviews in every profile.
|
|
337
|
+
|
|
338
|
+
The long `python3 -I -c ...` line the skill uses to call the conductor stays as it is: it is how the skill checks `flow-trust.py` against the sha256 it pins before running it, and a shorter wrapper would be one more file nothing checks. The session copies it from the skill; you never type it.
|
|
339
|
+
|
|
340
|
+
## Brainstorm before planning
|
|
341
|
+
|
|
342
|
+
When an idea is still fuzzy, the session can brainstorm it with you before it writes the brief: `/feature-flow <feature> brainstorm`, always in `careful`, and offered on its own when there is no bar yet or there are two real ways to build it. It asks you up to three questions, one at a time, sends a scout to see how the code does the nearest thing today, then lays out two or three options, each with a mermaid diagram, its pros and cons, its size and its risky areas, and recommends one. Your pick and the brief share one yes.
|
|
343
|
+
|
|
344
|
+
Six read only helpers work for the session during a brainstorm: a code scout, a web scout, the architect, designer and product owner, and `flow-skeptic`, who attacks each finished option so the session that wrote the options is not the one that judges them. Each gets its prompt from `brainstorm-prompt <helper> <question file>`, which counts them: `normal` allows 2 scouts, 1 web, 2 consultants and 1 skeptic per brainstorm, `careful` 3, 2, 3 and 1, and `FLOW_SCOUTS=off` no scouts. Helpers never write the brainstorm and never ask you anything; the session does both.
|
|
345
|
+
|
|
346
|
+
The result is `brainstorm.md` ([template](guides/templates/brainstorm.md)), committed with the plan. The planner follows its chosen option and copies its diagram into `spec.md`, the plan reviewer fails a plan that builds a rejected option or leaves a risky area below level 3, and a re-plan keeps the choice. It is skipped in `fast`, for an import, and with `auto`; with `agent`, the driving agent picks, the file says `Picked by: agent`, and the eval records it.
|
|
347
|
+
|
|
348
|
+
## Starting from Spec Kit or OpenSpec
|
|
349
|
+
|
|
350
|
+
If you already plan with [GitHub Spec Kit](https://github.com/github/spec-kit) or [OpenSpec](https://github.com/Fission-AI/OpenSpec), feature-flow can build what they planned:
|
|
351
|
+
|
|
352
|
+
```bash
|
|
353
|
+
feature-flow import specs/001-photo-albums albums # a Spec Kit feature folder (or its tasks.md)
|
|
354
|
+
feature-flow import openspec/changes/add-auth auth # an OpenSpec change folder
|
|
355
|
+
python3 scripts/flow-status.py albums --import specs/001-photo-albums # the same, from a repo install
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
Or ask the session to plan `albums` from `specs/001-photo-albums`. Either way it writes `plans/<feature>/`, never over an existing plan (`--dry-run` shows what it would write):
|
|
359
|
+
|
|
360
|
+
- **One ticket per phase or section**, its tasks as the Done when items, so thirty small tasks become five tickets with real reviews, not thirty.
|
|
361
|
+
- **Order:** each section waits for the one before. Spec Kit's user story phases (`[US1]`, `[US2]`) wait only for the phases before the first story, so with lanes they are built side by side, and the polish phase waits for every story.
|
|
362
|
+
- **Touches:** the paths the tasks name, when every task in the section names one.
|
|
363
|
+
- **spec.md** carries the source's `spec.md` and `plan.md` (Spec Kit) or `proposal.md` and `design.md` (OpenSpec).
|
|
364
|
+
- **What you add:** the commands (`commands.md` is the template), a `check` block per ticket and the levels. `flow-status.py <feature> --lint` says what is missing. The skill does this with you, then asks for a yes before it commits the plan.
|
|
365
|
+
|
|
289
366
|
## Long features and handoff
|
|
290
367
|
|
|
291
368
|
A session's context fills up, so the flow moves to a fresh session every few tickets. After `FLOW_TICKETS_PER_SESSION` tickets (default 4) pass review, `next` prints a `HANDOFF` line instead of the next ticket, for example `HANDOFF /feature-flow csv-export 3f9c0a1b2c3d4e5f.0a1b2c3d4e5f6a7b` (the last word is the runner's digest, which lets the new session check that the flow's files did not change in between). The session stops and tells you to open a new session and type that line. The new session picks up exactly where the last one stopped. Set `FLOW_TICKETS_PER_SESSION=0` to never hand off.
|
|
@@ -294,6 +371,8 @@ A session's context fills up, so the flow moves to a fresh session every few tic
|
|
|
294
371
|
- **Resuming after a closed session.** If a session ended without `HANDOFF` (you closed it, it crashed, it ran out of budget), the feature is still owned by it, and a new session stops and says so. Once you are sure the old session is gone, answer yes when the new session asks, or start it with `FLOW_TAKEOVER=1`. With `auto` the skill never takes over on its own.
|
|
295
372
|
- **Stuck on a ticket.** `python3 scripts/flow.py <feature> reset` (or `feature-flow reset <feature>`) reopens a ticket left `claimed` or `in-progress`, commits that, and clears the conductor's run state, so the next `/feature-flow <feature>` starts clean from the ticket files. `reset <NN>` reopens that one ticket, even a resolved one, to build it again. While a session owns the feature it needs `FLOW_TAKEOVER=1`. A mistyped command or feature name gets a `did you mean` hint.
|
|
296
373
|
- **Relay mode.** `FLOW_RELAY=1` hands off after every build and every review, so each phase gets a session of its own.
|
|
374
|
+
- **When an agent drives.** An orchestrating agent (another Claude session driving the skill for you) has no context to refresh, so handoffs are pure overhead. `/feature-flow <feature> agent` runs `start` with `FLOW_DRIVER=agent`: no `HANDOFF` unless `FLOW_TICKETS_PER_SESSION` is set by hand, builders skip the "continue in a fresh session" line (they leave it out whenever the flow runs them), and the eval records that an agent drove the run, so its stops, handoffs and resets are not read as your time. `next` runs the gate and the checks before it answers, which can take minutes: a caller with a 2 minute tool timeout should give it 10 minutes or more, or run it in the background.
|
|
375
|
+
- **Argument mistakes say what to do.** `verdict` without its file, `--after-build` in the wrong place (the runner now accepts it anywhere), a `next` after a REVIEW with no `verdict` in between (it used to hand out the same review again; now it changes nothing and says to run `verdict` first), a digest from another feature (the runner says to pass `FLOW_TRUST=new` on a feature's first call), and a commit made between a review and its `next` (the stop says how to take it out and make it again later).
|
|
297
376
|
- **Nobody needs to watch.** With `auto` the skill asks nothing, and a Claude Code cloud session keeps working while you are away. You only come back to type the `HANDOFF` line.
|
|
298
377
|
|
|
299
378
|
The state lives in `.feature-flow/state/` (the state, a log of every step, and the last review reply). That folder ignores itself, so it never shows up in `git status`, and a normal Codex session can write it, which it cannot do under `.git`.
|
|
@@ -310,6 +389,8 @@ python3 scripts/flow-status.py <feature> --counts one line of counts
|
|
|
310
389
|
python3 scripts/flow-status.py <feature> --check cycles, missing blockers, missing Done when, unordered mentions
|
|
311
390
|
python3 scripts/flow-status.py <feature> --lint --check plus: a check block (or `Check: none <why>`) on every ticket, a Test command
|
|
312
391
|
feature-flow report <feature> what a run did, from its log: builds, reviews, failed checks, stops
|
|
392
|
+
feature-flow import <spec-kit or openspec folder> <feature> start plans/<feature>/ from their task list
|
|
393
|
+
feature-flow eval <feature> [--later] record the run in plans/<feature>/eval.json, with your verdict (also: flow-status.py <feature> --eval)
|
|
313
394
|
python3 scripts/flow-status.py <feature> --mermaid the ticket graph, coloured by status (add "plain" for none)
|
|
314
395
|
python3 scripts/flow-status.py <feature> --json every ticket with status, blockers and readiness
|
|
315
396
|
python3 scripts/flow-view.py <feature> [--watch] the animated graph page, opened in your browser
|
|
@@ -325,11 +406,14 @@ The commands in `commands.md` run through `bash -c` on Linux and macOS and throu
|
|
|
325
406
|
|
|
326
407
|
| Variable | Default | Meaning |
|
|
327
408
|
|---|---|---|
|
|
409
|
+
| `FLOW_PROFILE` | unset | `careful`, `normal` or `fast`: fills the settings in this table that are not set; a `Profile:` line in `commands.md` does the same |
|
|
328
410
|
| `FLOW_TICKETS_PER_SESSION` | `4` | tickets per session before `HANDOFF`; `0` never hands off |
|
|
329
411
|
| `FLOW_RELAY` | `0` | `1` hands off after every build and every review |
|
|
412
|
+
| `FLOW_DRIVER` | `person` | read by `start`: `agent` when another agent drives the run: no handoffs (unless `FLOW_TICKETS_PER_SESSION` is set), and the eval says so |
|
|
330
413
|
| `FLOW_LANES` | `1` | read by `start`: `2` to `4` builds tickets with disjoint `Touches:` side by side in worktrees (not with `FLOW_RELAY`) |
|
|
331
414
|
| `FLOW_FAST` | unset | read by `start`: `1` defers the reviews of tickets below level 3 to one feature review at the end, `0` turns it off; unset keeps the run's setting |
|
|
332
415
|
| `FLOW_BUDGET` | unset | read by `start`: minutes of active work before fast mode turns on, then a re-plan offer; `off` drops it |
|
|
416
|
+
| `FLOW_BATCH` | `5` | fast mode: most small tickets one builder takes at once; `1` turns batches off |
|
|
333
417
|
| `FLOW_SCOUTS` | `on` | `off` lists no scouts before any phase |
|
|
334
418
|
| `FLOW_TAKEOVER` | unset | `1` lets `start` take a feature over from a session that is gone |
|
|
335
419
|
| `FLOW_MAX_RETRIES` | `2` | builds or reviews per step before the run stops |
|