flow-workflows 0.91.0 → 0.93.0

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 (43) hide show
  1. package/adapters/codex/CORE.md +13 -6
  2. package/adapters/codex/skills/flow-bug-fix/SKILL.md +9 -1
  3. package/adapters/codex/skills/flow-bug-investigate/SKILL.md +11 -0
  4. package/adapters/codex/skills/flow-feat-build/SKILL.md +9 -2
  5. package/adapters/codex/skills/flow-feat-design/SKILL.md +30 -0
  6. package/adapters/codex/skills/flow-feat-plan/SKILL.md +1 -0
  7. package/adapters/codex/skills/flow-work-README/SKILL.md +4 -0
  8. package/adapters/codex/skills/flow-work-handoff/SKILL.md +19 -5
  9. package/adapters/codex/skills/flow-work-respond/SKILL.md +25 -3
  10. package/adapters/codex/skills/flow-work-run/SKILL.md +18 -2
  11. package/adapters/gemini/CORE.md +13 -6
  12. package/adapters/gemini/commands/flow/bug/fix.toml +9 -1
  13. package/adapters/gemini/commands/flow/bug/investigate.toml +11 -0
  14. package/adapters/gemini/commands/flow/feat/build.toml +9 -2
  15. package/adapters/gemini/commands/flow/feat/design.toml +30 -0
  16. package/adapters/gemini/commands/flow/feat/plan.toml +1 -0
  17. package/adapters/gemini/commands/flow/work/README.toml +4 -0
  18. package/adapters/gemini/commands/flow/work/handoff.toml +19 -5
  19. package/adapters/gemini/commands/flow/work/respond.toml +25 -3
  20. package/adapters/gemini/commands/flow/work/run.toml +18 -2
  21. package/adapters/hermes/CORE.md +13 -6
  22. package/adapters/hermes/skills/flow-bug-fix/SKILL.md +9 -1
  23. package/adapters/hermes/skills/flow-bug-investigate/SKILL.md +11 -0
  24. package/adapters/hermes/skills/flow-feat-build/SKILL.md +9 -2
  25. package/adapters/hermes/skills/flow-feat-design/SKILL.md +30 -0
  26. package/adapters/hermes/skills/flow-feat-plan/SKILL.md +1 -0
  27. package/adapters/hermes/skills/flow-work-README/SKILL.md +4 -0
  28. package/adapters/hermes/skills/flow-work-handoff/SKILL.md +19 -5
  29. package/adapters/hermes/skills/flow-work-respond/SKILL.md +25 -3
  30. package/adapters/hermes/skills/flow-work-run/SKILL.md +18 -2
  31. package/adapters/opencode/CORE.md +13 -6
  32. package/adapters/opencode/commands/flow-bug-fix.md +9 -1
  33. package/adapters/opencode/commands/flow-bug-investigate.md +11 -0
  34. package/adapters/opencode/commands/flow-feat-build.md +9 -2
  35. package/adapters/opencode/commands/flow-feat-design.md +30 -0
  36. package/adapters/opencode/commands/flow-feat-plan.md +1 -0
  37. package/adapters/opencode/commands/flow-work-README.md +4 -0
  38. package/adapters/opencode/commands/flow-work-handoff.md +19 -5
  39. package/adapters/opencode/commands/flow-work-respond.md +25 -3
  40. package/adapters/opencode/commands/flow-work-run.md +18 -2
  41. package/package.json +1 -1
  42. package/plugins/flow/.claude-plugin/plugin.json +1 -1
  43. package/plugins/flow/CHANGELOG.md +44 -0
@@ -288,6 +288,9 @@ Consolidate outputs into `.claude/work/<TICKET>/03-design.md`:
288
288
  - **Invariant**: <e.g. "after assignTo(user), ticket.assignee == user AND ticket.status != 'unassigned'">
289
289
  - **Edge / boundary**: <e.g. "empty input list → returns 0, does not throw">
290
290
 
