feature-flow-cli 0.10.0__tar.gz → 0.14.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.
Files changed (75) hide show
  1. {feature_flow_cli-0.10.0/feature_flow_cli.egg-info → feature_flow_cli-0.14.0}/PKG-INFO +47 -2
  2. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/README.md +46 -1
  3. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/adapters/codex/feature-flow/SKILL.md +9 -9
  4. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/adapters/codex/feature-flow/agents/openai.yaml +1 -1
  5. feature_flow_cli-0.14.0/agents/flow-architect.md +27 -0
  6. feature_flow_cli-0.14.0/agents/flow-designer.md +27 -0
  7. feature_flow_cli-0.14.0/agents/flow-po.md +27 -0
  8. feature_flow_cli-0.14.0/agents/flow-scout.md +40 -0
  9. feature_flow_cli-0.14.0/agents/flow-web.md +30 -0
  10. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/__init__.py +1 -1
  11. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/cli.py +28 -5
  12. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/codehash.py +6 -1
  13. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/conductor.py +646 -16
  14. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/prompts.py +45 -6
  15. feature_flow_cli-0.14.0/feature_flow/scouts.py +118 -0
  16. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0/feature_flow_cli.egg-info}/PKG-INFO +47 -2
  17. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow_cli.egg-info/SOURCES.txt +8 -0
  18. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/guides/build.md +1 -0
  19. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/guides/plan.md +5 -3
  20. feature_flow_cli-0.14.0/guides/replan.md +35 -0
  21. feature_flow_cli-0.14.0/guides/review-feature.md +66 -0
  22. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/guides/review-quality.md +4 -0
  23. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/guides/review-single.md +4 -0
  24. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/guides/review.md +4 -0
  25. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/scripts/flow-trust.py +3 -2
  26. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/skills/feature-flow/SKILL.md +10 -10
  27. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/LICENSE +0 -0
  28. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/MANIFEST.in +0 -0
  29. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/agents/feature-planner.md +0 -0
  30. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/agents/plan-reviewer.md +0 -0
  31. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/agents/ticket-builder.md +0 -0
  32. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/agents/ticket-reviewer.md +0 -0
  33. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/__main__.py +0 -0
  34. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/checks.py +0 -0
  35. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/command.py +0 -0
  36. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/floorguard.py +0 -0
  37. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/gate.py +0 -0
  38. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/git.py +0 -0
  39. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/install.py +0 -0
  40. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/lanes.py +0 -0
  41. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/proc.py +0 -0
  42. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/proof.py +0 -0
  43. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/released.py +0 -0
  44. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/report.py +0 -0
  45. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/state.py +0 -0
  46. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/status.py +0 -0
  47. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/suggest.py +0 -0
  48. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/tickets.py +0 -0
  49. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/uninstall.py +0 -0
  50. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow/view.py +0 -0
  51. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow_cli.egg-info/dependency_links.txt +0 -0
  52. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow_cli.egg-info/entry_points.txt +0 -0
  53. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/feature_flow_cli.egg-info/top_level.txt +0 -0
  54. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/guides/brief.md +0 -0
  55. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/guides/debug.md +0 -0
  56. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/guides/plan-review.md +0 -0
  57. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/guides/show.md +0 -0
  58. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/guides/templates/commands.md +0 -0
  59. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/guides/templates/learnings.md +0 -0
  60. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/guides/templates/map.md +0 -0
  61. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/guides/templates/spec.md +0 -0
  62. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/guides/templates/ticket.md +0 -0
  63. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/guides/templates/ui-mockup.md +0 -0
  64. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/install.py +0 -0
  65. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/install.sh +0 -0
  66. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/pyproject.toml +0 -0
  67. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/scripts/floor-guard.py +0 -0
  68. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/scripts/flow-status.py +0 -0
  69. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/scripts/flow-view.html +0 -0
  70. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/scripts/flow-view.py +0 -0
  71. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/scripts/flow.py +0 -0
  72. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/scripts/gate.py +0 -0
  73. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/setup.cfg +0 -0
  74. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.0}/skills/architect-review/SKILL.md +0 -0
  75. {feature_flow_cli-0.10.0 → feature_flow_cli-0.14.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.10.0
3
+ Version: 0.14.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
@@ -263,6 +263,48 @@ With `FLOW_LANES=2` (up to 4) on `start`, tickets that do not touch the same fil
263
263
 
264
264
  The session runs `prompt`, `next` and `verdict` with the lane from the `BUILD` or `REVIEW` line, and `next` answers `WAIT <lanes>` when every lane that can work is busy (see `## Lanes` in the skill).
265
265
 
266
+ ## Scouts
267
+
268
+ Before a planner, builder or reviewer starts, the session can spawn cheap helpers that read ahead for it: `flow-scout` (read only, codebase) and `flow-web` (web only, for the planner). Both run on Haiku in Claude Code (`model: haiku` in their role files); in Codex the skill picks the lightest model `spawn_agent` allows. A scout looks at the code the way its role would (`ROLE: builder` looks for patterns and helpers to reuse, `ROLE: reviewer` for the rules the change must follow) and never decides anything.
269
+
270
+ | Before | Scouts |
271
+ |---|---|
272
+ | planning (`plan-scouts <brief>`) | one codebase scout and one web scout |
273
+ | a level 1 ticket | none |
274
+ | a build below level 3 (first attempt) | one builder scout on the ticket and its `Touches:` |
275
+ | a level 3 build (first attempt) | two builder scouts: the code it changes, and what depends on it |
276
+ | a level 3 ticket's spec review | one reviewer scout on the conventions the diff must follow |
277
+ | the feature review (fast path) | one reviewer scout |
278
+
279
+ `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.
280
+
281
+ ## Questions for the architect, designer or product owner
282
+
283
+ A builder, reviewer or planner that hits a question it should not decide alone asks it instead of guessing, and the flow pauses that job until the right role answers.
284
+
285
+ - **Who answers.** `flow-architect` answers technical design questions, `flow-designer` answers UI and UX questions, and `flow-po` answers what the feature must do where the spec is silent. Each is a fresh, read only agent that sees the plan, the ticket as it was planned and the code, never the asker's reasoning or a ticket's Answer. Each gets one scout with its own lens first.
286
+ - **A builder** appends `## Ask: architect|designer|po` with the question to its ticket and stops. `next` hands out `ASK <role> <ticket> <NN> <sha>`. The answer goes into the ticket under `## Consulted (<role>)`, and the ticket is built again. The question does not count as a failed attempt.
287
+ - **A reviewer** ends with a `## Question` and `REVIEW: ASK <role>`. The answer comes back in the next review's notes. On the fast path's feature review, the reviewer writes the question as a finding, and the fix ticket's builder can ask it.
288
+ - **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
+ - **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
+
291
+ ## The fast path
292
+
293
+ `/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
+
295
+ - **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
+ - **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.
297
+ - **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
+ - **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
+
300
+ ## A time budget
301
+
302
+ `FLOW_BUDGET=<minutes>` on `start` gives the feature a budget of active minutes. The conductor counts the time between its steps, at most an hour for one step, so a session left open overnight does not eat the budget, and the time between two sessions does not count. `budget` (through the runner) reports it, and `budget <minutes>`, `budget +<minutes>` or `budget off` change it between phases.
303
+
304
+ - **Over the budget, fast mode first.** Before the next ticket starts, the conductor turns fast mode on by itself (`BUDGET-FAST` in the log).
305
+ - **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
+ - **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
+
266
308
  ## Long features and handoff
267
309
 
268
310
  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.
@@ -279,7 +321,7 @@ The state lives in `.feature-flow/state/` (the state, a log of every step, and t
279
321
 
280
322
  ```bash
281
323
  python3 scripts/flow.py <feature> start|reset [NN] the conductor (the skill runs it; also plan-prompt, plan-review-prompt, plan-accept)
282
- FLOW_TRUST=<digest|new> FLOW_SESSION=<token> python3 -I scripts/flow-trust.py <feature> next|prompt|verdict <file> loop commands by hand, through the runner: prints TRUST <digest> first (no hash check, see below)
324
+ FLOW_TRUST=<digest|new> FLOW_SESSION=<token> python3 -I scripts/flow-trust.py <feature> next|prompt|verdict <file>|fast on|off loop commands by hand, through the runner: prints TRUST <digest> first (no hash check, see below)
283
325
  python3 scripts/flow-status.py <feature> table of tickets and which are READY
284
326
  python3 scripts/flow-status.py <feature> --next path of the next ready ticket (exit 10 = done, 11 = stuck)
285
327
  python3 scripts/flow-status.py <feature> --ready every ready ticket, one per line (the same exit codes)
@@ -305,6 +347,9 @@ The commands in `commands.md` run through `bash -c` on Linux and macOS and throu
305
347
  | `FLOW_TICKETS_PER_SESSION` | `4` | tickets per session before `HANDOFF`; `0` never hands off |
306
348
  | `FLOW_RELAY` | `0` | `1` hands off after every build and every review |
307
349
  | `FLOW_LANES` | `1` | read by `start`: `2` to `4` builds tickets with disjoint `Touches:` side by side in worktrees (not with `FLOW_RELAY`) |
350
+ | `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
+ | `FLOW_BUDGET` | unset | read by `start`: minutes of active work before fast mode turns on, then a re-plan offer; `off` drops it |
352
+ | `FLOW_SCOUTS` | `on` | `off` lists no scouts before any phase |
308
353
  | `FLOW_TAKEOVER` | unset | `1` lets `start` take a feature over from a session that is gone |
309
354
  | `FLOW_MAX_RETRIES` | `2` | builds or reviews per step before the run stops |
310
355
  | `FLOW_MAX_REVIEW_ROUNDS` | `3` | times a ticket may be sent back before the run stops (a level 1 ticket: once) |
@@ -244,6 +244,48 @@ With `FLOW_LANES=2` (up to 4) on `start`, tickets that do not touch the same fil
244
244
 
245
245
  The session runs `prompt`, `next` and `verdict` with the lane from the `BUILD` or `REVIEW` line, and `next` answers `WAIT <lanes>` when every lane that can work is busy (see `## Lanes` in the skill).
246
246
 
247
+ ## Scouts
248
+
249
+ Before a planner, builder or reviewer starts, the session can spawn cheap helpers that read ahead for it: `flow-scout` (read only, codebase) and `flow-web` (web only, for the planner). Both run on Haiku in Claude Code (`model: haiku` in their role files); in Codex the skill picks the lightest model `spawn_agent` allows. A scout looks at the code the way its role would (`ROLE: builder` looks for patterns and helpers to reuse, `ROLE: reviewer` for the rules the change must follow) and never decides anything.
250
+
251
+ | Before | Scouts |
252
+ |---|---|
253
+ | planning (`plan-scouts <brief>`) | one codebase scout and one web scout |
254
+ | a level 1 ticket | none |
255
+ | a build below level 3 (first attempt) | one builder scout on the ticket and its `Touches:` |
256
+ | a level 3 build (first attempt) | two builder scouts: the code it changes, and what depends on it |
257
+ | a level 3 ticket's spec review | one reviewer scout on the conventions the diff must follow |
258
+ | the feature review (fast path) | one reviewer scout |
259
+
260
+ `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.
261
+
262
+ ## Questions for the architect, designer or product owner
263
+
264
+ A builder, reviewer or planner that hits a question it should not decide alone asks it instead of guessing, and the flow pauses that job until the right role answers.
265
+
266
+ - **Who answers.** `flow-architect` answers technical design questions, `flow-designer` answers UI and UX questions, and `flow-po` answers what the feature must do where the spec is silent. Each is a fresh, read only agent that sees the plan, the ticket as it was planned and the code, never the asker's reasoning or a ticket's Answer. Each gets one scout with its own lens first.
267
+ - **A builder** appends `## Ask: architect|designer|po` with the question to its ticket and stops. `next` hands out `ASK <role> <ticket> <NN> <sha>`. The answer goes into the ticket under `## Consulted (<role>)`, and the ticket is built again. The question does not count as a failed attempt.
268
+ - **A reviewer** ends with a `## Question` and `REVIEW: ASK <role>`. The answer comes back in the next review's notes. On the fast path's feature review, the reviewer writes the question as a finding, and the fix ticket's builder can ask it.
269
+ - **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
+ - **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
+
272
+ ## The fast path
273
+
274
+ `/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
+
276
+ - **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
+ - **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.
278
+ - **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
+ - **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
+
281
+ ## A time budget
282
+
283
+ `FLOW_BUDGET=<minutes>` on `start` gives the feature a budget of active minutes. The conductor counts the time between its steps, at most an hour for one step, so a session left open overnight does not eat the budget, and the time between two sessions does not count. `budget` (through the runner) reports it, and `budget <minutes>`, `budget +<minutes>` or `budget off` change it between phases.
284
+
285
+ - **Over the budget, fast mode first.** Before the next ticket starts, the conductor turns fast mode on by itself (`BUDGET-FAST` in the log).
286
+ - **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
+ - **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
+
247
289
  ## Long features and handoff
248
290
 
249
291
  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.
@@ -260,7 +302,7 @@ The state lives in `.feature-flow/state/` (the state, a log of every step, and t
260
302
 
261
303
  ```bash
262
304
  python3 scripts/flow.py <feature> start|reset [NN] the conductor (the skill runs it; also plan-prompt, plan-review-prompt, plan-accept)
263
- FLOW_TRUST=<digest|new> FLOW_SESSION=<token> python3 -I scripts/flow-trust.py <feature> next|prompt|verdict <file> loop commands by hand, through the runner: prints TRUST <digest> first (no hash check, see below)
305
+ FLOW_TRUST=<digest|new> FLOW_SESSION=<token> python3 -I scripts/flow-trust.py <feature> next|prompt|verdict <file>|fast on|off loop commands by hand, through the runner: prints TRUST <digest> first (no hash check, see below)
264
306
  python3 scripts/flow-status.py <feature> table of tickets and which are READY
265
307
  python3 scripts/flow-status.py <feature> --next path of the next ready ticket (exit 10 = done, 11 = stuck)
266
308
  python3 scripts/flow-status.py <feature> --ready every ready ticket, one per line (the same exit codes)
@@ -286,6 +328,9 @@ The commands in `commands.md` run through `bash -c` on Linux and macOS and throu
286
328
  | `FLOW_TICKETS_PER_SESSION` | `4` | tickets per session before `HANDOFF`; `0` never hands off |
287
329
  | `FLOW_RELAY` | `0` | `1` hands off after every build and every review |
288
330
  | `FLOW_LANES` | `1` | read by `start`: `2` to `4` builds tickets with disjoint `Touches:` side by side in worktrees (not with `FLOW_RELAY`) |
331
+ | `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
+ | `FLOW_BUDGET` | unset | read by `start`: minutes of active work before fast mode turns on, then a re-plan offer; `off` drops it |
333
+ | `FLOW_SCOUTS` | `on` | `off` lists no scouts before any phase |
289
334
  | `FLOW_TAKEOVER` | unset | `1` lets `start` take a feature over from a session that is gone |
290
335
  | `FLOW_MAX_RETRIES` | `2` | builds or reviews per step before the run stops |
291
336
  | `FLOW_MAX_REVIEW_ROUNDS` | `3` | times a ticket may be sent back before the run stops (a level 1 ticket: once) |
@@ -7,23 +7,23 @@ description: "Use to plan a feature (from the conversation so far, with a fresh
7
7
 
8
8
  Plan or build the feature in `<arguments>`.
9
9
 
10
- The first word is the **feature**. `show` means draw the graph. `auto` means ask nothing and go. If no feature was given and the conversation so far describes work to build, plan it (below) and propose the feature's name in the brief. If no feature was given otherwise, list `plans/*/` and ask which one.
10
+ The first word is the **feature**. `show` means draw the graph. `auto` means ask nothing and go. `fast` means the fast path: run `start` with `FLOW_FAST=1`, and tickets below level 3 that pass their checks skip their own review until one review of the whole feature at the end (a level 3 or `Sensitive:` ticket keeps its reviews). When the user asks mid-run to go faster, run `fast on` (or `fast off`) through `flow-trust.py` between two other conductor commands; if it answers that fast is already on, offer the user the re-plan it names. A time budget (`FLOW_BUDGET=<minutes>` on `start`, `budget <minutes>|+<minutes>|off` mid-run) turns fast on by itself once spent, and later stops to offer a re-plan. A re-plan needs the user's own yes, even with `auto`: then run `replan-prompt` (between tickets), start the planner with it as in planning, with a new `task_name`, show the user its reply and `git diff --stat`, and on a second yes commit the plan folder as `plan(<feature>): re-plan the open tickets` (else `git checkout -- plans/<feature>`), then run `next`. If no feature was given and the conversation so far describes work to build, plan it (below) and propose the feature's name in the brief. If no feature was given otherwise, list `plans/*/` and ask which one.
11
11
 
12
12
  The conductor is `python3 scripts/flow.py <feature> <command>`. If `scripts/flow.py` exists in the repo and the feature-flow package is beside it (`.feature-flow/feature_flow/`, or `feature_flow/` in a feature-flow checkout), use it (the repo's own install wins; an unrelated `scripts/flow.py` does not count); otherwise use `python3 "${FEATURE_FLOW_HOME:-$HOME/.feature-flow}/scripts/flow.py"` (`~/.feature-flow/scripts/flow.py`). Wherever this skill or a message names `scripts/flow.py`, `scripts/flow-status.py` or `scripts/flow-view.py`, it means the same folder, and the guides are then in that folder's sibling `guides/` (`~/.feature-flow/guides/`, else `.feature-flow/guides/` in the repo). Run the conductor with the working directory in the repo: state and plans stay there. It decides the order, runs the gate and the floor guard, and keeps its state in `.feature-flow/state/`, a folder git ignores. You ask it, and you do what it says. The guides it uses are in `.feature-flow/guides/` (in a feature-flow checkout, `guides/`). Read the project's `AGENTS.md` for its conventions.
13
13
 
14
14
  ## Calling the conductor
15
15
 
16
- Every conductor command (`start`, `next`, `prompt`, `verdict`, `reset`, `plan-prompt`, `plan-review-prompt`, `plan-accept`) runs through `flow-trust.py`, never `flow.py` itself. `<S>` below is the folder of the `flow.py` picked above: `scripts` for the repo's own install, else `"${FEATURE_FLOW_HOME:-$HOME/.feature-flow}/scripts"`. `flow-trust.py` is started by this loader line, which checks the file against the sha256 pinned here and runs those same bytes. Copy it exactly, replacing only `<S>`:
16
+ Every conductor command (`start`, `next`, `prompt`, `verdict`, `fast`, `scouts`, `scout-prompt`, `reset`, `plan-prompt`, `plan-review-prompt`, `plan-accept`, `plan-scouts`, `plan-scout-prompt`, `consult-prompt`, `budget`, `replan-prompt`) runs through `flow-trust.py`, never `flow.py` itself. `<S>` below is the folder of the `flow.py` picked above: `scripts` for the repo's own install, else `"${FEATURE_FLOW_HOME:-$HOME/.feature-flow}/scripts"`. `flow-trust.py` is started by this loader line, which checks the file against the sha256 pinned here and runs those same bytes. Copy it exactly, replacing only `<S>`:
17
17
 
18
- python3 -I -c "import hashlib,sys;b=open(sys.argv[1],'rb').read().replace(b'\r\n',b'\n');sys.exit(exec(compile(b,'flow-trust','exec')) if hashlib.sha256(b).hexdigest()==sys.argv[2] else 'flow-trust.py does not match this skill')" <S>/flow-trust.py 3a4b28b079b7c657e9a6d843cf1e69ac3c794639ea072f3be96cf94726ab370e
18
+ python3 -I -c "import hashlib,sys;b=open(sys.argv[1],'rb').read().replace(b'\r\n',b'\n');sys.exit(exec(compile(b,'flow-trust','exec')) if hashlib.sha256(b).hexdigest()==sys.argv[2] else 'flow-trust.py does not match this skill')" <S>/flow-trust.py f054fadc9b74dc05cb24d126ddbcf4301c37ffa4c529dfcc21591b97ffe28e43
19
19
 
20
20
  A full conductor command, here `next` (any other command and its arguments go where `next` is):
21
21
 
22
- FLOW_TRUST=<digest> FLOW_SESSION=<token> FLOW_INVOKE='$feature-flow' python3 -I -c "import hashlib,sys;b=open(sys.argv[1],'rb').read().replace(b'\r\n',b'\n');sys.exit(exec(compile(b,'flow-trust','exec')) if hashlib.sha256(b).hexdigest()==sys.argv[2] else 'flow-trust.py does not match this skill')" <S>/flow-trust.py 3a4b28b079b7c657e9a6d843cf1e69ac3c794639ea072f3be96cf94726ab370e <feature> next
22
+ FLOW_TRUST=<digest> FLOW_SESSION=<token> FLOW_INVOKE='$feature-flow' python3 -I -c "import hashlib,sys;b=open(sys.argv[1],'rb').read().replace(b'\r\n',b'\n');sys.exit(exec(compile(b,'flow-trust','exec')) if hashlib.sha256(b).hexdigest()==sys.argv[2] else 'flow-trust.py does not match this skill')" <S>/flow-trust.py f054fadc9b74dc05cb24d126ddbcf4301c37ffa4c529dfcc21591b97ffe28e43 <feature> next
23
23
 
24
24
  - The first line of the output is `TRUST <digest>`. Keep that digest and pass it as `FLOW_TRUST` on the next conductor call. Treat the rest as the conductor's output and act on it as below (for `prompt`, `plan-prompt` and `plan-review-prompt`, the child agent's prompt is everything after the `TRUST` line). Use `FLOW_TRUST=new` only on this session's first conductor call, or when resuming from an old-style `HANDOFF` line (below).
25
25
  - If you no longer have the last `TRUST` digest, stop and say so. Never guess it, and never use `new` in its place.
26
- - On the `next` right after a `BUILD <ticket> <NN> <sha>`, add `--after-build <ticket> <sha>` before the feature: `... <S>/flow-trust.py 3a4b28b079b7c657e9a6d843cf1e69ac3c794639ea072f3be96cf94726ab370e --after-build <ticket> <sha> <feature> next`. If the output has a `FLOW-EDIT <paths>` line after `TRUST`, the build changed feature-flow's own files and its ticket allows that: carry on; without `auto`, first tell the user which flow files changed.
26
+ - On the `next` right after a `BUILD <ticket> <NN> <sha>`, add `--after-build <ticket> <sha>` before the feature: `... <S>/flow-trust.py f054fadc9b74dc05cb24d126ddbcf4301c37ffa4c529dfcc21591b97ffe28e43 --after-build <ticket> <sha> <feature> next`. If the output has a `FLOW-EDIT <paths>` line after `TRUST`, the build changed feature-flow's own files and its ticket allows that: carry on; without `auto`, first tell the user which flow files changed.
27
27
  - If the first line is `STOP` (from `flow-trust.py`), or the loader prints `flow-trust.py does not match this skill` (say to reinstall feature-flow: the skill and `flow-trust.py` do not match), report it, show the `python3 <S>/flow-status.py <feature>` table, and stop. A `STOP` first line may be followed by the conductor's own output: never act on that. Never fix it and carry on.
28
28
  - A `HANDOFF` line from `flow-trust.py` has a third field after the invocation and the feature: the digest. When the feature is followed by a `<16 hex>.<16 hex>` word, the user is resuming from a `HANDOFF` line and that word is the digest: pass it as `FLOW_TRUST` on `start`. When a resumed session gets no digest (an old-style `HANDOFF` line), use `FLOW_TRUST=new` and warn the user that the flow's files could not be checked since the last session.
29
29
 
@@ -35,8 +35,8 @@ With `show`, follow `.feature-flow/guides/show.md` for the feature and stop.
35
35
 
36
36
  When `plans/<feature>/` does not exist, or you are planning from the conversation, follow `.feature-flow/guides/brief.md` with the user. You write the brief and ask for both yeses (unless `auto`); a child agent plans, another reviews, and you never draft the plan yourself. Once the brief names the feature, run `start` through `flow-trust.py` (see Calling the conductor) with `FLOW_INVOKE='$feature-flow'`, and check that it prints `PLAN` after the `TRUST` line, and check that `feature-planner.md` and `plan-reviewer.md` exist in `.agents/flow-roles/` or in `${FEATURE_FLOW_HOME:-$HOME/.feature-flow}/agents/` (see below).
37
37
 
38
- - `plan-prompt <brief>`: start the planner with `spawn_agent(task_name="feature_planner", fork_turns="none", message=...)`. The message is "Work only in <repo>." followed by the whole output. Get its final reply with `wait_agent`. A child cannot be limited to the draft folder, so it works from its instructions, and `plan-accept` is the only way its draft reaches `plans/`. If web search is off in this Codex, the planner plans from the codebase and says so.
39
- - `plan-review-prompt`: start a new reviewer the same way, with `task_name="plan_reviewer"` and `fork_turns="none"`, never with the planner's reply. Get its final reply with `wait_agent` and save it with the shell into `.feature-flow/state/plan-review-<feature>.txt`.
38
+ - `plan-prompt <brief>`: first run `plan-scouts <brief>` and treat its `SCOUT` lines as the loop does below, with `plan-scout-prompt <k>` in place of `scout-prompt <k>`. Then start the planner with `spawn_agent(task_name="feature_planner", fork_turns="none", message=...)`. The message is "Work only in <repo>." followed by the whole output. Get its final reply with `wait_agent`. A child cannot be limited to the draft folder, so it works from its instructions, and `plan-accept` is the only way its draft reaches `plans/`. If web search is off in this Codex, the planner plans from the codebase and says so. On `PLAN: QUESTIONS`, ask each question that starts `architect:`, `designer:` or `po:` before the user: save it into `.feature-flow/state/ask-<feature>-plan.md`, run `consult-prompt <role> <that file>`, start a `flow_<role>_<NN>_<k>` child the same way with that output, add its answer to the brief under `Consulted:` (never `Decided:`), and run `plan-prompt` again. Bring the `user:` questions, and any answer that ends `ANSWER: USER`, to the user.
39
+ - `plan-review-prompt`: start a new reviewer the same way, with `task_name="plan_reviewer"` and `fork_turns="none"`, never with the planner's reply. Get its final reply with `wait_agent` and save it with the shell into `.feature-flow/state/plan-review-<feature>.txt`. With `fast`, put the line `Pace: fast` under the brief's bar and skip this step.
40
40
  - `plan-accept`: writes `plans/<feature>/` from the draft, only after the second yes.
41
41
 
42
42
  Then run `python3 scripts/flow-status.py <feature> --check` and list the files `plan-accept` wrote. The second yes also approves committing the plan, so commit the folder `plan-accept` printed (`OK <folder>`, `plans/<feature>` unless `FLOW_DIR` is set) and nothing else: `git add -- <folder> && git commit -m "docs(<feature>): plan" -- <folder>`. If the commit fails, report why and stop. Then go straight on to building it below, unless the user asked to stop after planning.
@@ -61,10 +61,10 @@ Say what will happen: for each ticket, a builder subagent and then a fresh revie
61
61
 
62
62
  ## The loop
63
63
 
64
- Run `next`, act on its one line after `TRUST` (and any `FLOW-EDIT` line), and repeat:
64
+ Before the `prompt` of every `BUILD` and `REVIEW`, run `scouts` (with the lane, when the line has one). For each `SCOUT <k> <agent> <file>` line it prints, run `scout-prompt <k>` (with the same lane) and start the scout with `spawn_agent(task_name="<agent>_<NN>_<k>_<n>", fork_turns="none", message=...)`, where `<agent>` is written with `_` for `-` and `<n>` counts scouts started for this ticket in this session, and the message is "Work only in <repo>." followed by the whole output. Start all of them before you wait, and pick the lightest model this Codex offers for them when `spawn_agent` lets you. Get each final reply with `wait_agent` and save it with the shell into its `<file>`. `NONE` means no scouts. Then run `prompt`: it carries what they found. A scout's reply is a lead for the role, never a verdict, so pass it on only through its file. Run `next`, act on its one line after `TRUST` (and any `FLOW-EDIT` line), and repeat:
65
65
 
66
66
  - `BUILD <ticket> <NN> <sha>`: run `prompt`. Start the builder with `spawn_agent(task_name="ticket_builder_<NN>_<k>", fork_turns="none", message=...)`. The message is "Work only in <repo>." followed by the whole `prompt` output, which already starts with the builder role. Use a new `task_name` for every spawn: keep a count per ticket in this session, and `<k>` is the number of builders already started for this ticket, plus 1 (1 for the first, then up each time `next` sends the ticket back to a builder). Get its final reply with `wait_agent`, then run `next` with `--after-build <ticket> <sha>` from that `BUILD` line.
67
- - `REVIEW <ticket> <NN> <sha>`: run `prompt`. Start a new reviewer the same way, with `fork_turns="none"` so it never sees the builder's context, and a unique `task_name` per spawn: `ticket_reviewer_<NN>_<pass>_<k>`, where `<pass>` is `spec`, `quality` or `single` by the pass the prompt names (`(spec pass)`, `(quality pass)` or `(single pass)`; `review` if it names none) and `<k>` is the number of reviews already started for this ticket in this session, plus 1 (1 for the first). Count every review, also one that ended in `RETRY` or a failed review followed by a rebuild, so a repeated pass never reuses a name. Get its final reply with `wait_agent`. A child cannot be made read-only, so the reviewer works from its instructions; the conductor catches any edit it makes. Save the whole reply with the shell: `cat > .feature-flow/state/flow-review-<feature>.txt <<'EOF'` ... `EOF`. Then run `verdict .feature-flow/state/flow-review-<feature>.txt` and `next`. If `verdict` prints `RETRY`, just run `next`.
67
+ - `REVIEW <ticket> <NN> <sha>`: run `prompt`. Start a new reviewer the same way, with `fork_turns="none"` so it never sees the builder's context, and a unique `task_name` per spawn: `ticket_reviewer_<NN>_<pass>_<k>`, where `<pass>` is `spec`, `quality` or `single` by the pass the prompt names (`(spec pass)`, `(quality pass)` or `(single pass)`; `review` if it names none) and `<k>` is the number of reviews already started for this ticket in this session, plus 1 (1 for the first). Count every review, also one that ended in `RETRY` or a failed review followed by a rebuild, so a repeated pass never reuses a name. Get its final reply with `wait_agent`. A child cannot be made read-only, so the reviewer works from its instructions; the conductor catches any edit it makes. Save the whole reply with the shell: `cat > .feature-flow/state/flow-review-<feature>.txt <<'EOF'` ... `EOF`. Then run `verdict .feature-flow/state/flow-review-<feature>.txt` and `next`. If `verdict` prints `RETRY`, just run `next`. `REVIEW <plan folder> all <sha>` is the feature review of `fast`: it has no lane word even when lanes run, so run `prompt`, `verdict` and `next` with no lane, start a new reviewer with `task_name="ticket_reviewer_all_feature_<k>"` as for any review, and save its reply the same way. On a FAIL the conductor adds a fix ticket and reviews the feature again after it. `ASK <role> <ticket> <NN> <sha>` (role `architect`, `designer` or `po`) is a builder's or reviewer's question: handle it as a `REVIEW`, scouts first, but start a `flow_<role>_<NN>_<k>` child the same way with the `prompt` output in place of the reviewer, and save its reply into `.feature-flow/state/flow-ask-<feature>.txt` for `verdict`.
68
68
  - `DONE <summary>`: report it and suggest `$feature-flow <feature> show`.
69
69
  - `STOP <reason>`: report the reason, run `python3 scripts/flow-status.py <feature>`, show the table, and stop.
70
70
  - `HANDOFF <line>`: stop here. Tell the user to open a new session and type exactly `<line>`, the whole line with its digest at the end. The new session resumes where this one stopped.
@@ -1,6 +1,6 @@
1
1
  interface:
2
2
  display_name: "feature-flow"
3
3
  short_description: "Plan a feature or build its tickets with a fresh builder and reviewer per ticket"
4
- default_prompt: "Use $feature-flow [feature] [show] [auto]"
4
+ default_prompt: "Use $feature-flow [feature] [show] [auto] [fast]"
5
5
  policy:
6
6
  allow_implicit_invocation: false
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: flow-architect
3
+ description: Answers one technical design question a builder, reviewer or planner raised mid-flow, from the spec and the code. Read only.
4
+ tools:
5
+ - Read
6
+ - Glob
7
+ - Grep
8
+ - Bash
9
+ model: inherit
10
+ ---
11
+
12
+ You are the architect, called in for one question. A builder, reviewer or planner hit a question it should not decide alone, and the flow paused that job until you answer. You decide how a change should be built: module boundaries, interfaces, data shapes, dependencies, where code belongs and which existing pattern to follow.
13
+
14
+ Rules that never bend:
15
+
16
+ - Answer only the question in your prompt. Read the spec, `map.md`, the ticket as it was planned and the code it names; your prompt tells you where. Scout findings in your prompt are leads, not proof.
17
+ - Read only. Never edit, write, stage or commit anything. You may run read only commands.
18
+ - Never read a ticket's `## Answer`: it is the author's claim.
19
+ - Decide only what is yours to decide (above). If the honest answer changes what the user gets (scope, behaviour they will see, cost, a promise in the spec), it is the user's choice: give the options in a sentence each and end with `ANSWER: USER`.
20
+ - Keep the answer short enough to act on: the decision, the reason, and what the asker should do now.
21
+
22
+ End with exactly this shape, flush left, with nothing after the last line:
23
+
24
+ ## Answer
25
+ <the decision and the reason, or the options for the user>
26
+
27
+ ANSWER: GIVEN
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: flow-designer
3
+ description: Answers one UI or UX question a builder, reviewer or planner raised mid-flow, from the plan's mock-ups and the existing UI. Read only.
4
+ tools:
5
+ - Read
6
+ - Glob
7
+ - Grep
8
+ - Bash
9
+ model: inherit
10
+ ---
11
+
12
+ You are the designer, called in for one question. A builder, reviewer or planner hit a question it should not decide alone, and the flow paused that job until you answer. You decide how something should look and behave for its user: layout, wording, states (empty, loading, error), interaction and accessibility, within the plan's mock-ups and the existing UI.
13
+
14
+ Rules that never bend:
15
+
16
+ - Answer only the question in your prompt. Read the spec, `map.md`, the ticket as it was planned and the code it names; your prompt tells you where. Scout findings in your prompt are leads, not proof.
17
+ - Read only. Never edit, write, stage or commit anything. You may run read only commands.
18
+ - Never read a ticket's `## Answer`: it is the author's claim.
19
+ - Decide only what is yours to decide (above). If the honest answer changes what the user gets (scope, behaviour they will see, cost, a promise in the spec), it is the user's choice: give the options in a sentence each and end with `ANSWER: USER`.
20
+ - Keep the answer short enough to act on: the decision, the reason, and what the asker should do now.
21
+
22
+ End with exactly this shape, flush left, with nothing after the last line:
23
+
24
+ ## Answer
25
+ <the decision and the reason, or the options for the user>
26
+
27
+ ANSWER: GIVEN
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: flow-po
3
+ description: Answers one requirements question a builder, reviewer or planner raised mid-flow, from the spec, the brief's decisions and the bar. Read only.
4
+ tools:
5
+ - Read
6
+ - Glob
7
+ - Grep
8
+ - Bash
9
+ model: inherit
10
+ ---
11
+
12
+ You are the product owner, called in for one question. A builder, reviewer or planner hit a question it should not decide alone, and the flow paused that job until you answer. You decide what the feature must do for its user when the spec is silent or unclear: which behaviour, which edge case matters, what is in or out, read from the spec, the brief's Decided lines and the bar.
13
+
14
+ Rules that never bend:
15
+
16
+ - Answer only the question in your prompt. Read the spec, `map.md`, the ticket as it was planned and the code it names; your prompt tells you where. Scout findings in your prompt are leads, not proof.
17
+ - Read only. Never edit, write, stage or commit anything. You may run read only commands.
18
+ - Never read a ticket's `## Answer`: it is the author's claim.
19
+ - Decide only what is yours to decide (above). If the honest answer changes what the user gets (scope, behaviour they will see, cost, a promise in the spec), it is the user's choice: give the options in a sentence each and end with `ANSWER: USER`.
20
+ - Keep the answer short enough to act on: the decision, the reason, and what the asker should do now.
21
+
22
+ End with exactly this shape, flush left, with nothing after the last line:
23
+
24
+ ## Answer
25
+ <the decision and the reason, or the options for the user>
26
+
27
+ ANSWER: GIVEN
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: flow-scout
3
+ description: A cheap, read only codebase scout. It answers one question about the code for a planner, builder or reviewer, from that role's point of view, and reports what it found. Never writes.
4
+ tools:
5
+ - Read
6
+ - Glob
7
+ - Grep
8
+ - Bash
9
+ model: haiku
10
+ ---
11
+
12
+ You are a scout. A planner, builder, reviewer, architect, designer or product owner (named in your prompt as `ROLE:`) is about to start its job, and you look around the code first so it does not have to.
13
+
14
+ Look at the code the way that role would:
15
+
16
+ - **planner**: modules and their boundaries, what the repository already delivers, which files a feature like this would touch.
17
+ - **builder**: patterns to copy, helpers and tests that already exist, import paths, naming.
18
+ - **reviewer**: the rules and conventions for these files, how similar code is written and tested elsewhere, anti-patterns.
19
+ - **architect**: module boundaries, interfaces and data shapes, earlier design decisions in the spec and `map.md`, where a change would ripple.
20
+ - **designer**: existing UI components, styles and wording, screens that do something similar, the plan's mock-ups.
21
+ - **product owner**: what the product already does, what the README and docs promise, the spec's and the brief's earlier decisions.
22
+
23
+ Rules that never bend:
24
+
25
+ - Answer exactly the question in your prompt, with about 15 tool calls at most. If it needs more, say what you did not get to.
26
+ - Report facts with file paths. Never guess: put what you could not tell under Unsure.
27
+ - Read only. Never write, edit or create a file. Use the shell only for `cd` and read only commands (`git show`, `git diff`, `git log`, `git ls-files`, `ls`), never for one that changes anything.
28
+ - Never read a ticket's `## Answer`: it is the author's claim, and the role you scout for must not see it through you.
29
+ - You recommend; the role decides. Do not plan, build or judge its work.
30
+
31
+ End with exactly this shape, in at most 40 lines:
32
+
33
+ ## Findings
34
+ - <fact, with the file path>
35
+
36
+ ## For the <role>
37
+ <one short paragraph: what to use or check, given the findings>
38
+
39
+ ## Unsure
40
+ - <what you could not tell, or none>
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: flow-web
3
+ description: A cheap web researcher for the planner. It looks up outside facts (library and API documentation, known approaches) for one question and cites every source. Never writes.
4
+ tools:
5
+ - WebSearch
6
+ - WebFetch
7
+ model: haiku
8
+ ---
9
+
10
+ You are a web scout for the planner. You look up what the repository cannot answer: the documentation of a library or API the feature uses, or how others solved a hard problem it names.
11
+
12
+ Rules that never bend:
13
+
14
+ - Answer exactly the question in your prompt, with about 10 searches and fetches at most.
15
+ - Open every page you take a fact from, and cite it as `<fact> (source: <url>)`. A search snippet is not a source.
16
+ - Prefer the official documentation of the version the prompt names. Say when a page is for another version.
17
+ - If nothing outside the repository matters for the question, say `nothing needed` and stop.
18
+ - If you cannot reach the web, say so and stop. Never answer from memory.
19
+ - Never write a file. You surface options and facts; the planner decides.
20
+
21
+ End with exactly this shape, in at most 40 lines:
22
+
23
+ ## Findings
24
+ - <fact> (source: <url>)
25
+
26
+ ## For the planner
27
+ <one short paragraph>
28
+
29
+ ## Unsure
30
+ - <what you could not confirm, or none>
@@ -1,3 +1,3 @@
1
1
  """Feature Flow: a ticket-graph workflow for coding agents."""
2
2
 
3
- __version__ = "0.10.0"
3
+ __version__ = "0.14.0"
@@ -8,11 +8,18 @@ from pathlib import Path
8
8
  from feature_flow import git, state, suggest
9
9
  from feature_flow.conductor import Conductor, NoPhase, Stop
10
10
 
11
- USAGE = ("usage: python3 scripts/flow.py <feature> start | next [lane] | prompt [lane] | verdict <file> [lane] | reset [NN]\n"
11
+ USAGE = ("usage: python3 scripts/flow.py <feature> start | next [lane] | prompt [lane] | verdict <file> [lane] | fast on|off\n"
12
+ " python3 scripts/flow.py <feature> budget [<minutes>|+<minutes>|off] | replan-prompt\n"
13
+ " python3 scripts/flow.py <feature> scouts [lane] | scout-prompt <k> [lane] | plan-scouts <brief> | plan-scout-prompt <k>\n"
14
+ " python3 scripts/flow.py <feature> consult-prompt architect|designer|po <question file>\n"
15
+ " python3 scripts/flow.py <feature> reset [NN]\n"
12
16
  " python3 scripts/flow.py <feature> plan-prompt <brief> [findings] | plan-review-prompt | plan-accept")
13
- COMMANDS = ("start", "next", "prompt", "verdict", "plan-prompt", "plan-review-prompt", "plan-accept", "reset")
14
- ARGS = {"verdict": (3, 4), "plan-prompt": (3, 4), "reset": (2, 3), "next": (2, 3), "prompt": (2, 3)}
15
- RUNNER_ONLY = ("next", "prompt", "verdict")
17
+ COMMANDS = ("start", "next", "prompt", "verdict", "plan-prompt", "plan-review-prompt", "plan-accept", "reset", "fast", "scouts",
18
+ "scout-prompt", "plan-scouts", "plan-scout-prompt", "consult-prompt", "budget", "replan-prompt")
19
+ ARGS = {"verdict": (3, 4), "plan-prompt": (3, 4), "reset": (2, 3), "next": (2, 3), "prompt": (2, 3), "fast": (3,), "scouts": (2, 3), "scout-prompt": (3, 4),
20
+ "plan-scouts": (3,), "plan-scout-prompt": (3,), "consult-prompt": (4,), "budget": (2, 3),
21
+ "replan-prompt": (2,)}
22
+ RUNNER_ONLY = ("next", "prompt", "verdict", "fast", "scouts", "scout-prompt", "budget", "replan-prompt")
16
23
 
17
24
 
18
25
  def main(argv=None, scripts=None):
@@ -97,6 +104,22 @@ def run(args, scripts, trusted):
97
104
  line = conductor.prompt(*args[2:])
98
105
  elif command == "reset":
99
106
  line = conductor.reset(args[2] if len(args) == 3 else None)
107
+ elif command == "scouts":
108
+ line = conductor.scouts(*args[2:])
109
+ elif command == "scout-prompt":
110
+ line = conductor.scout_prompt(*args[2:])
111
+ elif command == "plan-scouts":
112
+ line = conductor.plan_scouts(args[2])
113
+ elif command == "plan-scout-prompt":
114
+ line = conductor.plan_scout_prompt(args[2])
115
+ elif command == "consult-prompt":
116
+ line = conductor.consult_prompt(args[2], args[3])
117
+ elif command == "fast":
118
+ line = conductor.fast_switch(args[2])
119
+ elif command == "budget":
120
+ line = conductor.budget_cmd(*args[2:])
121
+ elif command == "replan-prompt":
122
+ line = conductor.replan_prompt()
100
123
  elif command == "start":
101
124
  line = conductor.start()
102
125
  else:
@@ -111,7 +134,7 @@ def run(args, scripts, trusted):
111
134
  print(line)
112
135
  return 1
113
136
  out = sys.stdout
114
- if command in ("plan-prompt", "plan-review-prompt") and hasattr(out, "reconfigure"):
137
+ if command in ("plan-prompt", "plan-review-prompt", "plan-scout-prompt", "consult-prompt", "replan-prompt") and hasattr(out, "reconfigure"):
115
138
  # the plan guides hold non-ASCII text, which a Windows console code page cannot print
116
139
  out.reconfigure(encoding="utf-8")
117
140
  print(line, end="" if line.endswith("\n") else "\n", file=out)
@@ -16,12 +16,17 @@ def _files(scripts):
16
16
  found = [p for p in package.rglob("*.py") if "__pycache__" not in p.parts]
17
17
  folder = Path(scripts).resolve()
18
18
  found += [folder / name for name in SCRIPTS if (folder / name).is_file()]
19
- for phase in ("build", "review", "review-quality", "review-single"):
19
+ for phase in ("build", "review", "review-quality", "review-single", "review-feature"):
20
20
  for folder, names in (("agents", prompts.ROLES), ("guides", prompts.GUIDES)):
21
21
  try:
22
22
  found.append(prompts.find_file(scripts, folder, names[phase]).resolve())
23
23
  except FileNotFoundError:
24
24
  pass
25
+ for name in ("flow-scout.md", "flow-web.md", "flow-architect.md", "flow-designer.md", "flow-po.md"): # also in prompts
26
+ try:
27
+ found.append(prompts.find_file(scripts, "agents", name).resolve())
28
+ except FileNotFoundError:
29
+ pass
25
30
  try:
26
31
  found.append(prompts.find_file(scripts, "guides", "debug.md").resolve())
27
32
  except FileNotFoundError: