flow-workflows 0.94.1 → 0.95.1

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 (48) hide show
  1. package/adapters/codex/CORE.md +29 -11
  2. package/adapters/codex/skills/flow-bug-investigate/SKILL.md +3 -3
  3. package/adapters/codex/skills/flow-bug-start/SKILL.md +6 -3
  4. package/adapters/codex/skills/flow-bug-validate/SKILL.md +1 -1
  5. package/adapters/codex/skills/flow-feat-design/SKILL.md +3 -3
  6. package/adapters/codex/skills/flow-feat-plan/SKILL.md +3 -3
  7. package/adapters/codex/skills/flow-feat-review/SKILL.md +1 -1
  8. package/adapters/codex/skills/flow-feat-start/SKILL.md +6 -3
  9. package/adapters/codex/skills/flow-feat-validate/SKILL.md +1 -1
  10. package/adapters/codex/skills/flow-work-README/SKILL.md +1 -1
  11. package/adapters/codex/skills/flow-work-resume/SKILL.md +1 -1
  12. package/adapters/gemini/CORE.md +29 -11
  13. package/adapters/gemini/commands/flow/bug/investigate.toml +3 -3
  14. package/adapters/gemini/commands/flow/bug/start.toml +6 -3
  15. package/adapters/gemini/commands/flow/bug/validate.toml +1 -1
  16. package/adapters/gemini/commands/flow/feat/design.toml +3 -3
  17. package/adapters/gemini/commands/flow/feat/plan.toml +3 -3
  18. package/adapters/gemini/commands/flow/feat/review.toml +1 -1
  19. package/adapters/gemini/commands/flow/feat/start.toml +6 -3
  20. package/adapters/gemini/commands/flow/feat/validate.toml +1 -1
  21. package/adapters/gemini/commands/flow/work/README.toml +1 -1
  22. package/adapters/gemini/commands/flow/work/resume.toml +1 -1
  23. package/adapters/hermes/CORE.md +29 -11
  24. package/adapters/hermes/skills/flow-bug-investigate/SKILL.md +3 -3
  25. package/adapters/hermes/skills/flow-bug-start/SKILL.md +6 -3
  26. package/adapters/hermes/skills/flow-bug-validate/SKILL.md +1 -1
  27. package/adapters/hermes/skills/flow-feat-design/SKILL.md +3 -3
  28. package/adapters/hermes/skills/flow-feat-plan/SKILL.md +3 -3
  29. package/adapters/hermes/skills/flow-feat-review/SKILL.md +1 -1
  30. package/adapters/hermes/skills/flow-feat-start/SKILL.md +6 -3
  31. package/adapters/hermes/skills/flow-feat-validate/SKILL.md +1 -1
  32. package/adapters/hermes/skills/flow-work-README/SKILL.md +1 -1
  33. package/adapters/hermes/skills/flow-work-resume/SKILL.md +1 -1
  34. package/adapters/opencode/CORE.md +29 -11
  35. package/adapters/opencode/commands/flow-bug-investigate.md +3 -3
  36. package/adapters/opencode/commands/flow-bug-start.md +6 -3
  37. package/adapters/opencode/commands/flow-bug-validate.md +1 -1
  38. package/adapters/opencode/commands/flow-feat-design.md +3 -3
  39. package/adapters/opencode/commands/flow-feat-plan.md +3 -3
  40. package/adapters/opencode/commands/flow-feat-review.md +1 -1
  41. package/adapters/opencode/commands/flow-feat-start.md +6 -3
  42. package/adapters/opencode/commands/flow-feat-validate.md +1 -1
  43. package/adapters/opencode/commands/flow-work-README.md +1 -1
  44. package/adapters/opencode/commands/flow-work-resume.md +1 -1
  45. package/package.json +1 -1
  46. package/plugins/flow/.claude-plugin/plugin.json +1 -1
  47. package/plugins/flow/CHANGELOG.md +32 -0
  48. package/plugins/flow/examples/FLOW.template.md +1 -1
@@ -17,7 +17,7 @@ Every `$flow-*` command assumes these rules. They are stated once, here, so a co
17
17
  carries what is specific to its phase. Read this once per session; a command that says "load
18
18
  `flow-core`" means this file.
19
19
 
20
- **This file belongs to flow `0.94.1`.** Compare it once, at the start of the session, against
20
+ **This file belongs to flow `0.95.1`.** Compare it once, at the start of the session, against
21
21
  `version` in `~/.claude/flow/.claude-plugin/plugin.json`. The two differing means the session
22
22
  is running a **mixture** — the commands from one copy of the plugin, these shared rules from another
23
23
  — which is exactly what happens when a branch or a release candidate is loaded over an installed
@@ -249,16 +249,18 @@ sensible default and record it.
249
249
 
250
250
  Asking these anyway is how a run in `guided`/`auto` degrades into a manual one.
251
251
 
252
- **A study made for handoff.** `git.handoff_branch` set and the mode not `unattended` → the study is
253
- built somewhere else, so wherever a study phase (`start`, `design`, `plan`, `investigate`) or
254
- `resume` would hand the work to `$flow-feat-build` or `$flow-bug-fix`, it hands it to
255
- `$flow-work-handoff` instead. Only the target changes: a Close that asks (`manual`) offers **Hand
252
+ **A study made for handoff.** A work started with `--study` (`$flow-feat-start`,
253
+ `$flow-bug-start`) records `meta.json.handoff: true`: it is studied here and built somewhere else.
254
+ That field set and the mode not `unattended` → wherever a study phase (`start`, `design`, `plan`,
255
+ `investigate`) or `resume` would hand the work to `$flow-feat-build` or `$flow-bug-fix`, it hands it
256
+ to `$flow-work-handoff` instead. Only the target changes: a Close that asks (`manual`) offers **Hand
256
257
  off the study** recommended and **Build here** second; a Close that chains (`guided`/`auto`) chains
257
- into handoff, whose push question is the one confirmation — no stop is added. In `unattended` the
258
- rule does not apply: the repo's `FLOW.md` reaches the server too, and a run that studies a ticket
259
- there goes on to build it — unless the orchestrator launched it as a study run (§2.1), which stops
260
- at the door to code. A repo that hands its studies off pairs the key with
261
- `autonomy.mode: auto`, and the study then runs on its own up to the push.
258
+ into handoff, whose push question is the one confirmation — no stop is added. A work started without
259
+ `--study` is built here, whatever `git.handoff_branch` says: the key only names where a study is
260
+ pushed, so one repo can hold both kinds of work. In `unattended` the rule does not apply: a run that
261
+ studies a ticket there goes on to build it — unless the orchestrator launched it as a study run
262
+ (§2.1), which stops at the door to code. With `autonomy.mode: auto`, a `--study` work runs on its
263
+ own up to the push.
262
264
 
263
265
  ### 2.1 `unattended` — where a person would have been asked
264
266
 