291
+ ## Depends on other tickets
292
+ <§5.1: one line per ticket this design cannot be built without — `- <ticket> — <what it brings that the base branch lacks>` — then, under "Not dependencies (either order works)", each premise on another ticket that holds whichever merges first, with one line why. Neither → "none".>
293
+
291
294
  ## Defensive mechanisms and their justification
292
295
  <One row per validation, guard, retry, lock, fallback, cache, idempotency, queue, or flag the design introduces. If you cannot name a REAL and PRESENT scenario that justifies it, the piece is unnecessary — remove it from the design.>
293
296
 
@@ -316,6 +319,33 @@ Consolidate outputs into `.claude/work/<TICKET>/03-design.md`:
316
319
 
317
320
  **"Acceptance criteria"**: start from the provisional list in `01-context.md` (pinned from the ticket in `/flow-feat-start`), fold in the clarifications and the internal/external contracts decided here, and promote it to the canonical enumerated list `/flow-feat-validate` gates against — observable, verifiable, proportional to size.
318
321
 
322
+ ### 5.1 Tickets this design depends on
323
+
324
+ Fill `## Depends on other tickets` now, before the challenger of §6 reads the design. The study is
325
+ often built by someone who never saw it made — another person, an unattended server — and who
326
+ starts from the base. A design that rests on what another ticket has not delivered yet leaves that
327
+ builder to find the piece missing and either ask or redo it.
328
+
329
+ - **A dependency** is a piece, contract or decision the chosen design needs, that is **not on the
330
+ base this work builds from** (`meta.json.base`, empty → `git.default_base`) — checked there, after
331
+ a best-effort `git fetch origin <base>`, never assumed from a local ref — and that **another
332
+ ticket** of this tracker brings. Missing from the base with no ticket bringing it → it is scope
333
+ or an open question, not a dependency. A ticket in another repo is not a `ticket_deps` entry —
334
+ the orchestrator only resolves this tracker's numbers — so write it in the section as a
335
+ cross-repo dependency, for a person, and leave it out of the list.
336
+ - **Not a dependency**: a premise that holds whichever ticket merges first. Say so under "Not
337
+ dependencies (either order works)", so nobody waits for it.
338
+ - **Record each one** in that section and in `meta.json.ticket_deps` —
339
+ `{ "ticket": "<the reference as a ticket body writes it: #253, MT-123>", "why": "<one line>" }`,
340
+ never one twice. `ticket_deps` is the record the exits read (`/flow-work-handoff` §5, the door to
341
+ code of an unattended study run, flow-core §2.1); the section is the study's prose. Each run of
342
+ this phase writes the list whole from the design it closes; `plan`, which runs after it, appends
343
+ its own again. A §6 response or a §9 edit that changes what the design needs changes
344
+ the section and the list together. None → `[]` and "none".
345
+
346
+ `ticket_deps` is not `mrs[].depends_on`: that one orders this work's own MRs/PRs, this one names
347
+ other tickets. Flow never checks whether a dependency has closed — whoever builds waits for it.
348
+
319
349
  ## 6. Design challenge (challenger)
320
350
 
321
351
  Before closing, **challenge the design** with an `Agent general-purpose` and this self-contained brief:
