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/CHANGELOG.md +657 -0
- package/LICENSE +21 -0
- package/README.md +189 -1
- package/banner.png +0 -0
- package/banner.svg +52 -0
- package/docs/concurrency.md +18 -0
- package/docs/development.md +37 -0
- package/docs/gates.md +29 -0
- package/docs/guardrails.md +27 -0
- package/docs/headless.md +42 -0
- package/docs/playbook.md +141 -0
- package/extensions/dev-flow.ts +1502 -0
- package/package.json +57 -5
- package/skills/dev-flow/SKILL.md +378 -0
- package/src/core.ts +1320 -0
- package/src/detect.ts +103 -0
- package/src/projectmd.ts +394 -0
- package/src/timeouts.ts +79 -0
package/package.json
CHANGED
|
@@ -1,10 +1,62 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-dev-flow",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
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
|
-
|
|
8
|
-
"
|
|
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
|
+
``. 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.
|