@@ -392,6 +394,7 @@ person asking for changes, a ticket that already has code — is `$flow-work-run
392
394
  | An approved study's branch (`run`, `why = start`, no build or fix begun) | record — fast-forwarded to its base when it holds no commit of its own (`$flow-work-run` §2); the base unreadable or the fast-forward failing → blocked. Not integrating: nothing of the run's is merged |
393
395
  | Integrating the base into the MR/PR's branch (`green`) | on `why = conflict`, record — `git merge origin/<base>` as the orchestrator left it, never rebase, each conflict resolved on its merits (`$flow-work-green` §5.C); on any other `why`, blocked — the orchestrator brings the base in |
394
396
  | Any offer about the work's own bookkeeping — a tracker issue, the first `KNOWLEDGE.md` or a knowledge save, a FLOW convention, an agent lesson or a saved specialist, the follow-up survey, carrying files over from the main checkout, a contract handoff, archiving the work | record — `Later`; nothing written outside the work folder |
397
+ | A wait — a suite, a quality gate, anything run in the background (`validate`, `review`) | in the turn, on its condition, with a deadline (§6.5) — never a supervisor, never a fixed-length sleep, never ending the turn to be woken |
395
398
  | A step the command cannot complete (a red suite it cannot fix, a tool missing, auth failing, the same check failing a second time) | blocked |
396
399
  | Anything `auto` already decides on its own (size, flow mechanics, WIP commits, the next command) | as `auto` |
397
400
 
@@ -800,7 +803,7 @@ merge now. Delegating that judgement is how a pipeline ends up declared green by
800
803
  cheapest to ask, which is the one thing `$flow-work-green` exists to forbid. Delegate the waiting
801
804
  and the evidence; the verdict stays here.
802
805
 
803
- **Then end the turn.** Dispatching a supervisor and staying in a poll loop of your own pays both
806
+ **Then end the turn** — except in `unattended`, below. Dispatching a supervisor and staying in a poll loop of your own pays both
804
807
  bills and saves nothing. What wakes you is whatever the harness offers — a background task that
805
808
  re-invokes you when it finishes, a scheduled wake-up, a message back to this thread; where it offers
806
809
  none, the supervisor's evidence file is read at your next stop, and **you say that** rather than
@@ -817,6 +820,21 @@ moving.
817
820
  than to run — the brief, the round trip and the report are the whole of the saving. And anything you
818
821
  must *react to* mid-wait is not a wait at all: it is the work, and it stays here.
819
822
 
823
+ **In `unattended`, the wait stays in the turn** (§2.1). Nobody can bring back a run whose turn
824
+ ended, and whether a headless harness re-invokes a run when its background task finishes is not
825
+ something the run can count on. So no supervisor and no ending the turn: the wait is sat through
826
+ here, on the condition it waits for, with a deadline —
827
+
828
+ - **In the foreground**, when the command fits the harness's own limit for one call.
829
+ - **Otherwise launched with its exit code written to a file**, then waited on by a loop that checks
830
+ for that file every few seconds and stops at the deadline — one tool call per stretch, each under
831
+ that same limit, repeated until the file appears or the deadline passes. The loop runs inside the
832
+ call, so its cycles cost nothing on this thread.
833
+ - **Never a fixed-length sleep.** A guessed duration pays the whole sleep when the suite finished in
834
+ a fraction of it, and wakes before the suite when the guess is short.
835
+
836
+ The deadline reached with nothing back → `blocked`, naming the command and how long it ran.
837
+
820
838
  ### 6.6 — Which agent a role resolves to
821
839
 
822
840
  **The harness already tells you which agents are installed**, each with a line on what it is for,
@@ -36,7 +36,7 @@ Read `~/.claude/flow/CORE.codex.md` first (shared rules: `FLOW.md` step 0, model
36
36
  **In `unattended`, before this phase's first step, read flow-core §2.1 whole — from its heading to the next section, unless it is already in your context whole; having read parts of it does not count** — the orchestrator command, the question stop and the way its answer comes back are all in it, and a phase that reads only part of it skips them.
37
37
 
38
38
  - Read `meta.json` and `00-summary.md`; open in full only `01-context.md`. (flow-core §5)
39
- - `type` is not `bug` → refuse. `size` is `XS` → suggest `$flow-bug-fix` — `git.handoff_branch` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff) — and stop.
39
+ - `type` is not `bug` → refuse. `size` is `XS` → suggest `$flow-bug-fix` — `meta.json.handoff` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff) — and stop.
40
40
  - Require `context` in `phases_done`.
41
41
 
42
42
  ## 1.5 Reproduce — what is failing, before why
@@ -232,5 +232,5 @@ If `knowledge.stage` is set and the root cause reveals a **non-obvious "why"** a
232
232
 
233
233
  - Update `meta.json`: `phase = "investigate"`, add to `phases_done`.
234
234
  - Overwrite `00-summary.md` whole (≤15 lines, flow-core §5).
235
- - Suggest `$flow-bug-fix` — `git.handoff_branch` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
236
- - **Autonomy handoff** (`autonomy.mode`, flow-core §2): `manual` → propose `$flow-bug-fix` with a single `AskUserQuestion`, invoke it only on confirmation; `guided`/`auto` → chain into it in this same turn. Either way: `git.handoff_branch` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
235
+ - Suggest `$flow-bug-fix` — `meta.json.handoff` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
236
+ - **Autonomy handoff** (`autonomy.mode`, flow-core §2): `manual` → propose `$flow-bug-fix` with a single `AskUserQuestion`, invoke it only on confirmation; `guided`/`auto` → chain into it in this same turn. Either way: `meta.json.handoff` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
@@ -22,12 +22,13 @@ Start a bug. `$ARGUMENTS` is **optional**:
22
22
 
23
23
  - **Given** — a ticket (format `tracker.prefix` from FLOW.md) → *ticket mode*: start from it (§1 reads it).
24
24
  - **Empty** — *ticket-less mode*: do **not** stop. Synthesize the bug from the conversation just held with the user (§1.5). Ask for a one-line symptom only if there is no conversation to draft from.
25
+ - **`--study`**, anywhere in `$ARGUMENTS` — a flag, not part of the identifier: take it out before deciding the mode. The bug is studied here and fixed somewhere else: §4 records `meta.json.handoff: true`, and the study ends at `$flow-work-handoff` instead of `fix` (flow-core §2, a study made for handoff). `git.handoff_branch` empty → say in one line that `--study` needs that key, and go on as a work fixed here. Without the flag the bug is fixed here, whatever `git.handoff_branch` says.
25
26
 
26
27
  **In `unattended`** (flow-core §2.1) this command asks nothing; each place it would ask resolves as
27
28
  that table says. Here: **the ticket is `<cmd> ticket --json`**, not the tracker — `number` is the
28
29
  identifier, `title` and `body` replace §1's tracker read, and its `comments` (already limited to
29
30
  authorised authors) are the whole thread of §1.1; `$ARGUMENTS` that disagrees with `number` is
30
- ignored and named. The order failing or empty → `blocked` · **the base is the ticket's `base`**
31
+ ignored and named, and `--study` is ignored (the orchestrator says why it launched the run). The order failing or empty → `blocked` · **the base is the ticket's `base`**
31
32
  (empty → `git.default_base`), recorded as `meta.json.base` — the branch of §3 starts there, and asks
32
33
  nothing · uncommitted changes, or a checkout not on that base → `blocked`: the orchestrator owns the
33
34
  checkout · the branch is named `<number>-<slug>` whatever `git.branch_pattern` says · cross-repo
@@ -47,7 +48,7 @@ Read `~/.claude/flow/CORE.codex.md` first (shared rules: `FLOW.md` step 0, model
47
48
  **In `unattended`, before this phase's first step, read flow-core §2.1 whole — from its heading to the next section, unless it is already in your context whole; having read parts of it does not count** — the orchestrator command, the question stop and the way its answer comes back are all in it, and a phase that reads only part of it skips them.
48
49
 
49
50
  - Verify you are in the correct repo.
50
- - **Determine the mode** from `$ARGUMENTS`: non-empty → *ticket mode* (identifier = `$ARGUMENTS`); empty → *ticket-less mode* (identifier = the slug resolved in §1.5).
51
+ - **Determine the mode** from `$ARGUMENTS` (`--study` already taken out): non-empty → *ticket mode* (identifier = `$ARGUMENTS`); empty → *ticket-less mode* (identifier = the slug resolved in §1.5).
51
52
  - Once the identifier is known, check whether the work already exists: ticket mode → glob `.claude/work/<TICKET>/` and `.claude/work/<TICKET>-*/` for a `meta.json` whose `ticket` equals `<TICKET>`; ticket-less → `.claude/work/<slug>/meta.json`, right after §1.5.2 decides the slug. If one exists, suggest `$flow-work-resume`.
52
53
  - This command **creates** `00-summary.md` (§4); there is nothing to read yet.
53
54
 
@@ -185,6 +186,8 @@ Create the work directory per §0: `.claude/work/<TICKET>-<slug>/` in ticket mod
185
186
 
186
187
  In `unattended`, add `"base"`: the ticket's `base`, or `git.default_base` when it is empty — never empty; the branch the fix starts from and targets. Omit it in every other mode.
187
188
 
189
+ Add `"handoff": true` only when `--study` was given and `git.handoff_branch` is set; omit it otherwise.
190
+
188
191
  Populate `related_repos` from §1.6 — one `{ "repo": "<name>", "scope": "<one line>", "status": "pending", "contract_handoff": "pending" | "none" }` per *other* repo the fix touches; `[]` for a single-repo fix. `pending` only when the fix **changes a surface that sibling consumes** (a payload key, an error code, a route, an event shape); otherwise `none`.
189
192
 
190
193
  **This fix *is* an accepted follow-up** (the ticket came from another work's `followups[]` — typically a prevention action or a neighbouring bug, flow-core §7) → set `origin: { "work": "<originating work dir>", "followup": "F<n>" }`, carry that entry's recorded `why` into `01-context.md` verbatim rather than re-deriving it, and move the originating entry to `in_progress` with `work` naming this folder. Not a follow-up → omit `origin`.
@@ -228,6 +231,6 @@ Run `tracker.start_cmd` with `{TICKET}` = `meta.json.ticket` and `{ASSIGNEE}` =
228
231
 
229
232
  ## 5. Close
230
233
 
231
- - Suggest the next command by size: `$flow-bug-fix` for XS (`git.handoff_branch` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff)), `$flow-bug-investigate` for the rest.
234
+ - Suggest the next command by size: `$flow-bug-fix` for XS (`meta.json.handoff` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff)), `$flow-bug-investigate` for the rest.
232
235
  - Overwrite `00-summary.md` whole (≤15 lines, flow-core §5).
233
236
  - Apply `autonomy.mode`: `manual` stops and recommends; `guided`/`auto` chain into that command automatically, subject to the hard gates.
@@ -41,7 +41,7 @@ Read `~/.claude/flow/CORE.codex.md` first (shared rules: `FLOW.md` step 0, model
41
41
 
42
42
  Then:
43
43
  1. Run only that test with `quality.test_one` from FLOW.md; it must pass.
44
- 2. Run the full suite with `quality.test` to rule out collateral regressions (in the background if slow; measured in tens of minutes → delegate it as a wait to a supervisor subagent on `models.supervisors`, flow-core §6.5 — it returns the exit code and the failing output, and the reading of them stays here).
44
+ 2. Run the full suite with `quality.test` to rule out collateral regressions (in the background if slow — in `unattended`, waited on in this turn, flow-core §6.5; otherwise, measured in tens of minutes → delegate it as a wait to a supervisor subagent on `models.supervisors`, flow-core §6.5 — it returns the exit code and the failing output, and the reading of them stays here).
45
45
  3. DB touched → verify the schema has no unexpected differences (`quality.db_update` or the FLOW.md equivalent, if defined; in `unattended` it is never run without an answer — a schema difference to apply is question
46
46
  `migration`, flow-core §2.1; the orchestrator's *Apply it* relaunches this phase, this site takes the
47
47
  answer just applied and runs it, and `05-validation.md` names that answer beside the migration).
@@ -40,7 +40,7 @@ after writing each challenge's Response.
40
40
 
41
41
  - Load `meta.json` by current branch — in `unattended`, the work `$flow-work-run` found (flow-core §2.1). Missing → ask the user to start with `$flow-feat-start`.
42
42
  - Read `meta.json` and `00-summary.md`; open in full only `01-context.md` (ticket, decisions, contracts received). (flow-core §5)
43
- - `size` is `XS` → suggest jumping to `$flow-feat-build` — `git.handoff_branch` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff) — and stop unless the user insists.
43
+ - `size` is `XS` → suggest jumping to `$flow-feat-build` — `meta.json.handoff` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff) — and stop unless the user insists.
44
44
 
45
45
  ## 1.5 Approaches — open the option space first (M/L)
46
46
 
@@ -438,6 +438,6 @@ Never invoke `knowledge.save` here — the final save is in `$flow-feat-ship` af
438
438
  - **Confirm the acceptance criteria** within the design review: present the enumerated list. If every criterion is unambiguous and verifiable, the review covers them — no separate prompt. `AskUserQuestion` **only** when a criterion is ambiguous, not verifiable, or one is likely missing for today's ticket (same restraint as the challenger). Apply the user's edits to `03-design.md` before advancing.
439
439
  - **In `manual`/`guided`**, ask the user to review the design; edit the artifact on requested changes before advancing. **In `auto`, do not ask** — record it as accepted per the handoff below. Not an unconditional stop.
440
440
  - Next step by size:
441
- - **XS / S**: suggest `$flow-feat-build` (1 single MR/PR, no planned split) — `git.handoff_branch` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
441
+ - **XS / S**: suggest `$flow-feat-build` (1 single MR/PR, no planned split) — `meta.json.handoff` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
442
442
  - **M / L**: suggest `$flow-feat-plan` to split the work into independently mergeable MRs/PRs before implementing.
443
- - **Autonomy handoff.** Design review is a genuine decision point: `manual` and `guided` ask for it before advancing. `auto` records the design as accepted in the artifact and **chains into the command for the size** in this same turn — `build` there: `git.handoff_branch` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff). `manual` proposes that command with a single `AskUserQuestion` (recommended option by default), never a written suggestion. Unresolved `high`-severity findings (§6) stop the flow in **every** mode — do not chain over them.
443
+ - **Autonomy handoff.** Design review is a genuine decision point: `manual` and `guided` ask for it before advancing. `auto` records the design as accepted in the artifact and **chains into the command for the size** in this same turn — `build` there: `meta.json.handoff` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff). `manual` proposes that command with a single `AskUserQuestion` (recommended option by default), never a written suggestion. Unresolved `high`-severity findings (§6) stop the flow in **every** mode — do not chain over them.
@@ -31,7 +31,7 @@ Delivery planning phase. **No code is written.** Splits the feature into MRs/PRs
31
31
  - Load `meta.json` by current branch — in `unattended`, the work `$flow-work-run` found (flow-core §2.1). Missing → send the user to `$flow-feat-start`.
32
32
  - Require `design` in `phases_done`. Missing → send to `$flow-feat-design` and stop.
33
33
  - Read `meta.json` and `00-summary.md`; open in full only `03-design.md` — and, when `01-context.md` has `## Study revisions` (a person's reply to an unattended study, flow-core §2.1), that section too: a request about the split is applied here, and goes into §2's brief. (flow-core §5)