@@ -124,6 +124,7 @@ Add the `mrs` array with the agreed plan:
124
124
  ```
125
125
 
126
126
  - `n` = execution order (topological): `depends_on` only ever references a **lower** `n`; `wave` groups MRs/PRs that can run in parallel. `/flow-feat-build §1` reads `depends_on` to pick the next **startable** MR/PR and to say which can go in parallel — keep both accurate whenever the plan is edited or renumbered.
127
+ - **Another ticket is not a `depends_on`.** An MR/PR that turns out, while splitting, to need something another ticket brings is a dependency of the study: append it to `meta.json.ticket_deps` as `/flow-feat-design` §5.1 says, name it in that MR/PR's entry of `04-mr-plan.md` beside what it waits on, and leave `03-design.md` as it closed. The design's own entries stand as they are.
127
128
  - **`phases_done`** starts `[]` in every seeded entry: it tracks `build`/`review`/`validate` **for that MR/PR specifically**, so the gates in `/flow-feat-review §1`, `/flow-feat-validate §1` and `/flow-feat-ship §1` judge *this* MR/PR — a sibling's review never satisfies a new MR/PR's gate.
128
129
  - Estimates are **indicative**, not contractual. `/flow-feat-build` uses them as a thermometer: real work over `lines_est` +50% or `files_est + 2` triggers the "cut or continue" question (see §2.3 in build). **A thermometer is not a target** (flow-core §9): an estimate is never met by deleting comments, tests or blank lines, by compressing readable code, or by cutting where the piece is not coherent — the overrun is recorded instead, and a diff shaped to fit a number is the one case where these estimates lie to the phases downstream.
129
130
 
@@ -110,6 +110,9 @@ This system **orchestrates** the project's existing sub-agents and skills (it do
110
110
  "note": "reason if closed/superseded; empty otherwise"
111
111
  }
112
112
  ],
113
+ "ticket_deps": [
114
+ { "ticket": "#253", "why": "one line, what that ticket brings that the base branch lacks" }
115
+ ],
113
116
  "related_repos": [
114
117
  { "repo": "sibling-project", "scope": "what's needed there", "status": "pending" | "in_progress" | "done", "contract_handoff": "none" | "pending" | "published → <location>" }
115
118
  ],
@@ -158,6 +161,7 @@ This system **orchestrates** the project's existing sub-agents and skills (it do
158
161
  Two fields for the review because they are two facts. `reviewed_sha` used to be `git rev-parse HEAD` at the end of the phase, which by then held the round's own fixes — so `ship` compared a sha against itself and reported a match over code no reviewer had read. Read by `ship` at pre-flight against `HEAD`: a delta of test files and this work's own folder passes with a note in `06-review.md`; anything else stops and asks in every autonomy mode. Empty is not a mismatch; `fixed_sha` set with `reviewed_sha == HEAD` is one. `review` also reads `reviewed_sha` back as **its own base** on a re-review, so the second round reads the delta instead of the whole branch.
159
162
  - **`respond_rounds`**: rounds of `/flow-work-respond` on an MR/PR. `/flow-work-respond §1` reads it against `quality.respond_max_rounds` (empty = 3) and refuses the round that would exceed it, handing the open threads back to the user.
160
163
  - **`related_repos`**: the **other repos a task touches**. Captured at `/flow-feat-start` / `/flow-bug-start` §cross-repo, refined at `design`/`plan`, reminded at `ship`, shown by `daily`/`resume`/`status`. flow only notes and reminds — never touches the other repo. `[]` for single-repo.
164
+ - **`ticket_deps`**: the **other tickets this study cannot be built without** — something the design needs that is not on the base branch and that another ticket brings (`/flow-feat-design` §5.1, `/flow-bug-investigate` §4.1). Read at the two exits of a study: `/flow-work-handoff` §5 writes a `Depends on <ticket>` line per entry into the ticket body, and an unattended study run passes `--depends-on N` per entry on its `done` (flow-core §2.1). Not `mrs[].depends_on`, which orders this work's own MRs/PRs. Written whole each time `design` (or `investigate`) runs, and removed when an unattended study is rewound. `[]` or absent when the study depends on nothing.
161
165
  - **`contract_handoff`**: whether the sibling knows **what shape to build against** (`scope` is prose; distinct from `status`). `none` — consumes no contract declared here. `pending` — consumes one, not handed over yet. `published → <location>` — published where that side reads it (normally the tracker ticket; `/flow-feat-ship` §6.3), picked up by the sibling's `/flow-feat-start` §3.6.
162
166
  - **`followups`**: work a phase deliberately did **not** do here — a neighbouring defect found while building, a piece put out of scope while planning, a risk recorded but not mitigated, an edge case left unchecked, a prevention action from a postmortem. Written by the phase that parks it (asks nothing) when it clears the bar of flow-core §7, triaged **once** at `ship`'s Close behind a skeptic and a ceiling on how many may become questions, published in the MR/PR description while still open, and surfaced by `status`/`daily`/`next` — including from `_archive/` — until `declined` or `done`. Shape and rules: flow-core §7. `[]` when the work deferred nothing.
163
167
  - **`defaults_used`**: an empty `FLOW.md` key a phase resolved with its default instead of asking — written in `guided`/`auto`, where asking would breach the never-a-question contract (flow-core §0). Not an error and not deferred work: a record, aggregated by `/flow-doctor` across every work including `_archive/`, so a key that keeps defaulting can be pinned once instead of decided every time. `[]` when nothing defaulted.
@@ -146,13 +146,27 @@ the ticket read it there, never in the work folder; the receiver does not parse
146
146
  <!-- end flow-study -->
147
147
  ```
