flow-workflows 0.92.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.
- package/adapters/codex/CORE.md +12 -5
- package/adapters/codex/skills/flow-bug-fix/SKILL.md +9 -1
- package/adapters/codex/skills/flow-bug-investigate/SKILL.md +11 -0
- package/adapters/codex/skills/flow-feat-build/SKILL.md +9 -2
- package/adapters/codex/skills/flow-feat-design/SKILL.md +30 -0
- package/adapters/codex/skills/flow-feat-plan/SKILL.md +1 -0
- package/adapters/codex/skills/flow-work-README/SKILL.md +4 -0
- package/adapters/codex/skills/flow-work-handoff/SKILL.md +19 -5
- package/adapters/codex/skills/flow-work-run/SKILL.md +18 -2
- package/adapters/gemini/CORE.md +12 -5
- package/adapters/gemini/commands/flow/bug/fix.toml +9 -1
- package/adapters/gemini/commands/flow/bug/investigate.toml +11 -0
- package/adapters/gemini/commands/flow/feat/build.toml +9 -2
- package/adapters/gemini/commands/flow/feat/design.toml +30 -0
- package/adapters/gemini/commands/flow/feat/plan.toml +1 -0
- package/adapters/gemini/commands/flow/work/README.toml +4 -0
- package/adapters/gemini/commands/flow/work/handoff.toml +19 -5
- package/adapters/gemini/commands/flow/work/run.toml +18 -2
- package/adapters/hermes/CORE.md +12 -5
- package/adapters/hermes/skills/flow-bug-fix/SKILL.md +9 -1
- package/adapters/hermes/skills/flow-bug-investigate/SKILL.md +11 -0
- package/adapters/hermes/skills/flow-feat-build/SKILL.md +9 -2
- package/adapters/hermes/skills/flow-feat-design/SKILL.md +30 -0
- package/adapters/hermes/skills/flow-feat-plan/SKILL.md +1 -0
- package/adapters/hermes/skills/flow-work-README/SKILL.md +4 -0
- package/adapters/hermes/skills/flow-work-handoff/SKILL.md +19 -5
- package/adapters/hermes/skills/flow-work-run/SKILL.md +18 -2
- package/adapters/opencode/CORE.md +12 -5
- package/adapters/opencode/commands/flow-bug-fix.md +9 -1
- package/adapters/opencode/commands/flow-bug-investigate.md +11 -0
- package/adapters/opencode/commands/flow-feat-build.md +9 -2
- package/adapters/opencode/commands/flow-feat-design.md +30 -0
- package/adapters/opencode/commands/flow-feat-plan.md +1 -0
- package/adapters/opencode/commands/flow-work-README.md +4 -0
- package/adapters/opencode/commands/flow-work-handoff.md +19 -5
- package/adapters/opencode/commands/flow-work-run.md +18 -2
- package/package.json +1 -1
- package/plugins/flow/.claude-plugin/plugin.json +1 -1
- package/plugins/flow/CHANGELOG.md +28 -0
package/adapters/hermes/CORE.md
CHANGED
|
@@ -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.
|
|
20
|
+
**This file belongs to flow `0.93.0`.** 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
|
|
@@ -253,7 +253,7 @@ assumed:
|
|
|
253
253
|
<cmd> ask --question-file F --options-file F [--recommended N] [--free-text] [--gate NAME]
|
|
254
254
|
<cmd> publish --title-file F --body-file F [--part N --of M]
|
|
255
255
|
<cmd> blocked --reason-file F
|
|
256
|
-
<cmd> done [--summary-file F]
|
|
256
|
+
<cmd> done [--summary-file F] [--depends-on N]…
|
|
257
257
|
<cmd> reply --thread ID --body-file F
|
|
258
258
|
```
|
|
259
259
|
|
|
@@ -314,12 +314,18 @@ runs the study phases as any run does, and three rules make it stop where it sho
|
|
|
314
314
|
study to code crosses that door, an answered question that resumes straight into `build`
|
|
315
315
|
included, so the phases before it carry no clause. The run kind is read there, never stored: the
|
|
316
316
|
approval reuses the same work folder with `why = start`.
|
|
317
|
-
- **At the door**, a study run first
|
|
317
|
+
- **At the door**, a study run first checks each `meta.json.ticket_deps` entry: `N` = its `ticket`
|
|
318
|
+
without a leading `#`, the form `ticket --json` prints `number`, and it must match
|
|
319
|
+
`[A-Za-z0-9][A-Za-z0-9._-]*` — an `N` that does not (a space, a shell character, a leading `-`)
|
|
320
|
+
is never put on a command line: `blocked`, naming the entry, before anything below is written.
|
|
321
|
+
Then it writes the statement of the change when the study holds none
|
|
318
322
|
(the command says which), then `done-summary.md` — the `flow-study` block of `/flow-work-handoff`
|
|
319
323
|
§5, the same sections from the same sources, and, when `01-context.md` lists `## Study revisions`,
|
|
320
324
|
the line `Revised at the reviewer's request: <n> reply(ies)` first under `## What and why`. It
|
|
321
325
|
overwrites `00-summary.md`, sets the panel's `attention` to `done` and closes with
|
|
322
|
-
`done --summary-file
|
|
326
|
+
`done --summary-file`, plus one `--depends-on N` per `meta.json.ticket_deps` entry, in its order —
|
|
327
|
+
so the orchestrator can hold the ticket until those land; what it does with them is its call.
|
|
328
|
+
Nothing else moves — no `mrs[]` entry, no branch, no brief — so
|
|
323
329
|
`meta.json.phase` stays at the last study phase and approval is an ordinary `start`.
|
|
324
330
|
- **A person's changes rewind the study.** `/flow-work-run` §2 adds the reply to the ticket in
|
|
325
331
|
`01-context.md` and sends the work back to `context`; the study phases then run again whole, the
|
|
@@ -332,7 +338,7 @@ person asking for changes, a ticket that already has code — is `/flow-work-run
|
|
|
332
338
|
| Where | In `unattended` |
|
|
333
339
|
|---|---|
|
|
334
340
|
| Business brief before code (`build`, `fix`) | record — the brief is written to the phase artifact, marked `recorded (unattended)`, and travels in the MR/PR body |
|
|
335
|
-
| The door to code in a study run (`build`, `fix` pre-flight) | done — `done-summary.md`, the study as `/flow-work-handoff` §5 writes it for the ticket |
|
|
341
|
+
| The door to code in a study run (`build`, `fix` pre-flight) | done — `done-summary.md`, the study as `/flow-work-handoff` §5 writes it for the ticket, and one `--depends-on` per `meta.json.ticket_deps` entry |
|
|
336
342
|
| Push and MR/PR creation (`ship`) | `publish` — the run commits on its own branch, writes title and body, and hands them over; the orchestrator pushes and opens the draft |
|
|
337
343
|
| Writing a DB schema change, index or migration — in any phase, a review's own fixes included — or applying one (`validate`) | question `migration`, before the first line of it is written or run — except in `respond` and `green`, where it is blocked: a schema change agreed after the MR/PR exists goes back through `build` |
|
|
338
344
|
| `review` with blockers or high-severity findings | question `high_findings` |
|
|
@@ -352,6 +358,7 @@ person asking for changes, a ticket that already has code — is `/flow-work-run
|
|
|
352
358
|
| The next MR/PR of a train (`ship` close) | record — not started: one MR/PR per unattended run |
|
|
353
359
|
| `build` with no startable MR/PR (its `depends_on` not `merged` in `meta.json`) | blocked — the reason names what must merge; an unattended `build` never stacks a branch on another, and never creates a remote branch |
|
|
354
360
|
| The parent of a stacked MR/PR merged — rebase and force-push | blocked — never force-push unattended |
|
|
361
|
+
| 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 |
|
|
355
362
|
| 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 |
|
|
356
363
|
| 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 |
|
|
357
364
|
| 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 |
|
|
@@ -36,7 +36,15 @@ Read `~/.claude/flow/CORE.hermes.md` first (shared rules: `FLOW.md` step 0, mode
|
|
|
36
36
|
would make — from the root cause and the constraints for the fix when the investigation has them,
|
|
37
37
|
the reproduction and the ticket otherwise, `## Study revisions` included — the person approves a
|
|
38
38
|
stated change, never `none`; then the summary, and
|
|
39
|
-
`<cmd> done --summary-file <work>/done-summary.md
|
|
39
|
+
`<cmd> done --summary-file <work>/done-summary.md`, plus `--depends-on N` per
|
|
40
|
+
`meta.json.ticket_deps` entry, `N` its `ticket` with the leading `#` dropped — a bare `#` starts a
|
|
41
|
+
shell comment — and checked against `[A-Za-z0-9][A-Za-z0-9._-]*` before anything is written, else
|
|
42
|
+
`blocked` (flow-core §2.1). Nothing else in this command runs.
|
|
43
|
+
- **`meta.json.ticket_deps` not empty, and not `unattended`** → the study rests on other tickets
|
|
44
|
+
(`/flow-feat-design` §5.1): name each — `<ticket> — <why>` — in the brief's stop (§2), one line,
|
|
45
|
+
so whoever builds confirms the piece is on **this work's branch**, not only on its base — the
|
|
46
|
+
branch was cut when the study began, and a piece that merged since needs the base brought in
|
|
47
|
+
before writing against it. Nothing is checked; waiting is the builder's call.
|
|
40
48
|
- `size` `XS`: may start without `investigate`, but require a 2-3 line description of the fix — an `## Intended fix` in `03-investigation.md` is that description.
|
|
41
49
|
- **An `## Intended fix` in `03-investigation.md` binds §2's brief at every size**: it is what a person approved at the end of a study (flow-core §2.1).
|
|
42
50
|
- `size` ≥ S: require `investigate` in `phases_done` (on S it will have run its reproduction half only).
|
|
@@ -174,10 +174,21 @@ If `agents.fanout_tool` is set in `FLOW.md`, run the sweep through that tool; br
|
|
|
174
174
|
- Do not touch X because…
|
|
175
175
|
- Consider Y because…
|
|
176
176
|
|
|
177
|
+
## Depends on other tickets
|
|
178
|
+
<§4.1: `- <ticket> — <what it brings that the base branch lacks>`, then "Not dependencies (either order works)", or "none".>
|
|
179
|
+
|
|
177
180
|
## Investigation challenges
|
|
178
181
|
<filled in by §5 with the challenger table>
|
|
179
182
|
```
|
|
180
183
|
|
|
184
|
+
### 4.1 Tickets this fix depends on
|
|
185
|
+
|
|
186
|
+
A fix can rest on another ticket the same way a design can — a corrected contract, a migration, a
|
|
187
|
+
decision that lands only when that ticket merges. Detect and record it before the challenger, exactly
|
|
188
|
+
as `/flow-feat-design` §5.1 says: the same rule, the same "Not dependencies (either order works)"
|
|
189
|
+
line, the same `meta.json.ticket_deps` entries, written under `## Depends on other tickets` in
|
|
190
|
+
`03-investigation.md`.
|
|
191
|
+
|
|
181
192
|
## 5. Root cause challenge (challenger)
|
|
182
193
|
|
|
183
194
|
Before closing, launch a `Agent general-purpose` challenger with this task:
|
|
@@ -33,8 +33,15 @@ Implementation phase. Code is written here.
|
|
|
33
33
|
and act as flow-core §2.1 "A study run" says. On `study` → this run writes no code: `size` XS and
|
|
34
34
|
no `03-design.md` → first write the 2–3 line note below as that file, from `01-context.md` (its
|
|
35
35
|
`## Study revisions` included) — the person approves a stated change, never `none`; then the
|
|
36
|
-
summary, and `<cmd> done --summary-file <work>/done-summary.md
|
|
37
|
-
|
|
36
|
+
summary, and `<cmd> done --summary-file <work>/done-summary.md`, plus `--depends-on N` per
|
|
37
|
+
`meta.json.ticket_deps` entry, `N` its `ticket` with the leading `#` dropped — a bare `#` starts a
|
|
38
|
+
shell comment — and checked against `[A-Za-z0-9][A-Za-z0-9._-]*` before anything is written, else
|
|
39
|
+
`blocked` (flow-core §2.1). Nothing else in this command runs.
|
|
40
|
+
- **`meta.json.ticket_deps` not empty, and not `unattended`** → the study rests on other tickets
|
|
41
|
+
(`/flow-feat-design` §5.1): name each — `<ticket> — <why>` — in the brief's stop (§2), one line,
|
|
42
|
+
so whoever builds confirms the piece is on **this work's branch**, not only on its base — the
|
|
43
|
+
branch was cut when the study began, and a piece that merged since needs the base brought in
|
|
44
|
+
before writing against it. Nothing is checked; waiting is the builder's call.
|
|
38
45
|
- `size` M/L: require both `03-design.md` **and** `04-mr-plan.md`. Plan missing → send to `/flow-feat-plan`; design missing → send to `/flow-feat-design`.
|
|
39
46
|
- `size` XS/S: may start without a design — ask the user for a 2-3 line note on what will be done and save it as a minimal `03-design.md`. No MR/PR plan (always 1 MR/PR).
|
|
40
47
|
- **If `meta.json.mrs` has more than one entry**: pick the **startable** MR/PR — the `pending` one with the **lowest `n` whose `depends_on` are all `merged`**. Dependencies still `pending`/`in_progress` → not startable, even with a low `n`. (No `wave`/`depends_on` — an older plan — → "first pending by `n`".)
|
|
@@ -290,6 +290,9 @@ Consolidate outputs into `.claude/work/<TICKET>/03-design.md`:
|
|
|
290
290
|
- **Invariant**: <e.g. "after assignTo(user), ticket.assignee == user AND ticket.status != 'unassigned'">
|
|
291
291
|
- **Edge / boundary**: <e.g. "empty input list → returns 0, does not throw">
|
|
292
292
|
|
|
293
|
+
## Depends on other tickets
|
|
294
|
+
<§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".>
|
|
295
|
+
|
|
293
296
|
## Defensive mechanisms and their justification
|
|
294
297
|
<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.>
|
|
295
298
|
|
|
@@ -318,6 +321,33 @@ Consolidate outputs into `.claude/work/<TICKET>/03-design.md`:
|
|
|
318
321
|
|
|
319
322
|
**"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.
|
|
320
323
|
|
|
324
|
+
### 5.1 Tickets this design depends on
|
|
325
|
+
|
|
326
|
+
Fill `## Depends on other tickets` now, before the challenger of §6 reads the design. The study is
|
|
327
|
+
often built by someone who never saw it made — another person, an unattended server — and who
|
|
328
|
+
starts from the base. A design that rests on what another ticket has not delivered yet leaves that
|
|
329
|
+
builder to find the piece missing and either ask or redo it.
|
|
330
|
+
|
|
331
|
+
- **A dependency** is a piece, contract or decision the chosen design needs, that is **not on the
|
|
332
|
+
base this work builds from** (`meta.json.base`, empty → `git.default_base`) — checked there, after
|
|
333
|
+
a best-effort `git fetch origin <base>`, never assumed from a local ref — and that **another
|
|
334
|
+
ticket** of this tracker brings. Missing from the base with no ticket bringing it → it is scope
|
|
335
|
+
or an open question, not a dependency. A ticket in another repo is not a `ticket_deps` entry —
|
|
336
|
+
the orchestrator only resolves this tracker's numbers — so write it in the section as a
|
|
337
|
+
cross-repo dependency, for a person, and leave it out of the list.
|
|
338
|
+
- **Not a dependency**: a premise that holds whichever ticket merges first. Say so under "Not
|
|
339
|
+
dependencies (either order works)", so nobody waits for it.
|
|
340
|
+
- **Record each one** in that section and in `meta.json.ticket_deps` —
|
|
341
|
+
`{ "ticket": "<the reference as a ticket body writes it: #253, MT-123>", "why": "<one line>" }`,
|
|
342
|
+
never one twice. `ticket_deps` is the record the exits read (`/flow-work-handoff` §5, the door to
|
|
343
|
+
code of an unattended study run, flow-core §2.1); the section is the study's prose. Each run of
|
|
344
|
+
this phase writes the list whole from the design it closes; `plan`, which runs after it, appends
|
|
345
|
+
its own again. A §6 response or a §9 edit that changes what the design needs changes
|
|
346
|
+
the section and the list together. None → `[]` and "none".
|
|
347
|
+
|
|
348
|
+
`ticket_deps` is not `mrs[].depends_on`: that one orders this work's own MRs/PRs, this one names
|
|
349
|
+
other tickets. Flow never checks whether a dependency has closed — whoever builds waits for it.
|
|
350
|
+
|
|
321
351
|
## 6. Design challenge (challenger)
|
|
322
352
|
|
|
323
353
|
Before closing, **challenge the design** with an `Agent general-purpose` and this self-contained brief:
|
|
@@ -126,6 +126,7 @@ Add the `mrs` array with the agreed plan:
|
|
|
126
126
|
```
|
|
127
127
|
|
|
128
128
|
- `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.
|
|
129
|
+
- **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.
|
|
129
130
|
- **`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.
|
|
130
131
|
- 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.
|
|
131
132
|
|
|
@@ -112,6 +112,9 @@ This system **orchestrates** the project's existing sub-agents and skills (it do
|
|
|
112
112
|
"note": "reason if closed/superseded; empty otherwise"
|
|
113
113
|
}
|
|
114
114
|
],
|
|
115
|
+
"ticket_deps": [
|
|
116
|
+
{ "ticket": "#253", "why": "one line, what that ticket brings that the base branch lacks" }
|
|
117
|
+
],
|
|
115
118
|
"related_repos": [
|
|
116
119
|
{ "repo": "sibling-project", "scope": "what's needed there", "status": "pending" | "in_progress" | "done", "contract_handoff": "none" | "pending" | "published → <location>" }
|
|
117
120
|
],
|
|
@@ -160,6 +163,7 @@ This system **orchestrates** the project's existing sub-agents and skills (it do
|
|
|
160
163
|
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.
|
|
161
164
|
- **`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.
|
|
162
165
|
- **`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.
|
|
166
|
+
- **`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.
|
|
163
167
|
- **`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.
|
|
164
168
|
- **`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.
|
|
165
169
|
- **`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.
|
|
@@ -148,13 +148,27 @@ the ticket read it there, never in the work folder; the receiver does not parse
|
|
|
148
148
|
<!-- end flow-study -->
|
|
149
149
|
```
|
|
150
150
|
|
|
151
|
-
Criteria keep their literal values.
|
|
152
|
-
|
|
151
|
+
Criteria keep their literal values. `## Design in brief` ends with each `meta.json.ticket_deps`
|
|
152
|
+
entry and its why — `Depends on #253: <why>` — so whoever approves the study sees what it waits
|
|
153
|
+
for; an unattended study's `done-summary.md` is this block, so it carries them too. The plan
|
|
154
|
+
lists each MR/PR with what it covers and what it waits on; a bug's plan is its single fix.
|
|
153
155
|
- **The new body**: the body read above with the block between the two markers replaced — or, with
|
|
154
|
-
no markers yet, the block appended after a blank line.
|
|
156
|
+
no markers yet, the block appended after a blank line. Then, for each `meta.json.ticket_deps`
|
|
157
|
+
entry (`/flow-feat-design` §5.1) whose line is not already a line of that body — same text,
|
|
158
|
+
ignoring case and surrounding whitespace — one line after the end marker, in `ticket_deps` order:
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
Depends on #253
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
`#253` being the entry's `ticket` as it stands. Outside the markers so a later rewrite of the
|
|
165
|
+
block leaves it alone, and never removed: a line a person wrote by hand looks exactly like one
|
|
166
|
+
flow wrote, and the convention is theirs too. Written to a `mktemp` file outside the
|
|
155
167
|
tree — `{BODY_FILE}` — so nothing of it can be committed later.
|
|
156
|
-
- **Show the block and ask** with `AskUserQuestion`, **in
|
|
157
|
-
|
|
168
|
+
- **Show the block, and the `Depends on` lines it adds, and ask** with `AskUserQuestion`, **in
|
|
169
|
+
every mode**: it writes to a shared tracker. A `Depends on` line already in the body, outside the
|
|
170
|
+
markers, that no entry names — a dependency a revised study dropped, or one a person added — is named in the same
|
|
171
|
+
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.
|
|
158
172
|
|
|
159
173
|
## 6. Close
|
|
160
174
|
|
|
@@ -67,7 +67,7 @@ of truth, and an argument that disagrees with it is ignored and named in the log
|
|
|
67
67
|
| `conflict` | exists | `/flow-work-green` — the MR/PR conflicts with its base; which base, and where it stands, come from `<cmd> events --json` |
|
|
68
68
|
| `review` · `pipeline` · `conflict` | none | `blocked` — there is no work of this ticket to answer for |
|
|
69
69
|
|
|
70
|
-
**The work's branch, on `start` and `study`.** The current branch is `meta.json.branch` →
|
|
70
|
+
**The work's branch, on `start` and `study`.** The current branch is `meta.json.branch` → no switch. It is
|
|
71
71
|
not — a study made on another machine arrives on the ticket's `base`, a run that died before its
|
|
72
72
|
closing order is relaunched there — then, in this order:
|
|
73
73
|
|
|
@@ -90,6 +90,21 @@ closing order is relaunched there — then, in this order:
|
|
|
90
90
|
`meta.json.branch` = it, `meta.json.base` = that base, `worktree` and `stacked_on` = `null` — paths and parents from the
|
|
91
91
|
other machine mean nothing here — and record `{ "key": "unattended:rehomed", "default": "<old branch> → <name> from <base>", "phase": "run" }`.
|
|
92
92
|
|
|
93
|
+
**On `start`, a study's branch catches up with its base** — once on the work's branch, the "no
|
|
94
|
+
switch" case included, and only while no build or fix has begun (neither `05-implementation.md` nor
|
|
95
|
+
`04-fix.md` exists). Every command below runs in the work's own checkout — step 2's worktree when
|
|
96
|
+
that is where it lives. A study writes no code, so its branch still sits where the base was when the
|
|
97
|
+
study began; an approval that waited for the tickets the study depends on (`meta.json.ticket_deps`)
|
|
98
|
+
would otherwise build on a base that lacks them. `<base>` = `meta.json.base`, empty →
|
|
99
|
+
`git.default_base`: `git fetch origin <base>`, then `<ref>` = `origin/<base>`; the fetch failing
|
|
100
|
+
with a remote configured → `blocked`, since a stale ref would leave the build on the old base
|
|
101
|
+
unnoticed. No remote → the local `<base>`. `git merge-base --is-ancestor HEAD <ref>` and `HEAD` is not
|
|
102
|
+
`<ref>` → the branch holds no commit of its own and the base moved: `git merge --ff-only <ref>`, and
|
|
103
|
+
record `{ "key": "unattended:base-caught-up", "default": "<old short sha> → <new short sha> on
|
|
104
|
+
<base>", "phase": "run" }`. The fast-forward fails → `blocked`, its message as the reason. Not an
|
|
105
|
+
ancestor → it holds commits a previous run made: leave it as it is — bringing the base into work in
|
|
106
|
+
progress is the orchestrator's (flow-core §2.1).
|
|
107
|
+
|
|
93
108
|
**A person's changes to a study, on `study`** (flow-core §2.1: they rewind it). The work's branch
|
|
94
109
|
first, as above. `<work>/study-revision.md` holds the reply, as the row above wrote it. Each step
|
|
95
110
|
can be run again: a run that dies part-way is finished by the next relaunch, whatever it serves.
|
|
@@ -113,7 +128,8 @@ can be run again: a run that dies part-way is finished by the next relaunch, wha
|
|
|
113
128
|
`study-revision.md` and earlier `before-*/` folders into `<work>/before-<id7>/` — never
|
|
114
129
|
overwriting a name already there — so no artifact, summary or agent answer of the discarded study
|
|
115
130
|
leaks into the next. Then `meta.json`: `phase` = `context`, `phases_done` = `["context"]`, `mrs`
|
|
116
|
-
removed (the row that blocks a work past the study guarantees nothing was built), `
|
|
131
|
+
removed (the row that blocks a work past the study guarantees nothing was built), `ticket_deps`
|
|
132
|
+
removed (the redone study finds its dependencies again), `notes`
|
|
117
133
|
emptied, and every `followups[]` entry a study phase wrote (`source` `design`, `plan` or
|
|
118
134
|
`investigate`) removed.
|
|
119
135
|
5. **Re-size**: estimate the size again with `/flow-feat-start` §4's table (`/flow-bug-start`'s for
|
|
@@ -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.
|
|
19
|
+
**This file belongs to flow `0.93.0`.** 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
|
|
@@ -252,7 +252,7 @@ assumed:
|
|
|
252
252
|
<cmd> ask --question-file F --options-file F [--recommended N] [--free-text] [--gate NAME]
|
|
253
253
|
<cmd> publish --title-file F --body-file F [--part N --of M]
|
|
254
254
|
<cmd> blocked --reason-file F
|
|
255
|
-
<cmd> done [--summary-file F]
|
|
255
|
+
<cmd> done [--summary-file F] [--depends-on N]…
|
|
256
256
|
<cmd> reply --thread ID --body-file F
|
|
257
257
|
```
|
|
258
258
|
|
|
@@ -313,12 +313,18 @@ runs the study phases as any run does, and three rules make it stop where it sho
|
|
|
313
313
|
study to code crosses that door, an answered question that resumes straight into `build`
|
|
314
314
|
included, so the phases before it carry no clause. The run kind is read there, never stored: the
|
|
315
315
|
approval reuses the same work folder with `why = start`.
|
|
316
|
-
- **At the door**, a study run first
|
|
316
|
+
- **At the door**, a study run first checks each `meta.json.ticket_deps` entry: `N` = its `ticket`
|
|
317
|
+
without a leading `#`, the form `ticket --json` prints `number`, and it must match
|
|
318
|
+
`[A-Za-z0-9][A-Za-z0-9._-]*` — an `N` that does not (a space, a shell character, a leading `-`)
|
|
319
|
+
is never put on a command line: `blocked`, naming the entry, before anything below is written.
|
|
320
|
+
Then it writes the statement of the change when the study holds none
|
|
317
321
|
(the command says which), then `done-summary.md` — the `flow-study` block of `/flow-work-handoff`
|
|
318
322
|
§5, the same sections from the same sources, and, when `01-context.md` lists `## Study revisions`,
|
|
319
323
|
the line `Revised at the reviewer's request: <n> reply(ies)` first under `## What and why`. It
|
|
320
324
|
overwrites `00-summary.md`, sets the panel's `attention` to `done` and closes with
|
|
321
|
-
`done --summary-file
|
|
325
|
+
`done --summary-file`, plus one `--depends-on N` per `meta.json.ticket_deps` entry, in its order —
|
|
326
|
+
so the orchestrator can hold the ticket until those land; what it does with them is its call.
|
|
327
|
+
Nothing else moves — no `mrs[]` entry, no branch, no brief — so
|
|
322
328
|
`meta.json.phase` stays at the last study phase and approval is an ordinary `start`.
|
|
323
329
|
- **A person's changes rewind the study.** `/flow-work-run` §2 adds the reply to the ticket in
|
|
324
330
|
`01-context.md` and sends the work back to `context`; the study phases then run again whole, the
|
|
@@ -331,7 +337,7 @@ person asking for changes, a ticket that already has code — is `/flow-work-run
|
|
|
331
337
|
| Where | In `unattended` |
|
|
332
338
|
|---|---|
|
|
333
339
|
| Business brief before code (`build`, `fix`) | record — the brief is written to the phase artifact, marked `recorded (unattended)`, and travels in the MR/PR body |
|
|
334
|
-
| The door to code in a study run (`build`, `fix` pre-flight) | done — `done-summary.md`, the study as `/flow-work-handoff` §5 writes it for the ticket |
|
|
340
|
+
| The door to code in a study run (`build`, `fix` pre-flight) | done — `done-summary.md`, the study as `/flow-work-handoff` §5 writes it for the ticket, and one `--depends-on` per `meta.json.ticket_deps` entry |
|
|
335
341
|
| Push and MR/PR creation (`ship`) | `publish` — the run commits on its own branch, writes title and body, and hands them over; the orchestrator pushes and opens the draft |
|
|
336
342
|
| Writing a DB schema change, index or migration — in any phase, a review's own fixes included — or applying one (`validate`) | question `migration`, before the first line of it is written or run — except in `respond` and `green`, where it is blocked: a schema change agreed after the MR/PR exists goes back through `build` |
|
|
337
343
|
| `review` with blockers or high-severity findings | question `high_findings` |
|
|
@@ -351,6 +357,7 @@ person asking for changes, a ticket that already has code — is `/flow-work-run
|
|
|
351
357
|
| The next MR/PR of a train (`ship` close) | record — not started: one MR/PR per unattended run |
|
|
352
358
|
| `build` with no startable MR/PR (its `depends_on` not `merged` in `meta.json`) | blocked — the reason names what must merge; an unattended `build` never stacks a branch on another, and never creates a remote branch |
|
|
353
359
|
| The parent of a stacked MR/PR merged — rebase and force-push | blocked — never force-push unattended |
|
|
360
|
+
| 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 |
|
|
354
361
|
| 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 |
|
|
355
362
|
| 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 |
|
|
356
363
|
| 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 |
|
|
@@ -34,7 +34,15 @@ Read `~/.claude/flow/CORE.opencode.md` first (shared rules: `FLOW.md` step 0, mo
|
|
|
34
34
|
would make — from the root cause and the constraints for the fix when the investigation has them,
|
|
35
35
|
the reproduction and the ticket otherwise, `## Study revisions` included — the person approves a
|
|
36
36
|
stated change, never `none`; then the summary, and
|
|
37
|
-
`<cmd> done --summary-file <work>/done-summary.md
|
|
37
|
+
`<cmd> done --summary-file <work>/done-summary.md`, plus `--depends-on N` per
|
|
38
|
+
`meta.json.ticket_deps` entry, `N` its `ticket` with the leading `#` dropped — a bare `#` starts a
|
|
39
|
+
shell comment — and checked against `[A-Za-z0-9][A-Za-z0-9._-]*` before anything is written, else
|
|
40
|
+
`blocked` (flow-core §2.1). Nothing else in this command runs.
|
|
41
|
+
- **`meta.json.ticket_deps` not empty, and not `unattended`** → the study rests on other tickets
|
|
42
|
+
(`/flow-feat-design` §5.1): name each — `<ticket> — <why>` — in the brief's stop (§2), one line,
|
|
43
|
+
so whoever builds confirms the piece is on **this work's branch**, not only on its base — the
|
|
44
|
+
branch was cut when the study began, and a piece that merged since needs the base brought in
|
|
45
|
+
before writing against it. Nothing is checked; waiting is the builder's call.
|
|
38
46
|
- `size` `XS`: may start without `investigate`, but require a 2-3 line description of the fix — an `## Intended fix` in `03-investigation.md` is that description.
|
|
39
47
|
- **An `## Intended fix` in `03-investigation.md` binds §2's brief at every size**: it is what a person approved at the end of a study (flow-core §2.1).
|
|
40
48
|
- `size` ≥ S: require `investigate` in `phases_done` (on S it will have run its reproduction half only).
|
|
@@ -172,10 +172,21 @@ If `agents.fanout_tool` is set in `FLOW.md`, run the sweep through that tool; br
|
|
|
172
172
|
- Do not touch X because…
|
|
173
173
|
- Consider Y because…
|
|
174
174
|
|
|
175
|
+
## Depends on other tickets
|
|
176
|
+
<§4.1: `- <ticket> — <what it brings that the base branch lacks>`, then "Not dependencies (either order works)", or "none".>
|
|
177
|
+
|
|
175
178
|
## Investigation challenges
|
|
176
179
|
<filled in by §5 with the challenger table>
|
|
177
180
|
```
|
|
178
181
|
|
|
182
|
+
### 4.1 Tickets this fix depends on
|
|
183
|
+
|
|
184
|
+
A fix can rest on another ticket the same way a design can — a corrected contract, a migration, a
|
|
185
|
+
decision that lands only when that ticket merges. Detect and record it before the challenger, exactly
|
|
186
|
+
as `/flow-feat-design` §5.1 says: the same rule, the same "Not dependencies (either order works)"
|
|
187
|
+
line, the same `meta.json.ticket_deps` entries, written under `## Depends on other tickets` in
|
|
188
|
+
`03-investigation.md`.
|
|
189
|
+
|
|
179
190
|
## 5. Root cause challenge (challenger)
|
|
180
191
|
|
|
181
192
|
Before closing, launch a `Agent general-purpose` challenger with this task:
|
|
@@ -31,8 +31,15 @@ Implementation phase. Code is written here.
|
|
|
31
31
|
and act as flow-core §2.1 "A study run" says. On `study` → this run writes no code: `size` XS and
|
|
32
32
|
no `03-design.md` → first write the 2–3 line note below as that file, from `01-context.md` (its
|
|
33
33
|
`## Study revisions` included) — the person approves a stated change, never `none`; then the
|
|
34
|
-
summary, and `<cmd> done --summary-file <work>/done-summary.md
|
|
35
|
-
|
|
34
|
+
summary, and `<cmd> done --summary-file <work>/done-summary.md`, plus `--depends-on N` per
|
|
35
|
+
`meta.json.ticket_deps` entry, `N` its `ticket` with the leading `#` dropped — a bare `#` starts a
|
|
36
|
+
shell comment — and checked against `[A-Za-z0-9][A-Za-z0-9._-]*` before anything is written, else
|
|
37
|
+
`blocked` (flow-core §2.1). Nothing else in this command runs.
|
|
38
|
+
- **`meta.json.ticket_deps` not empty, and not `unattended`** → the study rests on other tickets
|
|
39
|
+
(`/flow-feat-design` §5.1): name each — `<ticket> — <why>` — in the brief's stop (§2), one line,
|
|
40
|
+
so whoever builds confirms the piece is on **this work's branch**, not only on its base — the
|
|
41
|
+
branch was cut when the study began, and a piece that merged since needs the base brought in
|
|
42
|
+
before writing against it. Nothing is checked; waiting is the builder's call.
|
|
36
43
|
- `size` M/L: require both `03-design.md` **and** `04-mr-plan.md`. Plan missing → send to `/flow-feat-plan`; design missing → send to `/flow-feat-design`.
|
|
37
44
|
- `size` XS/S: may start without a design — ask the user for a 2-3 line note on what will be done and save it as a minimal `03-design.md`. No MR/PR plan (always 1 MR/PR).
|
|
38
45
|
- **If `meta.json.mrs` has more than one entry**: pick the **startable** MR/PR — the `pending` one with the **lowest `n` whose `depends_on` are all `merged`**. Dependencies still `pending`/`in_progress` → not startable, even with a low `n`. (No `wave`/`depends_on` — an older plan — → "first pending by `n`".)
|
|
@@ -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.
|
|
150
|
-
|
|
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.
|
|
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
|
|
155
|
-
|
|
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
|
|
|
@@ -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` →
|
|
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), `
|
|
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.
|
|
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.
|
|
6
|
+
"version": "0.93.0",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Alberto Vioque",
|
|
9
9
|
"email": "mashware@gmail.com"
|