pi-dev-flow 0.0.1-stage → 0.52.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/package.json CHANGED
@@ -1,10 +1,62 @@
1
1
  {
2
2
  "name": "pi-dev-flow",
3
- "version": "0.0.1-stage",
4
- "description": "Placeholder so npm accepts a trusted-publisher registration for pi-dev-flow. Publish 0.52.0 (CI) supersedes it.",
3
+ "version": "0.52.1",
4
+ "description": "Enforced feature workflow for Pi: plan → implement → pre-release → release, gated checkpoints, self-improvement reflections, one git worktree per feature, changelog + publish as part of the release",
5
+ "type": "module",
6
+ "keywords": [
7
+ "pi-package",
8
+ "pi",
9
+ "pi-coding-agent",
10
+ "extension",
11
+ "workflow",
12
+ "dev-flow",
13
+ "spec",
14
+ "plan",
15
+ "release",
16
+ "semver",
17
+ "changelog",
18
+ "git-worktree",
19
+ "guardrails"
20
+ ],
5
21
  "license": "MIT",
6
- "repository": {
7
- "type": "git",
8
- "url": "git+https://github.com/dmarchevsky/pi-dev-flow.git"
22
+ "repository": "https://github.com/dmarchevsky/pi-dev-flow",
23
+ "engines": {
24
+ "node": ">=22.19.0"
25
+ },
26
+ "files": [
27
+ "extensions/",
28
+ "src/",
29
+ "skills/",
30
+ "docs/",
31
+ "banner.svg",
32
+ "banner.png",
33
+ "README.md",
34
+ "CHANGELOG.md",
35
+ "LICENSE"
36
+ ],
37
+ "pi": {
38
+ "extensions": [
39
+ "./extensions/dev-flow.ts"
40
+ ],
41
+ "skills": [
42
+ "./skills"
43
+ ],
44
+ "image": "./banner.png"
45
+ },
46
+ "peerDependencies": {
47
+ "@earendil-works/pi-ai": "*",
48
+ "@earendil-works/pi-coding-agent": "*",
49
+ "@earendil-works/pi-tui": "*"
50
+ },
51
+ "devDependencies": {
52
+ "@earendil-works/pi-ai": "*",
53
+ "@earendil-works/pi-coding-agent": "*",
54
+ "@earendil-works/pi-tui": "*",
55
+ "@types/node": "^22.0.0",
56
+ "typescript": "^7.0.2"
57
+ },
58
+ "scripts": {
59
+ "build": "tsc --noEmit",
60
+ "test": "node --test"
9
61
  }
10
62
  }
@@ -0,0 +1,378 @@
1
+ ---
2
+ name: dev-flow
3
+ description: >
4
+ The repo's enforced feature workflow: plan → implement → pre-release →
5
+ release → done, one feature at a time, driven through the flow tool. Read before
6
+ starting ANY feature work in a repo that has a .dev-flow/ directory — the
7
+ stage guards block out-of-stage edits and main-branch git ops, so working
8
+ outside this flow fails at the guard.
9
+ ---
10
+
11
+ # dev-flow: the stage-by-stage playbook
12
+
13
+ Only the **flow tool** advances stages, and each gate refuses until its exit
14
+ criteria hold. Drive it with args arrays — `["start", "dark-mode", "--ui"]`,
15
+ `["test"]`, `["status"]`.
16
+
17
+ Ground rules:
18
+
19
+ - **The flow tool is the only invocation.** `flow` is **not a shell command**: a
20
+ bash call named `flow` has no binary behind it (the guard refuses it and names
21
+ the tool call) — never reach for bash, `npx`, or a path to run a gate.
22
+ - **You run the gates; the operator says words.** Never ask the operator to type
23
+ a `/flow ...` command — not at a checkpoint, not "just to check status", not as
24
+ a shortcut. Ask the checkpoint word in chat, then run the gate yourself.
25
+ `/flow` is the operator's **manual override**: surface it only when the session
26
+ is demonstrably wrong, stuck, or claiming a gate result it never ran (and
27
+ `/reload` when `flow version` says this session runs an older build).
28
+
29
+ - **One session = exactly one feature** (flow + branch + worktree); parallel
30
+ sessions, one feature each, are the model. The bind is automatic when one
31
+ unfinished feature exists and no live session already claims it
32
+ (`flow use <slug>` = explicit takeover); `flow start <slug>` sets the bind
33
+ (main checkout must be on the default branch). Unbound with several
34
+ unfinished features: gates demand an explicit slug and main-checkout writes
35
+ stay blocked. There is no bypass — an unbound session cannot edit source.
36
+ - **Project `flow-guard` rules** (`deny`/`confirm`/`protect`/`forbid` in
37
+ project.md `## global`) apply at **every** stage and are judged ahead of
38
+ dev-flow's verdicts — operator safety rules, not flow discipline. When one
39
+ fires, its reason is the answer: stop, show it, let the operator decide;
40
+ never route around it.
41
+ - **Every bash/shell call states its own `timeout`** or the guard refuses it
42
+ (`bashTimeout = require`, the default; the playbook may set `inject`). Name
43
+ the budget you actually expect.
44
+ - `.dev-flow/<slug>/state.json` is flow-owned — never read or write it;
45
+ `flow status` is your view. **project.md is the operator-owned playbook**
46
+ (test/build/run commands, default branch, forge, worktree path, safety
47
+ rules): read freely, **never edit** — changes go through `flow init --write`
48
+ on the operator's word. In-life playbook updates run as a docs flow:
49
+ project.md is editable only inside a docs/patch flow's worktree and is
50
+ committed to git like any file. A leftover `project.json` is never read; the
51
+ doctor flags it.
52
+ - Also obey the repo's own AGENTS.md and project skills: dev-flow sequences
53
+ stages, the project defines its conventions.
54
+ - **A guard blocking you means you are skipping a stage or writing outside
55
+ your feature** — run the gate instead of working around it. The guard reads
56
+ **commands**: quoted text is an argument's prose (a PR body discussing a
57
+ commit is not a commit); a wrapper that execs its argument
58
+ (`sh -c "git push origin main"`) is judged on its payload — blocked commands
59
+ cannot ride through one.
60
+ - **Checkpoints are one verb: Approve? / Verified? / Release? / Finish?** —
61
+ ask exactly that word as a **plain chat message**, mention that **yolo** is
62
+ an available answer, and stop. Never ask the operator to run a flow command
63
+ at a checkpoint — you run the gate when they have answered. The same verb
64
+ (or an explicit equivalent) in chat is the answer; then run that gate with
65
+ `--confirmed` — zero dialogs, **exactly one checkpoint per stage**. A
66
+ structured question tool (AskUserQuestion-style) is not chat and never
67
+ licenses `--confirmed`; never infer the answer.
68
+ - **yolo** at any checkpoint → run that gate `--yolo --confirmed`; every
69
+ later checkpoint is pre-confirmed — run the remaining gates back to back
70
+ without asking, honoring guidance attached to the word ("yolo, create a
71
+ patch version release" → bump patch; "yolo, no tag" → `--no-version`).
72
+ Checks and guardrails stay fully enforced — a flow-guard `confirm` rule
73
+ still asks the operator.
74
+ - At Release?, choosing **no version/tag for this flow** →
75
+ `flow release --no-version --confirmed` — the merge still owes a changelog
76
+ entry under `Unreleased`, which the next versioned release folds under its
77
+ version heading (default is versioned: bump + tag).
78
+ - **Modes are proposed, never taken**: every `flow start` carries the mode and
79
+ a one-line why; the operator grants it in chat and the gate refuses
80
+ `--patch`/`--docs` until the grant is anchored with `--confirmed` — never
81
+ self-grant. `normal` (default): a written plan is enforced (`plan/plan.md`
82
+ before Approve?). `--patch`: a small change you intend to release
83
+ (one-file fix, version chore) — no plan file, one chat line is the plan,
84
+ everything else identical. `--docs`: docs-only — no plan file **and no
85
+ tier-1 checks** (build/lint/test); worktree discipline and the full release
86
+ stay. A change that grows past one line or touches behavior is a normal
87
+ feature, not patch/docs.
88
+
89
+ ## Start
90
+
91
+ **No `.dev-flow/`?** `flow init` analyzes the repo and prints a **setup
92
+ brief**: what was detected plus one question per knob detection cannot decide
93
+ (forge github/gitlab/self, version manifest and tag convention, automatic
94
+ forge releases, registry artifacts like Docker Hub, the real
95
+ test/build/lint/health commands, tier-2 items, prose). Relay the questions
96
+ (one per knob, detected default shown, explain in a line when not obvious),
97
+ fill `flow init --draft` with the answers, present it, then apply
98
+ `flow init --write "<content>"` **only after the operator confirms** — never
99
+ hand-edit, never write project.md before the confirmation. The playbook
100
+ belongs in git; the chore is legal unbound:
101
+ `git add -f .dev-flow/project.md && DEV_FLOW_ALLOW_MAIN=1 git commit -m "track project.md"`
102
+ (force — a tracked file outranks a `.gitignore` of `.dev-flow/`; the env
103
+ prefix lets the installed hook accept a main commit that only touches the
104
+ playbook). **With existing config** `flow init` is a **doctor**: discuss
105
+ findings, fix via the same write path, never overwrite hand edits without
106
+ confirming; ghost feature dirs (a `plan/` whose `state.json` is gone) come
107
+ with a delete offer — surface the dialog, never delete on your own.
108
+ `flow doctor` runs the same probes **read-only** (prefer it when you only want
109
+ findings); `--force` re-detects from scratch, `--draft` prints without
110
+ writing.
111
+
112
+ `flow start <slug> [--ui]` — `--ui` whenever anything user-visible is touched;
113
+ slug lowercase words-dashed; check `flow status` for an active feature first.
114
+
115
+ ## Stage: plan
116
+
117
+ 1. Research the code the plan needs (reads are always allowed).
118
+ 2. **Clarify before drafting**: preliminary direction in chat (findings, shape
119
+ of the fix, open unknowns), mode proposal with its reason, your questions
120
+ and the operator's; draft only after the direction is confirmed.
121
+ 3. Write `.dev-flow/<slug>/plan/plan.md` — problem, approach, files to touch,
122
+ test strategy, risks; reviewable, not exhaustive. First check
123
+ `git log origin/<default>..<default> --oneline`: local-only default-branch
124
+ commits fall out of the worktree's base (push them or re-plan).
125
+ 4. **UI flag set?** Mockups live in `plan/mockups/`, one HTML per screen/state
126
+ (`<screen>.html`), linking the project's real stylesheet and class names
127
+ where they exist (relative links work from `.dev-flow/`). Every mockup
128
+ must be **rendered** — an unrendered mockup is not a mockup:
129
+ - Headless chromium: PATH `chromium`/`chromium-browser`/`google-chrome`,
130
+ else playwright's
131
+ `~/.cache/ms-playwright/*/chrome-headless-shell-linux64/chrome-headless-shell`.
132
+ Render at the project's widths (default phone 390, desktop 1280):
133
+ `<binary> --no-sandbox --disable-gpu --hide-scrollbars --virtual-time-budget=5000 --window-size=<width>,<height> --screenshot=plan/mockups/<screen>-<width>.png file://<absolute path to html>`
134
+ — height per screen, re-render if clipped.
135
+ - Embed every render in plan.md under its section —
136
+ `![<screen> — phone](mockups/<screen>-390.png)`. Image syntax only (a
137
+ filename in prose is a broken link); before Approve? re-check that every
138
+ tag points at an existing file.
139
+ - No chromium anywhere → tell the operator and ask; `*.html`-only plans
140
+ only with their OK (knob: `mockupGlobs`); never fake or skip silently.
141
+ - Gotchas: for a component question prefer a **static strip** — standalone
142
+ HTML with the real stylesheet carrying only the markup in question, one
143
+ first-try render; a full-page render is for layout context only. Shots
144
+ start top-left and never scroll — hide what is above a below-the-fold
145
+ region (inline `<style>`) or use a strip. `--user-data-dir` profiles keep
146
+ localStorage between shots — fresh profile dir per intended UI state.
147
+ Planned behavior must be visibly patched into the shot and captioned as
148
+ such — never caption the current app's render with the behavior you plan
149
+ to add. The app's repaint can destroy a transient state (an inline
150
+ editor) — freeze it for the shot (e.g. stub the render entry point after
151
+ opening). If the harness fights the same shot twice, verify that state
152
+ via DOM/code and move on — screenshots are a spot-check, not a test loop.
153
+ 5. Tell the user the plan is ready and **stop** — one word: **Approve?**
154
+ Answered → `flow approve --confirmed` (yolo → `flow approve --yolo
155
+ --confirmed`).
156
+
157
+ Approval creates the worktree and branch, running `commands.setup` inside when
158
+ configured — a failing setup fails the gate and the next `approve` **retries**
159
+ setup in the kept worktree (stamping `setupAt` on success) instead of silently
160
+ reusing it. A `--docs` feature runs no project command at all. No code edits
161
+ before approval. `(ui)` playbook items never apply to non-UI features or
162
+ appear in prompts.
163
+
164
+ ## Stage: implement
165
+
166
+ Work happens **only in the worktree** the gate created (path in `flow status`
167
+ or the injection line) — writes elsewhere are blocked; other sessions'
168
+ worktrees are theirs (attribution guards judge every path by its owning
169
+ feature).
170
+
171
+ 1. Implement per the approved plan with project conventions and the **stage
172
+ guidance injected at stage start** (tier-3 prose). Commit in the worktree
173
+ **as you go** — small reviewable commits; a twelve-file monolith saved for
174
+ the end faces review blind and is not crash-safe. The gate enforces the
175
+ habit: `flow verify` refuses while the branch holds **no commit** (checks
176
+ describe the working tree, so nothing committed means nothing reviewed was
177
+ ever recorded) and every verify line reports
178
+ `commits: N ahead of <default>, M uncommitted path(s)` — uncommitted paths
179
+ never block verify, they are what the operator sees they are approving.
180
+ 2. Write tests as you go (project framework: the `test` key / `flow-check`
181
+ blocks).
182
+ 3. `flow check` runs every tier-1 check (test, health, named `flow-check`
183
+ blocks) and records each; any later worktree edit invalidates checks and
184
+ the tier-2 confirmation — rerun before verify.
185
+ 4. UI flag set? An actual browser visual pass (screenshot or the project's
186
+ automated pass) — not just a typecheck.
187
+ 5. Done means **running and healthy with pre-existing data**, not "compiles":
188
+ `commands.seedData` (if set) puts real data in place, the app starts with
189
+ the `run` command, and the health check passes — `flow check` covers it
190
+ (seedData runs before health) and `flow verify` probes **the deployed app
191
+ again**, because the deploy is what has to be proven. Probes retry every 2s
192
+ up to `healthWait` (default 30s) — a service needing a moment after its
193
+ container starts is not a failed deploy; say so rather than declaring a
194
+ healthy deploy broken. Walk the **tier-2 checklist** (`- [ ]`) with the
195
+ operator honestly — it cannot be scripted. Then ask **Verified?** →
196
+ `flow verify --confirmed`. Fixes = iterate and re-verify; that loop is
197
+ free.
198
+
199
+ `flow verify` re-runs build, runs the `dev` deploy when configured (the
200
+ operator reviews the running app; the gate **prints what it ran** —
201
+ `build ran (…)` / `dev ran (…)` / `dev: none configured`; the command must
202
+ **background and exit**, e.g. `docker compose up -d .` — verify waits and kills
203
+ runs past 15 min), re-runs the health probe **against what it just deployed**
204
+ (`seedData` first when configured; a failing probe retries every 2s up to
205
+ `healthWait`, then refuses the gate reporting its attempts — a pre-deploy PASS
206
+ describes a container that no longer exists; no probe prints
207
+ `health: none configured` and the doctor flags it), and demands all tier-1
208
+ checks green before the single question. The operator's confirm covers the
209
+ tier-2 list as a set (hashed; edits reset it). A `--docs` feature prints
210
+ `docs mode: project commands skipped` and asks only the verify question.
211
+ Verify lands the feature in **pre-release**.
212
+
213
+ Mid-stage additions — do not bounce the flow, do not grow it silently:
214
+ **this feature grew** → stay at implement, append a `**Added mid-stage:**` line
215
+ to `plan.md` (what was asked and how), implement, `flow check` again — edits
216
+ invalidate checks and the tier-2 confirmation, so verify re-covers the
217
+ addition. **Different problem** → finish this feature first, then a new flow
218
+ (`flow start <new-slug>` after this one ships); never fold two features into
219
+ one plan, PR and verify — the
220
+ audit trail is the point. **Heavily amended plan** → show it and have the
221
+ operator re-approve in chat; verify remains the checkpoint — no reopen command
222
+ exists by design.
223
+
224
+ ## Stage: pre-release
225
+
226
+ Implemented, tested, running locally; prepare the release entirely in the
227
+ worktree — main-repo git state stays off-limits until this gate hands over.
228
+ **Versioning:** the `versioning.file` manifest is the single source of truth
229
+ and tags are `versioning.pattern` rendered from it — one number everywhere. If
230
+ `versioning.file` is unset, stop and clarify the scheme with the user; never
231
+ invent one mid-release. Sequence:
232
+
233
+ 1. `/ponytail-review` the change; fix every **must-have** and **should-have**
234
+ finding; `flow test` again if code changed.
235
+ 2. Update documentation to reflect the change.
236
+ 3. Update the changelog and bump the manifest to the exact version you will
237
+ tag — manifest, changelog and tag must agree; commit the prep on the feature
238
+ branch. A versioned release **folds the `Unreleased` section** (entries
239
+ `--no-version` flows left there) under the new version heading — the gate
240
+ refuses while it still holds entries.
241
+ 4. `flow check` — the prep edits invalidated the implement checks; the release
242
+ gate demands them green again.
243
+ 5. State what the PR will contain, present version and changelog entry,
244
+ **stop** — **Release?** → `flow release --confirmed`. The gate re-checks
245
+ tier-1, requires the manifest **ahead of the last tag** and the changelog to
246
+ mention it. Operator ships this flow **without version/tag** →
247
+ `flow release --no-version --confirmed` — no bump, but the changelog entry
248
+ under `Unreleased` is still required: the gate proves the branch changed the
249
+ changelog.
250
+
251
+ ## Stage: release
252
+
253
+ Cleared for main-repo git (merge/tag/push on the default branch is allowed only
254
+ here) — this stage publishes; the preparation happened in pre-release. Run in
255
+ the worktree unless noted:
256
+
257
+ 1. Commit everything, push the feature branch, open the PR, wait for the merge
258
+ (`gh pr merge` or ask the user) — without `--delete-branch`: it fails when
259
+ the default branch is checked out in the main worktree, and `flow finish`
260
+ deletes the branch on merge proof anyway.
261
+ 2. `git fetch`, confirm the merge landed, create the **annotated** tag
262
+ (`git tag -a`) and push the ref explicitly (`git push origin v<ver>`) —
263
+ never `--follow-tags` (it silently skips lightweight tags: they never reach
264
+ the remote, CI never publishes). After the merge a tag points at what
265
+ actually shipped. If CI publishes from the tag, set `release.artifact` in
266
+ the playbook — `release-done` then verifies the published artifact and
267
+ refuses local-only tags outright. Unversioned flow (`--no-version` granted):
268
+ no bump, no tag — publish the merge only (your entry rides under
269
+ `Unreleased` until the next versioned release folds it), `release-done`
270
+ asks nothing version-side.
271
+ 3. `flow release-done` — **no question** (the Release? answer covered the
272
+ publication). It re-verifies (tag on the default branch, on origin, artifact
273
+ when configured) against **the version the release gate stamped** — never a
274
+ re-read from a checkout that may be behind — and refuses anything older than
275
+ the newest matching tag on origin (lists come from `git ls-remote`, so an
276
+ unfetched clone never decides what is tagged). It creates the forge release
277
+ — `gh` for GitHub, `glab` for GitLab, nothing for `forge = self`, advisory
278
+ note if a CLI or remote is missing; body = the tag's annotation, else the
279
+ `release.changelog` entry for that version, else nothing with the reason
280
+ printed (annotate with `git tag -a`) — and records the release;
281
+ `flow finish` closes the feature out. Skipping the forge release
282
+ (`--no-release-create`, once, or `release.releases = false`, always) and
283
+ the artifact check (`--no-artifact-check`, once) are operator calls only —
284
+ act when told, never on your own. If `flow version` says this session runs
285
+ an older build than the checkout, **stop and ask the operator to `/reload`
286
+ before publishing** — gates execute the code loaded at session start.
287
+ Release-stage checklist items have no gate of their own: `release-done`
288
+ lists the open ones and the Finish? answer closes them.
289
+
290
+ ## Stage: finish
291
+
292
+ **Reflect before you finish** — `flow finish` deletes `.dev-flow/<slug>/` and
293
+ the session context goes with it. Run the end-of-session reflection (bare
294
+ `flow reflect` protocol under *Reflect*) now and park real issues with
295
+ `flow reflect`; then:
296
+
297
+ - issues parked → ask **Fold? Fix? Drop?** and stop: fold = write the items
298
+ into `.dev-flow/reflections.md` (your queue), fix = route them now via
299
+ `flow doctor`, drop = discard them. The answer replaces **Finish?** — act
300
+ on it, then run `flow finish --confirmed` without asking again;
301
+ - nothing parked → ask the operator **Finish?** → `flow finish --confirmed`.
302
+
303
+ The question covers the whole cleanup and mentions any commits that look
304
+ unmerged. `flow finish [slug]`:
305
+
306
+ - refuses until `release-done` recorded the release — abandoned features go
307
+ through `flow abort` instead;
308
+ - requires the main checkout **clean and pushed** — an uncommitted changelog or
309
+ a local-only release commit is exactly what it protects against;
310
+ - removes the worktree and branch, then deletes `.dev-flow/<slug>/` and
311
+ unbinds the session. A feature branch still on `origin` is deleted **only on
312
+ proof it was merged** — ancestor of `origin/<default>`, or a merged PR via gh
313
+ (squash merges); otherwise kept with a note. Uncommitted worktree edits block
314
+ finish; unmerged-looking commits called out at Finish? without an operator
315
+ answer → stop and show them.
316
+
317
+ Production deployment stays manual and out of scope: never ask the operator
318
+ whether a prod deploy happened.
319
+
320
+ ## When things go sideways
321
+
322
+ - Abandon a feature: `flow abort <slug>` unbinds — at plan stage (nothing
323
+ approved) it removes the feature outright; once a worktree exists the state
324
+ stays for manual recovery and the exact removal commands are printed.
325
+ - A gate refuses: its reasons list exactly what is missing — fix that, rerun
326
+ the gate.
327
+
328
+ ## Reflect (your suggestion queue)
329
+
330
+ Anything the playbook or plugin should improve (drifted commands, gate friction,
331
+ a plugin bug) gets parked, not complained about:
332
+ `flow reflect "<one-line note>"`; gate flags are ignored —
333
+ `flow reflect "<note>" --confirmed` queues the note alone. For a note to chase
334
+ **now**: `flow doctor "<observation>"` prints an investigation brief without
335
+ queueing. Notes land under `## playbook` or `## plugin` — the wording decides,
336
+ a note about both goes to both. The open count shows in status and stage
337
+ context; the operator decides:
338
+
339
+ - Reflect real friction only, one line each, never the same issue twice.
340
+ - **Bare `flow reflect` is the end-of-session reflection** — it runs as part
341
+ of every finish (before the slug folder is deleted — see Stage: finish) and
342
+ whenever the operator asks. It prints the
343
+ protocol: review the full session log (messages, tool calls, results);
344
+ re-check each open item against the current playbook and newer dev-flow
345
+ versions (`npm view pi-dev-flow version` vs the running version, or
346
+ `git ls-remote` for a git-installed copy — a newer one that fixes an
347
+ item → recommend updating the plugin, check it off); queue deduplicated new
348
+ findings; report playbook vs plugin items structurally; ask whether to fix
349
+ now. The command writes nothing; you execute the protocol.
350
+ - Plain `flow doctor` reviews the open items and **routes** each to the flow
351
+ that implements it — playbook item → docs flow; plugin item → upstream issue
352
+ (or a patch/normal flow in the dev-flow repo). To fold items in on the
353
+ operator's word: investigate, propose the fix, get confirmation, open the
354
+ routed flow (playbook items: `flow start fold-<topic> --docs --confirmed`)
355
+ and apply it there — project.md is editable only in that worktree. Check
356
+ items off in `.dev-flow/reflections.md` (your queue, gitignored, yours to
357
+ edit; not `project.md`) with `- [x]` and a `— folded: <what>` or
358
+ `— fixed: <what>` note.
359
+ - `## plugin` items, on the operator's go: search upstream first —
360
+ `gh issue list --repo <dev-flow repo> --state all --search "<keywords>"` —
361
+ an issue the author already answered (fixed or won't-fix) is reported back,
362
+ never re-filed; no match → offer to file one (`gh issue create`; `glab issue
363
+ create` on GitLab) with a detailed description, session evidence and a
364
+ suggested fix; the operator confirms.
365
+
366
+ ## Roadmap (your backlog)
367
+
368
+ `.dev-flow/roadmap.md` — a gitignored `- [ ]` checklist; the operator owns the
369
+ content, you maintain and honor it. Advisory like reflections, never gating:
370
+
371
+ - `flow roadmap` lists the open items (the count is surfaced in status and
372
+ stage context). Update on the operator's request —
373
+ `flow roadmap add "<feature>"` or direct file edits are equally fine.
374
+ - Handed a feature: `flow roadmap pick <n> <slug>` stamps the item with the
375
+ slug (pick is one verb — it starts nothing), then `flow start <slug>` builds
376
+ it as a normal flow; its `flow finish` checks the item off automatically.
377
+ - Shipped outside a flow: `flow roadmap done <n>` (date-stamped by hand);
378
+ `flow roadmap tidy` drops checked lines when history clutters the list.