34
- - **`size` `XS` or `S`** → warn that this phase does not apply (always 1 MR/PR), add `"plan:skipped"` to `phases_done`, suggest `$flow-feat-build` — `git.handoff_branch` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff). Stop.
34
+ - **`size` `XS` or `S`** → warn that this phase does not apply (always 1 MR/PR), add `"plan:skipped"` to `phases_done`, suggest `$flow-feat-build` — `meta.json.handoff` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff). Stop.
35
35
 
36
36
  ## 2. Work
37
37
 
@@ -166,5 +166,5 @@ A slice landing in **another repo** is not one of *this* repo's `mrs`: record it
166
166
 
167
167
  `∥` = no dependency between them, can be built in parallel or as a train; `→` = the next wave waits for the previous one to merge. Then the table with `#`, wave, `depends_on`, title and estimate. One line for the split rationale, and — when any pair was merged — one line saying how many were and what they would have cost (`merged #a into #b: would have been a wave of its own`). Nothing else — risks and discarded alternatives live in the artifact.
168
168
  - Changes requested → edit the artifact and `meta.json.mrs` before advancing.
169
- - Suggest `$flow-feat-build` to start the first MR/PR — `git.handoff_branch` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
170
- - **Autonomy handoff.** Approving the split is a genuine decision point: in `manual` and `guided` ask before advancing. In `auto`, record the plan as accepted in `04-mr-plan.md` and **chain into `$flow-feat-build` automatically** in this same turn. In `manual`, propose it with a single `AskUserQuestion`. Either way: `git.handoff_branch` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
169
+ - Suggest `$flow-feat-build` to start the first MR/PR — `meta.json.handoff` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
170
+ - **Autonomy handoff.** Approving the split is a genuine decision point: in `manual` and `guided` ask before advancing. In `auto`, record the plan as accepted in `04-mr-plan.md` and **chain into `$flow-feat-build` automatically** in this same turn. In `manual`, propose it with a single `AskUserQuestion`. Either way: `meta.json.handoff` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
@@ -302,7 +302,7 @@ Not run for XS/S, small diffs, or fewer than 4 ambiguous findings. When skipped,
302
302
 
303
303
  Read `quality.*` from `FLOW.md`. Empty → auto-discover equivalent commands (Makefile, npm/composer scripts, Gradle, dotnet, Xcode, Flutter…) and note what you use.