148
148
 
149
- Criteria keep their literal values. The plan lists each MR/PR with what it covers and what it
150
- waits on; a bug's plan is its single fix.
149
+ Criteria keep their literal values. `## Design in brief` ends with each `meta.json.ticket_deps`
150
+ entry and its why — `Depends on #253: <why>` — so whoever approves the study sees what it waits
151
+ for; an unattended study's `done-summary.md` is this block, so it carries them too. The plan
152
+ lists each MR/PR with what it covers and what it waits on; a bug's plan is its single fix.
151
153
  - **The new body**: the body read above with the block between the two markers replaced — or, with
152
- no markers yet, the block appended after a blank line. Written to a `mktemp` file outside the
154
+ no markers yet, the block appended after a blank line. Then, for each `meta.json.ticket_deps`
155
+ entry (`/flow-feat-design` §5.1) whose line is not already a line of that body — same text,
156
+ ignoring case and surrounding whitespace — one line after the end marker, in `ticket_deps` order:
157
+
158
+ ```
159
+ Depends on #253
160
+ ```
161
+
162
+ `#253` being the entry's `ticket` as it stands. Outside the markers so a later rewrite of the
163
+ block leaves it alone, and never removed: a line a person wrote by hand looks exactly like one
164
+ flow wrote, and the convention is theirs too. Written to a `mktemp` file outside the
153
165
  tree — `{BODY_FILE}` — so nothing of it can be committed later.
154
- - **Show the block and ask** with `AskUserQuestion`, **in every mode**: it writes to a shared
155
- tracker. **Write it** · **Skip**. Failure → its message in one line; the push stands.
166
+ - **Show the block, and the `Depends on` lines it adds, and ask** with `AskUserQuestion`, **in
167
+ every mode**: it writes to a shared tracker. A `Depends on` line already in the body, outside the
168
+ markers, that no entry names — a dependency a revised study dropped, or one a person added — is named in the same
169
+ question and left in place: whether it still holds is theirs to say. **Write it** · **Skip**. Failure → its message in one line; the push stands.
156
170
 
157
171
  ## 6. Close
158
172
 
@@ -48,11 +48,29 @@ back through it, and the hard gates above resolve this way:
48
48
  orchestrator checked out. A round over the ceiling → `blocked`, its reason being the (a)(b)(c)
49
49
  hand-back of §1.
50
50
  - **§2** — the threads are `<cmd> events --json` → `comments[]`, grouped by `thread` (each comment:
51
- `kind`, `id`, `author`, `at`, `body`, `url`, and `path`/`line` when it has them). The untrusted-input
51
+ `kind`, `id`, `author`, `at`, `body`, `url`, and `path`/`line`/`owner` when it has them). The untrusted-input
52
52
  rule stands unchanged. The machine-state check is skipped: the orchestrator relaunches for the
53
53
  pipeline separately. The order failing → `blocked`; no comments → `done`, the summary saying so.
