flow-workflows 0.80.0 → 0.81.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 +22 -38
- package/adapters/codex/skills/flow-bug-investigate/SKILL.md +1 -6
- package/adapters/codex/skills/flow-bug-review/SKILL.md +3 -3
- package/adapters/codex/skills/flow-doctor/SKILL.md +0 -3
- package/adapters/codex/skills/flow-feat-design/SKILL.md +1 -4
- package/adapters/codex/skills/flow-feat-review/SKILL.md +14 -15
- package/adapters/codex/skills/flow-work-README/SKILL.md +2 -3
- package/adapters/codex/skills/flow-work-resume/SKILL.md +0 -1
- package/adapters/gemini/CORE.md +22 -38
- package/adapters/gemini/commands/flow/bug/investigate.toml +1 -6
- package/adapters/gemini/commands/flow/bug/review.toml +3 -3
- package/adapters/gemini/commands/flow/doctor.toml +0 -3
- package/adapters/gemini/commands/flow/feat/design.toml +1 -4
- package/adapters/gemini/commands/flow/feat/review.toml +14 -15
- package/adapters/gemini/commands/flow/work/README.toml +2 -3
- package/adapters/gemini/commands/flow/work/resume.toml +0 -1
- package/adapters/hermes/CORE.md +22 -38
- package/adapters/hermes/skills/flow-bug-investigate/SKILL.md +1 -6
- package/adapters/hermes/skills/flow-bug-review/SKILL.md +3 -3
- package/adapters/hermes/skills/flow-doctor/SKILL.md +0 -3
- package/adapters/hermes/skills/flow-feat-design/SKILL.md +1 -4
- package/adapters/hermes/skills/flow-feat-review/SKILL.md +14 -15
- package/adapters/hermes/skills/flow-work-README/SKILL.md +2 -3
- package/adapters/hermes/skills/flow-work-resume/SKILL.md +0 -1
- package/adapters/opencode/CORE.md +22 -38
- package/adapters/opencode/commands/flow-bug-investigate.md +1 -6
- package/adapters/opencode/commands/flow-bug-review.md +3 -3
- package/adapters/opencode/commands/flow-doctor.md +0 -3
- package/adapters/opencode/commands/flow-feat-design.md +1 -4
- package/adapters/opencode/commands/flow-feat-review.md +14 -15
- package/adapters/opencode/commands/flow-work-README.md +2 -3
- package/adapters/opencode/commands/flow-work-resume.md +0 -1
- package/package.json +1 -1
- package/plugins/flow/.claude-plugin/plugin.json +1 -1
- package/plugins/flow/CHANGELOG.md +17 -0
|
@@ -40,7 +40,7 @@ Mandatory review phase. **`/flow-feat-ship` cannot run without passing through h
|
|
|
40
40
|
member runs its own `git diff` and opens the same files pays for that material once per agent, and
|
|
41
41
|
a reviewer that spends its turns exploring has fewer left to review. **Any non-zero exit is a
|
|
42
42
|
fallback, not a failure** — no CLI on the machine, a base that does not resolve, a network that
|
|
43
|
-
cannot reach it: read the diff from git
|
|
43
|
+
cannot reach it: read the diff from git and carry on, once, without retrying variants.
|
|
44
44
|
What is not optional is the `Review path` line of §8: a round that skipped the pack and one that
|
|
45
45
|
used it are indistinguishable from the artifact otherwise, which is how a phase quietly stops
|
|
46
46
|
paying for itself.
|
|
@@ -69,7 +69,7 @@ Mandatory review phase. **`/flow-feat-ship` cannot run without passing through h
|
|
|
69
69
|
|
|
70
70
|
### 1.5 Freeze what you are about to read, and resolve what to compare it against
|
|
71
71
|
|
|
72
|
-
Two questions, answered here and nowhere later: **which tree** this round reads, and **against which base**.
|
|
72
|
+
Two questions, answered here and nowhere later: **which tree** this round reads, and **against which base**. Neither is implicit: the checkout changes while the round runs, and `git.default_base` is not always the right base.
|
|
73
73
|
|
|
74
74
|
**The candidate.** A round applies its own fixes; the README's own first-minute example is *"3 reviewers, one finding — fixed"*. So "the working tree" is a different tree for the reviewer that read it first, for the skeptic that read it last, and for the `git rev-parse HEAD` taken at §9 — which by construction contains code no reviewer ever saw, and which `/flow-feat-ship §1` then compares against `HEAD` and finds equal. Resolve one revision before §2 launches anything:
|
|
75
75
|
|
|
@@ -79,11 +79,11 @@ Two questions, answered here and nowhere later: **which tree** this round reads,
|
|
|
79
79
|
- Anchor it so it cannot be collected: `git update-ref refs/flow/candidate/<TICKET> <sha>`. A `stash create` object is unreferenced, and a candidate the `ship` gate cannot resolve is a gate that reports nothing. The ref is local, never pushed, and `/flow-feat-ship §6.5` deletes it.
|
|
80
80
|
- Write `candidate_sha` to `meta.json` — work-level and in the current `mrs[]` entry — **in this pre-flight**. A candidate recorded after the reading is not a freeze.
|
|
81
81
|
|
|
82
|
-
**The review base.** `reviewed_sha`
|
|
82
|
+
**The review base.** `reviewed_sha` records the tree the last passing review read, and `ship` trusts it enough to stop a push. Reading only the delta since it keeps a second review from re-reading every line the first one cleared, and keeps §2.0 from resolving the tier on the accumulated total — a 30-line delta on a 900-line branch is a 30-line review. Resolve:
|
|
83
83
|
|
|
84
84
|
- The current MR/PR's `reviewed_sha` (work-level when there is no train) when it is **non-empty** and **an ancestor of the candidate** (`git merge-base --is-ancestor <sha> <candidate>`) → that is the base.
|
|
85
85
|
- Otherwise `git.default_base`. A `reviewed_sha` that is not an ancestor means history was rewritten or the branch recut; say so in one line rather than producing a nonsensical delta.
|
|
86
|
-
- **A first review has no `reviewed_sha` and reads the whole branch
|
|
86
|
+
- **A first review has no `reviewed_sha` and reads the whole branch**. The delta path only exists after a review that passed.
|
|
87
87
|
- `/flow-feat-review --full` ignores `reviewed_sha` and reads the branch on demand.
|
|
88
88
|
- **Fall back to `git.default_base` and say why** when either holds, because a delta cannot see how it interacts with what was cleared before: the delta touches a file the previous review left a finding on, or it changes an external contract copied under `/flow-feat-build §2.0bis`.
|
|
89
89
|
|
|
@@ -97,7 +97,7 @@ Scope for every reviewer: **the candidate revision of §1.5, against the review
|
|
|
97
97
|
|
|
98
98
|
**The CLI resolves it; you obey the output and record any deviation.** `npx flow-workflows@<version> tier --harness hermes --rev <candidate_sha> --base <review base>` prints, from the config it already parses: changed lines over the §1.5 range, diff size, `meta.json.size`, **effective size** (the lower of the two), the built-in `code-review` effort with and without the sensitive-surface bump, whether the panel runs, the resolved `agents.budget_max`/`fanout_max`, whether the measurement landed **within 10% under** a threshold that changed the tier, and which `quality.sensitive_paths` globs the diff matched, with the path that matched each.
|
|
99
99
|
|
|
100
|
-
Every step of that is arithmetic
|
|
100
|
+
Every step of that is arithmetic. A tier this agent derives itself writes the same artifact whether it measured the diff or eyeballed it — on the one number in this command that carries an incentive on it.
|
|
101
101
|
|
|
102
102
|
**Copy the output verbatim** into the `Review tier` and `Effective size` lines of §8, the way `bundle --checks` copies static analysis out. A computed line, not a narrated one.
|
|
103
103
|
|
|
@@ -107,7 +107,7 @@ Every step of that is arithmetic, and the cost of leaving it here was never main
|
|
|
107
107
|
- **Whether a matched path is a sensitive *diff*.** The bump asks what the change *does* there, not where it lives: it applies to **control flow, or the data that reaches a person, a charge or a stored record** — a new guard, a new `catch`, a changed condition, a changed value, a changed contract. It does **not** apply when the diff moves **observability alone**: a log level, a channel, a message's text, a metric, a comment. Mixed diff → not observability-only, so it bumps. **Say which of the two it was in one line**; a diff demoted here is the one place a missed defect is expensive.
|
|
108
108
|
- **Query changes.** §3.6 duels every query the diff adds or modifies, at every size, whatever this section resolved — routing them through the bump buys a second opinion on prose where §3.6 buys a plan.
|
|
109
109
|
|
|
110
|
-
**No CLI, or a non-zero exit → the prose fallback**, and `Review path` names it with the reason (the same contract the panel follows). Measure `git diff --shortstat <review base>...<candidate_sha>`; **≤150 → XS · 151-600 → S · 601-1500 → M · >1500 → L**; effective size = the lower of that and `meta.json.size`; `proportional` runs the built-in at **medium/high/high/xhigh** by size and the panel at M and above (at S only on a sensitive surface); the bump raises the effort one tier (medium→high→xhigh→**max**) and always runs the panel; `full` is **xhigh** plus the panel at any size, `light` is the built-in alone at **medium** with no panel, no §3 and no §6 — and a sensitive surface lifts `light` to the proportional tier for that work.
|
|
110
|
+
**No CLI, or a non-zero exit → the prose fallback**, and `Review path` names it with the reason (the same contract the panel follows). Measure `git diff --shortstat <review base>...<candidate_sha>`; **≤150 → XS · 151-600 → S · 601-1500 → M · >1500 → L**; effective size = the lower of that and `meta.json.size`; `proportional` runs the built-in at **medium/high/high/xhigh** by size and the panel at M and above (at S only on a sensitive surface); the bump raises the effort one tier (medium→high→xhigh→**max**) and always runs the panel; `full` is **xhigh** plus the panel at any size, `light` is the built-in alone at **medium** with no panel, no §3 and no §6 — and a sensitive surface lifts `light` to the proportional tier for that work.
|
|
111
111
|
|
|
112
112
|
**The diff pointing *higher* than `meta.json.size`** is worth one line in `06-review.md` (the work may be misclassified), never a heavier review. **The sensitive-surface bump is never scaled away** — a 12-line change to an authorization check still gets the panel, on a delta exactly as on a first review.
|
|
113
113
|
|
|
@@ -156,7 +156,7 @@ Launch the reviewers selected in §2.0 and **consolidate their findings into a s
|
|
|
156
156
|
|
|
157
157
|
When both run, deduplicate overlapping correctness/simplification findings (count each once). The `review_skill` specialists (offensive/defensive security, silent failures, architecture) are not repeated in later phases.
|
|
158
158
|
|
|
159
|
-
**Dedup keeps every source, not the first one.** A finding carries its **origin** from here to §8 — `built-in`, a panel role, or the pass that raised it (`§3.5`, `§3.6`, `§5`, `§5.5`) — and a finding more than one source raised lists all of them. Counted once, credited to each
|
|
159
|
+
**Dedup keeps every source, not the first one.** A finding carries its **origin** from here to §8 — `built-in`, a panel role, or the pass that raised it (`§3.5`, `§3.6`, `§5`, `§5.5`) — and a finding more than one source raised lists all of them. Counted once, credited to each: a finding only one pass saw and a finding three sources raised say opposite things about that pass, and §9 records the difference.
|
|
160
160
|
|
|
161
161
|
### 2.2 Design truth vs design rationale (do not inherit rationalizations)
|
|
162
162
|
`03-design.md` goes to reviewers as context, with unequal authority:
|
|
@@ -175,7 +175,7 @@ Only what §2 does **not** already cover; skipped entirely under `light` (§2.0)
|
|
|
175
175
|
|
|
176
176
|
## 3.5. Completeness sweep (anti-abandonment, M/L only)
|
|
177
177
|
|
|
178
|
-
Counters a reviewer abandoning a large diff early. **Only if
|
|
178
|
+
Counters a reviewer abandoning a large diff early. **Only if the effective size of §2.0 is M or L**, and only
|
|
179
179
|
if §2.0b's budget still covers it (it is the first phase dropped).
|
|
180
180
|
|
|
181
181
|
**It runs after §2-§3 are consolidated, never in parallel with them.** The whole phase is an audit of
|
|
@@ -267,7 +267,7 @@ Findings enter the normal flow: §6, then the output. Blinded for the same reaso
|
|
|
267
267
|
|
|
268
268
|
A filter against over-reporting, not a second review; narrow gate. Never runs under `light` (§2.0).
|
|
269
269
|
|
|
270
|
-
**When it runs.** All
|
|
270
|
+
**When it runs.** All four conditions:
|
|
271
271
|
|
|
272
272
|
| Condition | Threshold |
|
|
273
273
|
|---|---|
|
|
@@ -276,7 +276,7 @@ A filter against over-reporting, not a second review; narrow gate. Never runs un
|
|
|
276
276
|
| Findings | **≥ 4** ambiguous findings across §2-§5 |
|
|
277
277
|
| Budget | §2.0b's budget still covers a round (§6 is the second phase dropped) |
|
|
278
278
|
|
|
279
|
-
Read the real diff (`git diff --stat
|
|
279
|
+
Read the real diff (`git diff --stat <review base>...<candidate_sha>`, §1.5), not the recorded size.
|
|
280
280
|
|
|
281
281
|
When all three hold: in **`manual`**, offer it with `AskUserQuestion` ("Verify the ambiguous findings with skeptics in parallel? Discards false positives before you go fix them."). In **`guided`/`auto`, do not ask** — flow mechanics: run it and note in `06-review.md` that you did.
|
|
282
282
|
|
|
@@ -356,7 +356,7 @@ Write `.claude/work/<TICKET>/06-review.md`. The `Cost:` line of `## Summary` is
|
|
|
356
356
|
## Discarded by adversarial verification
|
|
357
357
|
<only if §6 was run; list of refuted findings with reason, or "not applicable">
|
|
358
358
|
<if the `fanout_max` cap left ambiguous findings unverified, list them here as "unverified (cap)">
|
|
359
|
-
<if §6 did not run, one line saying which condition did not hold — size, diff size, or
|
|
359
|
+
<if §6 did not run, one line saying which condition did not hold — size, diff size, count, or budget>
|
|
360
360
|
|
|
361
361
|
## Blockers (must-fix)
|
|
362
362
|
1. [file:line] · <origin> · description + concrete proposal
|
|
@@ -379,12 +379,11 @@ Write `.claude/work/<TICKET>/06-review.md`. The `Cost:` line of `## Summary` is
|
|
|
379
379
|
- Blockers → **do not advance `phase`**. Leave `phase = "build"`; the user resolves them.
|
|
380
380
|
- No blockers → `phase = "review"`, add to `phases_done`. **In a multi-MR/PR work**, also add `review` to the current `in_progress` MR/PR's own `phases_done` (its `mrs[]` entry) — `/flow-feat-ship §1` gates on it per MR/PR.
|
|
381
381
|
- **Record *what* you reviewed, and separately what you changed after reading it**, in the same write, work-level and — in a multi-MR/PR work — in this MR/PR's `mrs[]` entry too:
|
|
382
|
-
- `reviewed_sha` = **the candidate of §1.5**, the revision the reviewers actually read. Not `git rev-parse HEAD`, which
|
|
383
|
-
- `fixed_sha` = `git rev-parse HEAD` after this round's fixes, or **empty** when the round applied none. Two fields because they are two facts
|
|
382
|
+
- `reviewed_sha` = **the candidate of §1.5**, the revision the reviewers actually read. Not `git rev-parse HEAD`, which by then holds this round's own fixes — code no reviewer saw, recorded as reviewed, and `ship` finding it equal to `HEAD` every time.
|
|
383
|
+
- `fixed_sha` = `git rev-parse HEAD` after this round's fixes, or **empty** when the round applied none. Two fields because they are two facts.
|
|
384
384
|
- `phases_done` says a review *happened*; these say which tree, and `/flow-feat-ship §1` reads both before pushing. Written whenever the phase advances, never when it does not: a review that ended in blockers reviewed nothing that stands.
|
|
385
385
|
- **Record which pass found what**, in the same write: `meta.json.review_findings[]`, one entry per finding **per source** — `{ round, origin, severity, file, discarded_by_skeptic }`, and no finding text, which stays in the artifact. `flow review --record` writes these itself when the CLI ran the panel; when the agentic panel ran, write them here from the origins §2.1 carried. `flow cost` reads them back per origin: how many findings each pass contributed, how many only it raised, and how many of those survived §6. That last number is the only evidence a pass is still earning its words.
|
|
386
|
-
|
|
387
|
-
- **Stage what the review taught** (`knowledge.stage` set; silence by default). Review is where a project teaches the most and, until now, the one phase that never staged — a work with three review rounds and seventeen blockers produced zero knowledge cards because nothing asked for them while they were in context. Candidates are findings about the **domain or the codebase's real behaviour**, not about this diff: a library that does other than its name says, a test disguise that kept the suite green over a live defect, a module rule the reviewers had to cite from its own prose, a measurement. A blocker fixed here is not knowledge; *why it was written wrong* may be. Same evidence rule as `/flow-feat-design` §8 — one line of evidence per finding or it is not staged. One call per finding, one line to the user («Staged N finding(s) for `ship`»). Never `knowledge.save` here.
|
|
386
|
+
- **Stage what the review taught** (`knowledge.stage` set; silence by default). Review is where a project teaches the most, and this is the only moment its findings are in context. Candidates are findings about the **domain or the codebase's real behaviour**, not about this diff: a library that does other than its name says, a test disguise that kept the suite green over a live defect, a module rule the reviewers had to cite from its own prose, a measurement. A blocker fixed here is not knowledge; *why it was written wrong* may be. Same evidence rule as `/flow-feat-design` §8 — one line of evidence per finding or it is not staged. One call per finding, one line to the user («Staged N finding(s) for `ship`»). Never `knowledge.save` here.
|
|
388
387
|
- Overwrite `00-summary.md` whole (≤15 lines, flow-core §5).
|
|
389
388
|
- **Record what the agents missed** (flow-core §6.7, `agents.learn` not `off`; asking nothing): for each finding that survived, the panel member or named `agents.<role>` whose category it falls in and who did not report it, and the delegated `build` agent whose code it sits in → one `meta.json.agent_lessons[]` row each, only when the lesson passes the §6.7 test. The origins §2.1 carried are what make this possible — a finding with no origin teaches nobody.
|
|
390
389
|
- **Configuration this phase earned the right to ask about** (flow-core §0, `manual` only, at most one key per work, as an extra option on this same stop — never a question of its own): a `Cost:` line that went over `agents.budget_max` → `quality.review_depth`. In `guided`/`auto` neither is asked: the default is taken and recorded in `meta.json.defaults_used[]`.
|
|
@@ -85,7 +85,6 @@ This system **orchestrates** the project's existing sub-agents and skills (it do
|
|
|
85
85
|
"branch": "{PREFIX}XXXXX-slug",
|
|
86
86
|
"size": "XS" | "S" | "M" | "L",
|
|
87
87
|
"phase": "context" | "design" | "plan" | "build" | "review" | "validate" | "ship" | "investigate" | "fix" | "postmortem" | "done" | "abandoned",
|
|
88
|
-
// retired in v0.53.0 and still read from older works: "brainstorm" → treat as "context", "diagnose" → as "investigate"
|
|
89
88
|
"phases_done": ["context", ...],
|
|
90
89
|
"candidate_sha": "40-char sha the current review froze before reading, or ''",
|
|
91
90
|
"reviewed_sha": "40-char sha the last passing review read, or ''",
|
|
@@ -118,11 +117,11 @@ This system **orchestrates** the project's existing sub-agents and skills (it do
|
|
|
118
117
|
],
|
|
119
118
|
"followups": [
|
|
120
119
|
{ "id": "F1",
|
|
121
|
-
"kind": "prevention" | "audit" | "out-of-scope" | "risk" | "edge-case" | "other-bug",
|
|
120
|
+
"kind": "prevention" | "audit" | "out-of-scope" | "risk" | "edge-case" | "other-bug" | "tooling" | "decision",
|
|
122
121
|
"title": "one line, what would be done",
|
|
123
122
|
"why": "one line, why it was parked and why it still matters",
|
|
124
123
|
"source": "design" | "plan" | "build" | "validate" | "fix" | "postmortem",
|
|
125
|
-
"status": "proposed" | "accepted" | "in_progress" | "declined" | "done",
|
|
124
|
+
"status": "proposed" | "accepted" | "in_progress" | "declined" | "logged" | "done",
|
|
126
125
|
"ticket": null, "work": null, "note": "" }
|
|
127
126
|
],
|
|
128
127
|
"defaults_used": [
|
|
@@ -29,7 +29,6 @@ Use when returning to a work after a break (next morning, another session).
|
|
|
29
29
|
- `git branch --show-current`.
|
|
30
30
|
- Search `.claude/work/` for the `meta.json` whose `branch` matches.
|
|
31
31
|
- None found → ask the user for the ticket or whether to start a new one.
|
|
32
|
-
- **A `phase` retired in v0.53.0** — `brainstorm` or `diagnose`, from a work started before it — is mapped, never refused: `brainstorm` → `design` (its `02-brainstorm.md` is that command's §1.5 output, already done), `diagnose` → `investigate` (its `02-diagnose.md` is that command's §1.5 output). Say which mapping you applied, in one line, and suggest the mapped command. Do not rewrite `meta.json` for it; the phase advances normally at the next Close.
|
|
33
32
|
- `meta.json.worktree` non-null and the current directory is not that worktree → tell the user the work lives in a worktree and to `cd <worktree>` before continuing; run the repo-state checks below from there (`git -C <worktree> …`).
|
|
34
33
|
|
|
35
34
|
## 2. Recap
|
|
@@ -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.81.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
|
|
@@ -29,12 +29,9 @@ a command relies on is simply absent in that session, and nothing else will repo
|
|
|
29
29
|
- **Look before you read.** The first thing a phase does about configuration is list what is there:
|
|
30
30
|
`ls <root>/FLOW*.md` (the root being the one the next bullet resolves). One call, and it is not
|
|
31
31
|
optional — **an overlay you did not list is an overlay you did not read**, and nothing downstream
|
|
32
|
-
will notice.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
looking for the overlay sitting beside it — the models it set were silently the defaults, and
|
|
36
|
-
both runs reported the keys as unset with no way to tell that apart from a repo that never set
|
|
37
|
-
them. **Name the files this listing found the first time a phase reports any configured value**,
|
|
32
|
+
will notice. Every command and artifact calls the effective configuration "`FLOW.md`", a file that
|
|
33
|
+
exists, so reading it and stopping feels finished — and a missed overlay reports its keys as unset,
|
|
34
|
+
indistinguishable from a repo that never set them. **Name the files this listing found the first time a phase reports any configured value**,
|
|
38
35
|
so a missed overlay is visible in the artifact rather than invisible everywhere.
|
|
39
36
|
- Read `FLOW.md` at the repo root as the base, then the optional overlay for the harness running
|
|
40
37
|
this command: `FLOW.claude.md`, `FLOW.codex.md`, `FLOW.opencode.md`, `FLOW.gemini.md`,
|
|
@@ -67,11 +64,8 @@ a command relies on is simply absent in that session, and nothing else will repo
|
|
|
67
64
|
- **A fenced block in a FLOW file is an example, and an example is not configuration.** These
|
|
68
65
|
files are prose with keys in them, and the rule that decides what a key *is* — a `- key:` line
|
|
69
66
|
under a `## section` — knows nothing about triple backticks. So a block written to be pasted
|
|
70
|
-
("add this to try it once")
|
|
71
|
-
|
|
72
|
-
prose argued at length that it was deliberately unset, and every review round took the one-shot
|
|
73
|
-
path that prose warned against — with nothing anywhere to say so, because the file and the
|
|
74
|
-
configuration disagreed while both looked right. **Skip fenced regions when you read a FLOW
|
|
67
|
+
("add this to try it once") would be read as the configuration it illustrates, while the prose
|
|
68
|
+
around it says otherwise and nothing reports the disagreement. **Skip fenced regions when you read a FLOW
|
|
75
69
|
file**; `flow-workflows` does the same, so the two of you resolve the same config.
|
|
76
70
|
- Merge by section and key. A key present in the active overlay replaces the base value; a key
|
|
77
71
|
absent there inherits the base. **A present-but-empty overlay key masks the base** and resolves
|
|
@@ -92,7 +86,7 @@ a command relies on is simply absent in that session, and nothing else will repo
|
|
|
92
86
|
alongside whatever it was already asking. Resolve the destination by the ownership rule below.
|
|
93
87
|
Never a question of its own, never a key off the list, and at most **one key per work** — the
|
|
94
88
|
second one waits for the next work or for `/flow-init`.
|
|
95
|
-
3. `guided`/`auto` → take the default and **record** it: one line in the phase artifact
|
|
89
|
+
3. `guided`/`auto` → take the default and **record** it: one line in the phase artifact,
|
|
96
90
|
plus an entry in `meta.json.defaults_used[]` — `{ "key": "agents.security", "default":
|
|
97
91
|
"general-purpose", "phase": "review" }`. Asking here would break the never-a-question contract
|
|
98
92
|
(§2); recording keeps the decision readable afterwards, and `/flow-doctor` aggregates it.
|
|
@@ -119,8 +113,7 @@ a command relies on is simply absent in that session, and nothing else will repo
|
|
|
119
113
|
the consolidation appends to `KNOWLEDGE.md` at the repo root. Per-call timeout
|
|
120
114
|
`knowledge.timeout_s` (empty = 2 s); a failure or timeout → continue without it, silently.
|
|
121
115
|
**How a consolidation runs** (`ship`, `postmortem`, `abandon`, and the offer in `/flow-work-status`
|
|
122
|
-
when `read_staging` has entries). No role set at all → say so in one line and stop
|
|
123
|
-
worth a command of its own, which is why there is no longer one:
|
|
116
|
+
when `read_staging` has entries). No role set at all → say so in one line and stop:
|
|
124
117
|
|
|
125
118
|
1. **Read the staging** for this branch with `knowledge.read_staging`; the role empty → the "why"
|
|
126
119
|
findings already written in this work's artifacts (`03-design.md` ADR-light and challenges,
|
|
@@ -270,7 +263,7 @@ right now. **Any progress line you were about to type into the chat is a panel u
|
|
|
270
263
|
**Two transports, one document.** When the tools `panel_set` / `panel_patch` / `panel_get` are
|
|
271
264
|
available, this console is a pane of agent-terminal: publish the panel through them (§4.2) and
|
|
272
265
|
**stop writing `.claude/work/<work>/panel.json`** — while a pane is claimed, its file is not read at
|
|
273
|
-
all. When they are not there, write the file
|
|
266
|
+
all. When they are not there, write the file (§4.3). No work folder (lightweight
|
|
274
267
|
`respond`/`green`) → nothing to publish, either way.
|
|
275
268
|
|
|
276
269
|
**Look for them before you conclude they are missing**, once per session, in pre-flight. A harness
|
|
@@ -413,8 +406,7 @@ single largest token cost of a work, so every work carries a short handoff:
|
|
|
413
406
|
MR/PR of `04-mr-plan.md`; `review` opens the design's contracts and the implementation log;
|
|
414
407
|
`ship` opens the brief and the review verdict. A summary that does not answer the question you
|
|
415
408
|
have is the cue to open the artifact — never a licence to guess.
|
|
416
|
-
- Missing summary
|
|
417
|
-
summary at your Close.
|
|
409
|
+
- Missing summary → read the artifacts, write the summary at your Close.
|
|
418
410
|
- **Name the phase, never the command.** An artifact outlives the session that wrote it and may be
|
|
419
411
|
resumed from a different agent, where the same phase is invoked under another name. Write the
|
|
420
412
|
phase — `validate`, `review`, `ship #2` — not the invocation. Applies to `00-summary.md`,
|
|
@@ -449,7 +441,7 @@ around each of its own findings to work out which changes are its doing, and how
|
|
|
449
441
|
looks clean is clean by luck. **The parent thread is a writer too**: applying a round's fixes while
|
|
450
442
|
its agents are still reading is the same collision, from the side nobody counts.
|
|
451
443
|
|
|
452
|
-
So a round that contains a writer is not one round. Readers fan out freely
|
|
444
|
+
So a round that contains a writer is not one round. Readers fan out freely;
|
|
453
445
|
writers go one at a time, each either alone or in a worktree of its own, and the readers sit
|
|
454
446
|
entirely before them or entirely after them. The parent's own edits wait until the round is
|
|
455
447
|
consolidated. Ordering costs wall clock and the phase says so in one line — a reading nobody can
|
|
@@ -491,8 +483,7 @@ Dropping a silent agent is always allowed, and always reported (`N/M` reported).
|
|
|
491
483
|
no deadline is what costs a session.
|
|
492
484
|
|
|
493
485
|
**The budget belongs to the command, not to the round.** `agents.fanout_max` caps *one* parallel
|
|
494
|
-
round
|
|
495
|
-
compose: a review can run a panel, then area reinforcements, then a coverage sweep that relaunches
|
|
486
|
+
round, and the phases that fan out compose: a review can run a panel, then area reinforcements, then a coverage sweep that relaunches
|
|
496
487
|
the panel, then one skeptic per finding — each round inside its own cap and the command an order of
|
|
497
488
|
magnitude over what anyone intended.
|
|
498
489
|
|
|
@@ -557,15 +548,13 @@ must *react to* mid-wait is not a wait at all: it is the work, and it stays here
|
|
|
557
548
|
### 6.6 — Which agent a role resolves to
|
|
558
549
|
|
|
559
550
|
**The harness already tells you which agents are installed**, each with a line on what it is for,
|
|
560
|
-
and choosing the one that fits a piece of work is something you do well without being told.
|
|
561
|
-
that answers every empty role with `general-purpose` throws that away: a repo with a frontend
|
|
562
|
-
specialist installed and no `agents.frontend` got a generalist told to act like one. So wherever a
|
|
551
|
+
and choosing the one that fits a piece of work is something you do well without being told. Answering every empty role with `general-purpose` throws that away. So wherever a
|
|
563
552
|
command says *"`agents.<role>`, empty → `Agent general-purpose` with the role"*, it means this:
|
|
564
553
|
|
|
565
|
-
1. **`agents.<role>` names an agent** → that agent
|
|
554
|
+
1. **`agents.<role>` names an agent** → that agent.
|
|
566
555
|
2. **Empty** → the installed agent whose description fits the role **and this work's stack** best —
|
|
567
556
|
read the list your harness gives you, never a guess at a name. None fits clearly →
|
|
568
|
-
`general-purpose` with the role in the prompt
|
|
557
|
+
`general-purpose` with the role in the prompt. An agent that fits the role but not the
|
|
569
558
|
stack (a PHP reviewer on a React diff) does not fit.
|
|
570
559
|
|
|
571
560
|
**`agents.selection`** decides how far your judgement reaches:
|
|
@@ -711,11 +700,11 @@ one more thing the user has to decide about.
|
|
|
711
700
|
"title": "one line, what would be done",
|
|
712
701
|
"why": "one line, why it was parked and why it still matters",
|
|
713
702
|
"source": "design" | "plan" | "build" | "validate" | "fix" | "postmortem",
|
|
714
|
-
"status": "proposed" | "accepted" | "declined" | "logged" | "done",
|
|
703
|
+
"status": "proposed" | "accepted" | "in_progress" | "declined" | "logged" | "done",
|
|
715
704
|
"ticket": null, "work": null, "note": "" }
|
|
716
705
|
```
|
|
717
706
|
|
|
718
|
-
The artifact keeps its human-readable section
|
|
707
|
+
The artifact keeps its human-readable section, with the `F<n>` id in front of each
|
|
719
708
|
row so the prose and the record never drift. **The record is the addition, not a replacement**: a
|
|
720
709
|
reader of `05-implementation.md` still sees the ideas in context.
|
|
721
710
|
|
|
@@ -750,8 +739,8 @@ at `ship`'s Close, when the work is done and the user can see the whole set.
|
|
|
750
739
|
|
|
751
740
|
**A skeptic sorts them before the user sees them.** `/flow-*-review` already refuses to hand over an
|
|
752
741
|
unverified finding: its §6 gives each ambiguous one to a skeptic whose job is to *refute* it, burden
|
|
753
|
-
of proof on the finding. Deferred work
|
|
754
|
-
|
|
742
|
+
of proof on the finding. Deferred work needs the same filter: the phase that parked it is the one party that cannot judge
|
|
743
|
+
it, having just found it. So at Close, when
|
|
755
744
|
**3 or more** entries are still `proposed`, they go to a skeptic first (grouped into at most
|
|
756
745
|
`agents.fanout_max` briefs, the ceilings of §6 unchanged; **fewer than 3 → no agent**, the command
|
|
757
746
|
applies the bar itself):
|
|
@@ -778,15 +767,10 @@ Then, and only then, the survey:
|
|
|
778
767
|
**Not worth it** · **Later**. The `title` and `why` are the entire prompt. **`decision` entries
|
|
779
768
|
are asked as their product question** — they never go to the skeptic, a question's value not being
|
|
780
769
|
a thing to refute — and sit outside the ceiling.
|
|
781
|
-
- **`tooling` asks nothing.** `logged`, and a count on screen.
|
|
782
|
-
with slack in it was one question too many.
|
|
770
|
+
- **`tooling` asks nothing.** `logged`, and a count on screen.
|
|
783
771
|
- **Not worth it** → `declined`, with the reason if given. Never asked again.
|
|
784
772
|
- **`logged` is a status, not a destination.** The entry stays exactly where it already is — in
|
|
785
|
-
`meta.json.followups[]` and in its artifact section — and no file is written anywhere.
|
|
786
|
-
to append a line to a versioned debt log, one per repo; **that file is gone**. No command read it,
|
|
787
|
-
`status` and `daily` excluded it on purpose, and it duplicated a record the work already keeps
|
|
788
|
-
forever, so it grew without ever being triaged. A note nobody reads is not a lighter obligation
|
|
789
|
-
than a ticket, it is the same obligation with the reader removed. If a gap in the machinery is
|
|
773
|
+
`meta.json.followups[]` and in its artifact section — and no file is written anywhere. If a gap in the machinery is
|
|
790
774
|
worth someone's time, it is worth a ticket; if it is not, the record in the work is where it ends.
|
|
791
775
|
- **A `decision` answered** → the answer is written into the artifact that owns it and the entry
|
|
792
776
|
becomes `done` with the answer in `note`. Deferred again → stays `proposed`.
|
|
@@ -878,7 +862,7 @@ largest saving the review has.
|
|
|
878
862
|
|
|
879
863
|
**What follows from that is a temptation, and it belongs to the diff, not to the plan.** A threshold
|
|
880
864
|
that buys a lighter review pays whoever lands just under it: twelve lines below 150 is a review at
|
|
881
|
-
`medium
|
|
865
|
+
`medium`, twelve above it is one at `high`; at 600 the project panel joins. So, in every phase:
|
|
882
866
|
|
|
883
867
|
**The diff reports the change; the change is never shaped to fit the number.** Never delete a
|
|
884
868
|
comment, a test, a blank line or a log line, never compress readable code into fewer statements,
|
|
@@ -26,9 +26,7 @@ Read `~/.claude/flow/CORE.opencode.md` first (shared rules: `FLOW.md` step 0, mo
|
|
|
26
26
|
|
|
27
27
|
- Read `meta.json` and `00-summary.md`; open in full only `01-context.md`. (flow-core §5)
|
|
28
28
|
- `type` is not `bug` → refuse. `size` is `XS` → suggest `/flow-bug-fix` and stop.
|
|
29
|
-
- Require `context` in `phases_done`.
|
|
30
|
-
v0.53.0) is treated as having finished §1.5: read its `02-diagnose.md`, carry it into
|
|
31
|
-
`03-investigation.md`, and go straight to §3.
|
|
29
|
+
- Require `context` in `phases_done`.
|
|
32
30
|
|
|
33
31
|
## 1.5 Reproduce — what is failing, before why
|
|
34
32
|
|
|
@@ -36,9 +34,6 @@ Isolate **what** fails before looking for **why**. On **S** this is the whole of
|
|
|
36
34
|
first half and the chain is `start → investigate (reproduce only) → fix → …`; on **M/L** it is the
|
|
37
35
|
ground §3 stands on. **XS** skips straight to `/flow-bug-fix`.
|
|
38
36
|
|
|
39
|
-
*(This was the `bug:diagnose` command until v0.53.0. Reproducing and finding the cause were two commands
|
|
40
|
-
sharing five headings, and the S-size chain already ran them back to back.)*
|
|
41
|
-
|
|
42
37
|
1. **Focused knowledge query on the symptom.** `knowledge.search` set → 2-3 parallel queries about
|
|
43
38
|
the **suspected component** (handler, worker, endpoint, module): the same root cause often
|
|
44
39
|
returns wearing a different symptom. Dead-letter queue → `"DLX <handler-name>"`, `"retry policy
|
|
@@ -35,7 +35,7 @@ Read `~/.claude/flow/CORE.opencode.md` first (shared rules: `FLOW.md` step 0, mo
|
|
|
35
35
|
member runs its own `git diff` and opens the same files pays for that material once per agent, and
|
|
36
36
|
a reviewer that spends its turns exploring has fewer left to review. **Any non-zero exit is a
|
|
37
37
|
fallback, not a failure** — no CLI on the machine, a base that does not resolve, a network that
|
|
38
|
-
cannot reach it: read the diff from git
|
|
38
|
+
cannot reach it: read the diff from git and carry on, once, without retrying variants.
|
|
39
39
|
What is not optional is the `Review path` line of §7: a round that skipped the pack and one that
|
|
40
40
|
used it are indistinguishable from the artifact otherwise, which is how a phase quietly stops
|
|
41
41
|
paying for itself.
|
|
@@ -70,7 +70,7 @@ Read `~/.claude/flow/CORE.opencode.md` first (shared rules: `FLOW.md` step 0, mo
|
|
|
70
70
|
- **Review base**: the previous `reviewed_sha` when it is non-empty and an ancestor of the candidate, otherwise `git.default_base`, with the reason in one line. `--full` forces the whole branch.
|
|
71
71
|
- **Then**: `bundle --rev <candidate_sha> --base <review base>`, and every brief names that range rather than the live tree.
|
|
72
72
|
|
|
73
|
-
A fix is usually small enough that the delta and the branch are the same thing — which is exactly why the freeze matters more here than the scoping: a one-file fix whose round applies its own correction is the case where `
|
|
73
|
+
A fix is usually small enough that the delta and the branch are the same thing — which is exactly why the freeze matters more here than the scoping: a one-file fix whose round applies its own correction is the case where recording `HEAD` as reviewed would describe a tree nobody read.
|
|
74
74
|
|
|
75
75
|
## 2. Run the code reviews
|
|
76
76
|
|
|
@@ -233,7 +233,7 @@ Cost line: count every subagent this command launched — reviewers = §2.1 buil
|
|
|
233
233
|
- **Record *what* you reviewed, and separately what you changed after reading it** — `/flow-feat-review` §9, unchanged: `reviewed_sha` = the **candidate** of §1.5 (the revision the reviewers read, never `git rev-parse HEAD`, which by now holds this round's own fixes), and `fixed_sha` = `git rev-parse HEAD` after those fixes, empty when the round applied none. `phases_done` says a review happened; these two say on which tree and what moved afterwards, and `/flow-bug-ship §0` reads both against what is being pushed. Only when the phase advances: a review that ended in blockers reviewed nothing that stands.
|
|
234
234
|
- **Record which pass found what** — `/flow-feat-review §9`, unchanged: one `meta.json.review_findings[]` entry per finding **per source** (`{ round, origin, severity, file, discarded_by_skeptic }`, no finding text), written by `flow review --record` when the CLI ran the panel and by this Close when the agentic panel did. `flow cost` reads them back per origin, and the retirement rule is the same: a pass with no exclusive surviving finding across twenty reviews comes out of the command.
|
|
235
235
|
- **Record what the agents missed** — `/flow-feat-review §9`, unchanged: surviving findings in a category a panel member or named `agents.<role>` owns and did not report → `meta.json.agent_lessons[]` rows (flow-core §6.7), asking nothing. A fix is where this pays most: the defect already reached production once, and the reviewer that owns its category let it.
|
|
236
|
-
- **Stage what the review taught** (`knowledge.stage` set; silence by default). Review is where a project teaches the most and
|
|
236
|
+
- **Stage what the review taught** (`knowledge.stage` set; silence by default). Review is where a project teaches the most, and this is the only moment its findings are in context. Candidates are findings about the **domain or the codebase's real behaviour**, not about this diff: a library that does other than its name says, a test disguise that kept the suite green over a live defect, a module rule the reviewers had to cite from its own prose, a measurement. A blocker fixed here is not knowledge; *why it was written wrong* may be. Same evidence rule as `/flow-feat-design` §8 — one line of evidence per finding or it is not staged. One call per finding, one line to the user («Staged N finding(s) for `postmortem`/`ship`»). Never `knowledge.save` here.
|
|
237
237
|
- Overwrite `00-summary.md` whole (≤15 lines, flow-core §5).
|
|
238
238
|
- Stop body (after the flow-core §3 header): the findings that survived and what you did with each, plus the same Cost line as the Summary: "- Cost: <n>/<budget_max> subagents launched (<k> reviewers · <m> reinforcements · <s> skeptics), tier <light|proportional|full>".
|
|
239
239
|
- **Autonomy handoff.** Only without blockers — with blockers, stop in every mode. **M/L**: `manual` → propose `/flow-bug-postmortem` with a single `AskUserQuestion`; `guided`/`auto` → chain into it in this same turn. **XS/S**: the next step is `ship`, which pushes and opens the MR/PR — a hard gate in **every** mode: stop here and propose `/flow-bug-ship` with a single `AskUserQuestion`, never chaining into it.
|
|
@@ -45,9 +45,6 @@ Print this **before** the environment checks: a key nobody set is the commonest
|
|
|
45
45
|
below looks broken. Read against `examples/FLOW.template.md` — do not invent keys, and do report
|
|
46
46
|
documented keys absent from the effective configuration (the "empty → fallback" rows).
|
|
47
47
|
|
|
48
|
-
**This was the `config` command until v0.53.0.** One question — *what will the flow do in this repo* —
|
|
49
|
-
had two commands answering different halves of it.
|
|
50
|
-
|
|
51
48
|
### 1.5.1 Effective config, per section
|
|
52
49
|
|
|
53
50
|
For **every** documented key in `examples/FLOW.template.md`, one row:
|
|
@@ -25,7 +25,7 @@ Technical design phase. **Still no production code is written.** Opens the optio
|
|
|
25
25
|
## 1. Pre-flight
|
|
26
26
|
|
|
27
27
|
- Load `meta.json` by current branch. Missing → ask the user to start with `/flow-feat-start`.
|
|
28
|
-
- Read `meta.json` and `00-summary.md`; open in full only `01-context.md` (ticket, decisions, contracts received)
|
|
28
|
+
- Read `meta.json` and `00-summary.md`; open in full only `01-context.md` (ticket, decisions, contracts received). (flow-core §5)
|
|
29
29
|
- `size` is `XS` → suggest jumping to `/flow-feat-build` and stop unless the user insists.
|
|
30
30
|
|
|
31
31
|
## 1.5 Approaches — open the option space first (M/L)
|
|
@@ -34,9 +34,6 @@ Design that starts from the first idea is design that never had a second one. **
|
|
|
34
34
|
section; XS and S skip it** and go straight to §2 — the cost does not pay on a change whose shape is
|
|
35
35
|
obvious.
|
|
36
36
|
|
|
37
|
-
*(This was the `feat:brainstorm` command until v0.53.0: a command whose whole output only this one ever
|
|
38
|
-
read.)*
|
|
39
|
-
|
|
40
37
|
**No code, and no design yet.** The output of this section is a ranked set of options and one chosen
|
|
41
38
|
approach; §3 onwards designs *that* approach.
|
|
42
39
|
|
|
@@ -38,7 +38,7 @@ Mandatory review phase. **`/flow-feat-ship` cannot run without passing through h
|
|
|
38
38
|
member runs its own `git diff` and opens the same files pays for that material once per agent, and
|
|
39
39
|
a reviewer that spends its turns exploring has fewer left to review. **Any non-zero exit is a
|
|
40
40
|
fallback, not a failure** — no CLI on the machine, a base that does not resolve, a network that
|
|
41
|
-
cannot reach it: read the diff from git
|
|
41
|
+
cannot reach it: read the diff from git and carry on, once, without retrying variants.
|
|
42
42
|
What is not optional is the `Review path` line of §8: a round that skipped the pack and one that
|
|
43
43
|
used it are indistinguishable from the artifact otherwise, which is how a phase quietly stops
|
|
44
44
|
paying for itself.
|
|
@@ -67,7 +67,7 @@ Mandatory review phase. **`/flow-feat-ship` cannot run without passing through h
|
|
|
67
67
|
|
|
68
68
|
### 1.5 Freeze what you are about to read, and resolve what to compare it against
|
|
69
69
|
|
|
70
|
-
Two questions, answered here and nowhere later: **which tree** this round reads, and **against which base**.
|
|
70
|
+
Two questions, answered here and nowhere later: **which tree** this round reads, and **against which base**. Neither is implicit: the checkout changes while the round runs, and `git.default_base` is not always the right base.
|
|
71
71
|
|
|
72
72
|
**The candidate.** A round applies its own fixes; the README's own first-minute example is *"3 reviewers, one finding — fixed"*. So "the working tree" is a different tree for the reviewer that read it first, for the skeptic that read it last, and for the `git rev-parse HEAD` taken at §9 — which by construction contains code no reviewer ever saw, and which `/flow-feat-ship §1` then compares against `HEAD` and finds equal. Resolve one revision before §2 launches anything:
|
|
73
73
|
|
|
@@ -77,11 +77,11 @@ Two questions, answered here and nowhere later: **which tree** this round reads,
|
|
|
77
77
|
- Anchor it so it cannot be collected: `git update-ref refs/flow/candidate/<TICKET> <sha>`. A `stash create` object is unreferenced, and a candidate the `ship` gate cannot resolve is a gate that reports nothing. The ref is local, never pushed, and `/flow-feat-ship §6.5` deletes it.
|
|
78
78
|
- Write `candidate_sha` to `meta.json` — work-level and in the current `mrs[]` entry — **in this pre-flight**. A candidate recorded after the reading is not a freeze.
|
|
79
79
|
|
|
80
|
-
**The review base.** `reviewed_sha`
|
|
80
|
+
**The review base.** `reviewed_sha` records the tree the last passing review read, and `ship` trusts it enough to stop a push. Reading only the delta since it keeps a second review from re-reading every line the first one cleared, and keeps §2.0 from resolving the tier on the accumulated total — a 30-line delta on a 900-line branch is a 30-line review. Resolve:
|
|
81
81
|
|
|
82
82
|
- The current MR/PR's `reviewed_sha` (work-level when there is no train) when it is **non-empty** and **an ancestor of the candidate** (`git merge-base --is-ancestor <sha> <candidate>`) → that is the base.
|
|
83
83
|
- Otherwise `git.default_base`. A `reviewed_sha` that is not an ancestor means history was rewritten or the branch recut; say so in one line rather than producing a nonsensical delta.
|
|
84
|
-
- **A first review has no `reviewed_sha` and reads the whole branch
|
|
84
|
+
- **A first review has no `reviewed_sha` and reads the whole branch**. The delta path only exists after a review that passed.
|
|
85
85
|
- `/flow-feat-review --full` ignores `reviewed_sha` and reads the branch on demand.
|
|
86
86
|
- **Fall back to `git.default_base` and say why** when either holds, because a delta cannot see how it interacts with what was cleared before: the delta touches a file the previous review left a finding on, or it changes an external contract copied under `/flow-feat-build §2.0bis`.
|
|
87
87
|
|
|
@@ -95,7 +95,7 @@ Scope for every reviewer: **the candidate revision of §1.5, against the review
|
|
|
95
95
|
|
|
96
96
|
**The CLI resolves it; you obey the output and record any deviation.** `npx flow-workflows@<version> tier --harness opencode --rev <candidate_sha> --base <review base>` prints, from the config it already parses: changed lines over the §1.5 range, diff size, `meta.json.size`, **effective size** (the lower of the two), the built-in `code-review` effort with and without the sensitive-surface bump, whether the panel runs, the resolved `agents.budget_max`/`fanout_max`, whether the measurement landed **within 10% under** a threshold that changed the tier, and which `quality.sensitive_paths` globs the diff matched, with the path that matched each.
|
|
97
97
|
|
|
98
|
-
Every step of that is arithmetic
|
|
98
|
+
Every step of that is arithmetic. A tier this agent derives itself writes the same artifact whether it measured the diff or eyeballed it — on the one number in this command that carries an incentive on it.
|
|
99
99
|
|
|
100
100
|
**Copy the output verbatim** into the `Review tier` and `Effective size` lines of §8, the way `bundle --checks` copies static analysis out. A computed line, not a narrated one.
|
|
101
101
|
|
|
@@ -105,7 +105,7 @@ Every step of that is arithmetic, and the cost of leaving it here was never main
|
|
|
105
105
|
- **Whether a matched path is a sensitive *diff*.** The bump asks what the change *does* there, not where it lives: it applies to **control flow, or the data that reaches a person, a charge or a stored record** — a new guard, a new `catch`, a changed condition, a changed value, a changed contract. It does **not** apply when the diff moves **observability alone**: a log level, a channel, a message's text, a metric, a comment. Mixed diff → not observability-only, so it bumps. **Say which of the two it was in one line**; a diff demoted here is the one place a missed defect is expensive.
|
|
106
106
|
- **Query changes.** §3.6 duels every query the diff adds or modifies, at every size, whatever this section resolved — routing them through the bump buys a second opinion on prose where §3.6 buys a plan.
|
|
107
107
|
|
|
108
|
-
**No CLI, or a non-zero exit → the prose fallback**, and `Review path` names it with the reason (the same contract the panel follows). Measure `git diff --shortstat <review base>...<candidate_sha>`; **≤150 → XS · 151-600 → S · 601-1500 → M · >1500 → L**; effective size = the lower of that and `meta.json.size`; `proportional` runs the built-in at **medium/high/high/xhigh** by size and the panel at M and above (at S only on a sensitive surface); the bump raises the effort one tier (medium→high→xhigh→**max**) and always runs the panel; `full` is **xhigh** plus the panel at any size, `light` is the built-in alone at **medium** with no panel, no §3 and no §6 — and a sensitive surface lifts `light` to the proportional tier for that work.
|
|
108
|
+
**No CLI, or a non-zero exit → the prose fallback**, and `Review path` names it with the reason (the same contract the panel follows). Measure `git diff --shortstat <review base>...<candidate_sha>`; **≤150 → XS · 151-600 → S · 601-1500 → M · >1500 → L**; effective size = the lower of that and `meta.json.size`; `proportional` runs the built-in at **medium/high/high/xhigh** by size and the panel at M and above (at S only on a sensitive surface); the bump raises the effort one tier (medium→high→xhigh→**max**) and always runs the panel; `full` is **xhigh** plus the panel at any size, `light` is the built-in alone at **medium** with no panel, no §3 and no §6 — and a sensitive surface lifts `light` to the proportional tier for that work.
|
|
109
109
|
|
|
110
110
|
**The diff pointing *higher* than `meta.json.size`** is worth one line in `06-review.md` (the work may be misclassified), never a heavier review. **The sensitive-surface bump is never scaled away** — a 12-line change to an authorization check still gets the panel, on a delta exactly as on a first review.
|
|
111
111
|
|
|
@@ -154,7 +154,7 @@ Launch the reviewers selected in §2.0 and **consolidate their findings into a s
|
|
|
154
154
|
|
|
155
155
|
When both run, deduplicate overlapping correctness/simplification findings (count each once). The `review_skill` specialists (offensive/defensive security, silent failures, architecture) are not repeated in later phases.
|
|
156
156
|
|
|
157
|
-
**Dedup keeps every source, not the first one.** A finding carries its **origin** from here to §8 — `built-in`, a panel role, or the pass that raised it (`§3.5`, `§3.6`, `§5`, `§5.5`) — and a finding more than one source raised lists all of them. Counted once, credited to each
|
|
157
|
+
**Dedup keeps every source, not the first one.** A finding carries its **origin** from here to §8 — `built-in`, a panel role, or the pass that raised it (`§3.5`, `§3.6`, `§5`, `§5.5`) — and a finding more than one source raised lists all of them. Counted once, credited to each: a finding only one pass saw and a finding three sources raised say opposite things about that pass, and §9 records the difference.
|
|
158
158
|
|
|
159
159
|
### 2.2 Design truth vs design rationale (do not inherit rationalizations)
|
|
160
160
|
`03-design.md` goes to reviewers as context, with unequal authority:
|
|
@@ -173,7 +173,7 @@ Only what §2 does **not** already cover; skipped entirely under `light` (§2.0)
|
|
|
173
173
|
|
|
174
174
|
## 3.5. Completeness sweep (anti-abandonment, M/L only)
|
|
175
175
|
|
|
176
|
-
Counters a reviewer abandoning a large diff early. **Only if
|
|
176
|
+
Counters a reviewer abandoning a large diff early. **Only if the effective size of §2.0 is M or L**, and only
|
|
177
177
|
if §2.0b's budget still covers it (it is the first phase dropped).
|
|
178
178
|
|
|
179
179
|
**It runs after §2-§3 are consolidated, never in parallel with them.** The whole phase is an audit of
|
|
@@ -265,7 +265,7 @@ Findings enter the normal flow: §6, then the output. Blinded for the same reaso
|
|
|
265
265
|
|
|
266
266
|
A filter against over-reporting, not a second review; narrow gate. Never runs under `light` (§2.0).
|
|
267
267
|
|
|
268
|
-
**When it runs.** All
|
|
268
|
+
**When it runs.** All four conditions:
|
|
269
269
|
|
|
270
270
|
| Condition | Threshold |
|
|
271
271
|
|---|---|
|
|
@@ -274,7 +274,7 @@ A filter against over-reporting, not a second review; narrow gate. Never runs un
|
|
|
274
274
|
| Findings | **≥ 4** ambiguous findings across §2-§5 |
|
|
275
275
|
| Budget | §2.0b's budget still covers a round (§6 is the second phase dropped) |
|
|
276
276
|
|
|
277
|
-
Read the real diff (`git diff --stat
|
|
277
|
+
Read the real diff (`git diff --stat <review base>...<candidate_sha>`, §1.5), not the recorded size.
|
|
278
278
|
|
|
279
279
|
When all three hold: in **`manual`**, offer it with `AskUserQuestion` ("Verify the ambiguous findings with skeptics in parallel? Discards false positives before you go fix them."). In **`guided`/`auto`, do not ask** — flow mechanics: run it and note in `06-review.md` that you did.
|
|
280
280
|
|
|
@@ -354,7 +354,7 @@ Write `.claude/work/<TICKET>/06-review.md`. The `Cost:` line of `## Summary` is
|
|
|
354
354
|
## Discarded by adversarial verification
|
|
355
355
|
<only if §6 was run; list of refuted findings with reason, or "not applicable">
|
|
356
356
|
<if the `fanout_max` cap left ambiguous findings unverified, list them here as "unverified (cap)">
|
|
357
|
-
<if §6 did not run, one line saying which condition did not hold — size, diff size, or
|
|
357
|
+
<if §6 did not run, one line saying which condition did not hold — size, diff size, count, or budget>
|
|
358
358
|
|
|
359
359
|
## Blockers (must-fix)
|
|
360
360
|
1. [file:line] · <origin> · description + concrete proposal
|
|
@@ -377,12 +377,11 @@ Write `.claude/work/<TICKET>/06-review.md`. The `Cost:` line of `## Summary` is
|
|
|
377
377
|
- Blockers → **do not advance `phase`**. Leave `phase = "build"`; the user resolves them.
|
|
378
378
|
- No blockers → `phase = "review"`, add to `phases_done`. **In a multi-MR/PR work**, also add `review` to the current `in_progress` MR/PR's own `phases_done` (its `mrs[]` entry) — `/flow-feat-ship §1` gates on it per MR/PR.
|
|
379
379
|
- **Record *what* you reviewed, and separately what you changed after reading it**, in the same write, work-level and — in a multi-MR/PR work — in this MR/PR's `mrs[]` entry too:
|
|
380
|
-
- `reviewed_sha` = **the candidate of §1.5**, the revision the reviewers actually read. Not `git rev-parse HEAD`, which
|
|
381
|
-
- `fixed_sha` = `git rev-parse HEAD` after this round's fixes, or **empty** when the round applied none. Two fields because they are two facts
|
|
380
|
+
- `reviewed_sha` = **the candidate of §1.5**, the revision the reviewers actually read. Not `git rev-parse HEAD`, which by then holds this round's own fixes — code no reviewer saw, recorded as reviewed, and `ship` finding it equal to `HEAD` every time.
|
|
381
|
+
- `fixed_sha` = `git rev-parse HEAD` after this round's fixes, or **empty** when the round applied none. Two fields because they are two facts.
|
|
382
382
|
- `phases_done` says a review *happened*; these say which tree, and `/flow-feat-ship §1` reads both before pushing. Written whenever the phase advances, never when it does not: a review that ended in blockers reviewed nothing that stands.
|
|
383
383
|
- **Record which pass found what**, in the same write: `meta.json.review_findings[]`, one entry per finding **per source** — `{ round, origin, severity, file, discarded_by_skeptic }`, and no finding text, which stays in the artifact. `flow review --record` writes these itself when the CLI ran the panel; when the agentic panel ran, write them here from the origins §2.1 carried. `flow cost` reads them back per origin: how many findings each pass contributed, how many only it raised, and how many of those survived §6. That last number is the only evidence a pass is still earning its words.
|
|
384
|
-
|
|
385
|
-
- **Stage what the review taught** (`knowledge.stage` set; silence by default). Review is where a project teaches the most and, until now, the one phase that never staged — a work with three review rounds and seventeen blockers produced zero knowledge cards because nothing asked for them while they were in context. Candidates are findings about the **domain or the codebase's real behaviour**, not about this diff: a library that does other than its name says, a test disguise that kept the suite green over a live defect, a module rule the reviewers had to cite from its own prose, a measurement. A blocker fixed here is not knowledge; *why it was written wrong* may be. Same evidence rule as `/flow-feat-design` §8 — one line of evidence per finding or it is not staged. One call per finding, one line to the user («Staged N finding(s) for `ship`»). Never `knowledge.save` here.
|
|
384
|
+
- **Stage what the review taught** (`knowledge.stage` set; silence by default). Review is where a project teaches the most, and this is the only moment its findings are in context. Candidates are findings about the **domain or the codebase's real behaviour**, not about this diff: a library that does other than its name says, a test disguise that kept the suite green over a live defect, a module rule the reviewers had to cite from its own prose, a measurement. A blocker fixed here is not knowledge; *why it was written wrong* may be. Same evidence rule as `/flow-feat-design` §8 — one line of evidence per finding or it is not staged. One call per finding, one line to the user («Staged N finding(s) for `ship`»). Never `knowledge.save` here.
|
|
386
385
|
- Overwrite `00-summary.md` whole (≤15 lines, flow-core §5).
|
|
387
386
|
- **Record what the agents missed** (flow-core §6.7, `agents.learn` not `off`; asking nothing): for each finding that survived, the panel member or named `agents.<role>` whose category it falls in and who did not report it, and the delegated `build` agent whose code it sits in → one `meta.json.agent_lessons[]` row each, only when the lesson passes the §6.7 test. The origins §2.1 carried are what make this possible — a finding with no origin teaches nobody.
|
|
388
387
|
- **Configuration this phase earned the right to ask about** (flow-core §0, `manual` only, at most one key per work, as an extra option on this same stop — never a question of its own): a `Cost:` line that went over `agents.budget_max` → `quality.review_depth`. In `guided`/`auto` neither is asked: the default is taken and recorded in `meta.json.defaults_used[]`.
|
|
@@ -83,7 +83,6 @@ This system **orchestrates** the project's existing sub-agents and skills (it do
|
|
|
83
83
|
"branch": "{PREFIX}XXXXX-slug",
|
|
84
84
|
"size": "XS" | "S" | "M" | "L",
|
|
85
85
|
"phase": "context" | "design" | "plan" | "build" | "review" | "validate" | "ship" | "investigate" | "fix" | "postmortem" | "done" | "abandoned",
|
|
86
|
-
// retired in v0.53.0 and still read from older works: "brainstorm" → treat as "context", "diagnose" → as "investigate"
|
|
87
86
|
"phases_done": ["context", ...],
|
|
88
87
|
"candidate_sha": "40-char sha the current review froze before reading, or ''",
|
|
89
88
|
"reviewed_sha": "40-char sha the last passing review read, or ''",
|
|
@@ -116,11 +115,11 @@ This system **orchestrates** the project's existing sub-agents and skills (it do
|
|
|
116
115
|
],
|
|
117
116
|
"followups": [
|
|
118
117
|
{ "id": "F1",
|
|
119
|
-
"kind": "prevention" | "audit" | "out-of-scope" | "risk" | "edge-case" | "other-bug",
|
|
118
|
+
"kind": "prevention" | "audit" | "out-of-scope" | "risk" | "edge-case" | "other-bug" | "tooling" | "decision",
|
|
120
119
|
"title": "one line, what would be done",
|
|
121
120
|
"why": "one line, why it was parked and why it still matters",
|
|
122
121
|
"source": "design" | "plan" | "build" | "validate" | "fix" | "postmortem",
|
|
123
|
-
"status": "proposed" | "accepted" | "in_progress" | "declined" | "done",
|
|
122
|
+
"status": "proposed" | "accepted" | "in_progress" | "declined" | "logged" | "done",
|
|
124
123
|
"ticket": null, "work": null, "note": "" }
|
|
125
124
|
],
|
|
126
125
|
"defaults_used": [
|
|
@@ -27,7 +27,6 @@ Use when returning to a work after a break (next morning, another session).
|
|
|
27
27
|
- `git branch --show-current`.
|
|
28
28
|
- Search `.claude/work/` for the `meta.json` whose `branch` matches.
|
|
29
29
|
- None found → ask the user for the ticket or whether to start a new one.
|
|
30
|
-
- **A `phase` retired in v0.53.0** — `brainstorm` or `diagnose`, from a work started before it — is mapped, never refused: `brainstorm` → `design` (its `02-brainstorm.md` is that command's §1.5 output, already done), `diagnose` → `investigate` (its `02-diagnose.md` is that command's §1.5 output). Say which mapping you applied, in one line, and suggest the mapped command. Do not rewrite `meta.json` for it; the phase advances normally at the next Close.
|
|
31
30
|
- `meta.json.worktree` non-null and the current directory is not that worktree → tell the user the work lives in a worktree and to `cd <worktree>` before continuing; run the repo-state checks below from there (`git -C <worktree> …`).
|
|
32
31
|
|
|
33
32
|
## 2. Recap
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flow-workflows",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.81.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": {
|