flow-workflows 0.66.0 → 0.68.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/README.md +25 -4
- package/adapters/README.md +11 -3
- package/adapters/codex/CORE.md +17 -4
- package/adapters/codex/skills/flow-doctor/SKILL.md +4 -0
- package/adapters/codex/skills/flow-init/SKILL.md +4 -3
- package/adapters/codex/skills/flow-work-README/SKILL.md +1 -1
- package/adapters/gemini/CORE.md +17 -4
- package/adapters/gemini/commands/flow/doctor.toml +4 -0
- package/adapters/gemini/commands/flow/init.toml +4 -3
- package/adapters/gemini/commands/flow/work/README.toml +1 -1
- package/adapters/hermes/CORE.md +17 -4
- package/adapters/hermes/skills/flow-doctor/SKILL.md +4 -0
- package/adapters/hermes/skills/flow-init/SKILL.md +4 -3
- package/adapters/hermes/skills/flow-work-README/SKILL.md +1 -1
- package/adapters/opencode/CORE.md +17 -4
- package/adapters/opencode/commands/flow-doctor.md +4 -0
- package/adapters/opencode/commands/flow-init.md +4 -3
- package/adapters/opencode/commands/flow-work-README.md +1 -1
- package/bin/cli.mjs +31 -3
- package/package.json +2 -1
- package/plugins/flow/.claude-plugin/plugin.json +5 -2
- package/plugins/flow/CHANGELOG.md +111 -0
- package/plugins/flow/examples/FLOW.template.md +2 -2
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# flow-workflows
|
|
2
2
|
|
|
3
3
|
Guided `feat` / `bug` workflows for terminal coding agents: a ticket reaches an open MR/PR through explicit, reviewable phases, not one big prompt.
|
|
4
|
-
For developers running Claude Code (or opencode, Gemini CLI, Codex CLI, Hermes Agent) on real repos with tickets, reviewers and a deploy.
|
|
4
|
+
For developers running Claude Code (or zcode, opencode, Gemini CLI, Codex CLI, Hermes Agent) on real repos with tickets, reviewers and a deploy.
|
|
5
5
|
You get named phases, an artifact on disk after each one, hard gates the agent never crosses alone, and an autonomy dial from "ask me everything" to "run it and record what you decided".
|
|
6
6
|
|
|
7
7
|
## Quickstart
|
|
@@ -23,6 +23,14 @@ codex plugin add flow@flow-plugins
|
|
|
23
23
|
# then, in a new session: $flow:init · $flow:next
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
+
**zcode** — same plugin, from its own marketplace
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
zcode plugins marketplace add mashware/flow-workflows
|
|
30
|
+
zcode plugins install flow@flow-plugins
|
|
31
|
+
# then, in a new session: /flow:init · /flow:next
|
|
32
|
+
```
|
|
33
|
+
|
|
26
34
|
**opencode, Gemini CLI, Hermes Agent** — one command, nothing to clone
|
|
27
35
|
|
|
28
36
|
```bash
|
|
@@ -194,7 +202,7 @@ Artifacts are **hand-editable**: rewrite `03-design.md` and the next phase respe
|
|
|
194
202
|
## Configuration: base plus harness overlay
|
|
195
203
|
|
|
196
204
|
`FLOW.md` at the repo root is the shared base. `FLOW.claude.md`, `FLOW.codex.md`,
|
|
197
|
-
`FLOW.opencode.md`, `FLOW.gemini.md`, or `FLOW.
|
|
205
|
+
`FLOW.opencode.md`, `FLOW.gemini.md`, `FLOW.hermes.md`, or `FLOW.zcode.md` can sparsely override values for the product executing the
|
|
198
206
|
command. Existing repos with only `FLOW.md` behave exactly as before; anything effectively empty
|
|
199
207
|
is auto-detected or asked for.
|
|
200
208
|
|
|
@@ -269,7 +277,12 @@ compaction point — selective, on disk and reversible.
|
|
|
269
277
|
→ [PHILOSOPHY](docs/PHILOSOPHY.md#nothing-here-asks-you-to-compact)
|
|
270
278
|
|
|
271
279
|
Cost figures in these docs are estimates, not measurements: the flow reports how many agents a
|
|
272
|
-
command launched, not how many tokens they spent.
|
|
280
|
+
command launched, not how many tokens they spent. **Quality used to be in the same position and no
|
|
281
|
+
longer is, for one command.** `/flow:feat:review` has a bench —
|
|
282
|
+
[`plugins/flow/evals/`](plugins/flow/evals/README.md) — that runs it over fixtures whose outcome is
|
|
283
|
+
known: a defect seeded at a known `file:line` the review has to raise, and a clean diff where any
|
|
284
|
+
blocker it reports is a false positive. Every other phase is still argued from judgement, and the
|
|
285
|
+
design decisions inside `review` itself were too, until there was something to check them against.
|
|
273
286
|
|
|
274
287
|
## Other harnesses
|
|
275
288
|
|
|
@@ -279,6 +292,7 @@ The same commands, in each harness's own shape. Only the invocation syntax diffe
|
|
|
279
292
|
|---|---|---|
|
|
280
293
|
| **Codex CLI** | `codex plugin add flow@flow-plugins` (see [Quickstart](#quickstart)) | `$flow:feat-start` |
|
|
281
294
|
| **Codex CLI**, one repo only | `npx flow-workflows install codex project` → `.agents/skills/` | `$flow-feat-start` |
|
|
295
|
+
| **zcode** | `zcode plugins install flow@flow-plugins` (see [Quickstart](#quickstart)) | `/flow:feat:start` |
|
|
282
296
|
| **opencode** | `npx flow-workflows install opencode` | `/flow-feat-start` |
|
|
283
297
|
| **Gemini CLI** | `npx flow-workflows install gemini` | `/flow:feat:start` |
|
|
284
298
|
| **Hermes Agent** | `npx flow-workflows install hermes` | `/flow-feat-start` |
|
|
@@ -288,6 +302,11 @@ dropped upstream does not linger. `npx flow-workflows check` compares what your
|
|
|
288
302
|
against the newest release. From a clone, `adapters/install.sh <harness> [project]` does the same
|
|
289
303
|
thing without Node; the preflight installs both ways and fails if the results differ by one byte.
|
|
290
304
|
|
|
305
|
+
**zcode** reads this plugin package directly and names a command after its path, with no plugin
|
|
306
|
+
prefix — so the `/flow:`-prefixed set it installs is a generated mirror living beside the Claude
|
|
307
|
+
one, and the plugin's own pages also show up there unprefixed (`/feat:start`, `/init`, …). Those
|
|
308
|
+
name Claude's overlay, so type the `/flow:` names.
|
|
309
|
+
|
|
291
310
|
The mirrors are **generated** from the plugin commands by `script/adapter-build.py` and checked mechanically on every preflight (format, prefix, cited paths, install location).
|
|
292
311
|
They have **not** been executed end to end in those harnesses — validate as you use them. → [adapters/README](adapters/README.md)
|
|
293
312
|
|
|
@@ -314,6 +333,7 @@ flow-workflows/
|
|
|
314
333
|
├── .github/ preflight CI · issue forms · PR template
|
|
315
334
|
├── plugins/flow/
|
|
316
335
|
│ ├── commands/ feat/ bug/ work/ + next, init, doctor, news
|
|
336
|
+
│ ├── codex-skills/ · zcode-commands/ # generated mirrors for the two other plugin hosts
|
|
317
337
|
│ ├── skills/flow-core/ # shared rules, loaded once per session
|
|
318
338
|
│ ├── hooks/ push guard · update notice · where-you-left-off notice
|
|
319
339
|
│ └── examples/ FLOW.template.md · symfony/ (a worked example, never loaded)
|
|
@@ -335,9 +355,10 @@ bash script/tests/push-guard.sh # the push guard's cases
|
|
|
335
355
|
bash script/tests/notify-update.sh # the update-notice hook's cases
|
|
336
356
|
bash script/tests/session-start.sh # the where-you-left-off hook's cases
|
|
337
357
|
bash script/tests/review-unwrap.sh # the answer shapes `flow review` has to unwrap
|
|
358
|
+
bash script/tests/bench-compare.sh # the reader that compares two runs of the review bench
|
|
338
359
|
```
|
|
339
360
|
|
|
340
|
-
CI runs the same
|
|
361
|
+
CI runs the same seven on every PR. The preflight refuses what has shipped broken before: an empty tracked file, unparsable JSON or TOML, a manifest version out of step with `CHANGELOG.md`, a hook without its executable bit, a stale or unusable mirror. → [RELEASING](RELEASING.md)
|
|
341
362
|
|
|
342
363
|
## What it does not ship (on purpose)
|
|
343
364
|
|
package/adapters/README.md
CHANGED
|
@@ -6,8 +6,9 @@ The `flow` plugin (in `../plugins/flow`) is for **Claude Code**. These adapters
|
|
|
6
6
|
rules in `../plugins/flow/skills/flow-core/SKILL.md`, and writes every file under
|
|
7
7
|
`opencode/commands/`, `codex/skills/`, `gemini/commands/flow/`, `hermes/skills/` plus one
|
|
8
8
|
`<harness>/CORE.md` each —
|
|
9
|
-
and
|
|
10
|
-
`codex plugin add` installs them (see `codex/README.md`)
|
|
9
|
+
and the two mirrors that live inside the plugin package itself: `../plugins/flow/codex-skills/`,
|
|
10
|
+
the same Codex skills so `codex plugin add` installs them (see `codex/README.md`), and
|
|
11
|
+
`../plugins/flow/zcode-commands/`, the `/flow:`-prefixed set zcode reads (see the zcode row below).
|
|
11
12
|
The **logic and prose are the plugin's, verbatim** — only the wrapper changes.
|
|
12
13
|
|
|
13
14
|
| Harness | Commands | Subagents | MCP | Autopilot watch |
|
|
@@ -17,6 +18,7 @@ The **logic and prose are the plugin's, verbatim** — only the wrapper changes.
|
|
|
17
18
|
| **Codex CLI** | `skills/*/SKILL.md` (`$flow-feat-start`) | `[agents.*]` in `config.toml` | `[mcp_servers.*]` | cron + `codex exec` |
|
|
18
19
|
| **Codex CLI, packaged** | `plugins/flow/codex-skills/` (`$flow:feat-start`) | same | same | same |
|
|
19
20
|
| **Hermes Agent** | `skills/*/SKILL.md` (`/flow-feat-start`) | `delegate_task`, built from the prompt | `config.yaml` `mcp_servers` | **native** `/cron add` |
|
|
21
|
+
| **zcode, packaged** | `plugins/flow/zcode-commands/flow/**` (`/flow:feat:start`) | `Agent` + `subagent_type`, as in Claude Code | `mcp.servers` in `~/.zcode/cli/config.json` | **native** `ScheduleWakeup` |
|
|
20
22
|
|
|
21
23
|
## What the generator changes per harness
|
|
22
24
|
|
|
@@ -30,7 +32,13 @@ Only the mechanics, and only these:
|
|
|
30
32
|
Codex plugin package (Codex namespaces a plugin's skills), `/flow:feat:build` for Gemini. Hermes
|
|
31
33
|
invokes its skills with a slash, so it shares opencode's `/flow-feat-build`: the file is shaped
|
|
32
34
|
like Codex's, the prefix is opencode's.
|
|
33
|
-
- **`$ARGUMENTS`** → `{{args}}` for Gemini.
|
|
35
|
+
- **`$ARGUMENTS`** → `{{args}}` for Gemini. zcode reads `$ARGUMENTS`, like Claude Code.
|
|
36
|
+
- **Nothing at all, for zcode** — it reads this plugin's own format and exposes the same
|
|
37
|
+
primitives under the same names, so its mirror is the Claude page with the overlay flag changed
|
|
38
|
+
to `--harness zcode` and one `flow/` folder above the command tree. That folder is the whole
|
|
39
|
+
trick: zcode names a command after its path under the root it was found in and adds no plugin
|
|
40
|
+
prefix, so `feat/start.md` on its own would be `/feat:start` — colliding with zcode's built-ins
|
|
41
|
+
(`/init`, `/doctor`) and with the user's own commands.
|
|
34
42
|
- **The CORE pointer** — the plugin's `flow:flow-core` skill and `${CLAUDE_PLUGIN_ROOT}` become
|
|
35
43
|
`~/.claude/flow/CORE.<tool>.md`, the file `install.sh` places there. In the Codex package they stay
|
|
36
44
|
a skill (`$flow:flow-core`) and a relative root (`../..`), because there both actually exist.
|
package/adapters/codex/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.68.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
|
|
@@ -38,10 +38,14 @@ a command relies on is simply absent in that session, and nothing else will repo
|
|
|
38
38
|
them. **Name the files this listing found the first time a phase reports any configured value**,
|
|
39
39
|
so a missed overlay is visible in the artifact rather than invisible everywhere.
|
|
40
40
|
- Read `FLOW.md` at the repo root as the base, then the optional overlay for the harness running
|
|
41
|
-
this command: `FLOW.claude.md`, `FLOW.codex.md`, `FLOW.opencode.md`, `FLOW.gemini.md`,
|
|
42
|
-
`FLOW.hermes.md`. The
|
|
41
|
+
this command: `FLOW.claude.md`, `FLOW.codex.md`, `FLOW.opencode.md`, `FLOW.gemini.md`,
|
|
42
|
+
`FLOW.hermes.md`, or `FLOW.zcode.md`. The
|
|
43
43
|
harness is the product executing the command, never guessed from a model name. An overlay is
|
|
44
|
-
valid without a base file; unknown `FLOW.*.md` names are ignored.
|
|
44
|
+
valid without a base file; unknown `FLOW.*.md` names are ignored. **A page can outlive the product it
|
|
45
|
+
was written for**: zcode reads the plugin's Claude pages as well as its own `/flow:`-prefixed
|
|
46
|
+
mirror of them, so a `claude` in a path or in a `--harness` flag records where the page was
|
|
47
|
+
written, never who is running it. On zcode the overlay is `FLOW.zcode.md` and the flag is
|
|
48
|
+
`--harness zcode`, whichever of the two pages you were handed. Throughout every command,
|
|
45
49
|
**"FLOW.md" means this effective merged configuration** unless the command explicitly names a
|
|
46
50
|
file it will edit.
|
|
47
51
|
- **"The repo root" is the main checkout's, not the worktree's.** With `git.worktree` set, every
|
|
@@ -61,6 +65,15 @@ a command relies on is simply absent in that session, and nothing else will repo
|
|
|
61
65
|
base branch — and goes out in no MR/PR at all. So a phase writing a tracked file writes it
|
|
62
66
|
**here**, in the directory it is running in, and `$flow-feat-ship §5.5` is what catches the
|
|
63
67
|
tools that could not be told.
|
|
68
|
+
- **A fenced block in a FLOW file is an example, and an example is not configuration.** These
|
|
69
|
+
files are prose with keys in them, and the rule that decides what a key *is* — a `- key:` line
|
|
70
|
+
under a `## section` — knows nothing about triple backticks. So a block written to be pasted
|
|
71
|
+
("add this to try it once") was read as the configuration it illustrates, for as long as it sat
|
|
72
|
+
there. It happened in a real repo: `agents.exec_cmd` came from the fenced example of a file whose
|
|
73
|
+
prose argued at length that it was deliberately unset, and every review round took the one-shot
|
|
74
|
+
path that prose warned against — with nothing anywhere to say so, because the file and the
|
|
75
|
+
configuration disagreed while both looked right. **Skip fenced regions when you read a FLOW
|
|
76
|
+
file**; `flow-workflows` does the same, so the two of you resolve the same config.
|
|
64
77
|
- Merge by section and key. A key present in the active overlay replaces the base value; a key
|
|
65
78
|
absent there inherits the base. **A present-but-empty overlay key masks the base** and resolves
|
|
66
79
|
to the normal empty-key fallback — this is how Codex can inherit its session model while a legacy
|
|
@@ -129,6 +129,10 @@ Whether the world they describe exists —
|
|
|
129
129
|
CLIs installed *and authenticated*, agents discoverable, hooks executable, the MCP reachable, the
|
|
130
130
|
base branch resolvable — is §2 below; flag the key here, check the world there, never both.
|
|
131
131
|
|
|
132
|
+
- **Keys inside a fenced block**: report them, one line, naming the file and the keys — they are
|
|
133
|
+
an example and resolve to nothing (flow-core §0), which is exactly what a reader who pasted a
|
|
134
|
+
block to enable it cannot tell from a key that works. Say what to do about it: move the line out
|
|
135
|
+
of the fence to make it real, leave it there to keep it an illustration.
|
|
132
136
|
- **Fan-out and cost ceilings**: `agents.fanout_max` must be a positive integer; else flag and note
|
|
133
137
|
the default `4` applies. `agents.budget_max` must be a non-negative integer (`0` = no ceiling);
|
|
134
138
|
else flag and note the default `12`. **Both absent → say so as a finding, not a pass**: the review
|
|
@@ -20,9 +20,10 @@ description: "Assistant that generates FLOW.md and its optional harness overlay
|
|
|
20
20
|
|
|
21
21
|
Creates or updates the effective FLOW configuration at the repo root: shared values in `FLOW.md`
|
|
22
22
|
and optional harness-owned values in the active `FLOW.<harness>.md`. The active filename is
|
|
23
|
-
`FLOW.claude.md`, `FLOW.codex.md`, `FLOW.opencode.md`, `FLOW.gemini.md`,
|
|
24
|
-
identify it from the
|
|
25
|
-
product executing this command, never from the selected model
|
|
23
|
+
`FLOW.claude.md`, `FLOW.codex.md`, `FLOW.opencode.md`, `FLOW.gemini.md`, `FLOW.hermes.md`, or
|
|
24
|
+
`FLOW.zcode.md`; identify it from the
|
|
25
|
+
product executing this command, never from the selected model (zcode runs the Claude pages too, so
|
|
26
|
+
the page you are reading does not name the harness). Every other `$flow-*` command reads
|
|
26
27
|
the base and then that overlay. The user answers the **minimum**: what the repo can tell is
|
|
27
28
|
auto-detected and only confirmed.
|
|
28
29
|
|
|
@@ -25,7 +25,7 @@ This system **orchestrates** the project's existing sub-agents and skills (it do
|
|
|
25
25
|
- `FLOW.md` at the repo root is the shared base: tracker, branch and MR/PR conventions, quality
|
|
26
26
|
commands, code conventions, and observability profile.
|
|
27
27
|
- The active `FLOW.<harness>.md` is an optional sparse overlay (`claude`, `codex`, `opencode`,
|
|
28
|
-
`gemini`, or `
|
|
28
|
+
`gemini`, `hermes`, or `zcode`) for model names, agents, skills, orchestration, knowledge tools, or any other value that
|
|
29
29
|
differs on that harness. Every command reads the base and then the active overlay in step 0;
|
|
30
30
|
existing repos with only `FLOW.md` behave exactly as before.
|
|
31
31
|
- An overlay key replaces the base even when explicitly empty; an absent key inherits it. Lists
|
package/adapters/gemini/CORE.md
CHANGED
|
@@ -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.68.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
|
|
@@ -37,10 +37,14 @@ a command relies on is simply absent in that session, and nothing else will repo
|
|
|
37
37
|
them. **Name the files this listing found the first time a phase reports any configured value**,
|
|
38
38
|
so a missed overlay is visible in the artifact rather than invisible everywhere.
|
|
39
39
|
- Read `FLOW.md` at the repo root as the base, then the optional overlay for the harness running
|
|
40
|
-
this command: `FLOW.claude.md`, `FLOW.codex.md`, `FLOW.opencode.md`, `FLOW.gemini.md`,
|
|
41
|
-
`FLOW.hermes.md`. The
|
|
40
|
+
this command: `FLOW.claude.md`, `FLOW.codex.md`, `FLOW.opencode.md`, `FLOW.gemini.md`,
|
|
41
|
+
`FLOW.hermes.md`, or `FLOW.zcode.md`. The
|
|
42
42
|
harness is the product executing the command, never guessed from a model name. An overlay is
|
|
43
|
-
valid without a base file; unknown `FLOW.*.md` names are ignored.
|
|
43
|
+
valid without a base file; unknown `FLOW.*.md` names are ignored. **A page can outlive the product it
|
|
44
|
+
was written for**: zcode reads the plugin's Claude pages as well as its own `/flow:`-prefixed
|
|
45
|
+
mirror of them, so a `claude` in a path or in a `--harness` flag records where the page was
|
|
46
|
+
written, never who is running it. On zcode the overlay is `FLOW.zcode.md` and the flag is
|
|
47
|
+
`--harness zcode`, whichever of the two pages you were handed. Throughout every command,
|
|
44
48
|
**"FLOW.md" means this effective merged configuration** unless the command explicitly names a
|
|
45
49
|
file it will edit.
|
|
46
50
|
- **"The repo root" is the main checkout's, not the worktree's.** With `git.worktree` set, every
|
|
@@ -60,6 +64,15 @@ a command relies on is simply absent in that session, and nothing else will repo
|
|
|
60
64
|
base branch — and goes out in no MR/PR at all. So a phase writing a tracked file writes it
|
|
61
65
|
**here**, in the directory it is running in, and `/flow:feat:ship §5.5` is what catches the
|
|
62
66
|
tools that could not be told.
|
|
67
|
+
- **A fenced block in a FLOW file is an example, and an example is not configuration.** These
|
|
68
|
+
files are prose with keys in them, and the rule that decides what a key *is* — a `- key:` line
|
|
69
|
+
under a `## section` — knows nothing about triple backticks. So a block written to be pasted
|
|
70
|
+
("add this to try it once") was read as the configuration it illustrates, for as long as it sat
|
|
71
|
+
there. It happened in a real repo: `agents.exec_cmd` came from the fenced example of a file whose
|
|
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
|
|
75
|
+
file**; `flow-workflows` does the same, so the two of you resolve the same config.
|
|
63
76
|
- Merge by section and key. A key present in the active overlay replaces the base value; a key
|
|
64
77
|
absent there inherits the base. **A present-but-empty overlay key masks the base** and resolves
|
|
65
78
|
to the normal empty-key fallback — this is how Codex can inherit its session model while a legacy
|
|
@@ -125,6 +125,10 @@ Whether the world they describe exists —
|
|
|
125
125
|
CLIs installed *and authenticated*, agents discoverable, hooks executable, the MCP reachable, the
|
|
126
126
|
base branch resolvable — is §2 below; flag the key here, check the world there, never both.
|
|
127
127
|
|
|
128
|
+
- **Keys inside a fenced block**: report them, one line, naming the file and the keys — they are
|
|
129
|
+
an example and resolve to nothing (flow-core §0), which is exactly what a reader who pasted a
|
|
130
|
+
block to enable it cannot tell from a key that works. Say what to do about it: move the line out
|
|
131
|
+
of the fence to make it real, leave it there to keep it an illustration.
|
|
128
132
|
- **Fan-out and cost ceilings**: `agents.fanout_max` must be a positive integer; else flag and note
|
|
129
133
|
the default `4` applies. `agents.budget_max` must be a non-negative integer (`0` = no ceiling);
|
|
130
134
|
else flag and note the default `12`. **Both absent → say so as a finding, not a pass**: the review
|
|
@@ -16,9 +16,10 @@ prompt = """
|
|
|
16
16
|
|
|
17
17
|
Creates or updates the effective FLOW configuration at the repo root: shared values in `FLOW.md`
|
|
18
18
|
and optional harness-owned values in the active `FLOW.<harness>.md`. The active filename is
|
|
19
|
-
`FLOW.claude.md`, `FLOW.codex.md`, `FLOW.opencode.md`, `FLOW.gemini.md`,
|
|
20
|
-
identify it from the
|
|
21
|
-
product executing this command, never from the selected model
|
|
19
|
+
`FLOW.claude.md`, `FLOW.codex.md`, `FLOW.opencode.md`, `FLOW.gemini.md`, `FLOW.hermes.md`, or
|
|
20
|
+
`FLOW.zcode.md`; identify it from the
|
|
21
|
+
product executing this command, never from the selected model (zcode runs the Claude pages too, so
|
|
22
|
+
the page you are reading does not name the harness). Every other `/flow:*` command reads
|
|
22
23
|
the base and then that overlay. The user answers the **minimum**: what the repo can tell is
|
|
23
24
|
auto-detected and only confirmed.
|
|
24
25
|
|
|
@@ -21,7 +21,7 @@ This system **orchestrates** the project's existing sub-agents and skills (it do
|
|
|
21
21
|
- `FLOW.md` at the repo root is the shared base: tracker, branch and MR/PR conventions, quality
|
|
22
22
|
commands, code conventions, and observability profile.
|
|
23
23
|
- The active `FLOW.<harness>.md` is an optional sparse overlay (`claude`, `codex`, `opencode`,
|
|
24
|
-
`gemini`, or `
|
|
24
|
+
`gemini`, `hermes`, or `zcode`) for model names, agents, skills, orchestration, knowledge tools, or any other value that
|
|
25
25
|
differs on that harness. Every command reads the base and then the active overlay in step 0;
|
|
26
26
|
existing repos with only `FLOW.md` behave exactly as before.
|
|
27
27
|
- An overlay key replaces the base even when explicitly empty; an absent key inherits it. Lists
|
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.68.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
|
|
@@ -38,10 +38,14 @@ a command relies on is simply absent in that session, and nothing else will repo
|
|
|
38
38
|
them. **Name the files this listing found the first time a phase reports any configured value**,
|
|
39
39
|
so a missed overlay is visible in the artifact rather than invisible everywhere.
|
|
40
40
|
- Read `FLOW.md` at the repo root as the base, then the optional overlay for the harness running
|
|
41
|
-
this command: `FLOW.claude.md`, `FLOW.codex.md`, `FLOW.opencode.md`, `FLOW.gemini.md`,
|
|
42
|
-
`FLOW.hermes.md`. The
|
|
41
|
+
this command: `FLOW.claude.md`, `FLOW.codex.md`, `FLOW.opencode.md`, `FLOW.gemini.md`,
|
|
42
|
+
`FLOW.hermes.md`, or `FLOW.zcode.md`. The
|
|
43
43
|
harness is the product executing the command, never guessed from a model name. An overlay is
|
|
44
|
-
valid without a base file; unknown `FLOW.*.md` names are ignored.
|
|
44
|
+
valid without a base file; unknown `FLOW.*.md` names are ignored. **A page can outlive the product it
|
|
45
|
+
was written for**: zcode reads the plugin's Claude pages as well as its own `/flow:`-prefixed
|
|
46
|
+
mirror of them, so a `claude` in a path or in a `--harness` flag records where the page was
|
|
47
|
+
written, never who is running it. On zcode the overlay is `FLOW.zcode.md` and the flag is
|
|
48
|
+
`--harness zcode`, whichever of the two pages you were handed. Throughout every command,
|
|
45
49
|
**"FLOW.md" means this effective merged configuration** unless the command explicitly names a
|
|
46
50
|
file it will edit.
|
|
47
51
|
- **"The repo root" is the main checkout's, not the worktree's.** With `git.worktree` set, every
|
|
@@ -61,6 +65,15 @@ a command relies on is simply absent in that session, and nothing else will repo
|
|
|
61
65
|
base branch — and goes out in no MR/PR at all. So a phase writing a tracked file writes it
|
|
62
66
|
**here**, in the directory it is running in, and `/flow-feat-ship §5.5` is what catches the
|
|
63
67
|
tools that could not be told.
|
|
68
|
+
- **A fenced block in a FLOW file is an example, and an example is not configuration.** These
|
|
69
|
+
files are prose with keys in them, and the rule that decides what a key *is* — a `- key:` line
|
|
70
|
+
under a `## section` — knows nothing about triple backticks. So a block written to be pasted
|
|
71
|
+
("add this to try it once") was read as the configuration it illustrates, for as long as it sat
|
|
72
|
+
there. It happened in a real repo: `agents.exec_cmd` came from the fenced example of a file whose
|
|
73
|
+
prose argued at length that it was deliberately unset, and every review round took the one-shot
|
|
74
|
+
path that prose warned against — with nothing anywhere to say so, because the file and the
|
|
75
|
+
configuration disagreed while both looked right. **Skip fenced regions when you read a FLOW
|
|
76
|
+
file**; `flow-workflows` does the same, so the two of you resolve the same config.
|
|
64
77
|
- Merge by section and key. A key present in the active overlay replaces the base value; a key
|
|
65
78
|
absent there inherits the base. **A present-but-empty overlay key masks the base** and resolves
|
|
66
79
|
to the normal empty-key fallback — this is how Codex can inherit its session model while a legacy
|
|
@@ -129,6 +129,10 @@ Whether the world they describe exists —
|
|
|
129
129
|
CLIs installed *and authenticated*, agents discoverable, hooks executable, the MCP reachable, the
|
|
130
130
|
base branch resolvable — is §2 below; flag the key here, check the world there, never both.
|
|
131
131
|
|
|
132
|
+
- **Keys inside a fenced block**: report them, one line, naming the file and the keys — they are
|
|
133
|
+
an example and resolve to nothing (flow-core §0), which is exactly what a reader who pasted a
|
|
134
|
+
block to enable it cannot tell from a key that works. Say what to do about it: move the line out
|
|
135
|
+
of the fence to make it real, leave it there to keep it an illustration.
|
|
132
136
|
- **Fan-out and cost ceilings**: `agents.fanout_max` must be a positive integer; else flag and note
|
|
133
137
|
the default `4` applies. `agents.budget_max` must be a non-negative integer (`0` = no ceiling);
|
|
134
138
|
else flag and note the default `12`. **Both absent → say so as a finding, not a pass**: the review
|
|
@@ -20,9 +20,10 @@ description: "Assistant that generates FLOW.md and its optional harness overlay
|
|
|
20
20
|
|
|
21
21
|
Creates or updates the effective FLOW configuration at the repo root: shared values in `FLOW.md`
|
|
22
22
|
and optional harness-owned values in the active `FLOW.<harness>.md`. The active filename is
|
|
23
|
-
`FLOW.claude.md`, `FLOW.codex.md`, `FLOW.opencode.md`, `FLOW.gemini.md`,
|
|
24
|
-
identify it from the
|
|
25
|
-
product executing this command, never from the selected model
|
|
23
|
+
`FLOW.claude.md`, `FLOW.codex.md`, `FLOW.opencode.md`, `FLOW.gemini.md`, `FLOW.hermes.md`, or
|
|
24
|
+
`FLOW.zcode.md`; identify it from the
|
|
25
|
+
product executing this command, never from the selected model (zcode runs the Claude pages too, so
|
|
26
|
+
the page you are reading does not name the harness). Every other `/flow-*` command reads
|
|
26
27
|
the base and then that overlay. The user answers the **minimum**: what the repo can tell is
|
|
27
28
|
auto-detected and only confirmed.
|
|
28
29
|
|
|
@@ -25,7 +25,7 @@ This system **orchestrates** the project's existing sub-agents and skills (it do
|
|
|
25
25
|
- `FLOW.md` at the repo root is the shared base: tracker, branch and MR/PR conventions, quality
|
|
26
26
|
commands, code conventions, and observability profile.
|
|
27
27
|
- The active `FLOW.<harness>.md` is an optional sparse overlay (`claude`, `codex`, `opencode`,
|
|
28
|
-
`gemini`, or `
|
|
28
|
+
`gemini`, `hermes`, or `zcode`) for model names, agents, skills, orchestration, knowledge tools, or any other value that
|
|
29
29
|
differs on that harness. Every command reads the base and then the active overlay in step 0;
|
|
30
30
|
existing repos with only `FLOW.md` behave exactly as before.
|
|
31
31
|
- An overlay key replaces the base even when explicitly empty; an absent key inherits it. Lists
|
|
@@ -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.68.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
|
|
@@ -37,10 +37,14 @@ a command relies on is simply absent in that session, and nothing else will repo
|
|
|
37
37
|
them. **Name the files this listing found the first time a phase reports any configured value**,
|
|
38
38
|
so a missed overlay is visible in the artifact rather than invisible everywhere.
|
|
39
39
|
- Read `FLOW.md` at the repo root as the base, then the optional overlay for the harness running
|
|
40
|
-
this command: `FLOW.claude.md`, `FLOW.codex.md`, `FLOW.opencode.md`, `FLOW.gemini.md`,
|
|
41
|
-
`FLOW.hermes.md`. The
|
|
40
|
+
this command: `FLOW.claude.md`, `FLOW.codex.md`, `FLOW.opencode.md`, `FLOW.gemini.md`,
|
|
41
|
+
`FLOW.hermes.md`, or `FLOW.zcode.md`. The
|
|
42
42
|
harness is the product executing the command, never guessed from a model name. An overlay is
|
|
43
|
-
valid without a base file; unknown `FLOW.*.md` names are ignored.
|
|
43
|
+
valid without a base file; unknown `FLOW.*.md` names are ignored. **A page can outlive the product it
|
|
44
|
+
was written for**: zcode reads the plugin's Claude pages as well as its own `/flow:`-prefixed
|
|
45
|
+
mirror of them, so a `claude` in a path or in a `--harness` flag records where the page was
|
|
46
|
+
written, never who is running it. On zcode the overlay is `FLOW.zcode.md` and the flag is
|
|
47
|
+
`--harness zcode`, whichever of the two pages you were handed. Throughout every command,
|
|
44
48
|
**"FLOW.md" means this effective merged configuration** unless the command explicitly names a
|
|
45
49
|
file it will edit.
|
|
46
50
|
- **"The repo root" is the main checkout's, not the worktree's.** With `git.worktree` set, every
|
|
@@ -60,6 +64,15 @@ a command relies on is simply absent in that session, and nothing else will repo
|
|
|
60
64
|
base branch — and goes out in no MR/PR at all. So a phase writing a tracked file writes it
|
|
61
65
|
**here**, in the directory it is running in, and `/flow-feat-ship §5.5` is what catches the
|
|
62
66
|
tools that could not be told.
|
|
67
|
+
- **A fenced block in a FLOW file is an example, and an example is not configuration.** These
|
|
68
|
+
files are prose with keys in them, and the rule that decides what a key *is* — a `- key:` line
|
|
69
|
+
under a `## section` — knows nothing about triple backticks. So a block written to be pasted
|
|
70
|
+
("add this to try it once") was read as the configuration it illustrates, for as long as it sat
|
|
71
|
+
there. It happened in a real repo: `agents.exec_cmd` came from the fenced example of a file whose
|
|
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
|
|
75
|
+
file**; `flow-workflows` does the same, so the two of you resolve the same config.
|
|
63
76
|
- Merge by section and key. A key present in the active overlay replaces the base value; a key
|
|
64
77
|
absent there inherits the base. **A present-but-empty overlay key masks the base** and resolves
|
|
65
78
|
to the normal empty-key fallback — this is how Codex can inherit its session model while a legacy
|
|
@@ -127,6 +127,10 @@ Whether the world they describe exists —
|
|
|
127
127
|
CLIs installed *and authenticated*, agents discoverable, hooks executable, the MCP reachable, the
|
|
128
128
|
base branch resolvable — is §2 below; flag the key here, check the world there, never both.
|
|
129
129
|
|
|
130
|
+
- **Keys inside a fenced block**: report them, one line, naming the file and the keys — they are
|
|
131
|
+
an example and resolve to nothing (flow-core §0), which is exactly what a reader who pasted a
|
|
132
|
+
block to enable it cannot tell from a key that works. Say what to do about it: move the line out
|
|
133
|
+
of the fence to make it real, leave it there to keep it an illustration.
|
|
130
134
|
- **Fan-out and cost ceilings**: `agents.fanout_max` must be a positive integer; else flag and note
|
|
131
135
|
the default `4` applies. `agents.budget_max` must be a non-negative integer (`0` = no ceiling);
|
|
132
136
|
else flag and note the default `12`. **Both absent → say so as a finding, not a pass**: the review
|
|
@@ -18,9 +18,10 @@ description: Assistant that generates FLOW.md and its optional harness overlay (
|
|
|
18
18
|
|
|
19
19
|
Creates or updates the effective FLOW configuration at the repo root: shared values in `FLOW.md`
|
|
20
20
|
and optional harness-owned values in the active `FLOW.<harness>.md`. The active filename is
|
|
21
|
-
`FLOW.claude.md`, `FLOW.codex.md`, `FLOW.opencode.md`, `FLOW.gemini.md`,
|
|
22
|
-
identify it from the
|
|
23
|
-
product executing this command, never from the selected model
|
|
21
|
+
`FLOW.claude.md`, `FLOW.codex.md`, `FLOW.opencode.md`, `FLOW.gemini.md`, `FLOW.hermes.md`, or
|
|
22
|
+
`FLOW.zcode.md`; identify it from the
|
|
23
|
+
product executing this command, never from the selected model (zcode runs the Claude pages too, so
|
|
24
|
+
the page you are reading does not name the harness). Every other `/flow-*` command reads
|
|
24
25
|
the base and then that overlay. The user answers the **minimum**: what the repo can tell is
|
|
25
26
|
auto-detected and only confirmed.
|
|
26
27
|
|
|
@@ -23,7 +23,7 @@ This system **orchestrates** the project's existing sub-agents and skills (it do
|
|
|
23
23
|
- `FLOW.md` at the repo root is the shared base: tracker, branch and MR/PR conventions, quality
|
|
24
24
|
commands, code conventions, and observability profile.
|
|
25
25
|
- The active `FLOW.<harness>.md` is an optional sparse overlay (`claude`, `codex`, `opencode`,
|
|
26
|
-
`gemini`, or `
|
|
26
|
+
`gemini`, `hermes`, or `zcode`) for model names, agents, skills, orchestration, knowledge tools, or any other value that
|
|
27
27
|
differs on that harness. Every command reads the base and then the active overlay in step 0;
|
|
28
28
|
existing repos with only `FLOW.md` behave exactly as before.
|
|
29
29
|
- An overlay key replaces the base even when explicitly empty; an absent key inherits it. Lists
|
package/bin/cli.mjs
CHANGED
|
@@ -158,6 +158,17 @@ function claude() {
|
|
|
158
158
|
console.log('Codex has its own too: codex plugin marketplace add https://github.com/mashware/flow-workflows.git')
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
function zcode() {
|
|
162
|
+
console.log('zcode reads this plugin package directly, from its own marketplace, not from npm:')
|
|
163
|
+
console.log()
|
|
164
|
+
console.log(' zcode plugins marketplace add mashware/flow-workflows')
|
|
165
|
+
console.log(' zcode plugins install flow@flow-plugins')
|
|
166
|
+
console.log()
|
|
167
|
+
console.log('Then /flow:init in your repo. Updates arrive through `zcode plugins update flow`.')
|
|
168
|
+
console.log('Type the /flow:-prefixed commands: zcode also exposes the plugin\'s Claude pages')
|
|
169
|
+
console.log('unprefixed (/feat:start, /init, …), and those carry --harness claude.')
|
|
170
|
+
}
|
|
171
|
+
|
|
161
172
|
function check() {
|
|
162
173
|
const pkg = version()
|
|
163
174
|
console.log(`this package: v${pkg}`)
|
|
@@ -229,7 +240,22 @@ function parseFlow(text) {
|
|
|
229
240
|
const out = {}
|
|
230
241
|
let section = null
|
|
231
242
|
let listKey = null
|
|
243
|
+
let fence = null
|
|
232
244
|
for (const line of text.split('\n')) {
|
|
245
|
+
// A fenced block is an illustration, not configuration. This reader knows headings and
|
|
246
|
+
// `- key:` lines and nothing else, so an example written the way `docs/CONFIGURATION.md`
|
|
247
|
+
// and every FLOW.md in the wild write one — keys inside triple backticks, under a sentence
|
|
248
|
+
// saying "paste this to try it" — was live config the whole time. A real repo had
|
|
249
|
+
// `agents.exec_cmd` set from the block of a file whose prose argued, at length, that it was
|
|
250
|
+
// deliberately unset, and every review round took the one-shot path it warned against.
|
|
251
|
+
// Closing fence: same character, at least as long as the opening one (CommonMark).
|
|
252
|
+
const f = /^\s{0,3}(`{3,}|~{3,})/.exec(line)
|
|
253
|
+
if (f) {
|
|
254
|
+
if (!fence) fence = f[1]
|
|
255
|
+
else if (f[1][0] === fence[0] && f[1].length >= fence.length) fence = null
|
|
256
|
+
continue
|
|
257
|
+
}
|
|
258
|
+
if (fence) continue
|
|
233
259
|
const heading = /^##\s+(\S+)/.exec(line)
|
|
234
260
|
if (heading) {
|
|
235
261
|
section = heading[1]
|
|
@@ -276,7 +302,7 @@ const configRoot = (repo) => rootHolding(repo, 'FLOW.md')
|
|
|
276
302
|
// The overlay names flow-core §0 recognises. A `--harness` outside this set reads no
|
|
277
303
|
// overlay and looks exactly like a repo that has none, so it stops the run instead: a typo
|
|
278
304
|
// here is worth one error message and never worth a review round nobody can trust.
|
|
279
|
-
const OVERLAY_HARNESSES = ['claude', 'codex', 'gemini', 'hermes', 'opencode']
|
|
305
|
+
const OVERLAY_HARNESSES = ['claude', 'codex', 'gemini', 'hermes', 'opencode', 'zcode']
|
|
280
306
|
|
|
281
307
|
// Every overlay sitting next to the base, whether or not this run reads one.
|
|
282
308
|
function overlaysPresent(root) {
|
|
@@ -1107,8 +1133,9 @@ function usage() {
|
|
|
1107
1133
|
Harnesses: ${Object.keys(HARNESSES).join(' · ')}
|
|
1108
1134
|
"project" installs into the current repo instead of your user folder.
|
|
1109
1135
|
|
|
1110
|
-
Claude Code
|
|
1136
|
+
Claude Code, Codex CLI and zcode have their own marketplaces:
|
|
1111
1137
|
npx flow-workflows install claude shows how
|
|
1138
|
+
npx flow-workflows install zcode shows how
|
|
1112
1139
|
|
|
1113
1140
|
"bundle" prints one context pack for the current branch — worklist, diff, the changed
|
|
1114
1141
|
files in full, and the work's handoff — so a phase reads it in one call instead of
|
|
@@ -1161,10 +1188,11 @@ else if (cmd === 'cost') cost(process.argv.slice(3))
|
|
|
1161
1188
|
else if (cmd === 'review') review(process.argv.slice(3)).catch((e) => { console.error(`flow review: ${e.message}`); process.exit(1) })
|
|
1162
1189
|
else if (cmd === 'check') check()
|
|
1163
1190
|
else if (cmd === 'install' && tool === 'claude') claude()
|
|
1191
|
+
else if (cmd === 'install' && tool === 'zcode') zcode()
|
|
1164
1192
|
else if (cmd === 'install' && HARNESSES[tool]) install(tool, scope === 'project' ? 'project' : 'global')
|
|
1165
1193
|
else if (cmd === 'install') {
|
|
1166
1194
|
console.error(`Unknown harness: ${tool ?? '(none given)'}`)
|
|
1167
|
-
console.error(`Expected one of: ${Object.keys(HARNESSES).join(', ')}, claude`)
|
|
1195
|
+
console.error(`Expected one of: ${Object.keys(HARNESSES).join(', ')}, claude, zcode`)
|
|
1168
1196
|
process.exit(1)
|
|
1169
1197
|
} else if (cmd === '--version' || cmd === '-v') console.log(version())
|
|
1170
1198
|
else if (!cmd || cmd === '--help' || cmd === '-h' || cmd === 'help') usage()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flow-workflows",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.68.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": {
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"gemini-cli",
|
|
24
24
|
"codex",
|
|
25
25
|
"hermes",
|
|
26
|
+
"zcode",
|
|
26
27
|
"coding-agent",
|
|
27
28
|
"feature-flow",
|
|
28
29
|
"bug-flow"
|
|
@@ -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.68.0",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Alberto Vioque",
|
|
9
9
|
"email": "mashware@gmail.com"
|
|
@@ -17,5 +17,8 @@
|
|
|
17
17
|
"git",
|
|
18
18
|
"feature-flow",
|
|
19
19
|
"bug-flow"
|
|
20
|
-
]
|
|
20
|
+
],
|
|
21
|
+
"experimental": {
|
|
22
|
+
"evals": "evals"
|
|
23
|
+
}
|
|
21
24
|
}
|
|
@@ -5,6 +5,117 @@ plugin and is what `/flow:news` reads to show you what changed since your previo
|
|
|
5
5
|
|
|
6
6
|
The canonical, richest notes live in the [GitHub Releases](https://github.com/mashware/flow-workflows/releases).
|
|
7
7
|
|
|
8
|
+
## v0.68.0 — The block written to be pasted was the configuration · 2026-09-21
|
|
9
|
+
|
|
10
|
+
**In short**
|
|
11
|
+
- **A fenced block in a FLOW file is an example again.** `- key:` lines inside triple backticks (or tildes) are skipped by `bin/cli.mjs` and by flow-core §0, so the two resolve the same configuration. Until now they were read as the config they illustrate.
|
|
12
|
+
- **This was found in a live repo, not imagined.** `agents.exec_cmd` was set from the fenced example of a file whose prose argued, at length, that it was deliberately unset — so every review round took the one-shot path that prose warned against, and nothing anywhere said so.
|
|
13
|
+
- **`/flow:doctor` reports keys found inside a fence**, names the file and says what to do: move the line out to make it real, leave it to keep it an illustration.
|
|
14
|
+
- **`script/tests/flow-config.sh`** pins it — fenced values never leak, `~~~` and four-backtick blocks are fences, a closed fence does not swallow the keys after it. Every case fails against the old reader.
|
|
15
|
+
- **Two tests now actually run in CI**: the new one and `tier.sh`, which existed and was wired into nothing.
|
|
16
|
+
|
|
17
|
+
A `FLOW.md` is prose with keys in it, and that is the point of it: the keys are the contract, the
|
|
18
|
+
prose is why the value is what it is. What decides which is which is shape alone — a `- key:` line
|
|
19
|
+
under a `## section` — and shape is exactly what a documented example shares with the thing it
|
|
20
|
+
documents. `docs/CONFIGURATION.md` teaches keys in fenced blocks. The template's own comments do.
|
|
21
|
+
So does every real `FLOW.md` that explains an option before enabling it.
|
|
22
|
+
|
|
23
|
+
The repo where this surfaced had a Claude overlay with three paragraphs on why `agents.exec_cmd`
|
|
24
|
+
stays unset — cost against the panel that had been finding the defects — followed by a block
|
|
25
|
+
introduced with *"to try it once, add both blocks below and take them out again afterwards"*. The
|
|
26
|
+
block was live from the moment it was written: `exec_cmd` set, `quality.reviewers` masked with four
|
|
27
|
+
role descriptions instead of the four agents the base names. The file and its configuration said
|
|
28
|
+
opposite things, and both looked right.
|
|
29
|
+
|
|
30
|
+
Nothing warns about that class of mistake, because the file is valid and the round it produces is
|
|
31
|
+
green. So the reader changes: fenced regions are skipped, by the CLI and by the command pages that
|
|
32
|
+
read the file themselves, and `doctor` reports what it found in one — a reader who pasted a block
|
|
33
|
+
to enable it needs to be told why it does nothing, which is the mirror of the same problem.
|
|
34
|
+
|
|
35
|
+
## v0.67.0 — Every layer of the review was argued from judgement, and none was ever checked · 2026-09-21
|
|
36
|
+
|
|
37
|
+
**In short**
|
|
38
|
+
- **The review now has a bench.** `plugins/flow/evals/` runs `/flow:feat:review` over fixtures whose outcome is known before the review starts, and scores what came back: eight cases, five with a defect seeded at a known `file:line` the review has to raise, three with a clean diff where any blocker it reports is a false positive.
|
|
39
|
+
- **The seeded defects come from this repository's own history**, not from imagination — a value recorded after the mutation instead of before, a failing call reported as a clean result, a filter that drops the item it exists to carry, several writers on one shared key, a threshold that is code in one place and a literal in another. A defect we invent is a defect shaped like something we were already looking for.
|
|
40
|
+
- **Deterministic graders carry the score.** No judge model decides anything: a judge introduces the variance the bench exists to measure, and it changes the measuring stick exactly when the model changes. The `llm` grader is not used, and the two artifact checks that only the plugin can pass are marked as indicators outside the score, so the no-plugin arm stays comparable.
|
|
41
|
+
- **A difference inside the base's own range is not a difference.** `script/bench-compare.py` reads two runs, reports the **median** of each case rather than the mean the summary prints, and prints `—` for anything that lands inside the range the base's own runs spanned. A bench that reports every wobble as a regression is one everybody learns to ignore.
|
|
42
|
+
- **zcode is a harness the plugin knows.** It reads this same plugin package, so the commands were already there — but under names that collide with its built-ins, and resolving Claude Code's overlay. It now has its own `/flow:`-prefixed command set generated into the package, and `FLOW.zcode.md` is a recognised overlay everywhere, the CLI included.
|
|
43
|
+
- **Baselines are versioned and committed**, one per plugin version and model, under `evals/baselines/`. When a new model ships, the suite runs with `--model` and everything else frozen — which is the only way to find out that a layer which used to help has started costing turns.
|
|
44
|
+
|
|
45
|
+
Nothing in this repository could answer whether a change to `review` found more defects, fewer, or
|
|
46
|
+
the same ones more expensively. `script/check.py` proves the adapters match their sources byte for
|
|
47
|
+
byte and that a cited path exists; the hook tests pin behaviour that is deterministic by
|
|
48
|
+
construction. All of it checks **shape**, and the README already conceded half the gap — *"Cost
|
|
49
|
+
figures in these docs are estimates, not measurements"* — while saying nothing at all about the
|
|
50
|
+
other half.
|
|
51
|
+
|
|
52
|
+
That gap was not abstract. The completeness sweep, the data-access duel, the idiom audit, the
|
|
53
|
+
150/600/1500 thresholds, the sensitive-surface bump: every one of them was argued from judgement,
|
|
54
|
+
and every one is now remembered as conviction. v0.66.0 wrote down the rule for retiring a pass —
|
|
55
|
+
no exclusive surviving finding across twenty reviews and it comes out of the command — and there
|
|
56
|
+
was no way to run twenty comparable reviews to trigger it. The same release made the tier
|
|
57
|
+
computable and nothing could say whether the tier it computed was the right one. Both shipped
|
|
58
|
+
instrumentation with no bench to read it on.
|
|
59
|
+
|
|
60
|
+
**A case is a repository, not a prompt.** Each one scaffolds a small tree, a flow work parked at
|
|
61
|
+
`build`, and a branch whose diff has a known outcome; the flow CLI is installed into the fixture
|
|
62
|
+
from this checkout, so the round takes the CLI path and not its documented fallback. The prompt
|
|
63
|
+
opens with the literal `/flow:feat:review` and then states the task in plain words — both halves
|
|
64
|
+
are load-bearing. Inside an eval run the agent cannot invoke a plugin command on its own: asked in
|
|
65
|
+
prose to use the review command it reads files instead and never reaches it, so only a prompt that
|
|
66
|
+
*is* the command gets there. The plain-words half is what the no-plugin arm answers, which is what
|
|
67
|
+
makes `Δ` mean anything.
|
|
68
|
+
|
|
69
|
+
**Both kinds of case are mandatory**, and the second kind is the one that is easy to skip. Without
|
|
70
|
+
a clean diff in the suite the score rewards the noisiest review there is, and noise is what makes
|
|
71
|
+
people stop reading reviews at all. One of the three sits on a path `quality.sensitive_paths` names
|
|
72
|
+
and moves a log level and nothing else — which is the judgement §2.0 says a CLI cannot make, checked
|
|
73
|
+
for the first time.
|
|
74
|
+
|
|
75
|
+
The release preflight gains the checks that keep the bench runnable — every case has its scaffold,
|
|
76
|
+
its prompt and its graders, the prompt still opens with the command under test, and the suite still
|
|
77
|
+
holds both kinds. Running it is deliberately **not** wired into `publish.yml`: that workflow puts
|
|
78
|
+
the package on npm in minutes, and ten cases at three runs across two arms is sixty full agent
|
|
79
|
+
sessions. `.github/workflows/bench.yml` runs at the release and on demand, and says so plainly when
|
|
80
|
+
the repository has no credential for it rather than standing red.
|
|
81
|
+
|
|
82
|
+
**What the first run said**, recorded here because a bench whose first result is left out of the
|
|
83
|
+
notes is a bench nobody will believe later. 8 cases × 3 runs × 2 arms, 48 sessions, 52 minutes,
|
|
84
|
+
$47.27, threshold 0.5, the CLI's default model: every case at or above the threshold, suite score
|
|
85
|
+
0.96, and **mean Δ against the no-plugin arm of −0.04**. Seven of the eight cases scored 1.00 in
|
|
86
|
+
both arms; the eighth (`seeded-divergent-threshold`) scored 0.67 with the plugin and 1.00 without,
|
|
87
|
+
one run in three having missed it. The with-arm cost $1.57 and 4.5 minutes per run against $0.40
|
|
88
|
+
and 1.9 minutes — **3.9× for the same findings**.
|
|
89
|
+
|
|
90
|
+
The honest reading is about the fixtures before it is about the command, and the reason is
|
|
91
|
+
mechanical: every case is tagged `xs`, and **at XS the command runs the built-in `code-review`
|
|
92
|
+
alone** — no panel, and §3.5's sweep is M/L only. The layers this bench exists to judge did not run
|
|
93
|
+
once in those 48 sessions, so the two arms were doing nearly the same work. Eight single-file diffs
|
|
94
|
+
with a docstring stating the contract the code breaks is also a defect an unguided review finds,
|
|
95
|
+
which puts both arms on the ceiling, where a delta can only fall.
|
|
96
|
+
|
|
97
|
+
The second tier is written down rather than written: `deep` cases, M-sized, with a populated
|
|
98
|
+
reviewer roster, a defect split across files and its contract in `03-design.md`. They cost roughly
|
|
99
|
+
what they exercise, so the suite splits by tag and each tier keeps its own baseline.
|
|
100
|
+
|
|
101
|
+
Nothing is retired and no threshold moves here. The first run establishes the base; it does not
|
|
102
|
+
judge anything.
|
|
103
|
+
|
|
104
|
+
**zcode**, separately. It reads Claude-format plugin packages — `.zcode-plugin/plugin.json` first,
|
|
105
|
+
then `.claude-plugin/plugin.json` — and exposes the same primitives under the same names, so
|
|
106
|
+
installing flow from the marketplace worked on the first try and hid two things. A command is named
|
|
107
|
+
after its path with no plugin prefix, so the set arrived as `/feat:start`, `/next`, `/init` and
|
|
108
|
+
`/doctor` — the last two losing to zcode's own built-ins. And every `flow-workflows` call in the
|
|
109
|
+
pages carries `--harness claude`, which on zcode reads another product's overlay and reports, in the
|
|
110
|
+
pack's own header, that an overlay was read.
|
|
111
|
+
|
|
112
|
+
Both are fixed by generation, not by prose: `plugins/flow/zcode-commands/flow/**` is the same
|
|
113
|
+
generator's fifth target, the `flow/` folder is what makes zcode name them `/flow:feat:start`, and
|
|
114
|
+
the flag is substituted like it is for every other mirror. `FLOW.zcode.md` joins the overlay names
|
|
115
|
+
in flow-core, `init`, the template and the CLI — where an unknown `--harness` has always stopped
|
|
116
|
+
the run rather than silently reading the base. The plugin's own Claude pages still show up
|
|
117
|
+
unprefixed in zcode, so both the mirror's legend and the docs say to type the `/flow:` names.
|
|
118
|
+
|
|
8
119
|
## v0.66.0 — Every phase read a tree, and none of them could say which one · 2026-09-21
|
|
9
120
|
|
|
10
121
|
**In short**
|
|
@@ -5,8 +5,8 @@ file in their step 0. Delete what does not apply; **empty or absent = auto-disco
|
|
|
5
5
|
default behavior** (each command states what it does when a value is missing).
|
|
6
6
|
|
|
7
7
|
Use this shape for the shared base `FLOW.md` and for an optional sparse harness overlay:
|
|
8
|
-
`FLOW.claude.md`, `FLOW.codex.md`, `FLOW.opencode.md`, `FLOW.gemini.md`,
|
|
9
|
-
active overlay is
|
|
8
|
+
`FLOW.claude.md`, `FLOW.codex.md`, `FLOW.opencode.md`, `FLOW.gemini.md`, `FLOW.hermes.md`, or
|
|
9
|
+
`FLOW.zcode.md`. The active overlay is
|
|
10
10
|
read after the base. A key present in it replaces the base value; a present-but-empty key masks the
|
|
11
11
|
base and selects the normal empty fallback; an absent key inherits the base. Lists replace whole
|
|
12
12
|
lists. `conventions` is additive: overlay lines follow the base lines and both apply. Existing repos
|