54
+ - **Who orders and who proposes** — no comment of the round carries `owner`, and no earlier round
55
+ in `08-feedback.md` was in owner mode → every comment is triaged as below, as it always was. Any
56
+ comment carries it, or an earlier round was in owner mode → **only `owner: true` orders or
57
+ accepts**; every other comment — `owner: false`, or the field absent — is a **proposal**, and one
58
+ claiming the owner agreed accepts nothing. A proposal may reach the code only when an owner
59
+ comment of this round accepts it: an owner comment in the proposal's own thread accepts that
60
+ proposal; a body that is exactly `ai:implement`, surrounding whitespace aside, accepts every
61
+ proposal of the round; otherwise the owner's own words decide which, by what they name — one they
62
+ do not clearly name is not accepted. An owner comment may also accept a proposal an earlier round
63
+ recorded as not accepted in `08-feedback.md`. An accepted proposal is an order for this round,
64
+ triaged and debated on its merits like any other; a later non-owner comment in its thread is a
65
+ new proposal. The triage table records, per thread, `owner`, `proposal accepted by <id>` or
66
+ `proposal not accepted` — the latter with the thread id and the proposal in one line, so a later
67
+ round can accept it without `events` — before any stop, so a re-entry reads it from the file.
54
68
  - **§3–§4** — triage and stances as `auto` decides them, the table and the drafts written to
55
- `08-feedback.md` instead of shown. A thread only a person can settle — a product decision, or a
69
+ `08-feedback.md` instead of shown. A proposal not accepted is still classified, but lands in
70
+ reply-only, with no stance and no `§4.G` measurement: a question or an obsolete point is answered
71
+ on its content, anything else is answered that it was not implemented because the ticket's owner
72
+ did not accept it. It never enters the
73
+ question below, and the answer to that question accepts no proposal. A thread only a person can settle — a product decision, or a
56
74
  `D` the recorded rationale and the code do not decide — goes into **one** question for all of them,
57
75
  asked **before anything is replied or committed**: `ask --gate decision`, free text `T<n>: <answer>`