304
304
 
305
- Launch in parallel (background if slow):
305
+ Launch in parallel (background if slow; in `unattended`, waited on in this turn, flow-core §6.5):
306
306
  - `quality.style_fix`
307
307
  - `quality.static_analysis`
308
308
  - `quality.test_one` (if there are new tests, with the appropriate filter)
@@ -28,12 +28,14 @@ Read `~/.claude/flow/CORE.codex.md` first (shared rules: `FLOW.md` step 0, model
28
28
 
29
29
  - **Given** — an identifier in `tracker.prefix` format from `FLOW.md` → *ticket mode* (§2 reads it).
30
30
  - **Empty** — *ticket-less mode*: do **not** stop or demand a ticket. Draft a ticket from the conversation just held (§2.5), as `$flow-feat-ship` builds the MR/PR body from the work log. Ask for a one-liner only if there is no conversation to draft from.
31
+ - **`--study`**, anywhere in `$ARGUMENTS` — a flag, not part of the identifier: take it out before deciding the mode. The work is studied here and built somewhere else: §6 records `meta.json.handoff: true`, and the study ends at `$flow-work-handoff` instead of `build` (flow-core §2, a study made for handoff). `git.handoff_branch` empty → say in one line that `--study` needs that key, and go on as a work built here. Without the flag the work is built here, whatever `git.handoff_branch` says.
31
32
 
32
33
  **In `unattended`** (flow-core §2.1) this command asks nothing; each place it would ask resolves as
33
34
  that table says. Here: **the ticket is `<cmd> ticket --json`**, not the tracker — `number` is the
34
35
  identifier, `title` and `body` replace §2's tracker read, and its `comments` (already limited to
35
36
  authorised authors) are the whole thread of §2.1, read as that section says; `$ARGUMENTS` that
36
- disagrees with `number` is ignored and named. The order failing or empty → `blocked` (there is no
37
+ disagrees with `number` is ignored and named, and `--study` is ignored (the orchestrator says why it
38
+ launched the run). The order failing or empty → `blocked` (there is no
37
39
  conversation to draft from and nobody to paste it) · **the base is the ticket's `base`** (empty →
38
40
  `git.default_base`), recorded as `meta.json.base` — the branch of §5.2 starts there, never from
39
41
  where the checkout stands, and §5.1 asks nothing · uncommitted changes, or a checkout not on that
@@ -53,7 +55,7 @@ its reason file in a `mktemp -d` directory (flow-core §2.1).
53
55
  - Read the effective FLOW configuration per flow-core §0; no FLOW layer present → each
54
56
  step's default. This command **creates** `00-summary.md` (§6) instead of reading it (flow-core §5).
55
57
  - No recognizable project structure → warn and stop.
56
- - **Determine the mode**: `$ARGUMENTS` non-empty → *ticket mode* (identifier = `$ARGUMENTS`); empty → *ticket-less* (identifier = the §2.5 slug).
58
+ - **Determine the mode** (`--study` already taken out): `$ARGUMENTS` non-empty → *ticket mode* (identifier = `$ARGUMENTS`); empty → *ticket-less* (identifier = the §2.5 slug).
57
59
  - Once the identifier is known, check the work does not exist: ticket mode → glob `.claude/work/<TICKET>/` and `.claude/work/<TICKET>-*/` for a `meta.json` whose `ticket` equals `<TICKET>`; ticket-less → `.claude/work/<slug>/meta.json`, right after the slug is decided in §2.5. Exists → do not overwrite; warn and suggest `$flow-work-resume`.
58
60
 
59
61
  **Work directory naming.** Work lives in `.claude/work/<work-dir>/`. `meta.json.ticket` stays the **pure identifier** (real ticket id, or the slug in ticket-less local-only) — it feeds the tracker view, the issue link and `{TICKET}`. The directory adds a slug:
@@ -254,6 +256,7 @@ Create the work directory per §1: `.claude/work/<TICKET>-<slug>/` (ticket mode)
254
256
  }
255
257
  ```
256
258
 
259
+ - `handoff` — `true` only when `--study` was given and `git.handoff_branch` is set; omit it otherwise.
257
260
  - Ticket-less (§2.5) → `draft_from_conversation: true`, `tracker_issue` = created issue id/url (or `null` if local-only). Ticket mode → defaults above.
258
261
  - `base` — `unattended` only: the ticket's `base`, or `git.default_base` when it is empty — never empty (the branch every MR/PR of this work starts from and targets; `$flow-work-run` refreshes it on `merged`). Omit it in every other mode.
259
262
  - `related_repos` from §3.5 — one `{ "repo": "<name>", "scope": "<one line>", "status": "pending", "contract_handoff": "pending" | "none" }` per *other* repo; `[]` for a single-repo task.
@@ -309,5 +312,5 @@ Run `tracker.start_cmd` with `{TICKET}` = `meta.json.ticket`, `{ASSIGNEE}` = `tr
309
312
  ## 7. Close
310
313
 
311
314
  - Overwrite `00-summary.md` whole (≤15 lines, flow-core §5) — first written in §6; refresh it if §6.5 changed anything.
312
- - Report **following the stop header** (flow-core §3), branch added, body 2-3 lines: ticket, size, branch; recommended next command per the §4 table (`build` on XS: `git.handoff_branch` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff)) — in `guided`/`auto` you run it in this same turn, so there is no report and no question here: update the panel and chain (flow-core §3).
315
+ - Report **following the stop header** (flow-core §3), branch added, body 2-3 lines: ticket, size, branch; recommended next command per the §4 table (`build` on XS: `meta.json.handoff` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff)) — in `guided`/`auto` you run it in this same turn, so there is no report and no question here: update the panel and chain (flow-core §3).
313
316
  - Apply `autonomy.mode`: `manual` → stop and let the user invoke the recommended command; `guided`/`auto` → chain into it, subject to the hard gates (the §5 branch-base ambiguity already stops on its own).
@@ -46,7 +46,7 @@ One of the three below writes and two of them read, so they do not all go at onc
46
46
 
47
47
  **A green suite is not a performance result** — a tiny fixture database proves a query's **rows**, never its **plan**. If `$flow-feat-review §3.6` left any query verdict `unresolved`, or an acceptance criterion concerns speed or volume: run the measurement of **`$flow-work-query §4`** with the volumes in `data.volumes` (or a data set shaped like them — the distribution matters more than the total), record plan and timings, and gate on the result. No `data.*` configuration and the criterion cannot be measured → it is `unproven` with the reason, never silently `proven`.
48
48
 
49
- 3. **Full suite**: run `quality.test` from `FLOW.md` in the background; if empty, auto-discover the project's test command and note what you use. **A suite measured in tens of minutes is a wait, not a step**: hand it to a supervisor subagent on `models.supervisors` (flow-core §6.5) — it runs it, times out, and brings back the exit code plus the failing tests' output, never a reading of whether those failures matter. Short suites stay here; delegating ninety seconds costs more than running them. A repo with more than one suite chains them in that one key (`make test && make test-frontend`); when it does not and the diff touches a suite the key misses, run that one too and say so in one line.
49
+ 3. **Full suite**: run `quality.test` from `FLOW.md` in the background (in `unattended`, waited on in this turn, flow-core §6.5); if empty, auto-discover the project's test command and note what you use. **A suite measured in tens of minutes is a wait, not a step**: hand it to a supervisor subagent on `models.supervisors` (flow-core §6.5) — it runs it, times out, and brings back the exit code plus the failing tests' output, never a reading of whether those failures matter. Short suites stay here; delegating ninety seconds costs more than running them. A repo with more than one suite chains them in that one key (`make test && make test-frontend`); when it does not and the diff touches a suite the key misses, run that one too and say so in one line.
50
50
 
51
51
  ## 3. Criteria coverage (S and larger)
52
52
 
