flow-workflows 0.84.0 → 0.85.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/adapters/codex/CORE.md +5 -4
- package/adapters/codex/skills/flow-feat-ship/SKILL.md +1 -1
- package/adapters/codex/skills/flow-work-README/SKILL.md +1 -1
- package/adapters/codex/skills/flow-work-green/SKILL.md +26 -1
- package/adapters/codex/skills/flow-work-respond/SKILL.md +44 -1
- package/adapters/codex/skills/flow-work-run/SKILL.md +4 -2
- package/adapters/gemini/CORE.md +5 -4
- package/adapters/gemini/commands/flow/feat/ship.toml +1 -1
- package/adapters/gemini/commands/flow/work/README.toml +1 -1
- package/adapters/gemini/commands/flow/work/green.toml +26 -1
- package/adapters/gemini/commands/flow/work/respond.toml +44 -1
- package/adapters/gemini/commands/flow/work/run.toml +4 -2
- package/adapters/hermes/CORE.md +5 -4
- package/adapters/hermes/skills/flow-feat-ship/SKILL.md +1 -1
- package/adapters/hermes/skills/flow-work-README/SKILL.md +1 -1
- package/adapters/hermes/skills/flow-work-green/SKILL.md +26 -1
- package/adapters/hermes/skills/flow-work-respond/SKILL.md +44 -1
- package/adapters/hermes/skills/flow-work-run/SKILL.md +4 -2
- package/adapters/opencode/CORE.md +5 -4
- package/adapters/opencode/commands/flow-feat-ship.md +1 -1
- package/adapters/opencode/commands/flow-work-README.md +1 -1
- package/adapters/opencode/commands/flow-work-green.md +26 -1
- package/adapters/opencode/commands/flow-work-respond.md +44 -1
- package/adapters/opencode/commands/flow-work-run.md +4 -2
- package/package.json +1 -1
- package/plugins/flow/.claude-plugin/plugin.json +1 -1
- package/plugins/flow/CHANGELOG.md +26 -0
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.85.1`.** Compare it once, at the start of the session, against
|
|
21
21
|
`version` in `~/.claude/flow/.claude-plugin/plugin.json`. The two differing means the session
|
|
22
22
|
is running a **mixture** — the commands from one copy of the plugin, these shared rules from another
|
|
23
23
|
— which is exactly what happens when a branch or a release candidate is loaded over an installed
|
|
@@ -258,7 +258,8 @@ assumed:
|
|
|
258
258
|
recommended one first), title, body, reason and summary are written into the work folder
|
|
259
259
|
(`ask-question.md`, `ask-options.md`, `publish-title.md`, `publish-body.md`, `blocked-reason.md`,
|
|
260
260
|
`done-summary.md`) — or a `mktemp -d` directory before the folder exists — and passed by path. A
|
|
261
|
-
backtick or a quote in a ticket title must never meet a shell.
|
|
261
|
+
backtick or a quote in a ticket title must never meet a shell. `publish-title.md` holds **one
|
|
262
|
+
line**, the title alone — no `#`, no second line: the orchestrator refuses a title file with two.
|
|
262
263
|
- **The orchestrator pushes and opens the MR/PR; the run never does.** No `git push`, no `gh`, no
|
|
263
264
|
`glab`, no tracker write in this mode — not before `ship`, not in it. The orchestrator also keeps,
|
|
264
265
|
between runs, the work folder as the run left it and the work branch at the commit where it
|
|
@@ -290,7 +291,7 @@ run has.
|
|
|
290
291
|
|---|---|
|
|
291
292
|
| Business brief before code (`build`, `fix`) | record — the brief is written to the phase artifact, marked `recorded (unattended)`, and travels in the MR/PR body |
|
|
292
293
|
| Push and MR/PR creation (`ship`) | `publish` — the run commits on its own branch, writes title and body, and hands them over; the orchestrator pushes and opens the draft |
|
|
293
|
-
| Writing a DB schema change, index or migration — in any phase, a review's own fixes included — or applying one (`validate`) | question `migration`, before the first line of it is written or run |
|
|
294
|
+
| Writing a DB schema change, index or migration — in any phase, a review's own fixes included — or applying one (`validate`) | question `migration`, before the first line of it is written or run — except in `respond` and `green`, where it is blocked: a schema change agreed after the MR/PR exists goes back through `build` |
|
|
294
295
|
| `review` with blockers or high-severity findings | question `high_findings` |
|
|
295
296
|
| `validate` with a red suite or a criterion `unproven` | blocked — the phase does not advance and does not chain. **One exception, and it is measured, never judged**: every failing test also fails, under the same name, on the base (`git merge-base HEAD <git.default_base>`, run in a detached worktree), none of them lives in a file this diff touches, and none is the test that proves an acceptance criterion → record `{"key":"unattended:validate-red-base","default":"<n> red on HEAD and on base <short sha>: <test names>","phase":"validate"}` and advance; `ship` lists those tests under "Not verified — needs a human". Short of all three — a failure the base does not reproduce, a base that cannot be run, a test this diff touched — blocked |
|
|
296
297
|
| A product decision (§7 `decision`) | question `decision` |
|
|
@@ -382,7 +383,7 @@ the next review would take *Fix them* again, with nothing left to fix.
|
|
|
382
383
|
| `clarify` | `design` §1.5.5 / §9 | `design` | §1.5.5 — the choice and the size check / §9 | `03-design.md` "Decisions clarified while choosing the approach" / the criterion it clarifies | free text |
|
|
383
384
|
| `design_challenge` | `design` §6 | `design` | §7 | the "Response" of each high finding | *Apply the recommended response to each* · free text `F<n>: <response>` |
|
|
384
385
|
| `investigation_challenge` | `investigate` | `investigate` | the section after the challenge | the "Response" of each high finding | *Apply the recommended response to each* · free text `F<n>: <response>` |
|
|
385
|
-
| `decision` | any phase | the same phase | the step that surfaced it | where that phase keeps its decisions (§7) | the options that were on the table · free text |
|
|
386
|
+
| `decision` | any phase | the same phase — `work:respond` for a review round | the step that surfaced it — the end of §4 for a review round | where that phase keeps its decisions (§7) — this round's section of `08-feedback.md` for a review round | the options that were on the table · free text |
|
|
386
387
|
| `migration` | `build` / `fix` | the same phase | the unticked plan step that writes it | "Decisions made during implementation" in `05-implementation.md` / `04-fix.md` | *Write it and continue* · *Change the design first* |
|
|
387
388
|
| `migration` | `validate` (apply) | the same phase | its pre-flight — it re-runs whole, and its apply site takes the answer just applied | `meta.json.defaults_used[]` only — the artifact is written whole at the end, and names the answer beside the migration it applied (`07-validation.md` "Edge cases verified" / `05-validation.md`) | *Apply it* |
|
|
388
389
|
| `migration` | `ship` (pre-deploy SQL) | the same phase | its pre-flight — the draft lives only in context; the site takes the answer just applied | `05-implementation.md` / `04-fix.md`, beside the SQL | *The SQL is complete — ship it* |
|
|
@@ -31,7 +31,7 @@ it hands the finished MR/PR to the orchestrator, which pushes the branch and ope
|
|
|
31
31
|
place it would ask:
|
|
32
32
|
|
|
33
33
|
- **The MR/PR itself (§3–§4)** — no confirmation and no forge. §2's title and description are
|
|
34
|
-
written to `publish-title.md` and `publish-body.md` in the work folder; the body gains one line
|
|
34
|
+
written to `publish-title.md` (one line, the title alone) and `publish-body.md` in the work folder; the body gains one line
|
|
35
35
|
saying an unattended run prepared it and nobody confirmed its brief. §4.0's branch check still
|
|
36
36
|
runs (never the base; the name starts with `<ticket>-`) — and an upstream on the base is unset
|
|
37
37
|
(`git branch --unset-upstream`), with no push after it. §4.1–§4.3 do not: no push, no
|
|
@@ -248,7 +248,7 @@ Two signals arrive on an open MR/PR, each with its own cross-cutting loop (feat
|
|
|
248
248
|
resume; otherwise status.
|
|
249
249
|
- `$flow-work-daily [question]` — the **work assistant** (daily standup), read-only. **Local** (`.claude/work/` + git) + **forge** (open MRs/PRs, reviews awaiting you, red CI, unmergeable, unresolved threads via `git.cli`) + **tracker** (assigned tickets, priority changes via `tracker.tool`); where they cross, concrete commands (`$flow-feat-start`, `$flow-work-green`, `$flow-work-respond`). No argument → *yesterday · today · blockers*; a question → just that. External sources best-effort, never blocking; the only write is a "last seen" marker, like `$flow-news`.
|
|
250
250
|
- `$flow-work-status` — all works in `.claude/work/`, current phase, divergence with git.
|
|
251
|
-
- `$flow-work-run [ticket]` — the **entry an orchestrator launches** for an `unattended` run: asks it `why` (start · answer · merged), routes to the phase that answers it, and makes no decision of its own. Refuses to run in any other mode.
|
|
251
|
+
- `$flow-work-run [ticket]` — the **entry an orchestrator launches** for an `unattended` run: asks it `why` (start · answer · merged · review · pipeline), routes to the phase that answers it, and makes no decision of its own. Refuses to run in any other mode.
|
|
252
252
|
- `$flow-work-resume` — detects the branch, reads `meta.json`, recaps, suggests the next step. **Re-reads the ticket's comment thread** (§2.5), reports only what is new since `01-context.md`, appends it to the artifact; never amends the design on its own.
|
|
253
253
|
- `$flow-work-try <branch>` / `$flow-work-try --back` — point the main checkout at a branch to test it here, then return; re-syncs per `git.worktree_resync`. Resolves the work behind the branch and, once the environment is up, **prints the manual test plan already written** (the `needs-manual`/`unproven` criteria, or the acceptance criteria when `validate` has not run) and offers to collect Pass/Fail/Blocked into the validation artifact. No work behind the branch → the plain switch, as before.
|
|
254
254
|
- `$flow-work-clean [--dry-run]` — **periodic sweep** of finished work's residue: worktree, local branch, `.claude/work/` folder (intermediate train MR/PRs never set `phase: done`, so the `ship`/`abandon` prompt never fires). Verdict per branch from **the forge** with local fallbacks, including patch-equivalence for **squash merges** (`git branch --merged` misses them); acts only on `merged`/`empty`. `unknown` never a candidate; dirty and unpushed protected; work folders **archived, never deleted**; remote never touched. **`autonomy.mode` does not authorize deletion**: `auto` confirms the list too. `--purge-archive <N>d`: separate opt-in pass over `_archive/`, only folders already committed to git.
|
|
@@ -36,13 +36,38 @@ Read `~/.claude/flow/CORE.codex.md` first (shared rules: `FLOW.md` step 0, model
|
|
|
36
36
|
|
|
37
37
|
**Panel words are closed** — `mark`: `done` · `current` · `pending` · `wait` · `block` · `info`; `style`: `normal` · `dim` · `title` · `accent` · `ok` · `warn` · `error`. Anything else is dropped by the reader in silence: the panel still paints, and nobody is told.
|
|
38
38
|
|
|
39
|
-
**
|
|
39
|
+
**In `unattended`, before this phase's first step, read flow-core §2.1 whole — from its heading to the next section, unless it is already in your context whole; having read parts of it does not count** — the orchestrator command, the question stop and the way its answer comes back are all in it, and a phase that reads only part of it skips them.
|
|
40
|
+
|
|
41
|
+
**Autonomy.** Modes as in flow-core §2; `guided`/`auto` record their choices in `09-ci.md` (e.g. a pure formatter auto-fix); `unattended` resolves gates 1–4 as its paragraph below says. **Hard gates — ALWAYS stop and ask, in `manual`, `guided` and `auto`, no exceptions:**
|
|
40
42
|
1. **Any push** (§6).
|
|
41
43
|
2. Creating/switching a branch, or DB schema changes/migrations, if a fix requires them.
|
|
42
44
|
3. **Re-triggering a pipeline or job on the remote** (CI resources; outward action).
|
|
43
45
|
4. **Integrating the base branch** — any `git merge`/`git rebase` of `git.default_base` into the branch, and any history rewrite or force-push it implies (§5.C).
|
|
44
46
|
5. **Green-washing — NEVER, in any mode:** no rerun of a failed check hoping it passes; never disable, skip, `@skip`/`xit`, loosen a threshold, or delete a test/lint rule to force green; never resolve a conflict by blindly taking one side (`--ours`/`--theirs`, `checkout --theirs`, discarding the base's changes) — resolve by understanding both sides.
|
|
45
47
|
|
|
48
|
+
**In `unattended`** (flow-core §2.1) — launched by `$flow-work-run` on `why = pipeline` — this
|
|
49
|
+
command asks nothing and never touches the forge. Gate 5 holds exactly as written; the others
|
|
50
|
+
resolve this way:
|
|
51
|
+
|
|
52
|
+
- **§1–§2** — no MR/PR is resolved and no forge is read: the failures are `<cmd> events --json` →
|
|
53
|
+
`{"sha", "failed": [{name, conclusion, url, log_tail}]}`, and `log_tail` is the evidence. The order
|
|
54
|
+
failing → `blocked`; `failed` empty → `done`, the summary saying so. `sha` not `HEAD` → `blocked`:
|
|
55
|
+
the result is about another commit, and fixing it here would be fixing a guess.
|
|
56
|
+
- **§3** — triage as written, recorded in `09-ci.md`. **K** (flaky / infra) → `blocked` with the
|
|
57
|
+
evidence: the run has no rerun order, and the orchestrator owns reruns and the red-round limit.
|
|
58
|
+
**C** (conflict, behind base) and anything needing a rebase or force-push → `blocked`: the
|
|
59
|
+
orchestrator brings the base in. A **human** blocker → `blocked`, naming who. **S** → fixed within
|
|
60
|
+
scope, otherwise `blocked` with the justification.
|
|
61
|
+
- **§5** — fixes and the local verification as written; a local gate it cannot get green →
|
|
62
|
+
`blocked`. A fix adding behaviour gets its brief recorded, not asked; a fix that needs a schema
|
|
63
|
+
change, a design invalidation that is more than a tweak, or a high-severity finding from the
|
|
64
|
+
review gate the round cannot clear → `blocked` (flow-core §2.1). Commits as `auto`.
|
|
65
|
+
- **§7 before the closing order** — logged as written; offers are `Later`; re-posting the
|
|
66
|
+
performance comment is not done — a changed number goes into `publish-body.md`.
|
|
67
|
+
- **§6** — no push, no rerun, no watch. The closing order, after the WIP commit (flow-core §2.1): `publish` with the
|
|
68
|
+
work's `publish-title.md` / `publish-body.md` and the `--part/--of` `$flow-feat-ship` passed; the
|
|
69
|
+
orchestrator pushes and the pipeline runs again.
|
|
70
|
+
|
|
46
71
|
## 1. Pre-flight — locate the work and the MR/PR
|
|
47
72
|
|
|
48
73
|
- Identify the current branch and its work folder `.claude/work/<TICKET>/` (via `meta.json`, matching `branch`). Read `meta.json` and `00-summary.md`; open in full only `09-ci.md` (previous rounds) and, when §3/§5.C need the recorded "why", `03-design.md`, `05-implementation.md`/`04-fix.md`. (flow-core §5)
|
|
@@ -32,7 +32,9 @@ Read `~/.claude/flow/CORE.codex.md` first (shared rules: `FLOW.md` step 0, model
|
|
|
32
32
|
|
|
33
33
|
**Panel words are closed** — `mark`: `done` · `current` · `pending` · `wait` · `block` · `info`; `style`: `normal` · `dim` · `title` · `accent` · `ok` · `warn` · `error`. Anything else is dropped by the reader in silence: the panel still paints, and nobody is told.
|
|
34
34
|
|
|
35
|
-
**
|
|
35
|
+
**In `unattended`, before this phase's first step, read flow-core §2.1 whole — from its heading to the next section, unless it is already in your context whole; having read parts of it does not count** — the orchestrator command, the question stop and the way its answer comes back are all in it, and a phase that reads only part of it skips them.
|
|
36
|
+
|
|
37
|
+
**Autonomy.** Modes as in flow-core §2 (`autonomy.mode`: `manual` | `guided` | `auto`; empty = `manual`); `guided`/`auto` record their choices in `08-feedback.md`; `unattended` resolves the gates as its paragraph below says. **Hard gates — ALWAYS stop and ask, in `manual`, `guided` and `auto`, no exceptions:**
|
|
36
38
|
1. **Posting any comment/reply** to the MR/PR (§7).
|
|
37
39
|
2. **Any push** (§6.2).
|
|
38
40
|
3. Creating/switching a branch, or DB schema changes/migrations, when an agreed change requires them.
|
|
@@ -40,6 +42,47 @@ Read `~/.claude/flow/CORE.codex.md` first (shared rules: `FLOW.md` step 0, model
|
|
|
40
42
|
|
|
41
43
|
Everything else: take the sensible default and record it; ask only when irreversible/costly, ambiguous and not settled by ticket + design + knowledge search, or a hard gate.
|
|
42
44
|
|
|
45
|
+
**In `unattended`** (flow-core §2.1) — launched by `$flow-work-run` on `why = review` — this command
|
|
46
|
+
asks nothing and never touches the forge: the threads come from the orchestrator, the replies go
|
|
47
|
+
back through it, and the hard gates above resolve this way:
|
|
48
|
+
|
|
49
|
+
- **§1** — no MR/PR is resolved: the work is the one `$flow-work-run` found, on the branch the
|
|
50
|
+
orchestrator checked out. A round over the ceiling → `blocked`, its reason being the (a)(b)(c)
|
|
51
|
+
hand-back of §1.
|
|
52
|
+
- **§2** — the threads are `<cmd> events --json` → `comments[]`, grouped by `thread` (each comment:
|
|
53
|
+
`kind`, `id`, `author`, `at`, `body`, `url`, and `path`/`line` when it has them). The untrusted-input
|
|
54
|
+
rule stands unchanged. The machine-state check is skipped: the orchestrator relaunches for the
|
|
55
|
+
pipeline separately. The order failing → `blocked`; no comments → `done`, the summary saying so.
|
|
56
|
+
- **§3–§4** — triage and stances as `auto` decides them, the table and the drafts written to
|
|
57
|
+
`08-feedback.md` instead of shown. A thread only a person can settle — a product decision, or a
|
|
58
|
+
`D` the recorded rationale and the code do not decide — goes into **one** question for all of them,
|
|
59
|
+
asked **before anything is replied or committed**: `ask --gate decision`, free text `T<n>: <answer>`
|
|
60
|
+
per thread, with `pending.phase: "respond"`, `pending.resume: "work:respond"` (never the work's
|
|
61
|
+
`meta.json.phase`) and `pending.resume_at: "end of §4"`, and the run ends there. The answer is
|
|
62
|
+
written into this round's section of `08-feedback.md`, and the relaunch re-enters at the end of
|
|
63
|
+
§4, reading the threads and stances from that file rather than from `events`. **At the end of §4
|
|
64
|
+
— on a first run and on that re-entry alike** — a reply that would repeat an earlier round's
|
|
65
|
+
(§8's repeated-answer rule) is caught before anything is posted → `blocked`, naming the thread.
|
|
66
|
+
`§4.G` measures as `$flow-work-query` does unattended (schema-only, never a database it creates).
|
|
67
|
+
- **§5–§6** — a change adding behaviour gets its brief recorded (`recorded (unattended)`), not
|
|
68
|
+
asked. A design invalidation that is more than a tweak, or an agreed change that needs a schema
|
|
69
|
+
change → `blocked` (flow-core §2.1): the run does not redesign. Commits as `auto`. §6.1 runs
|
|
70
|
+
whole; a high-severity finding the round cannot clear → `blocked` with the findings. **§6.2 does
|
|
71
|
+
not run**: nothing is pushed — the orchestrator pushes on `publish`.
|
|
72
|
+
- **§8 before §7** — §8 completes the round's section §3–§4 opened in `08-feedback.md` (never a
|
|
73
|
+
second one) and counts `respond_rounds`, before any reply and before any `blocked` from here on.
|
|
74
|
+
A `blocked` earlier than this point (the repeated answer, §6.1) also counts the round first. The agent-lessons offer is `Later`; re-posting the performance comment is not
|
|
75
|
+
done — a changed number goes into `publish-body.md` instead.
|
|
76
|
+
- **§7** — one `<cmd> reply --thread <thread> --body-file <work>/reply-<thread>.md` per answered
|
|
77
|
+
thread, the reply naming the commit that changes the code. **Never resolve.** A `reply` that exits
|
|
78
|
+
≠ 0 is recorded in `08-feedback.md` and the remaining replies still go out.
|
|
79
|
+
- **The one closing order**, after the WIP commit (flow-core §2.1): code changed this round →
|
|
80
|
+
`publish` with the work's `publish-title.md` / `publish-body.md` (updated when the round changed
|
|
81
|
+
what they say, and naming any thread whose reply failed) and the `--part/--of` `$flow-feat-ship`
|
|
82
|
+
passed — the commits the replies name must reach the branch; no code changed and every reply went
|
|
83
|
+
out → `done`, the summary listing the threads answered; no code changed and a reply failed →
|
|
84
|
+
`blocked`, naming those threads.
|
|
85
|
+
|
|
43
86
|
## 1. Pre-flight — locate the work and the MR/PR
|
|
44
87
|
|
|
45
88
|
- Identify the current branch and its work folder `.claude/work/<TICKET>/` (the `meta.json` whose `branch` matches). Read `meta.json` and `00-summary.md`; open in full only `08-feedback.md` (spent rounds, below) and, in §3, the rationale artifacts a thread needs (`03-design.md`, `05-implementation.md`/`04-fix.md`). (flow-core §5)
|
|
@@ -38,7 +38,7 @@ of truth, and an argument that disagrees with it is ignored and named in the log
|
|
|
38
38
|
- Run `<cmd> why`. It fails, or prints anything but `start`, `answer`, `review`, `pipeline` or
|
|
39
39
|
`merged` → print what it returned and its stderr in the §3 header and end. No closing order: an
|
|
40
40
|
orchestrator that cannot say why it launched the run cannot take one either.
|
|
41
|
-
- Run `<cmd> ticket --json` and keep `number`, `title`, `base` and `kind` (`kind` absent → `feat
|
|
41
|
+
- Run `<cmd> ticket --json` and keep `number`, `title`, `base` and `kind` (`kind` absent or `null` → `feat`: the tracker could not tell, so flow decides). `kind` is re-read on every run; only `start` uses it — once the work exists, its folder says feat or bug.
|
|
42
42
|
It fails or prints no `number` → `blocked` (flow-core §2.1).
|
|
43
43
|
- Find the work: the `meta.json` under `.claude/work/` whose `ticket` equals `number` (archive
|
|
44
44
|
excluded). None is not an error — it is the "none" of the table below.
|
|
@@ -55,7 +55,9 @@ of truth, and an argument that disagrees with it is ignored and named in the log
|
|
|
55
55
|
| `answer` | nothing pending | `blocked` — there is no question for that answer to decide |
|
|
56
56
|
| `merged` | exists, something published | the entry of `meta.json.mrs` whose `status` is `published` (the only one: one MR/PR per run) becomes `merged`; set `meta.json.base` to the `base` just read; the next startable MR/PR → `$flow-feat-build`; none left, or a work with no `mrs` and `published` true (one MR/PR, every bug) → `phase = done` and `done`, the summary naming the ticket as complete |
|
|
57
57
|
| `merged` | none, or nothing published | `blocked` — nothing of this ticket was published from here |
|
|
58
|
-
| `review`
|
|
58
|
+
| `review` | exists | `$flow-work-respond` — the threads come from `<cmd> events --json` |
|
|
59
|
+
| `pipeline` | exists | `$flow-work-green` — the failed jobs come from `<cmd> events --json` |
|
|
60
|
+
| `review` · `pipeline` | none | `blocked` — there is no work of this ticket to answer for |
|
|
59
61
|
|
|
60
62
|
The phase you hand the run to is unattended too: it reads §2.1, chains as `auto` and makes the
|
|
61
63
|
run's one closing order. This command makes none of its own except the re-sent `ask`, the `blocked`
|
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.85.1`.** Compare it once, at the start of the session, against
|
|
20
20
|
`version` in `~/.claude/flow/.claude-plugin/plugin.json`. The two differing means the session
|
|
21
21
|
is running a **mixture** — the commands from one copy of the plugin, these shared rules from another
|
|
22
22
|
— which is exactly what happens when a branch or a release candidate is loaded over an installed
|
|
@@ -257,7 +257,8 @@ assumed:
|
|
|
257
257
|
recommended one first), title, body, reason and summary are written into the work folder
|
|
258
258
|
(`ask-question.md`, `ask-options.md`, `publish-title.md`, `publish-body.md`, `blocked-reason.md`,
|
|
259
259
|
`done-summary.md`) — or a `mktemp -d` directory before the folder exists — and passed by path. A
|
|
260
|
-
backtick or a quote in a ticket title must never meet a shell.
|
|
260
|
+
backtick or a quote in a ticket title must never meet a shell. `publish-title.md` holds **one
|
|
261
|
+
line**, the title alone — no `#`, no second line: the orchestrator refuses a title file with two.
|
|
261
262
|
- **The orchestrator pushes and opens the MR/PR; the run never does.** No `git push`, no `gh`, no
|
|
262
263
|
`glab`, no tracker write in this mode — not before `ship`, not in it. The orchestrator also keeps,
|
|
263
264
|
between runs, the work folder as the run left it and the work branch at the commit where it
|
|
@@ -289,7 +290,7 @@ run has.
|
|
|
289
290
|
|---|---|
|
|
290
291
|
| Business brief before code (`build`, `fix`) | record — the brief is written to the phase artifact, marked `recorded (unattended)`, and travels in the MR/PR body |
|
|
291
292
|
| Push and MR/PR creation (`ship`) | `publish` — the run commits on its own branch, writes title and body, and hands them over; the orchestrator pushes and opens the draft |
|
|
292
|
-
| Writing a DB schema change, index or migration — in any phase, a review's own fixes included — or applying one (`validate`) | question `migration`, before the first line of it is written or run |
|
|
293
|
+
| Writing a DB schema change, index or migration — in any phase, a review's own fixes included — or applying one (`validate`) | question `migration`, before the first line of it is written or run — except in `respond` and `green`, where it is blocked: a schema change agreed after the MR/PR exists goes back through `build` |
|
|
293
294
|
| `review` with blockers or high-severity findings | question `high_findings` |
|
|
294
295
|
| `validate` with a red suite or a criterion `unproven` | blocked — the phase does not advance and does not chain. **One exception, and it is measured, never judged**: every failing test also fails, under the same name, on the base (`git merge-base HEAD <git.default_base>`, run in a detached worktree), none of them lives in a file this diff touches, and none is the test that proves an acceptance criterion → record `{"key":"unattended:validate-red-base","default":"<n> red on HEAD and on base <short sha>: <test names>","phase":"validate"}` and advance; `ship` lists those tests under "Not verified — needs a human". Short of all three — a failure the base does not reproduce, a base that cannot be run, a test this diff touched — blocked |
|
|
295
296
|
| A product decision (§7 `decision`) | question `decision` |
|
|
@@ -381,7 +382,7 @@ the next review would take *Fix them* again, with nothing left to fix.
|
|
|
381
382
|
| `clarify` | `design` §1.5.5 / §9 | `design` | §1.5.5 — the choice and the size check / §9 | `03-design.md` "Decisions clarified while choosing the approach" / the criterion it clarifies | free text |
|
|
382
383
|
| `design_challenge` | `design` §6 | `design` | §7 | the "Response" of each high finding | *Apply the recommended response to each* · free text `F<n>: <response>` |
|
|
383
384
|
| `investigation_challenge` | `investigate` | `investigate` | the section after the challenge | the "Response" of each high finding | *Apply the recommended response to each* · free text `F<n>: <response>` |
|
|
384
|
-
| `decision` | any phase | the same phase | the step that surfaced it | where that phase keeps its decisions (§7) | the options that were on the table · free text |
|
|
385
|
+
| `decision` | any phase | the same phase — `work:respond` for a review round | the step that surfaced it — the end of §4 for a review round | where that phase keeps its decisions (§7) — this round's section of `08-feedback.md` for a review round | the options that were on the table · free text |
|
|
385
386
|
| `migration` | `build` / `fix` | the same phase | the unticked plan step that writes it | "Decisions made during implementation" in `05-implementation.md` / `04-fix.md` | *Write it and continue* · *Change the design first* |
|
|
386
387
|
| `migration` | `validate` (apply) | the same phase | its pre-flight — it re-runs whole, and its apply site takes the answer just applied | `meta.json.defaults_used[]` only — the artifact is written whole at the end, and names the answer beside the migration it applied (`07-validation.md` "Edge cases verified" / `05-validation.md`) | *Apply it* |
|
|
387
388
|
| `migration` | `ship` (pre-deploy SQL) | the same phase | its pre-flight — the draft lives only in context; the site takes the answer just applied | `05-implementation.md` / `04-fix.md`, beside the SQL | *The SQL is complete — ship it* |
|
|
@@ -27,7 +27,7 @@ it hands the finished MR/PR to the orchestrator, which pushes the branch and ope
|
|
|
27
27
|
place it would ask:
|
|
28
28
|
|
|
29
29
|
- **The MR/PR itself (§3–§4)** — no confirmation and no forge. §2's title and description are
|
|
30
|
-
written to `publish-title.md` and `publish-body.md` in the work folder; the body gains one line
|
|
30
|
+
written to `publish-title.md` (one line, the title alone) and `publish-body.md` in the work folder; the body gains one line
|
|
31
31
|
saying an unattended run prepared it and nobody confirmed its brief. §4.0's branch check still
|
|
32
32
|
runs (never the base; the name starts with `<ticket>-`) — and an upstream on the base is unset
|
|
33
33
|
(`git branch --unset-upstream`), with no push after it. §4.1–§4.3 do not: no push, no
|
|
@@ -244,7 +244,7 @@ Two signals arrive on an open MR/PR, each with its own cross-cutting loop (feat
|
|
|
244
244
|
resume; otherwise status.
|
|
245
245
|
- `/flow:work:daily [question]` — the **work assistant** (daily standup), read-only. **Local** (`.claude/work/` + git) + **forge** (open MRs/PRs, reviews awaiting you, red CI, unmergeable, unresolved threads via `git.cli`) + **tracker** (assigned tickets, priority changes via `tracker.tool`); where they cross, concrete commands (`/flow:feat:start`, `/flow:work:green`, `/flow:work:respond`). No argument → *yesterday · today · blockers*; a question → just that. External sources best-effort, never blocking; the only write is a "last seen" marker, like `/flow:news`.
|
|
246
246
|
- `/flow:work:status` — all works in `.claude/work/`, current phase, divergence with git.
|
|
247
|
-
- `/flow:work:run [ticket]` — the **entry an orchestrator launches** for an `unattended` run: asks it `why` (start · answer · merged), routes to the phase that answers it, and makes no decision of its own. Refuses to run in any other mode.
|
|
247
|
+
- `/flow:work:run [ticket]` — the **entry an orchestrator launches** for an `unattended` run: asks it `why` (start · answer · merged · review · pipeline), routes to the phase that answers it, and makes no decision of its own. Refuses to run in any other mode.
|
|
248
248
|
- `/flow:work:resume` — detects the branch, reads `meta.json`, recaps, suggests the next step. **Re-reads the ticket's comment thread** (§2.5), reports only what is new since `01-context.md`, appends it to the artifact; never amends the design on its own.
|
|
249
249
|
- `/flow:work:try <branch>` / `/flow:work:try --back` — point the main checkout at a branch to test it here, then return; re-syncs per `git.worktree_resync`. Resolves the work behind the branch and, once the environment is up, **prints the manual test plan already written** (the `needs-manual`/`unproven` criteria, or the acceptance criteria when `validate` has not run) and offers to collect Pass/Fail/Blocked into the validation artifact. No work behind the branch → the plain switch, as before.
|
|
250
250
|
- `/flow:work:clean [--dry-run]` — **periodic sweep** of finished work's residue: worktree, local branch, `.claude/work/` folder (intermediate train MR/PRs never set `phase: done`, so the `ship`/`abandon` prompt never fires). Verdict per branch from **the forge** with local fallbacks, including patch-equivalence for **squash merges** (`git branch --merged` misses them); acts only on `merged`/`empty`. `unknown` never a candidate; dirty and unpushed protected; work folders **archived, never deleted**; remote never touched. **`autonomy.mode` does not authorize deletion**: `auto` confirms the list too. `--purge-archive <N>d`: separate opt-in pass over `_archive/`, only folders already committed to git.
|
|
@@ -32,13 +32,38 @@ Read `~/.claude/flow/CORE.gemini.md` first (shared rules: `FLOW.md` step 0, mode
|
|
|
32
32
|
|
|
33
33
|
**Panel words are closed** — `mark`: `done` · `current` · `pending` · `wait` · `block` · `info`; `style`: `normal` · `dim` · `title` · `accent` · `ok` · `warn` · `error`. Anything else is dropped by the reader in silence: the panel still paints, and nobody is told.
|
|
34
34
|
|
|
35
|
-
**
|
|
35
|
+
**In `unattended`, before this phase's first step, read flow-core §2.1 whole — from its heading to the next section, unless it is already in your context whole; having read parts of it does not count** — the orchestrator command, the question stop and the way its answer comes back are all in it, and a phase that reads only part of it skips them.
|
|
36
|
+
|
|
37
|
+
**Autonomy.** Modes as in flow-core §2; `guided`/`auto` record their choices in `09-ci.md` (e.g. a pure formatter auto-fix); `unattended` resolves gates 1–4 as its paragraph below says. **Hard gates — ALWAYS stop and ask, in `manual`, `guided` and `auto`, no exceptions:**
|
|
36
38
|
1. **Any push** (§6).
|
|
37
39
|
2. Creating/switching a branch, or DB schema changes/migrations, if a fix requires them.
|
|
38
40
|
3. **Re-triggering a pipeline or job on the remote** (CI resources; outward action).
|
|
39
41
|
4. **Integrating the base branch** — any `git merge`/`git rebase` of `git.default_base` into the branch, and any history rewrite or force-push it implies (§5.C).
|
|
40
42
|
5. **Green-washing — NEVER, in any mode:** no rerun of a failed check hoping it passes; never disable, skip, `@skip`/`xit`, loosen a threshold, or delete a test/lint rule to force green; never resolve a conflict by blindly taking one side (`--ours`/`--theirs`, `checkout --theirs`, discarding the base's changes) — resolve by understanding both sides.
|
|
41
43
|
|
|
44
|
+
**In `unattended`** (flow-core §2.1) — launched by `/flow:work:run` on `why = pipeline` — this
|
|
45
|
+
command asks nothing and never touches the forge. Gate 5 holds exactly as written; the others
|
|
46
|
+
resolve this way:
|
|
47
|
+
|
|
48
|
+
- **§1–§2** — no MR/PR is resolved and no forge is read: the failures are `<cmd> events --json` →
|
|
49
|
+
`{"sha", "failed": [{name, conclusion, url, log_tail}]}`, and `log_tail` is the evidence. The order
|
|
50
|
+
failing → `blocked`; `failed` empty → `done`, the summary saying so. `sha` not `HEAD` → `blocked`:
|
|
51
|
+
the result is about another commit, and fixing it here would be fixing a guess.
|
|
52
|
+
- **§3** — triage as written, recorded in `09-ci.md`. **K** (flaky / infra) → `blocked` with the
|
|
53
|
+
evidence: the run has no rerun order, and the orchestrator owns reruns and the red-round limit.
|
|
54
|
+
**C** (conflict, behind base) and anything needing a rebase or force-push → `blocked`: the
|
|
55
|
+
orchestrator brings the base in. A **human** blocker → `blocked`, naming who. **S** → fixed within
|
|
56
|
+
scope, otherwise `blocked` with the justification.
|
|
57
|
+
- **§5** — fixes and the local verification as written; a local gate it cannot get green →
|
|
58
|
+
`blocked`. A fix adding behaviour gets its brief recorded, not asked; a fix that needs a schema
|
|
59
|
+
change, a design invalidation that is more than a tweak, or a high-severity finding from the
|
|
60
|
+
review gate the round cannot clear → `blocked` (flow-core §2.1). Commits as `auto`.
|
|
61
|
+
- **§7 before the closing order** — logged as written; offers are `Later`; re-posting the
|
|
62
|
+
performance comment is not done — a changed number goes into `publish-body.md`.
|
|
63
|
+
- **§6** — no push, no rerun, no watch. The closing order, after the WIP commit (flow-core §2.1): `publish` with the
|
|
64
|
+
work's `publish-title.md` / `publish-body.md` and the `--part/--of` `/flow:feat:ship` passed; the
|
|
65
|
+
orchestrator pushes and the pipeline runs again.
|
|
66
|
+
|
|
42
67
|
## 1. Pre-flight — locate the work and the MR/PR
|
|
43
68
|
|
|
44
69
|
- Identify the current branch and its work folder `.claude/work/<TICKET>/` (via `meta.json`, matching `branch`). Read `meta.json` and `00-summary.md`; open in full only `09-ci.md` (previous rounds) and, when §3/§5.C need the recorded "why", `03-design.md`, `05-implementation.md`/`04-fix.md`. (flow-core §5)
|
|
@@ -28,7 +28,9 @@ Read `~/.claude/flow/CORE.gemini.md` first (shared rules: `FLOW.md` step 0, mode
|
|
|
28
28
|
|
|
29
29
|
**Panel words are closed** — `mark`: `done` · `current` · `pending` · `wait` · `block` · `info`; `style`: `normal` · `dim` · `title` · `accent` · `ok` · `warn` · `error`. Anything else is dropped by the reader in silence: the panel still paints, and nobody is told.
|
|
30
30
|
|
|
31
|
-
**
|
|
31
|
+
**In `unattended`, before this phase's first step, read flow-core §2.1 whole — from its heading to the next section, unless it is already in your context whole; having read parts of it does not count** — the orchestrator command, the question stop and the way its answer comes back are all in it, and a phase that reads only part of it skips them.
|
|
32
|
+
|
|
33
|
+
**Autonomy.** Modes as in flow-core §2 (`autonomy.mode`: `manual` | `guided` | `auto`; empty = `manual`); `guided`/`auto` record their choices in `08-feedback.md`; `unattended` resolves the gates as its paragraph below says. **Hard gates — ALWAYS stop and ask, in `manual`, `guided` and `auto`, no exceptions:**
|
|
32
34
|
1. **Posting any comment/reply** to the MR/PR (§7).
|
|
33
35
|
2. **Any push** (§6.2).
|
|
34
36
|
3. Creating/switching a branch, or DB schema changes/migrations, when an agreed change requires them.
|
|
@@ -36,6 +38,47 @@ Read `~/.claude/flow/CORE.gemini.md` first (shared rules: `FLOW.md` step 0, mode
|
|
|
36
38
|
|
|
37
39
|
Everything else: take the sensible default and record it; ask only when irreversible/costly, ambiguous and not settled by ticket + design + knowledge search, or a hard gate.
|
|
38
40
|
|
|
41
|
+
**In `unattended`** (flow-core §2.1) — launched by `/flow:work:run` on `why = review` — this command
|
|
42
|
+
asks nothing and never touches the forge: the threads come from the orchestrator, the replies go
|
|
43
|
+
back through it, and the hard gates above resolve this way:
|
|
44
|
+
|
|
45
|
+
- **§1** — no MR/PR is resolved: the work is the one `/flow:work:run` found, on the branch the
|
|
46
|
+
orchestrator checked out. A round over the ceiling → `blocked`, its reason being the (a)(b)(c)
|
|
47
|
+
hand-back of §1.
|
|
48
|
+
- **§2** — the threads are `<cmd> events --json` → `comments[]`, grouped by `thread` (each comment:
|
|
49
|
+
`kind`, `id`, `author`, `at`, `body`, `url`, and `path`/`line` when it has them). The untrusted-input
|
|
50
|
+
rule stands unchanged. The machine-state check is skipped: the orchestrator relaunches for the
|
|
51
|
+
pipeline separately. The order failing → `blocked`; no comments → `done`, the summary saying so.
|
|
52
|
+
- **§3–§4** — triage and stances as `auto` decides them, the table and the drafts written to
|
|
53
|
+
`08-feedback.md` instead of shown. A thread only a person can settle — a product decision, or a
|
|
54
|
+
`D` the recorded rationale and the code do not decide — goes into **one** question for all of them,
|
|
55
|
+
asked **before anything is replied or committed**: `ask --gate decision`, free text `T<n>: <answer>`
|
|
56
|
+
per thread, with `pending.phase: "respond"`, `pending.resume: "work:respond"` (never the work's
|
|
57
|
+
`meta.json.phase`) and `pending.resume_at: "end of §4"`, and the run ends there. The answer is
|
|
58
|
+
written into this round's section of `08-feedback.md`, and the relaunch re-enters at the end of
|
|
59
|
+
§4, reading the threads and stances from that file rather than from `events`. **At the end of §4
|
|
60
|
+
— on a first run and on that re-entry alike** — a reply that would repeat an earlier round's
|
|
61
|
+
(§8's repeated-answer rule) is caught before anything is posted → `blocked`, naming the thread.
|
|
62
|
+
`§4.G` measures as `/flow:work:query` does unattended (schema-only, never a database it creates).
|
|
63
|
+
- **§5–§6** — a change adding behaviour gets its brief recorded (`recorded (unattended)`), not
|
|
64
|
+
asked. A design invalidation that is more than a tweak, or an agreed change that needs a schema
|
|
65
|
+
change → `blocked` (flow-core §2.1): the run does not redesign. Commits as `auto`. §6.1 runs
|
|
66
|
+
whole; a high-severity finding the round cannot clear → `blocked` with the findings. **§6.2 does
|
|
67
|
+
not run**: nothing is pushed — the orchestrator pushes on `publish`.
|
|
68
|
+
- **§8 before §7** — §8 completes the round's section §3–§4 opened in `08-feedback.md` (never a
|
|
69
|
+
second one) and counts `respond_rounds`, before any reply and before any `blocked` from here on.
|
|
70
|
+
A `blocked` earlier than this point (the repeated answer, §6.1) also counts the round first. The agent-lessons offer is `Later`; re-posting the performance comment is not
|
|
71
|
+
done — a changed number goes into `publish-body.md` instead.
|
|
72
|
+
- **§7** — one `<cmd> reply --thread <thread> --body-file <work>/reply-<thread>.md` per answered
|
|
73
|
+
thread, the reply naming the commit that changes the code. **Never resolve.** A `reply` that exits
|
|
74
|
+
≠ 0 is recorded in `08-feedback.md` and the remaining replies still go out.
|
|
75
|
+
- **The one closing order**, after the WIP commit (flow-core §2.1): code changed this round →
|
|
76
|
+
`publish` with the work's `publish-title.md` / `publish-body.md` (updated when the round changed
|
|
77
|
+
what they say, and naming any thread whose reply failed) and the `--part/--of` `/flow:feat:ship`
|
|
78
|
+
passed — the commits the replies name must reach the branch; no code changed and every reply went
|
|
79
|
+
out → `done`, the summary listing the threads answered; no code changed and a reply failed →
|
|
80
|
+
`blocked`, naming those threads.
|
|
81
|
+
|
|
39
82
|
## 1. Pre-flight — locate the work and the MR/PR
|
|
40
83
|
|
|
41
84
|
- Identify the current branch and its work folder `.claude/work/<TICKET>/` (the `meta.json` whose `branch` matches). Read `meta.json` and `00-summary.md`; open in full only `08-feedback.md` (spent rounds, below) and, in §3, the rationale artifacts a thread needs (`03-design.md`, `05-implementation.md`/`04-fix.md`). (flow-core §5)
|
|
@@ -34,7 +34,7 @@ of truth, and an argument that disagrees with it is ignored and named in the log
|
|
|
34
34
|
- Run `<cmd> why`. It fails, or prints anything but `start`, `answer`, `review`, `pipeline` or
|
|
35
35
|
`merged` → print what it returned and its stderr in the §3 header and end. No closing order: an
|
|
36
36
|
orchestrator that cannot say why it launched the run cannot take one either.
|
|
37
|
-
- Run `<cmd> ticket --json` and keep `number`, `title`, `base` and `kind` (`kind` absent → `feat
|
|
37
|
+
- Run `<cmd> ticket --json` and keep `number`, `title`, `base` and `kind` (`kind` absent or `null` → `feat`: the tracker could not tell, so flow decides). `kind` is re-read on every run; only `start` uses it — once the work exists, its folder says feat or bug.
|
|
38
38
|
It fails or prints no `number` → `blocked` (flow-core §2.1).
|
|
39
39
|
- Find the work: the `meta.json` under `.claude/work/` whose `ticket` equals `number` (archive
|
|
40
40
|
excluded). None is not an error — it is the "none" of the table below.
|
|
@@ -51,7 +51,9 @@ of truth, and an argument that disagrees with it is ignored and named in the log
|
|
|
51
51
|
| `answer` | nothing pending | `blocked` — there is no question for that answer to decide |
|
|
52
52
|
| `merged` | exists, something published | the entry of `meta.json.mrs` whose `status` is `published` (the only one: one MR/PR per run) becomes `merged`; set `meta.json.base` to the `base` just read; the next startable MR/PR → `/flow:feat:build`; none left, or a work with no `mrs` and `published` true (one MR/PR, every bug) → `phase = done` and `done`, the summary naming the ticket as complete |
|
|
53
53
|
| `merged` | none, or nothing published | `blocked` — nothing of this ticket was published from here |
|
|
54
|
-
| `review`
|
|
54
|
+
| `review` | exists | `/flow:work:respond` — the threads come from `<cmd> events --json` |
|
|
55
|
+
| `pipeline` | exists | `/flow:work:green` — the failed jobs come from `<cmd> events --json` |
|
|
56
|
+
| `review` · `pipeline` | none | `blocked` — there is no work of this ticket to answer for |
|
|
55
57
|
|
|
56
58
|
The phase you hand the run to is unattended too: it reads §2.1, chains as `auto` and makes the
|
|
57
59
|
run's one closing order. This command makes none of its own except the re-sent `ask`, the `blocked`
|
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.85.1`.** Compare it once, at the start of the session, against
|
|
21
21
|
`version` in `~/.claude/flow/.claude-plugin/plugin.json`. The two differing means the session
|
|
22
22
|
is running a **mixture** — the commands from one copy of the plugin, these shared rules from another
|
|
23
23
|
— which is exactly what happens when a branch or a release candidate is loaded over an installed
|
|
@@ -258,7 +258,8 @@ assumed:
|
|
|
258
258
|
recommended one first), title, body, reason and summary are written into the work folder
|
|
259
259
|
(`ask-question.md`, `ask-options.md`, `publish-title.md`, `publish-body.md`, `blocked-reason.md`,
|
|
260
260
|
`done-summary.md`) — or a `mktemp -d` directory before the folder exists — and passed by path. A
|
|
261
|
-
backtick or a quote in a ticket title must never meet a shell.
|
|
261
|
+
backtick or a quote in a ticket title must never meet a shell. `publish-title.md` holds **one
|
|
262
|
+
line**, the title alone — no `#`, no second line: the orchestrator refuses a title file with two.
|
|
262
263
|
- **The orchestrator pushes and opens the MR/PR; the run never does.** No `git push`, no `gh`, no
|
|
263
264
|
`glab`, no tracker write in this mode — not before `ship`, not in it. The orchestrator also keeps,
|
|
264
265
|
between runs, the work folder as the run left it and the work branch at the commit where it
|
|
@@ -290,7 +291,7 @@ run has.
|
|
|
290
291
|
|---|---|
|
|
291
292
|
| Business brief before code (`build`, `fix`) | record — the brief is written to the phase artifact, marked `recorded (unattended)`, and travels in the MR/PR body |
|
|
292
293
|
| Push and MR/PR creation (`ship`) | `publish` — the run commits on its own branch, writes title and body, and hands them over; the orchestrator pushes and opens the draft |
|
|
293
|
-
| Writing a DB schema change, index or migration — in any phase, a review's own fixes included — or applying one (`validate`) | question `migration`, before the first line of it is written or run |
|
|
294
|
+
| Writing a DB schema change, index or migration — in any phase, a review's own fixes included — or applying one (`validate`) | question `migration`, before the first line of it is written or run — except in `respond` and `green`, where it is blocked: a schema change agreed after the MR/PR exists goes back through `build` |
|
|
294
295
|
| `review` with blockers or high-severity findings | question `high_findings` |
|
|
295
296
|
| `validate` with a red suite or a criterion `unproven` | blocked — the phase does not advance and does not chain. **One exception, and it is measured, never judged**: every failing test also fails, under the same name, on the base (`git merge-base HEAD <git.default_base>`, run in a detached worktree), none of them lives in a file this diff touches, and none is the test that proves an acceptance criterion → record `{"key":"unattended:validate-red-base","default":"<n> red on HEAD and on base <short sha>: <test names>","phase":"validate"}` and advance; `ship` lists those tests under "Not verified — needs a human". Short of all three — a failure the base does not reproduce, a base that cannot be run, a test this diff touched — blocked |
|
|
296
297
|
| A product decision (§7 `decision`) | question `decision` |
|
|
@@ -382,7 +383,7 @@ the next review would take *Fix them* again, with nothing left to fix.
|
|
|
382
383
|
| `clarify` | `design` §1.5.5 / §9 | `design` | §1.5.5 — the choice and the size check / §9 | `03-design.md` "Decisions clarified while choosing the approach" / the criterion it clarifies | free text |
|
|
383
384
|
| `design_challenge` | `design` §6 | `design` | §7 | the "Response" of each high finding | *Apply the recommended response to each* · free text `F<n>: <response>` |
|
|
384
385
|
| `investigation_challenge` | `investigate` | `investigate` | the section after the challenge | the "Response" of each high finding | *Apply the recommended response to each* · free text `F<n>: <response>` |
|
|
385
|
-
| `decision` | any phase | the same phase | the step that surfaced it | where that phase keeps its decisions (§7) | the options that were on the table · free text |
|
|
386
|
+
| `decision` | any phase | the same phase — `work:respond` for a review round | the step that surfaced it — the end of §4 for a review round | where that phase keeps its decisions (§7) — this round's section of `08-feedback.md` for a review round | the options that were on the table · free text |
|
|
386
387
|
| `migration` | `build` / `fix` | the same phase | the unticked plan step that writes it | "Decisions made during implementation" in `05-implementation.md` / `04-fix.md` | *Write it and continue* · *Change the design first* |
|
|
387
388
|
| `migration` | `validate` (apply) | the same phase | its pre-flight — it re-runs whole, and its apply site takes the answer just applied | `meta.json.defaults_used[]` only — the artifact is written whole at the end, and names the answer beside the migration it applied (`07-validation.md` "Edge cases verified" / `05-validation.md`) | *Apply it* |
|
|
388
389
|
| `migration` | `ship` (pre-deploy SQL) | the same phase | its pre-flight — the draft lives only in context; the site takes the answer just applied | `05-implementation.md` / `04-fix.md`, beside the SQL | *The SQL is complete — ship it* |
|
|
@@ -31,7 +31,7 @@ it hands the finished MR/PR to the orchestrator, which pushes the branch and ope
|
|
|
31
31
|
place it would ask:
|
|
32
32
|
|
|
33
33
|
- **The MR/PR itself (§3–§4)** — no confirmation and no forge. §2's title and description are
|
|
34
|
-
written to `publish-title.md` and `publish-body.md` in the work folder; the body gains one line
|
|
34
|
+
written to `publish-title.md` (one line, the title alone) and `publish-body.md` in the work folder; the body gains one line
|
|
35
35
|
saying an unattended run prepared it and nobody confirmed its brief. §4.0's branch check still
|
|
36
36
|
runs (never the base; the name starts with `<ticket>-`) — and an upstream on the base is unset
|
|
37
37
|
(`git branch --unset-upstream`), with no push after it. §4.1–§4.3 do not: no push, no
|
|
@@ -248,7 +248,7 @@ Two signals arrive on an open MR/PR, each with its own cross-cutting loop (feat
|
|
|
248
248
|
resume; otherwise status.
|
|
249
249
|
- `/flow-work-daily [question]` — the **work assistant** (daily standup), read-only. **Local** (`.claude/work/` + git) + **forge** (open MRs/PRs, reviews awaiting you, red CI, unmergeable, unresolved threads via `git.cli`) + **tracker** (assigned tickets, priority changes via `tracker.tool`); where they cross, concrete commands (`/flow-feat-start`, `/flow-work-green`, `/flow-work-respond`). No argument → *yesterday · today · blockers*; a question → just that. External sources best-effort, never blocking; the only write is a "last seen" marker, like `/flow-news`.
|
|
250
250
|
- `/flow-work-status` — all works in `.claude/work/`, current phase, divergence with git.
|
|
251
|
-
- `/flow-work-run [ticket]` — the **entry an orchestrator launches** for an `unattended` run: asks it `why` (start · answer · merged), routes to the phase that answers it, and makes no decision of its own. Refuses to run in any other mode.
|
|
251
|
+
- `/flow-work-run [ticket]` — the **entry an orchestrator launches** for an `unattended` run: asks it `why` (start · answer · merged · review · pipeline), routes to the phase that answers it, and makes no decision of its own. Refuses to run in any other mode.
|
|
252
252
|
- `/flow-work-resume` — detects the branch, reads `meta.json`, recaps, suggests the next step. **Re-reads the ticket's comment thread** (§2.5), reports only what is new since `01-context.md`, appends it to the artifact; never amends the design on its own.
|
|
253
253
|
- `/flow-work-try <branch>` / `/flow-work-try --back` — point the main checkout at a branch to test it here, then return; re-syncs per `git.worktree_resync`. Resolves the work behind the branch and, once the environment is up, **prints the manual test plan already written** (the `needs-manual`/`unproven` criteria, or the acceptance criteria when `validate` has not run) and offers to collect Pass/Fail/Blocked into the validation artifact. No work behind the branch → the plain switch, as before.
|
|
254
254
|
- `/flow-work-clean [--dry-run]` — **periodic sweep** of finished work's residue: worktree, local branch, `.claude/work/` folder (intermediate train MR/PRs never set `phase: done`, so the `ship`/`abandon` prompt never fires). Verdict per branch from **the forge** with local fallbacks, including patch-equivalence for **squash merges** (`git branch --merged` misses them); acts only on `merged`/`empty`. `unknown` never a candidate; dirty and unpushed protected; work folders **archived, never deleted**; remote never touched. **`autonomy.mode` does not authorize deletion**: `auto` confirms the list too. `--purge-archive <N>d`: separate opt-in pass over `_archive/`, only folders already committed to git.
|
|
@@ -36,13 +36,38 @@ Read `~/.claude/flow/CORE.hermes.md` first (shared rules: `FLOW.md` step 0, mode
|
|
|
36
36
|
|
|
37
37
|
**Panel words are closed** — `mark`: `done` · `current` · `pending` · `wait` · `block` · `info`; `style`: `normal` · `dim` · `title` · `accent` · `ok` · `warn` · `error`. Anything else is dropped by the reader in silence: the panel still paints, and nobody is told.
|
|
38
38
|
|
|
39
|
-
**
|
|
39
|
+
**In `unattended`, before this phase's first step, read flow-core §2.1 whole — from its heading to the next section, unless it is already in your context whole; having read parts of it does not count** — the orchestrator command, the question stop and the way its answer comes back are all in it, and a phase that reads only part of it skips them.
|
|
40
|
+
|
|
41
|
+
**Autonomy.** Modes as in flow-core §2; `guided`/`auto` record their choices in `09-ci.md` (e.g. a pure formatter auto-fix); `unattended` resolves gates 1–4 as its paragraph below says. **Hard gates — ALWAYS stop and ask, in `manual`, `guided` and `auto`, no exceptions:**
|
|
40
42
|
1. **Any push** (§6).
|
|
41
43
|
2. Creating/switching a branch, or DB schema changes/migrations, if a fix requires them.
|
|
42
44
|
3. **Re-triggering a pipeline or job on the remote** (CI resources; outward action).
|
|
43
45
|
4. **Integrating the base branch** — any `git merge`/`git rebase` of `git.default_base` into the branch, and any history rewrite or force-push it implies (§5.C).
|
|
44
46
|
5. **Green-washing — NEVER, in any mode:** no rerun of a failed check hoping it passes; never disable, skip, `@skip`/`xit`, loosen a threshold, or delete a test/lint rule to force green; never resolve a conflict by blindly taking one side (`--ours`/`--theirs`, `checkout --theirs`, discarding the base's changes) — resolve by understanding both sides.
|
|
45
47
|
|
|
48
|
+
**In `unattended`** (flow-core §2.1) — launched by `/flow-work-run` on `why = pipeline` — this
|
|
49
|
+
command asks nothing and never touches the forge. Gate 5 holds exactly as written; the others
|
|
50
|
+
resolve this way:
|
|
51
|
+
|
|
52
|
+
- **§1–§2** — no MR/PR is resolved and no forge is read: the failures are `<cmd> events --json` →
|
|
53
|
+
`{"sha", "failed": [{name, conclusion, url, log_tail}]}`, and `log_tail` is the evidence. The order
|
|
54
|
+
failing → `blocked`; `failed` empty → `done`, the summary saying so. `sha` not `HEAD` → `blocked`:
|
|
55
|
+
the result is about another commit, and fixing it here would be fixing a guess.
|
|
56
|
+
- **§3** — triage as written, recorded in `09-ci.md`. **K** (flaky / infra) → `blocked` with the
|
|
57
|
+
evidence: the run has no rerun order, and the orchestrator owns reruns and the red-round limit.
|
|
58
|
+
**C** (conflict, behind base) and anything needing a rebase or force-push → `blocked`: the
|
|
59
|
+
orchestrator brings the base in. A **human** blocker → `blocked`, naming who. **S** → fixed within
|
|
60
|
+
scope, otherwise `blocked` with the justification.
|
|
61
|
+
- **§5** — fixes and the local verification as written; a local gate it cannot get green →
|
|
62
|
+
`blocked`. A fix adding behaviour gets its brief recorded, not asked; a fix that needs a schema
|
|
63
|
+
change, a design invalidation that is more than a tweak, or a high-severity finding from the
|
|
64
|
+
review gate the round cannot clear → `blocked` (flow-core §2.1). Commits as `auto`.
|
|
65
|
+
- **§7 before the closing order** — logged as written; offers are `Later`; re-posting the
|
|
66
|
+
performance comment is not done — a changed number goes into `publish-body.md`.
|
|
67
|
+
- **§6** — no push, no rerun, no watch. The closing order, after the WIP commit (flow-core §2.1): `publish` with the
|
|
68
|
+
work's `publish-title.md` / `publish-body.md` and the `--part/--of` `/flow-feat-ship` passed; the
|
|
69
|
+
orchestrator pushes and the pipeline runs again.
|
|
70
|
+
|
|
46
71
|
## 1. Pre-flight — locate the work and the MR/PR
|
|
47
72
|
|
|
48
73
|
- Identify the current branch and its work folder `.claude/work/<TICKET>/` (via `meta.json`, matching `branch`). Read `meta.json` and `00-summary.md`; open in full only `09-ci.md` (previous rounds) and, when §3/§5.C need the recorded "why", `03-design.md`, `05-implementation.md`/`04-fix.md`. (flow-core §5)
|
|
@@ -32,7 +32,9 @@ Read `~/.claude/flow/CORE.hermes.md` first (shared rules: `FLOW.md` step 0, mode
|
|
|
32
32
|
|
|
33
33
|
**Panel words are closed** — `mark`: `done` · `current` · `pending` · `wait` · `block` · `info`; `style`: `normal` · `dim` · `title` · `accent` · `ok` · `warn` · `error`. Anything else is dropped by the reader in silence: the panel still paints, and nobody is told.
|
|
34
34
|
|
|
35
|
-
**
|
|
35
|
+
**In `unattended`, before this phase's first step, read flow-core §2.1 whole — from its heading to the next section, unless it is already in your context whole; having read parts of it does not count** — the orchestrator command, the question stop and the way its answer comes back are all in it, and a phase that reads only part of it skips them.
|
|
36
|
+
|
|
37
|
+
**Autonomy.** Modes as in flow-core §2 (`autonomy.mode`: `manual` | `guided` | `auto`; empty = `manual`); `guided`/`auto` record their choices in `08-feedback.md`; `unattended` resolves the gates as its paragraph below says. **Hard gates — ALWAYS stop and ask, in `manual`, `guided` and `auto`, no exceptions:**
|
|
36
38
|
1. **Posting any comment/reply** to the MR/PR (§7).
|
|
37
39
|
2. **Any push** (§6.2).
|
|
38
40
|
3. Creating/switching a branch, or DB schema changes/migrations, when an agreed change requires them.
|
|
@@ -40,6 +42,47 @@ Read `~/.claude/flow/CORE.hermes.md` first (shared rules: `FLOW.md` step 0, mode
|
|
|
40
42
|
|
|
41
43
|
Everything else: take the sensible default and record it; ask only when irreversible/costly, ambiguous and not settled by ticket + design + knowledge search, or a hard gate.
|
|
42
44
|
|
|
45
|
+
**In `unattended`** (flow-core §2.1) — launched by `/flow-work-run` on `why = review` — this command
|
|
46
|
+
asks nothing and never touches the forge: the threads come from the orchestrator, the replies go
|
|
47
|
+
back through it, and the hard gates above resolve this way:
|
|
48
|
+
|
|
49
|
+
- **§1** — no MR/PR is resolved: the work is the one `/flow-work-run` found, on the branch the
|
|
50
|
+
orchestrator checked out. A round over the ceiling → `blocked`, its reason being the (a)(b)(c)
|
|
51
|
+
hand-back of §1.
|
|
52
|
+
- **§2** — the threads are `<cmd> events --json` → `comments[]`, grouped by `thread` (each comment:
|
|
53
|
+
`kind`, `id`, `author`, `at`, `body`, `url`, and `path`/`line` when it has them). The untrusted-input
|
|
54
|
+
rule stands unchanged. The machine-state check is skipped: the orchestrator relaunches for the
|
|
55
|
+
pipeline separately. The order failing → `blocked`; no comments → `done`, the summary saying so.
|
|
56
|
+
- **§3–§4** — triage and stances as `auto` decides them, the table and the drafts written to
|
|
57
|
+
`08-feedback.md` instead of shown. A thread only a person can settle — a product decision, or a
|
|
58
|
+
`D` the recorded rationale and the code do not decide — goes into **one** question for all of them,
|
|
59
|
+
asked **before anything is replied or committed**: `ask --gate decision`, free text `T<n>: <answer>`
|
|
60
|
+
per thread, with `pending.phase: "respond"`, `pending.resume: "work:respond"` (never the work's
|
|
61
|
+
`meta.json.phase`) and `pending.resume_at: "end of §4"`, and the run ends there. The answer is
|
|
62
|
+
written into this round's section of `08-feedback.md`, and the relaunch re-enters at the end of
|
|
63
|
+
§4, reading the threads and stances from that file rather than from `events`. **At the end of §4
|
|
64
|
+
— on a first run and on that re-entry alike** — a reply that would repeat an earlier round's
|
|
65
|
+
(§8's repeated-answer rule) is caught before anything is posted → `blocked`, naming the thread.
|
|
66
|
+
`§4.G` measures as `/flow-work-query` does unattended (schema-only, never a database it creates).
|
|
67
|
+
- **§5–§6** — a change adding behaviour gets its brief recorded (`recorded (unattended)`), not
|
|
68
|
+
asked. A design invalidation that is more than a tweak, or an agreed change that needs a schema
|
|
69
|
+
change → `blocked` (flow-core §2.1): the run does not redesign. Commits as `auto`. §6.1 runs
|
|
70
|
+
whole; a high-severity finding the round cannot clear → `blocked` with the findings. **§6.2 does
|
|
71
|
+
not run**: nothing is pushed — the orchestrator pushes on `publish`.
|
|
72
|
+
- **§8 before §7** — §8 completes the round's section §3–§4 opened in `08-feedback.md` (never a
|
|
73
|
+
second one) and counts `respond_rounds`, before any reply and before any `blocked` from here on.
|
|
74
|
+
A `blocked` earlier than this point (the repeated answer, §6.1) also counts the round first. The agent-lessons offer is `Later`; re-posting the performance comment is not
|
|
75
|
+
done — a changed number goes into `publish-body.md` instead.
|
|
76
|
+
- **§7** — one `<cmd> reply --thread <thread> --body-file <work>/reply-<thread>.md` per answered
|
|
77
|
+
thread, the reply naming the commit that changes the code. **Never resolve.** A `reply` that exits
|
|
78
|
+
≠ 0 is recorded in `08-feedback.md` and the remaining replies still go out.
|
|
79
|
+
- **The one closing order**, after the WIP commit (flow-core §2.1): code changed this round →
|
|
80
|
+
`publish` with the work's `publish-title.md` / `publish-body.md` (updated when the round changed
|
|
81
|
+
what they say, and naming any thread whose reply failed) and the `--part/--of` `/flow-feat-ship`
|
|
82
|
+
passed — the commits the replies name must reach the branch; no code changed and every reply went
|
|
83
|
+
out → `done`, the summary listing the threads answered; no code changed and a reply failed →
|
|
84
|
+
`blocked`, naming those threads.
|
|
85
|
+
|
|
43
86
|
## 1. Pre-flight — locate the work and the MR/PR
|
|
44
87
|
|
|
45
88
|
- Identify the current branch and its work folder `.claude/work/<TICKET>/` (the `meta.json` whose `branch` matches). Read `meta.json` and `00-summary.md`; open in full only `08-feedback.md` (spent rounds, below) and, in §3, the rationale artifacts a thread needs (`03-design.md`, `05-implementation.md`/`04-fix.md`). (flow-core §5)
|
|
@@ -38,7 +38,7 @@ of truth, and an argument that disagrees with it is ignored and named in the log
|
|
|
38
38
|
- Run `<cmd> why`. It fails, or prints anything but `start`, `answer`, `review`, `pipeline` or
|
|
39
39
|
`merged` → print what it returned and its stderr in the §3 header and end. No closing order: an
|
|
40
40
|
orchestrator that cannot say why it launched the run cannot take one either.
|
|
41
|
-
- Run `<cmd> ticket --json` and keep `number`, `title`, `base` and `kind` (`kind` absent → `feat
|
|
41
|
+
- Run `<cmd> ticket --json` and keep `number`, `title`, `base` and `kind` (`kind` absent or `null` → `feat`: the tracker could not tell, so flow decides). `kind` is re-read on every run; only `start` uses it — once the work exists, its folder says feat or bug.
|
|
42
42
|
It fails or prints no `number` → `blocked` (flow-core §2.1).
|
|
43
43
|
- Find the work: the `meta.json` under `.claude/work/` whose `ticket` equals `number` (archive
|
|
44
44
|
excluded). None is not an error — it is the "none" of the table below.
|
|
@@ -55,7 +55,9 @@ of truth, and an argument that disagrees with it is ignored and named in the log
|
|
|
55
55
|
| `answer` | nothing pending | `blocked` — there is no question for that answer to decide |
|
|
56
56
|
| `merged` | exists, something published | the entry of `meta.json.mrs` whose `status` is `published` (the only one: one MR/PR per run) becomes `merged`; set `meta.json.base` to the `base` just read; the next startable MR/PR → `/flow-feat-build`; none left, or a work with no `mrs` and `published` true (one MR/PR, every bug) → `phase = done` and `done`, the summary naming the ticket as complete |
|
|
57
57
|
| `merged` | none, or nothing published | `blocked` — nothing of this ticket was published from here |
|
|
58
|
-
| `review`
|
|
58
|
+
| `review` | exists | `/flow-work-respond` — the threads come from `<cmd> events --json` |
|
|
59
|
+
| `pipeline` | exists | `/flow-work-green` — the failed jobs come from `<cmd> events --json` |
|
|
60
|
+
| `review` · `pipeline` | none | `blocked` — there is no work of this ticket to answer for |
|
|
59
61
|
|
|
60
62
|
The phase you hand the run to is unattended too: it reads §2.1, chains as `auto` and makes the
|
|
61
63
|
run's one closing order. This command makes none of its own except the re-sent `ask`, the `blocked`
|
|
@@ -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.85.1`.** Compare it once, at the start of the session, against
|
|
20
20
|
`version` in `~/.claude/flow/.claude-plugin/plugin.json`. The two differing means the session
|
|
21
21
|
is running a **mixture** — the commands from one copy of the plugin, these shared rules from another
|
|
22
22
|
— which is exactly what happens when a branch or a release candidate is loaded over an installed
|
|
@@ -257,7 +257,8 @@ assumed:
|
|
|
257
257
|
recommended one first), title, body, reason and summary are written into the work folder
|
|
258
258
|
(`ask-question.md`, `ask-options.md`, `publish-title.md`, `publish-body.md`, `blocked-reason.md`,
|
|
259
259
|
`done-summary.md`) — or a `mktemp -d` directory before the folder exists — and passed by path. A
|
|
260
|
-
backtick or a quote in a ticket title must never meet a shell.
|
|
260
|
+
backtick or a quote in a ticket title must never meet a shell. `publish-title.md` holds **one
|
|
261
|
+
line**, the title alone — no `#`, no second line: the orchestrator refuses a title file with two.
|
|
261
262
|
- **The orchestrator pushes and opens the MR/PR; the run never does.** No `git push`, no `gh`, no
|
|
262
263
|
`glab`, no tracker write in this mode — not before `ship`, not in it. The orchestrator also keeps,
|
|
263
264
|
between runs, the work folder as the run left it and the work branch at the commit where it
|
|
@@ -289,7 +290,7 @@ run has.
|
|
|
289
290
|
|---|---|
|
|
290
291
|
| Business brief before code (`build`, `fix`) | record — the brief is written to the phase artifact, marked `recorded (unattended)`, and travels in the MR/PR body |
|
|
291
292
|
| Push and MR/PR creation (`ship`) | `publish` — the run commits on its own branch, writes title and body, and hands them over; the orchestrator pushes and opens the draft |
|
|
292
|
-
| Writing a DB schema change, index or migration — in any phase, a review's own fixes included — or applying one (`validate`) | question `migration`, before the first line of it is written or run |
|
|
293
|
+
| Writing a DB schema change, index or migration — in any phase, a review's own fixes included — or applying one (`validate`) | question `migration`, before the first line of it is written or run — except in `respond` and `green`, where it is blocked: a schema change agreed after the MR/PR exists goes back through `build` |
|
|
293
294
|
| `review` with blockers or high-severity findings | question `high_findings` |
|
|
294
295
|
| `validate` with a red suite or a criterion `unproven` | blocked — the phase does not advance and does not chain. **One exception, and it is measured, never judged**: every failing test also fails, under the same name, on the base (`git merge-base HEAD <git.default_base>`, run in a detached worktree), none of them lives in a file this diff touches, and none is the test that proves an acceptance criterion → record `{"key":"unattended:validate-red-base","default":"<n> red on HEAD and on base <short sha>: <test names>","phase":"validate"}` and advance; `ship` lists those tests under "Not verified — needs a human". Short of all three — a failure the base does not reproduce, a base that cannot be run, a test this diff touched — blocked |
|
|
295
296
|
| A product decision (§7 `decision`) | question `decision` |
|
|
@@ -381,7 +382,7 @@ the next review would take *Fix them* again, with nothing left to fix.
|
|
|
381
382
|
| `clarify` | `design` §1.5.5 / §9 | `design` | §1.5.5 — the choice and the size check / §9 | `03-design.md` "Decisions clarified while choosing the approach" / the criterion it clarifies | free text |
|
|
382
383
|
| `design_challenge` | `design` §6 | `design` | §7 | the "Response" of each high finding | *Apply the recommended response to each* · free text `F<n>: <response>` |
|
|
383
384
|
| `investigation_challenge` | `investigate` | `investigate` | the section after the challenge | the "Response" of each high finding | *Apply the recommended response to each* · free text `F<n>: <response>` |
|
|
384
|
-
| `decision` | any phase | the same phase | the step that surfaced it | where that phase keeps its decisions (§7) | the options that were on the table · free text |
|
|
385
|
+
| `decision` | any phase | the same phase — `work:respond` for a review round | the step that surfaced it — the end of §4 for a review round | where that phase keeps its decisions (§7) — this round's section of `08-feedback.md` for a review round | the options that were on the table · free text |
|
|
385
386
|
| `migration` | `build` / `fix` | the same phase | the unticked plan step that writes it | "Decisions made during implementation" in `05-implementation.md` / `04-fix.md` | *Write it and continue* · *Change the design first* |
|
|
386
387
|
| `migration` | `validate` (apply) | the same phase | its pre-flight — it re-runs whole, and its apply site takes the answer just applied | `meta.json.defaults_used[]` only — the artifact is written whole at the end, and names the answer beside the migration it applied (`07-validation.md` "Edge cases verified" / `05-validation.md`) | *Apply it* |
|
|
387
388
|
| `migration` | `ship` (pre-deploy SQL) | the same phase | its pre-flight — the draft lives only in context; the site takes the answer just applied | `05-implementation.md` / `04-fix.md`, beside the SQL | *The SQL is complete — ship it* |
|
|
@@ -29,7 +29,7 @@ it hands the finished MR/PR to the orchestrator, which pushes the branch and ope
|
|
|
29
29
|
place it would ask:
|
|
30
30
|
|
|
31
31
|
- **The MR/PR itself (§3–§4)** — no confirmation and no forge. §2's title and description are
|
|
32
|
-
written to `publish-title.md` and `publish-body.md` in the work folder; the body gains one line
|
|
32
|
+
written to `publish-title.md` (one line, the title alone) and `publish-body.md` in the work folder; the body gains one line
|
|
33
33
|
saying an unattended run prepared it and nobody confirmed its brief. §4.0's branch check still
|
|
34
34
|
runs (never the base; the name starts with `<ticket>-`) — and an upstream on the base is unset
|
|
35
35
|
(`git branch --unset-upstream`), with no push after it. §4.1–§4.3 do not: no push, no
|
|
@@ -246,7 +246,7 @@ Two signals arrive on an open MR/PR, each with its own cross-cutting loop (feat
|
|
|
246
246
|
resume; otherwise status.
|
|
247
247
|
- `/flow-work-daily [question]` — the **work assistant** (daily standup), read-only. **Local** (`.claude/work/` + git) + **forge** (open MRs/PRs, reviews awaiting you, red CI, unmergeable, unresolved threads via `git.cli`) + **tracker** (assigned tickets, priority changes via `tracker.tool`); where they cross, concrete commands (`/flow-feat-start`, `/flow-work-green`, `/flow-work-respond`). No argument → *yesterday · today · blockers*; a question → just that. External sources best-effort, never blocking; the only write is a "last seen" marker, like `/flow-news`.
|
|
248
248
|
- `/flow-work-status` — all works in `.claude/work/`, current phase, divergence with git.
|
|
249
|
-
- `/flow-work-run [ticket]` — the **entry an orchestrator launches** for an `unattended` run: asks it `why` (start · answer · merged), routes to the phase that answers it, and makes no decision of its own. Refuses to run in any other mode.
|
|
249
|
+
- `/flow-work-run [ticket]` — the **entry an orchestrator launches** for an `unattended` run: asks it `why` (start · answer · merged · review · pipeline), routes to the phase that answers it, and makes no decision of its own. Refuses to run in any other mode.
|
|
250
250
|
- `/flow-work-resume` — detects the branch, reads `meta.json`, recaps, suggests the next step. **Re-reads the ticket's comment thread** (§2.5), reports only what is new since `01-context.md`, appends it to the artifact; never amends the design on its own.
|
|
251
251
|
- `/flow-work-try <branch>` / `/flow-work-try --back` — point the main checkout at a branch to test it here, then return; re-syncs per `git.worktree_resync`. Resolves the work behind the branch and, once the environment is up, **prints the manual test plan already written** (the `needs-manual`/`unproven` criteria, or the acceptance criteria when `validate` has not run) and offers to collect Pass/Fail/Blocked into the validation artifact. No work behind the branch → the plain switch, as before.
|
|
252
252
|
- `/flow-work-clean [--dry-run]` — **periodic sweep** of finished work's residue: worktree, local branch, `.claude/work/` folder (intermediate train MR/PRs never set `phase: done`, so the `ship`/`abandon` prompt never fires). Verdict per branch from **the forge** with local fallbacks, including patch-equivalence for **squash merges** (`git branch --merged` misses them); acts only on `merged`/`empty`. `unknown` never a candidate; dirty and unpushed protected; work folders **archived, never deleted**; remote never touched. **`autonomy.mode` does not authorize deletion**: `auto` confirms the list too. `--purge-archive <N>d`: separate opt-in pass over `_archive/`, only folders already committed to git.
|
|
@@ -34,13 +34,38 @@ Read `~/.claude/flow/CORE.opencode.md` first (shared rules: `FLOW.md` step 0, mo
|
|
|
34
34
|
|
|
35
35
|
**Panel words are closed** — `mark`: `done` · `current` · `pending` · `wait` · `block` · `info`; `style`: `normal` · `dim` · `title` · `accent` · `ok` · `warn` · `error`. Anything else is dropped by the reader in silence: the panel still paints, and nobody is told.
|
|
36
36
|
|
|
37
|
-
**
|
|
37
|
+
**In `unattended`, before this phase's first step, read flow-core §2.1 whole — from its heading to the next section, unless it is already in your context whole; having read parts of it does not count** — the orchestrator command, the question stop and the way its answer comes back are all in it, and a phase that reads only part of it skips them.
|
|
38
|
+
|
|
39
|
+
**Autonomy.** Modes as in flow-core §2; `guided`/`auto` record their choices in `09-ci.md` (e.g. a pure formatter auto-fix); `unattended` resolves gates 1–4 as its paragraph below says. **Hard gates — ALWAYS stop and ask, in `manual`, `guided` and `auto`, no exceptions:**
|
|
38
40
|
1. **Any push** (§6).
|
|
39
41
|
2. Creating/switching a branch, or DB schema changes/migrations, if a fix requires them.
|
|
40
42
|
3. **Re-triggering a pipeline or job on the remote** (CI resources; outward action).
|
|
41
43
|
4. **Integrating the base branch** — any `git merge`/`git rebase` of `git.default_base` into the branch, and any history rewrite or force-push it implies (§5.C).
|
|
42
44
|
5. **Green-washing — NEVER, in any mode:** no rerun of a failed check hoping it passes; never disable, skip, `@skip`/`xit`, loosen a threshold, or delete a test/lint rule to force green; never resolve a conflict by blindly taking one side (`--ours`/`--theirs`, `checkout --theirs`, discarding the base's changes) — resolve by understanding both sides.
|
|
43
45
|
|
|
46
|
+
**In `unattended`** (flow-core §2.1) — launched by `/flow-work-run` on `why = pipeline` — this
|
|
47
|
+
command asks nothing and never touches the forge. Gate 5 holds exactly as written; the others
|
|
48
|
+
resolve this way:
|
|
49
|
+
|
|
50
|
+
- **§1–§2** — no MR/PR is resolved and no forge is read: the failures are `<cmd> events --json` →
|
|
51
|
+
`{"sha", "failed": [{name, conclusion, url, log_tail}]}`, and `log_tail` is the evidence. The order
|
|
52
|
+
failing → `blocked`; `failed` empty → `done`, the summary saying so. `sha` not `HEAD` → `blocked`:
|
|
53
|
+
the result is about another commit, and fixing it here would be fixing a guess.
|
|
54
|
+
- **§3** — triage as written, recorded in `09-ci.md`. **K** (flaky / infra) → `blocked` with the
|
|
55
|
+
evidence: the run has no rerun order, and the orchestrator owns reruns and the red-round limit.
|
|
56
|
+
**C** (conflict, behind base) and anything needing a rebase or force-push → `blocked`: the
|
|
57
|
+
orchestrator brings the base in. A **human** blocker → `blocked`, naming who. **S** → fixed within
|
|
58
|
+
scope, otherwise `blocked` with the justification.
|
|
59
|
+
- **§5** — fixes and the local verification as written; a local gate it cannot get green →
|
|
60
|
+
`blocked`. A fix adding behaviour gets its brief recorded, not asked; a fix that needs a schema
|
|
61
|
+
change, a design invalidation that is more than a tweak, or a high-severity finding from the
|
|
62
|
+
review gate the round cannot clear → `blocked` (flow-core §2.1). Commits as `auto`.
|
|
63
|
+
- **§7 before the closing order** — logged as written; offers are `Later`; re-posting the
|
|
64
|
+
performance comment is not done — a changed number goes into `publish-body.md`.
|
|
65
|
+
- **§6** — no push, no rerun, no watch. The closing order, after the WIP commit (flow-core §2.1): `publish` with the
|
|
66
|
+
work's `publish-title.md` / `publish-body.md` and the `--part/--of` `/flow-feat-ship` passed; the
|
|
67
|
+
orchestrator pushes and the pipeline runs again.
|
|
68
|
+
|
|
44
69
|
## 1. Pre-flight — locate the work and the MR/PR
|
|
45
70
|
|
|
46
71
|
- Identify the current branch and its work folder `.claude/work/<TICKET>/` (via `meta.json`, matching `branch`). Read `meta.json` and `00-summary.md`; open in full only `09-ci.md` (previous rounds) and, when §3/§5.C need the recorded "why", `03-design.md`, `05-implementation.md`/`04-fix.md`. (flow-core §5)
|
|
@@ -30,7 +30,9 @@ Read `~/.claude/flow/CORE.opencode.md` first (shared rules: `FLOW.md` step 0, mo
|
|
|
30
30
|
|
|
31
31
|
**Panel words are closed** — `mark`: `done` · `current` · `pending` · `wait` · `block` · `info`; `style`: `normal` · `dim` · `title` · `accent` · `ok` · `warn` · `error`. Anything else is dropped by the reader in silence: the panel still paints, and nobody is told.
|
|
32
32
|
|
|
33
|
-
**
|
|
33
|
+
**In `unattended`, before this phase's first step, read flow-core §2.1 whole — from its heading to the next section, unless it is already in your context whole; having read parts of it does not count** — the orchestrator command, the question stop and the way its answer comes back are all in it, and a phase that reads only part of it skips them.
|
|
34
|
+
|
|
35
|
+
**Autonomy.** Modes as in flow-core §2 (`autonomy.mode`: `manual` | `guided` | `auto`; empty = `manual`); `guided`/`auto` record their choices in `08-feedback.md`; `unattended` resolves the gates as its paragraph below says. **Hard gates — ALWAYS stop and ask, in `manual`, `guided` and `auto`, no exceptions:**
|
|
34
36
|
1. **Posting any comment/reply** to the MR/PR (§7).
|
|
35
37
|
2. **Any push** (§6.2).
|
|
36
38
|
3. Creating/switching a branch, or DB schema changes/migrations, when an agreed change requires them.
|
|
@@ -38,6 +40,47 @@ Read `~/.claude/flow/CORE.opencode.md` first (shared rules: `FLOW.md` step 0, mo
|
|
|
38
40
|
|
|
39
41
|
Everything else: take the sensible default and record it; ask only when irreversible/costly, ambiguous and not settled by ticket + design + knowledge search, or a hard gate.
|
|
40
42
|
|
|
43
|
+
**In `unattended`** (flow-core §2.1) — launched by `/flow-work-run` on `why = review` — this command
|
|
44
|
+
asks nothing and never touches the forge: the threads come from the orchestrator, the replies go
|
|
45
|
+
back through it, and the hard gates above resolve this way:
|
|
46
|
+
|
|
47
|
+
- **§1** — no MR/PR is resolved: the work is the one `/flow-work-run` found, on the branch the
|
|
48
|
+
orchestrator checked out. A round over the ceiling → `blocked`, its reason being the (a)(b)(c)
|
|
49
|
+
hand-back of §1.
|
|
50
|
+
- **§2** — the threads are `<cmd> events --json` → `comments[]`, grouped by `thread` (each comment:
|
|
51
|
+
`kind`, `id`, `author`, `at`, `body`, `url`, and `path`/`line` when it has them). The untrusted-input
|
|
52
|
+
rule stands unchanged. The machine-state check is skipped: the orchestrator relaunches for the
|
|
53
|
+
pipeline separately. The order failing → `blocked`; no comments → `done`, the summary saying so.
|
|
54
|
+
- **§3–§4** — triage and stances as `auto` decides them, the table and the drafts written to
|
|
55
|
+
`08-feedback.md` instead of shown. A thread only a person can settle — a product decision, or a
|
|
56
|
+
`D` the recorded rationale and the code do not decide — goes into **one** question for all of them,
|
|
57
|
+
asked **before anything is replied or committed**: `ask --gate decision`, free text `T<n>: <answer>`
|
|
58
|
+
per thread, with `pending.phase: "respond"`, `pending.resume: "work:respond"` (never the work's
|
|
59
|
+
`meta.json.phase`) and `pending.resume_at: "end of §4"`, and the run ends there. The answer is
|
|
60
|
+
written into this round's section of `08-feedback.md`, and the relaunch re-enters at the end of
|
|
61
|
+
§4, reading the threads and stances from that file rather than from `events`. **At the end of §4
|
|
62
|
+
— on a first run and on that re-entry alike** — a reply that would repeat an earlier round's
|
|
63
|
+
(§8's repeated-answer rule) is caught before anything is posted → `blocked`, naming the thread.
|
|
64
|
+
`§4.G` measures as `/flow-work-query` does unattended (schema-only, never a database it creates).
|
|
65
|
+
- **§5–§6** — a change adding behaviour gets its brief recorded (`recorded (unattended)`), not
|
|
66
|
+
asked. A design invalidation that is more than a tweak, or an agreed change that needs a schema
|
|
67
|
+
change → `blocked` (flow-core §2.1): the run does not redesign. Commits as `auto`. §6.1 runs
|
|
68
|
+
whole; a high-severity finding the round cannot clear → `blocked` with the findings. **§6.2 does
|
|
69
|
+
not run**: nothing is pushed — the orchestrator pushes on `publish`.
|
|
70
|
+
- **§8 before §7** — §8 completes the round's section §3–§4 opened in `08-feedback.md` (never a
|
|
71
|
+
second one) and counts `respond_rounds`, before any reply and before any `blocked` from here on.
|
|
72
|
+
A `blocked` earlier than this point (the repeated answer, §6.1) also counts the round first. The agent-lessons offer is `Later`; re-posting the performance comment is not
|
|
73
|
+
done — a changed number goes into `publish-body.md` instead.
|
|
74
|
+
- **§7** — one `<cmd> reply --thread <thread> --body-file <work>/reply-<thread>.md` per answered
|
|
75
|
+
thread, the reply naming the commit that changes the code. **Never resolve.** A `reply` that exits
|
|
76
|
+
≠ 0 is recorded in `08-feedback.md` and the remaining replies still go out.
|
|
77
|
+
- **The one closing order**, after the WIP commit (flow-core §2.1): code changed this round →
|
|
78
|
+
`publish` with the work's `publish-title.md` / `publish-body.md` (updated when the round changed
|
|
79
|
+
what they say, and naming any thread whose reply failed) and the `--part/--of` `/flow-feat-ship`
|
|
80
|
+
passed — the commits the replies name must reach the branch; no code changed and every reply went
|
|
81
|
+
out → `done`, the summary listing the threads answered; no code changed and a reply failed →
|
|
82
|
+
`blocked`, naming those threads.
|
|
83
|
+
|
|
41
84
|
## 1. Pre-flight — locate the work and the MR/PR
|
|
42
85
|
|
|
43
86
|
- Identify the current branch and its work folder `.claude/work/<TICKET>/` (the `meta.json` whose `branch` matches). Read `meta.json` and `00-summary.md`; open in full only `08-feedback.md` (spent rounds, below) and, in §3, the rationale artifacts a thread needs (`03-design.md`, `05-implementation.md`/`04-fix.md`). (flow-core §5)
|
|
@@ -36,7 +36,7 @@ of truth, and an argument that disagrees with it is ignored and named in the log
|
|
|
36
36
|
- Run `<cmd> why`. It fails, or prints anything but `start`, `answer`, `review`, `pipeline` or
|
|
37
37
|
`merged` → print what it returned and its stderr in the §3 header and end. No closing order: an
|
|
38
38
|
orchestrator that cannot say why it launched the run cannot take one either.
|
|
39
|
-
- Run `<cmd> ticket --json` and keep `number`, `title`, `base` and `kind` (`kind` absent → `feat
|
|
39
|
+
- Run `<cmd> ticket --json` and keep `number`, `title`, `base` and `kind` (`kind` absent or `null` → `feat`: the tracker could not tell, so flow decides). `kind` is re-read on every run; only `start` uses it — once the work exists, its folder says feat or bug.
|
|
40
40
|
It fails or prints no `number` → `blocked` (flow-core §2.1).
|
|
41
41
|
- Find the work: the `meta.json` under `.claude/work/` whose `ticket` equals `number` (archive
|
|
42
42
|
excluded). None is not an error — it is the "none" of the table below.
|
|
@@ -53,7 +53,9 @@ of truth, and an argument that disagrees with it is ignored and named in the log
|
|
|
53
53
|
| `answer` | nothing pending | `blocked` — there is no question for that answer to decide |
|
|
54
54
|
| `merged` | exists, something published | the entry of `meta.json.mrs` whose `status` is `published` (the only one: one MR/PR per run) becomes `merged`; set `meta.json.base` to the `base` just read; the next startable MR/PR → `/flow-feat-build`; none left, or a work with no `mrs` and `published` true (one MR/PR, every bug) → `phase = done` and `done`, the summary naming the ticket as complete |
|
|
55
55
|
| `merged` | none, or nothing published | `blocked` — nothing of this ticket was published from here |
|
|
56
|
-
| `review`
|
|
56
|
+
| `review` | exists | `/flow-work-respond` — the threads come from `<cmd> events --json` |
|
|
57
|
+
| `pipeline` | exists | `/flow-work-green` — the failed jobs come from `<cmd> events --json` |
|
|
58
|
+
| `review` · `pipeline` | none | `blocked` — there is no work of this ticket to answer for |
|
|
57
59
|
|
|
58
60
|
The phase you hand the run to is unattended too: it reads §2.1, chains as `auto` and makes the
|
|
59
61
|
run's one closing order. This command makes none of its own except the re-sent `ask`, the `blocked`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flow-workflows",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.85.1",
|
|
4
4
|
"description": "Guided feat/bug workflows (start→ship), post-deploy monitoring and multi-agent code review, stack-agnostic. Each repo uses a shared FLOW.md plus optional harness overlay.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "flow",
|
|
4
4
|
"displayName": "Flow — guided dev workflows",
|
|
5
5
|
"description": "Guided feat/bug workflows (start→ship), post-deploy monitoring and multi-agent code review, stack-agnostic. Each repo uses a shared FLOW.md plus optional harness overlay.",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.85.1",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Alberto Vioque",
|
|
9
9
|
"email": "mashware@gmail.com"
|
|
@@ -5,6 +5,32 @@ 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.85.1 — An unattended run reads the orchestrator's answers as agent-runner sends them · 2026-10-01
|
|
9
|
+
|
|
10
|
+
**In short**
|
|
11
|
+
- **A ticket whose tracker cannot tell feat from bug starts as a feature.** agent-runner sends
|
|
12
|
+
`kind: null` in that case; `/flow:work:run` now reads it the same as a missing `kind`.
|
|
13
|
+
- **The PR title goes to the orchestrator as one line.** agent-runner refuses a title file with two
|
|
14
|
+
lines; flow now says so where the run writes it.
|
|
15
|
+
- Nothing changes in `manual`, `guided` or `auto`. Follows #177.
|
|
16
|
+
|
|
17
|
+
## v0.85.0 — An unattended run answers its reviewers and fixes its own pipeline · 2026-10-01
|
|
18
|
+
|
|
19
|
+
**In short**
|
|
20
|
+
- **Review comments on a draft no longer stop an unattended run.** Relaunched with `why = review`,
|
|
21
|
+
`/flow:work:run` hands the run to `/flow:work:respond`, which reads the threads from the
|
|
22
|
+
orchestrator (`events --json`), answers each one through it (`reply --thread … --body-file …`),
|
|
23
|
+
commits what was agreed and hands the work back with `publish` — or `done` when only replies were
|
|
24
|
+
needed. It still never resolves a thread.
|
|
25
|
+
- **A red pipeline is fixed at the root, or named.** Relaunched with `why = pipeline`,
|
|
26
|
+
`/flow:work:green` reads the failed jobs and their log tails from the orchestrator, fixes and
|
|
27
|
+
verifies locally, and ends with `publish`. A flake, an infrastructure failure, a conflict, or
|
|
28
|
+
anything that needs a rebase or a force-push ends `blocked` with the reason: reruns and the
|
|
29
|
+
red-round limit belong to the orchestrator. Green-washing stays forbidden in every mode.
|
|
30
|
+
- **What only a person can settle is asked once, before anything is posted**: one question for
|
|
31
|
+
every thread that needs a product decision or a call the recorded design does not make.
|
|
32
|
+
- Nothing changes in `manual`, `guided` or `auto`. Completes #177.
|
|
33
|
+
|
|
8
34
|
## v0.84.0 — An unattended run talks to its orchestrator through one command · 2026-10-01
|
|
9
35
|
|
|
10
36
|
**In short**
|