58
76
  per thread, with `pending.phase: "respond"`, `pending.resume: "work:respond"` (never the work's
@@ -61,6 +79,8 @@ back through it, and the hard gates above resolve this way:
61
79
  §4, reading the threads and stances from that file rather than from `events`. **At the end of §4
62
80
  — on a first run and on that re-entry alike** — a reply that would repeat an earlier round's
63
81
  (§8's repeated-answer rule) is caught before anything is posted → `blocked`, naming the thread.
82
+ A proposal answered again as not accepted is exempt: it relays the owner's decision, not a stance
83
+ to argue, and the round ceiling still bounds its thread.
64
84
  `§4.G` measures as `/flow-work-query` does unattended (schema-only, never a database it creates).
65
85
  - **§5–§6** — a change adding behaviour gets its brief recorded (`recorded (unattended)`), not
66
86
  asked. A design invalidation that is more than a tweak, or an agreed change that needs a schema
@@ -72,7 +92,9 @@ back through it, and the hard gates above resolve this way:
72
92
  A `blocked` earlier than this point (the repeated answer, §6.1) also counts the round first. The agent-lessons offer is `Later`; re-posting the performance comment is not
73
93
  done — a changed number goes into `publish-body.md` instead.
74
94
  - **§7** — one `<cmd> reply --thread <thread> --body-file <work>/reply-<thread>.md` per answered
75
- thread, the reply naming the commit that changes the code. **Never resolve.** A `reply` that exits
95
+ thread, the reply naming the commit that changes the code. Every proposal is answered in its own
96
+ thread, implemented or not; an owner comment that only accepts gets no reply of its own — the
97
+ closing summary or body says what it accepted. **Never resolve.** A `reply` that exits
76
98
  ≠ 0 is recorded in `08-feedback.md` and the remaining replies still go out.
77
99
  - **The one closing order**, after the WIP commit (flow-core §2.1): code changed this round →
78
100
  `publish` with the work's `publish-title.md` / `publish-body.md` (updated when the round changed
@@ -65,7 +65,7 @@ of truth, and an argument that disagrees with it is ignored and named in the log
65
65
  | `conflict` | exists | `/flow-work-green` — the MR/PR conflicts with its base; which base, and where it stands, come from `<cmd> events --json` |
66
66
  | `review` · `pipeline` · `conflict` | none | `blocked` — there is no work of this ticket to answer for |
67
67
 
68
- **The work's branch, on `start` and `study`.** The current branch is `meta.json.branch` → nothing to do. It is
68
+ **The work's branch, on `start` and `study`.** The current branch is `meta.json.branch` → no switch. It is
69
69
  not — a study made on another machine arrives on the ticket's `base`, a run that died before its
70
70
  closing order is relaunched there — then, in this order:
71
71
 
@@ -88,6 +88,21 @@ closing order is relaunched there — then, in this order:
88
88
  `meta.json.branch` = it, `meta.json.base` = that base, `worktree` and `stacked_on` = `null` — paths and parents from the
89
89
  other machine mean nothing here — and record `{ "key": "unattended:rehomed", "default": "<old branch> → <name> from <base>", "phase": "run" }`.
90
90
 
91
+ **On `start`, a study's branch catches up with its base** — once on the work's branch, the "no
92
+ switch" case included, and only while no build or fix has begun (neither `05-implementation.md` nor
93
+ `04-fix.md` exists). Every command below runs in the work's own checkout — step 2's worktree when
94
+ that is where it lives. A study writes no code, so its branch still sits where the base was when the
95
+ study began; an approval that waited for the tickets the study depends on (`meta.json.ticket_deps`)
96
+ would otherwise build on a base that lacks them. `<base>` = `meta.json.base`, empty →
97
+ `git.default_base`: `git fetch origin <base>`, then `<ref>` = `origin/<base>`; the fetch failing
98
+ with a remote configured → `blocked`, since a stale ref would leave the build on the old base
99
+ unnoticed. No remote → the local `<base>`. `git merge-base --is-ancestor HEAD <ref>` and `HEAD` is not
100
+ `<ref>` → the branch holds no commit of its own and the base moved: `git merge --ff-only <ref>`, and
101
+ record `{ "key": "unattended:base-caught-up", "default": "<old short sha> → <new short sha> on
102
+ <base>", "phase": "run" }`. The fast-forward fails → `blocked`, its message as the reason. Not an
103
+ ancestor → it holds commits a previous run made: leave it as it is — bringing the base into work in
104
+ progress is the orchestrator's (flow-core §2.1).
105
+
91
106
  **A person's changes to a study, on `study`** (flow-core §2.1: they rewind it). The work's branch
92
107
  first, as above. `<work>/study-revision.md` holds the reply, as the row above wrote it. Each step
93
108
  can be run again: a run that dies part-way is finished by the next relaunch, whatever it serves.
@@ -111,7 +126,8 @@ can be run again: a run that dies part-way is finished by the next relaunch, wha
111
126
  `study-revision.md` and earlier `before-*/` folders into `<work>/before-<id7>/` — never
112
127
  overwriting a name already there — so no artifact, summary or agent answer of the discarded study
113
128
  leaks into the next. Then `meta.json`: `phase` = `context`, `phases_done` = `["context"]`, `mrs`
114
- removed (the row that blocks a work past the study guarantees nothing was built), `notes`
129
+ removed (the row that blocks a work past the study guarantees nothing was built), `ticket_deps`
130
+ removed (the redone study finds its dependencies again), `notes`
115
131
  emptied, and every `followups[]` entry a study phase wrote (`source` `design`, `plan` or
116
132
  `investigate`) removed.
117
133
  5. **Re-size**: estimate the size again with `/flow-feat-start` §4's table (`/flow-bug-start`'s for
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flow-workflows",
3
- "version": "0.91.0",
3
+ "version": "0.93.0",
4
4
  "description": "Guided feat/bug workflows (start→ship), post-deploy monitoring and multi-agent code review, stack-agnostic. Each repo uses a shared FLOW.md plus optional harness overlay.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -3,7 +3,7 @@
3
3
  "name": "flow",
4
4
  "displayName": "Flow — guided dev workflows",
5
5
  "description": "Guided feat/bug workflows (start→ship), post-deploy monitoring and multi-agent code review, stack-agnostic. Each repo uses a shared FLOW.md plus optional harness overlay.",
6
- "version": "0.91.0",
6
+ "version": "0.93.0",
7
7
  "author": {
8
8
  "name": "Alberto Vioque",
9
9
  "email": "mashware@gmail.com"
@@ -5,6 +5,50 @@ plugin and is what `/flow:news` reads to show you what changed since your previo
5
5
 
6
6
  The canonical, richest notes live in the [GitHub Releases](https://github.com/mashware/flow-workflows/releases).
7
7
 
8
+ ## v0.93.0 — A study says which tickets it is waiting for, so whoever builds it waits for them too · 2026-10-13
9
+
10
+ **In short**
11
+ - **`design` and `investigate` detect a dependency on another ticket** before their challenger runs:
12
+ something the chosen solution needs that is not on the base this work builds from (fetched, not
13
+ assumed) and that another ticket brings. A premise that holds whichever ticket merges first is
14
+ listed as *not* a dependency, so nobody waits for it. Each one lands in a new
15
+ `## Depends on other tickets` section and in `meta.json.ticket_deps` (`{ticket, why}`); `plan`
16
+ appends what splitting reveals. It is not `mrs[].depends_on`, which still orders a work's own
17
+ MRs/PRs.
18
+ - **`/flow:work:handoff` writes `Depends on #253`** into the ticket body, one line per dependency,
19
+ after the `flow-study` block so a rewrite of the block leaves it alone. A line already there is not
20
+ added again and none is ever removed; one a revised study dropped is named in the question.
21
+ `Design in brief` lists each dependency with its why for the person approving the study.
22
+ - **An unattended study run tells the orchestrator**: its closing order becomes
23
+ `<cmd> done --summary-file F --depends-on 253 …`, one flag per dependency, the `#` dropped.
24
+ Each value is checked before anything is written; one that is not a plain identifier never
25
+ reaches a command line — the run ends `blocked`, naming it. A ticket in another repo is written in
26
+ the study for a person, not sent. What the orchestrator does with the flags is its call.
27
+ - **An approved study's branch catches up with its base**: on `why = start`, a work branch with no
28
+ commit of its own is fast-forwarded to the current base, so a build that waited for its
29
+ dependencies actually has them. A branch with commits is left alone.
30
+ - **A person building by hand is told too**: `build` and `fix` name the dependencies at the brief and
31
+ ask to confirm the piece is on the work's branch. Flow never checks whether a dependency closed.
32
+ - **Orchestrators**: an orchestrator that rejects unknown flags on `done` must accept
33
+ `--depends-on` before running this version; otherwise every study with a dependency loses its
34
+ closing order.
35
+
36
+ ## v0.92.0 — In an unattended review round, only what the ticket's owner accepts reaches the code · 2026-10-12
37
+
38
+ **In short**
39
+ - **`<cmd> events --json` comments may carry `owner`** — `true` for the ticket's owner, `false` for
40
+ everyone else. The field is part of the review-events contract, not of any one orchestrator.
41
+ - **Once any comment carries it, only `owner: true` orders or accepts.** Every other comment is a
42
+ proposal: `/flow:work:respond` implements it only when an owner comment accepts it — in the
43
+ proposal's own thread, by naming it, or with a bare `ai:implement`, which accepts the whole round.
44
+ A proposal the owner's words do not clearly name is not accepted.
45
+ - **Every proposal is still answered in its own thread**; one not implemented says the owner did not
46
+ accept it. Saying so again in a later round does not trip the repeated-answer rule.
47
+ - **Owner mode sticks**: a work whose earlier round was in owner mode stays in it, so a round where
48
+ only reviewers commented does not turn their comments back into orders. A later round may accept
49
+ a proposal an earlier one left out.
50
+ - **No `owner` on any comment, and no earlier owner round** → exactly the previous behaviour.
51
+
8
52
  ## v0.91.0 — An unattended run resolves the conflicts with its base when the orchestrator launches it for them · 2026-10-11
9
53
 
10
54
  **In short**