@@ -256,7 +256,7 @@ Two signals arrive on an open MR/PR, each with its own cross-cutting loop (feat
256
256
  - `$flow-work-daily [question]` — the **work assistant** (daily standup), read-only. **Local** (`.claude/work/` + git) + **forge** (open MRs/PRs, reviews awaiting you, red CI, unmergeable, unresolved threads via `git.cli`) + **tracker** (assigned tickets, priority changes via `tracker.tool`); where they cross, concrete commands (`$flow-feat-start`, `$flow-work-green`, `$flow-work-respond`). No argument → *yesterday · today · blockers*; a question → just that. External sources best-effort, never blocking; the only write is a "last seen" marker, like `$flow-news`.
257
257
  - `$flow-work-status` — all works in `.claude/work/`, current phase, divergence with git.
258
258
  - `$flow-work-run [ticket]` — the **entry an orchestrator launches** for an `unattended` run: asks it `why` (start · study · answer · merged · review · pipeline), routes to the phase that answers it — a `study` run stops at the door to code with a summary for a person to approve — and makes no decision of its own. Refuses to run in any other mode.
259
- - `$flow-work-handoff` — hands a **finished study** to whoever builds it elsewhere (an unattended server, another machine): refuses an unfinished one, pushes only this work's folder as a parentless commit to `git.handoff_branch` without touching the checkout, asks before the push, then offers a marked summary for the ticket body (`tracker.edit_cmd`).
259
+ - `$flow-work-handoff` — hands a **finished study** to whoever builds it elsewhere (an unattended server, another machine): refuses an unfinished one, pushes only this work's folder as a parentless commit to `git.handoff_branch` without touching the checkout, asks before the push, then offers a marked summary for the ticket body (`tracker.edit_cmd`). A work started with `$flow-feat-start --study` (or `$flow-bug-start --study`) ends its study here on its own; one started without the flag is built here, even with the key set.
260
260
  - `$flow-work-resume` — detects the branch, reads `meta.json`, recaps, suggests the next step. **Re-reads the ticket's comment thread** (§2.5), reports only what is new since `01-context.md`, appends it to the artifact; never amends the design on its own.
261
261
  - `$flow-work-try <branch>` / `$flow-work-try --back` — point the main checkout at a branch to test it here, then return; re-syncs per `git.worktree_resync`. Resolves the work behind the branch and, once the environment is up, **prints the manual test plan already written** (the `needs-manual`/`unproven` criteria, or the acceptance criteria when `validate` has not run) and offers to collect Pass/Fail/Blocked into the validation artifact. No work behind the branch → the plain switch, as before.
262
262
  - `$flow-work-clean [--dry-run]` — **periodic sweep** of finished work's residue: worktree, local branch, `.claude/work/` folder (intermediate train MR/PRs never set `phase: done`, so the `ship`/`abandon` prompt never fires). Verdict per branch from **the forge** with local fallbacks, including patch-equivalence for **squash merges** (`git branch --merged` misses them); acts only on `merged`/`empty`. `unknown` never a candidate; dirty and unpushed protected; work folders **archived, never deleted**; remote never touched. **`autonomy.mode` does not authorize deletion**: `auto` confirms the list too. `--purge-archive <N>d`: separate opt-in pass over `_archive/`, only folders already committed to git.
@@ -92,7 +92,7 @@ With what is new (there is already work on disk):
92
92
  ## 4. Next step
93
93
 
94
94
  - An `Unattended:` line → the question is the orchestrator's to bring back: say so, and that answering it here instead means clearing `meta.json.pending` and continuing in this session's mode; the next step itself comes from `phase` as always.
95
- - Suggest the concrete command from `phase` and `size` — a study whose next step is `build` or `fix`: `git.handoff_branch` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff). Interrupted phase (e.g. `build` with an empty artifact) → suggest rerunning it with `$flow-feat-build` or `$flow-bug-fix`.
95
+ - Suggest the concrete command from `phase` and `size` — a study whose next step is `build` or `fix`: `meta.json.handoff` set and not `unattended` → `$flow-work-handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff). Interrupted phase (e.g. `build` with an empty artifact) → suggest rerunning it with `$flow-feat-build` or `$flow-bug-fix`.
96
96
  - §2.5 found something new → let it inform the suggestion (a contract that arrived after you left may mean rerunning `design` rather than continuing `build`); say why in one line.
97
97
  - `meta.json.related_repos` entries not `done` → remind that a **sibling repo still has a pending part** (`<repo>: <scope>`, plus `contract not handed over` when its `contract_handoff` is `pending`); suggest `$flow-feat-start <TICKET>` there. flow only reminds; it never scans or touches the other repo.
98
98
  - Do not advance on your own. The user decides.
@@ -16,7 +16,7 @@ Every `/flow:*` command assumes these rules. They are stated once, here, so a co
16
16
  carries what is specific to its phase. Read this once per session; a command that says "load
17
17
  `flow-core`" means this file.
18
18
 
19
- **This file belongs to flow `0.94.1`.** Compare it once, at the start of the session, against
19
+ **This file belongs to flow `0.95.1`.** Compare it once, at the start of the session, against
20
20
  `version` in `~/.claude/flow/.claude-plugin/plugin.json`. The two differing means the session
21
21
  is running a **mixture** — the commands from one copy of the plugin, these shared rules from another
22
22
  — which is exactly what happens when a branch or a release candidate is loaded over an installed
@@ -248,16 +248,18 @@ sensible default and record it.
248
248
 
249
249
  Asking these anyway is how a run in `guided`/`auto` degrades into a manual one.
250
250
 
251
- **A study made for handoff.** `git.handoff_branch` set and the mode not `unattended` → the study is
252
- built somewhere else, so wherever a study phase (`start`, `design`, `plan`, `investigate`) or
253
- `resume` would hand the work to `/flow:feat:build` or `/flow:bug:fix`, it hands it to
254
- `/flow:work:handoff` instead. Only the target changes: a Close that asks (`manual`) offers **Hand
251
+ **A study made for handoff.** A work started with `--study` (`/flow:feat:start`,
252
+ `/flow:bug:start`) records `meta.json.handoff: true`: it is studied here and built somewhere else.
253
+ That field set and the mode not `unattended` → wherever a study phase (`start`, `design`, `plan`,
254
+ `investigate`) or `resume` would hand the work to `/flow:feat:build` or `/flow:bug:fix`, it hands it
255
+ to `/flow:work:handoff` instead. Only the target changes: a Close that asks (`manual`) offers **Hand
255
256
  off the study** recommended and **Build here** second; a Close that chains (`guided`/`auto`) chains
256
- into handoff, whose push question is the one confirmation — no stop is added. In `unattended` the
257
- rule does not apply: the repo's `FLOW.md` reaches the server too, and a run that studies a ticket
258
- there goes on to build it — unless the orchestrator launched it as a study run (§2.1), which stops
259
- at the door to code. A repo that hands its studies off pairs the key with
260
- `autonomy.mode: auto`, and the study then runs on its own up to the push.
257
+ into handoff, whose push question is the one confirmation — no stop is added. A work started without
258
+ `--study` is built here, whatever `git.handoff_branch` says: the key only names where a study is
259
+ pushed, so one repo can hold both kinds of work. In `unattended` the rule does not apply: a run that
260
+ studies a ticket there goes on to build it — unless the orchestrator launched it as a study run
261
+ (§2.1), which stops at the door to code. With `autonomy.mode: auto`, a `--study` work runs on its
262
+ own up to the push.
261
263
 
262
264
  ### 2.1 `unattended` — where a person would have been asked
263
265
 
@@ -391,6 +393,7 @@ person asking for changes, a ticket that already has code — is `/flow:work:run
391
393
  | An approved study's branch (`run`, `why = start`, no build or fix begun) | record — fast-forwarded to its base when it holds no commit of its own (`/flow:work:run` §2); the base unreadable or the fast-forward failing → blocked. Not integrating: nothing of the run's is merged |
392
394
  | Integrating the base into the MR/PR's branch (`green`) | on `why = conflict`, record — `git merge origin/<base>` as the orchestrator left it, never rebase, each conflict resolved on its merits (`/flow:work:green` §5.C); on any other `why`, blocked — the orchestrator brings the base in |
393
395
  | Any offer about the work's own bookkeeping — a tracker issue, the first `KNOWLEDGE.md` or a knowledge save, a FLOW convention, an agent lesson or a saved specialist, the follow-up survey, carrying files over from the main checkout, a contract handoff, archiving the work | record — `Later`; nothing written outside the work folder |
396
+ | A wait — a suite, a quality gate, anything run in the background (`validate`, `review`) | in the turn, on its condition, with a deadline (§6.5) — never a supervisor, never a fixed-length sleep, never ending the turn to be woken |
394
397
  | A step the command cannot complete (a red suite it cannot fix, a tool missing, auth failing, the same check failing a second time) | blocked |
395
398
  | Anything `auto` already decides on its own (size, flow mechanics, WIP commits, the next command) | as `auto` |
396
399
 
@@ -799,7 +802,7 @@ merge now. Delegating that judgement is how a pipeline ends up declared green by
799
802
  cheapest to ask, which is the one thing `/flow:work:green` exists to forbid. Delegate the waiting
800
803
  and the evidence; the verdict stays here.
801
804
 
802
- **Then end the turn.** Dispatching a supervisor and staying in a poll loop of your own pays both
805
+ **Then end the turn** — except in `unattended`, below. Dispatching a supervisor and staying in a poll loop of your own pays both
803
806
  bills and saves nothing. What wakes you is whatever the harness offers — a background task that
804
807
  re-invokes you when it finishes, a scheduled wake-up, a message back to this thread; where it offers
805
808
  none, the supervisor's evidence file is read at your next stop, and **you say that** rather than
@@ -816,6 +819,21 @@ moving.
816
819
  than to run — the brief, the round trip and the report are the whole of the saving. And anything you
817
820
  must *react to* mid-wait is not a wait at all: it is the work, and it stays here.
818
821
 
822
+ **In `unattended`, the wait stays in the turn** (§2.1). Nobody can bring back a run whose turn
823
+ ended, and whether a headless harness re-invokes a run when its background task finishes is not
824
+ something the run can count on. So no supervisor and no ending the turn: the wait is sat through
825
+ here, on the condition it waits for, with a deadline —
826
+
827
+ - **In the foreground**, when the command fits the harness's own limit for one call.
828
+ - **Otherwise launched with its exit code written to a file**, then waited on by a loop that checks
829
+ for that file every few seconds and stops at the deadline — one tool call per stretch, each under
830
+ that same limit, repeated until the file appears or the deadline passes. The loop runs inside the
831
+ call, so its cycles cost nothing on this thread.
832
+ - **Never a fixed-length sleep.** A guessed duration pays the whole sleep when the suite finished in
833
+ a fraction of it, and wakes before the suite when the guess is short.
834
+
835
+ The deadline reached with nothing back → `blocked`, naming the command and how long it ran.
836
+
819
837
  ### 6.6 — Which agent a role resolves to
820
838
 
821
839
  **The harness already tells you which agents are installed**, each with a line on what it is for,
@@ -32,7 +32,7 @@ Read `~/.claude/flow/CORE.gemini.md` first (shared rules: `FLOW.md` step 0, mode
32
32
  **In `unattended`, before this phase's first step, read flow-core §2.1 whole — from its heading to the next section, unless it is already in your context whole; having read parts of it does not count** — the orchestrator command, the question stop and the way its answer comes back are all in it, and a phase that reads only part of it skips them.
33
33
 
34
34
  - Read `meta.json` and `00-summary.md`; open in full only `01-context.md`. (flow-core §5)
35
- - `type` is not `bug` → refuse. `size` is `XS` → suggest `/flow:bug:fix` — `git.handoff_branch` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff) — and stop.
35
+ - `type` is not `bug` → refuse. `size` is `XS` → suggest `/flow:bug:fix` — `meta.json.handoff` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff) — and stop.
36
36
  - Require `context` in `phases_done`.
37
37
 
38
38
  ## 1.5 Reproduce — what is failing, before why
@@ -228,6 +228,6 @@ If `knowledge.stage` is set and the root cause reveals a **non-obvious "why"** a
228
228
 
229
229
  - Update `meta.json`: `phase = "investigate"`, add to `phases_done`.
230
230
  - Overwrite `00-summary.md` whole (≤15 lines, flow-core §5).
231
- - Suggest `/flow:bug:fix` — `git.handoff_branch` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
232
- - **Autonomy handoff** (`autonomy.mode`, flow-core §2): `manual` → propose `/flow:bug:fix` with a single `AskUserQuestion`, invoke it only on confirmation; `guided`/`auto` → chain into it in this same turn. Either way: `git.handoff_branch` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
231
+ - Suggest `/flow:bug:fix` — `meta.json.handoff` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
232
+ - **Autonomy handoff** (`autonomy.mode`, flow-core §2): `manual` → propose `/flow:bug:fix` with a single `AskUserQuestion`, invoke it only on confirmation; `guided`/`auto` → chain into it in this same turn. Either way: `meta.json.handoff` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
233
233
  """
@@ -18,12 +18,13 @@ Start a bug. `{{args}}` is **optional**:
18
18
 
19
19
  - **Given** — a ticket (format `tracker.prefix` from FLOW.md) → *ticket mode*: start from it (§1 reads it).
20
20
  - **Empty** — *ticket-less mode*: do **not** stop. Synthesize the bug from the conversation just held with the user (§1.5). Ask for a one-line symptom only if there is no conversation to draft from.
21
+ - **`--study`**, anywhere in `{{args}}` — a flag, not part of the identifier: take it out before deciding the mode. The bug is studied here and fixed somewhere else: §4 records `meta.json.handoff: true`, and the study ends at `/flow:work:handoff` instead of `fix` (flow-core §2, a study made for handoff). `git.handoff_branch` empty → say in one line that `--study` needs that key, and go on as a work fixed here. Without the flag the bug is fixed here, whatever `git.handoff_branch` says.
21
22
 
22
23
  **In `unattended`** (flow-core §2.1) this command asks nothing; each place it would ask resolves as
23
24
  that table says. Here: **the ticket is `<cmd> ticket --json`**, not the tracker — `number` is the
24
25
  identifier, `title` and `body` replace §1's tracker read, and its `comments` (already limited to
25
26
  authorised authors) are the whole thread of §1.1; `{{args}}` that disagrees with `number` is
26
- ignored and named. The order failing or empty → `blocked` · **the base is the ticket's `base`**
27
+ ignored and named, and `--study` is ignored (the orchestrator says why it launched the run). The order failing or empty → `blocked` · **the base is the ticket's `base`**
27
28
  (empty → `git.default_base`), recorded as `meta.json.base` — the branch of §3 starts there, and asks
28
29
  nothing · uncommitted changes, or a checkout not on that base → `blocked`: the orchestrator owns the
29
30
  checkout · the branch is named `<number>-<slug>` whatever `git.branch_pattern` says · cross-repo
@@ -43,7 +44,7 @@ Read `~/.claude/flow/CORE.gemini.md` first (shared rules: `FLOW.md` step 0, mode
43
44
  **In `unattended`, before this phase's first step, read flow-core §2.1 whole — from its heading to the next section, unless it is already in your context whole; having read parts of it does not count** — the orchestrator command, the question stop and the way its answer comes back are all in it, and a phase that reads only part of it skips them.
44
45
 
45
46
  - Verify you are in the correct repo.
46
- - **Determine the mode** from `{{args}}`: non-empty → *ticket mode* (identifier = `{{args}}`); empty → *ticket-less mode* (identifier = the slug resolved in §1.5).
47
+ - **Determine the mode** from `{{args}}` (`--study` already taken out): non-empty → *ticket mode* (identifier = `{{args}}`); empty → *ticket-less mode* (identifier = the slug resolved in §1.5).
47
48
  - Once the identifier is known, check whether the work already exists: ticket mode → glob `.claude/work/<TICKET>/` and `.claude/work/<TICKET>-*/` for a `meta.json` whose `ticket` equals `<TICKET>`; ticket-less → `.claude/work/<slug>/meta.json`, right after §1.5.2 decides the slug. If one exists, suggest `/flow:work:resume`.
48
49
  - This command **creates** `00-summary.md` (§4); there is nothing to read yet.
49
50
 
@@ -181,6 +182,8 @@ Create the work directory per §0: `.claude/work/<TICKET>-<slug>/` in ticket mod
181
182
 
182
183
  In `unattended`, add `"base"`: the ticket's `base`, or `git.default_base` when it is empty — never empty; the branch the fix starts from and targets. Omit it in every other mode.
183
184
 
185
+ Add `"handoff": true` only when `--study` was given and `git.handoff_branch` is set; omit it otherwise.
186
+
184
187
  Populate `related_repos` from §1.6 — one `{ "repo": "<name>", "scope": "<one line>", "status": "pending", "contract_handoff": "pending" | "none" }` per *other* repo the fix touches; `[]` for a single-repo fix. `pending` only when the fix **changes a surface that sibling consumes** (a payload key, an error code, a route, an event shape); otherwise `none`.
185
188
 
186
189
  **This fix *is* an accepted follow-up** (the ticket came from another work's `followups[]` — typically a prevention action or a neighbouring bug, flow-core §7) → set `origin: { "work": "<originating work dir>", "followup": "F<n>" }`, carry that entry's recorded `why` into `01-context.md` verbatim rather than re-deriving it, and move the originating entry to `in_progress` with `work` naming this folder. Not a follow-up → omit `origin`.
@@ -224,7 +227,7 @@ Run `tracker.start_cmd` with `{TICKET}` = `meta.json.ticket` and `{ASSIGNEE}` =
224
227
 
225
228
  ## 5. Close
226
229
 
227
- - Suggest the next command by size: `/flow:bug:fix` for XS (`git.handoff_branch` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff)), `/flow:bug:investigate` for the rest.
230
+ - Suggest the next command by size: `/flow:bug:fix` for XS (`meta.json.handoff` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff)), `/flow:bug:investigate` for the rest.
228
231
  - Overwrite `00-summary.md` whole (≤15 lines, flow-core §5).
229
232
  - Apply `autonomy.mode`: `manual` stops and recommends; `guided`/`auto` chain into that command automatically, subject to the hard gates.
230
233
  """
@@ -37,7 +37,7 @@ Read `~/.claude/flow/CORE.gemini.md` first (shared rules: `FLOW.md` step 0, mode
37
37
 
38
38
  Then:
39
39
  1. Run only that test with `quality.test_one` from FLOW.md; it must pass.
40
- 2. Run the full suite with `quality.test` to rule out collateral regressions (in the background if slow; measured in tens of minutes → delegate it as a wait to a supervisor subagent on `models.supervisors`, flow-core §6.5 — it returns the exit code and the failing output, and the reading of them stays here).
40
+ 2. Run the full suite with `quality.test` to rule out collateral regressions (in the background if slow — in `unattended`, waited on in this turn, flow-core §6.5; otherwise, measured in tens of minutes → delegate it as a wait to a supervisor subagent on `models.supervisors`, flow-core §6.5 — it returns the exit code and the failing output, and the reading of them stays here).
41
41
  3. DB touched → verify the schema has no unexpected differences (`quality.db_update` or the FLOW.md equivalent, if defined; in `unattended` it is never run without an answer — a schema difference to apply is question
42
42
  `migration`, flow-core §2.1; the orchestrator's *Apply it* relaunches this phase, this site takes the
43
43
  answer just applied and runs it, and `05-validation.md` names that answer beside the migration).
@@ -36,7 +36,7 @@ after writing each challenge's Response.
36
36
 
37
37
  - Load `meta.json` by current branch — in `unattended`, the work `/flow:work:run` found (flow-core §2.1). Missing → ask the user to start with `/flow:feat:start`.
38
38
  - Read `meta.json` and `00-summary.md`; open in full only `01-context.md` (ticket, decisions, contracts received). (flow-core §5)
39
- - `size` is `XS` → suggest jumping to `/flow:feat:build` — `git.handoff_branch` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff) — and stop unless the user insists.
39
+ - `size` is `XS` → suggest jumping to `/flow:feat:build` — `meta.json.handoff` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff) — and stop unless the user insists.
40
40
 
41
41
  ## 1.5 Approaches — open the option space first (M/L)
42
42
 
@@ -434,7 +434,7 @@ Never invoke `knowledge.save` here — the final save is in `/flow:feat:ship` af
434
434
  - **Confirm the acceptance criteria** within the design review: present the enumerated list. If every criterion is unambiguous and verifiable, the review covers them — no separate prompt. `AskUserQuestion` **only** when a criterion is ambiguous, not verifiable, or one is likely missing for today's ticket (same restraint as the challenger). Apply the user's edits to `03-design.md` before advancing.
435
435
  - **In `manual`/`guided`**, ask the user to review the design; edit the artifact on requested changes before advancing. **In `auto`, do not ask** — record it as accepted per the handoff below. Not an unconditional stop.
436
436
  - Next step by size:
437
- - **XS / S**: suggest `/flow:feat:build` (1 single MR/PR, no planned split) — `git.handoff_branch` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
437
+ - **XS / S**: suggest `/flow:feat:build` (1 single MR/PR, no planned split) — `meta.json.handoff` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
438
438
  - **M / L**: suggest `/flow:feat:plan` to split the work into independently mergeable MRs/PRs before implementing.
439
- - **Autonomy handoff.** Design review is a genuine decision point: `manual` and `guided` ask for it before advancing. `auto` records the design as accepted in the artifact and **chains into the command for the size** in this same turn — `build` there: `git.handoff_branch` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff). `manual` proposes that command with a single `AskUserQuestion` (recommended option by default), never a written suggestion. Unresolved `high`-severity findings (§6) stop the flow in **every** mode — do not chain over them.
439
+ - **Autonomy handoff.** Design review is a genuine decision point: `manual` and `guided` ask for it before advancing. `auto` records the design as accepted in the artifact and **chains into the command for the size** in this same turn — `build` there: `meta.json.handoff` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff). `manual` proposes that command with a single `AskUserQuestion` (recommended option by default), never a written suggestion. Unresolved `high`-severity findings (§6) stop the flow in **every** mode — do not chain over them.
440
440
  """
@@ -27,7 +27,7 @@ Delivery planning phase. **No code is written.** Splits the feature into MRs/PRs
27
27
  - Load `meta.json` by current branch — in `unattended`, the work `/flow:work:run` found (flow-core §2.1). Missing → send the user to `/flow:feat:start`.
28
28
  - Require `design` in `phases_done`. Missing → send to `/flow:feat:design` and stop.
29
29
  - Read `meta.json` and `00-summary.md`; open in full only `03-design.md` — and, when `01-context.md` has `## Study revisions` (a person's reply to an unattended study, flow-core §2.1), that section too: a request about the split is applied here, and goes into §2's brief. (flow-core §5)
30
- - **`size` `XS` or `S`** → warn that this phase does not apply (always 1 MR/PR), add `"plan:skipped"` to `phases_done`, suggest `/flow:feat:build` — `git.handoff_branch` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff). Stop.
30
+ - **`size` `XS` or `S`** → warn that this phase does not apply (always 1 MR/PR), add `"plan:skipped"` to `phases_done`, suggest `/flow:feat:build` — `meta.json.handoff` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff). Stop.
31
31
 
32
32
  ## 2. Work
33
33
 
@@ -162,6 +162,6 @@ A slice landing in **another repo** is not one of *this* repo's `mrs`: record it
162
162
 
163
163
  `∥` = no dependency between them, can be built in parallel or as a train; `→` = the next wave waits for the previous one to merge. Then the table with `#`, wave, `depends_on`, title and estimate. One line for the split rationale, and — when any pair was merged — one line saying how many were and what they would have cost (`merged #a into #b: would have been a wave of its own`). Nothing else — risks and discarded alternatives live in the artifact.
164
164
  - Changes requested → edit the artifact and `meta.json.mrs` before advancing.
165
- - Suggest `/flow:feat:build` to start the first MR/PR — `git.handoff_branch` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
166
- - **Autonomy handoff.** Approving the split is a genuine decision point: in `manual` and `guided` ask before advancing. In `auto`, record the plan as accepted in `04-mr-plan.md` and **chain into `/flow:feat:build` automatically** in this same turn. In `manual`, propose it with a single `AskUserQuestion`. Either way: `git.handoff_branch` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
165
+ - Suggest `/flow:feat:build` to start the first MR/PR — `meta.json.handoff` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
166
+ - **Autonomy handoff.** Approving the split is a genuine decision point: in `manual` and `guided` ask before advancing. In `auto`, record the plan as accepted in `04-mr-plan.md` and **chain into `/flow:feat:build` automatically** in this same turn. In `manual`, propose it with a single `AskUserQuestion`. Either way: `meta.json.handoff` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff).
167
167
  """
@@ -298,7 +298,7 @@ Not run for XS/S, small diffs, or fewer than 4 ambiguous findings. When skipped,
298
298
 
299
299
  Read `quality.*` from `FLOW.md`. Empty → auto-discover equivalent commands (Makefile, npm/composer scripts, Gradle, dotnet, Xcode, Flutter…) and note what you use.
300
300
 
301
- Launch in parallel (background if slow):
301
+ Launch in parallel (background if slow; in `unattended`, waited on in this turn, flow-core §6.5):
302
302
  - `quality.style_fix`
303
303
  - `quality.static_analysis`
304
304
  - `quality.test_one` (if there are new tests, with the appropriate filter)
@@ -24,12 +24,14 @@ Read `~/.claude/flow/CORE.gemini.md` first (shared rules: `FLOW.md` step 0, mode
24
24
 
25
25
  - **Given** — an identifier in `tracker.prefix` format from `FLOW.md` → *ticket mode* (§2 reads it).
26
26
  - **Empty** — *ticket-less mode*: do **not** stop or demand a ticket. Draft a ticket from the conversation just held (§2.5), as `/flow:feat:ship` builds the MR/PR body from the work log. Ask for a one-liner only if there is no conversation to draft from.
27
+ - **`--study`**, anywhere in `{{args}}` — a flag, not part of the identifier: take it out before deciding the mode. The work is studied here and built somewhere else: §6 records `meta.json.handoff: true`, and the study ends at `/flow:work:handoff` instead of `build` (flow-core §2, a study made for handoff). `git.handoff_branch` empty → say in one line that `--study` needs that key, and go on as a work built here. Without the flag the work is built here, whatever `git.handoff_branch` says.
27
28
 
28
29
  **In `unattended`** (flow-core §2.1) this command asks nothing; each place it would ask resolves as
29
30
  that table says. Here: **the ticket is `<cmd> ticket --json`**, not the tracker — `number` is the
30
31
  identifier, `title` and `body` replace §2's tracker read, and its `comments` (already limited to
31
32
  authorised authors) are the whole thread of §2.1, read as that section says; `{{args}}` that
32
- disagrees with `number` is ignored and named. The order failing or empty → `blocked` (there is no
33
+ disagrees with `number` is ignored and named, and `--study` is ignored (the orchestrator says why it
34
+ launched the run). The order failing or empty → `blocked` (there is no
33
35
  conversation to draft from and nobody to paste it) · **the base is the ticket's `base`** (empty →
34
36
  `git.default_base`), recorded as `meta.json.base` — the branch of §5.2 starts there, never from
35
37
  where the checkout stands, and §5.1 asks nothing · uncommitted changes, or a checkout not on that
@@ -49,7 +51,7 @@ its reason file in a `mktemp -d` directory (flow-core §2.1).
49
51
  - Read the effective FLOW configuration per flow-core §0; no FLOW layer present → each
50
52
  step's default. This command **creates** `00-summary.md` (§6) instead of reading it (flow-core §5).
51
53
  - No recognizable project structure → warn and stop.
52
- - **Determine the mode**: `{{args}}` non-empty → *ticket mode* (identifier = `{{args}}`); empty → *ticket-less* (identifier = the §2.5 slug).
54
+ - **Determine the mode** (`--study` already taken out): `{{args}}` non-empty → *ticket mode* (identifier = `{{args}}`); empty → *ticket-less* (identifier = the §2.5 slug).
53
55
  - Once the identifier is known, check the work does not exist: ticket mode → glob `.claude/work/<TICKET>/` and `.claude/work/<TICKET>-*/` for a `meta.json` whose `ticket` equals `<TICKET>`; ticket-less → `.claude/work/<slug>/meta.json`, right after the slug is decided in §2.5. Exists → do not overwrite; warn and suggest `/flow:work:resume`.
54
56
 
55
57
  **Work directory naming.** Work lives in `.claude/work/<work-dir>/`. `meta.json.ticket` stays the **pure identifier** (real ticket id, or the slug in ticket-less local-only) — it feeds the tracker view, the issue link and `{TICKET}`. The directory adds a slug:
@@ -250,6 +252,7 @@ Create the work directory per §1: `.claude/work/<TICKET>-<slug>/` (ticket mode)
250
252
  }
251
253
  ```
252
254
 
255
+ - `handoff` — `true` only when `--study` was given and `git.handoff_branch` is set; omit it otherwise.
253
256
  - Ticket-less (§2.5) → `draft_from_conversation: true`, `tracker_issue` = created issue id/url (or `null` if local-only). Ticket mode → defaults above.
254
257
  - `base` — `unattended` only: the ticket's `base`, or `git.default_base` when it is empty — never empty (the branch every MR/PR of this work starts from and targets; `/flow:work:run` refreshes it on `merged`). Omit it in every other mode.
255
258
  - `related_repos` from §3.5 — one `{ "repo": "<name>", "scope": "<one line>", "status": "pending", "contract_handoff": "pending" | "none" }` per *other* repo; `[]` for a single-repo task.
@@ -305,6 +308,6 @@ Run `tracker.start_cmd` with `{TICKET}` = `meta.json.ticket`, `{ASSIGNEE}` = `tr
305
308
  ## 7. Close
306
309
 
307
310
  - Overwrite `00-summary.md` whole (≤15 lines, flow-core §5) — first written in §6; refresh it if §6.5 changed anything.
308
- - Report **following the stop header** (flow-core §3), branch added, body 2-3 lines: ticket, size, branch; recommended next command per the §4 table (`build` on XS: `git.handoff_branch` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff)) — in `guided`/`auto` you run it in this same turn, so there is no report and no question here: update the panel and chain (flow-core §3).
311
+ - Report **following the stop header** (flow-core §3), branch added, body 2-3 lines: ticket, size, branch; recommended next command per the §4 table (`build` on XS: `meta.json.handoff` set and not `unattended` → `/flow:work:handoff` in its place, **Hand off the study** recommended and **Build here** second where it asks (flow-core §2, a study made for handoff)) — in `guided`/`auto` you run it in this same turn, so there is no report and no question here: update the panel and chain (flow-core §3).
309
312
  - Apply `autonomy.mode`: `manual` → stop and let the user invoke the recommended command; `guided`/`auto` → chain into it, subject to the hard gates (the §5 branch-base ambiguity already stops on its own).
310
313
  """
@@ -42,7 +42,7 @@ One of the three below writes and two of them read, so they do not all go at onc
42
42
 
43
43
  **A green suite is not a performance result** — a tiny fixture database proves a query's **rows**, never its **plan**. If `/flow:feat:review §3.6` left any query verdict `unresolved`, or an acceptance criterion concerns speed or volume: run the measurement of **`/flow:work:query §4`** with the volumes in `data.volumes` (or a data set shaped like them — the distribution matters more than the total), record plan and timings, and gate on the result. No `data.*` configuration and the criterion cannot be measured → it is `unproven` with the reason, never silently `proven`.
44
44
 
45
- 3. **Full suite**: run `quality.test` from `FLOW.md` in the background; if empty, auto-discover the project's test command and note what you use. **A suite measured in tens of minutes is a wait, not a step**: hand it to a supervisor subagent on `models.supervisors` (flow-core §6.5) — it runs it, times out, and brings back the exit code plus the failing tests' output, never a reading of whether those failures matter. Short suites stay here; delegating ninety seconds costs more than running them. A repo with more than one suite chains them in that one key (`make test && make test-frontend`); when it does not and the diff touches a suite the key misses, run that one too and say so in one line.
45
+ 3. **Full suite**: run `quality.test` from `FLOW.md` in the background (in `unattended`, waited on in this turn, flow-core §6.5); if empty, auto-discover the project's test command and note what you use. **A suite measured in tens of minutes is a wait, not a step**: hand it to a supervisor subagent on `models.supervisors` (flow-core §6.5) — it runs it, times out, and brings back the exit code plus the failing tests' output, never a reading of whether those failures matter. Short suites stay here; delegating ninety seconds costs more than running them. A repo with more than one suite chains them in that one key (`make test && make test-frontend`); when it does not and the diff touches a suite the key misses, run that one too and say so in one line.
46
46
 
47
47
  ## 3. Criteria coverage (S and larger)
48
48