Skip to content

Commit 66ab2df

Browse files
chore(skills): enforce PostGenerationCommands and TestCommands in generator skill
- dot-add-generator: add Iron Law #5 requiring non-empty PostGenerationCommands and TestCommands for any generator producing typed/compiled output; add matching Common mistakes entry - dot-add-question: add checklist item and Common mistakes entry requiring verification of both command fields on newly-wired generators - Both skills: update docs rules to require documentation updates on every flow or generator change
1 parent 1d54cda commit 66ab2df

3 files changed

Lines changed: 747 additions & 0 deletions

File tree

Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
---
2+
name: dot-add-flow
3+
description: Add a complete new flow to `dot` — a `flows/<name>.go` file with its full question graph, a `Generators` resolver, registration in `flows/registry.go`, every new generator the flow needs (delegating to `dot-add-generator`), every new question (delegating to `dot-add-question`), and a full set of `tools/test-flow/testdata/` fixtures. Trigger when the user says "add a flow", "new flow", "ajoute un flow", "create a scaffold for X", or describes a brand-new wizard that doesn't fit any existing flow.
4+
source: local-git-analysis
5+
version: 1.0.0
6+
---
7+
8+
# dot — Add a Flow
9+
10+
A **flow** is a top-level wizard entry point (`dot scaffold <flow-id>`). It is a `FlowDef` declared in `flows/<name>.go`, registered in `flows/registry.go`, and composed of:
11+
12+
- A question graph (root → … → `confirmGenerate`)
13+
- A `Generators` resolver that maps the populated `ProjectSpec` to ordered `Invocation`s
14+
- Generators that may be reused from existing ones or freshly added
15+
- Test fixtures in `tools/test-flow/testdata/`
16+
17+
This skill orchestrates the full flow lifecycle, deferring to `dot-add-question` and `dot-add-generator` for sub-tasks.
18+
19+
---
20+
21+
## HARD RULES (Iron Law — never skip)
22+
23+
1. **Two announcements, then act.** Before any code change:
24+
- **Phase A — Generator plan**: list every new or modified generator (per `dot-add-generator` rules), including version bumps and doc updates.
25+
- **Phase B — Question plan**: list every question in the new flow with `ID_`, type, label, options, edges, and what each answer triggers in the resolver (per `dot-add-question` rules).
26+
Then **ASK** for confirmation. Do not start writing files until the user says proceed.
27+
2. **Unique, stable, kebab-case flow ID.** Used in `dot scaffold <id>` and referenced by every fixture. Never collide with existing IDs (`init`, `fullstack`, `microservices`, `plugin-template`, …) — check `flows/registry.go`.
28+
3. **Every question ID is unique across the whole flow.** No collision with itself, no collision with existing flows if generators are shared.
29+
4. **Reuse before you create.** Walk the existing `generators/` list; reuse anything that matches. Only add a new generator when no existing one fits. Each new generator goes through the full `dot-add-generator` workflow.
30+
5. **The resolver must cover every reachable answer combination.** No silent gaps. If the user can answer X, some `Invocation` must result from it (or you must explicitly comment that X is intentionally a no-op).
31+
6. **Fixtures cover every distinct branch.** At minimum: one happy-path fixture; one fixture per major branching choice (auth on/off, db on/off, each architecture, each formatter, …). Use the timestamped naming convention `YYYYMMDDhhMM_<flow>_<variant>.json`.
32+
7. **Tests across all layers**:
33+
- Unit tests for non-trivial pure logic in any new generator (`<name>_test.go`)
34+
- Manifest `Validators` for structural checks (file presence, JSON keys)
35+
- `TestCommands` that build / typecheck / unit-test / lint the generated project
36+
- For DB generators: `drizzle-kit generate` (or equivalent) as a post-gen command
37+
- End-to-end via `make test-flows`
38+
8. **Bump version + update doc** on every modified existing generator.
39+
9. **Formatters depend on `*`** (run last). Apply to any formatter introduced by the new flow.
40+
41+
---
42+
43+
## Step-by-step workflow
44+
45+
### 1. Understand the target
46+
47+
Capture from the user (or ASK):
48+
49+
- **Flow ID** (kebab-case), **Title**, **Description**
50+
- **Stack** (Go, TypeScript, Rust, multi-app monorepo, …)
51+
- **Choice points** (architecture, ORM, auth, lint/format, …)
52+
- **Loops** if multi-app
53+
54+
### 2. Inventory existing assets
55+
56+
- Read `generators/` directory listing — note which generators map to each choice point
57+
- Read `flows/init.go` (and other flows) for established patterns (constants, terminal `confirmGenerate`, validation helpers like `nonEmpty`)
58+
- Read `internal/cli/registry.go` to know what is wired
59+
60+
### 3. Phase A — Generator plan (MANDATORY announcement)
61+
62+
Output:
63+
64+
```
65+
Flow `<flow-id>` — Generator plan
66+
67+
Reuse (no changes):
68+
- <name> — used when <answer> == <value>
69+
- …
70+
71+
Modify (existing generators that must change for this flow):
72+
- generators/<name>/ — <what changes, why> — version <old> → <new>
73+
- docs/contributor/generators/<name>.md — sections to update
74+
- …
75+
76+
Add (brand-new generators — each via dot-add-generator):
77+
- <name> — purpose, depends on <list>, conflicts with <list>, writes <files>, post-gen <cmds>, test cmds <cmds>
78+
- …
79+
80+
Resolver outline (order matters — deps will be expanded by topo sort):
81+
1. base_project
82+
2. <…>
83+
N. <formatter — DependsOn: ["*"]>
84+
```
85+
86+
Stop and ASK.
87+
88+
### 4. Phase B — Question plan (MANDATORY announcement)
89+
90+
Output:
91+
92+
```
93+
Flow `<flow-id>` — Question plan
94+
95+
Graph (root → … → confirmGenerate):
96+
<ID_> (<type>) — "<label>"
97+
└── <option/then/else> → <next ID_ or End>
98+
…
99+
100+
Per-answer impact on resolver:
101+
- <ID_> == <value> → add <generators>
102+
- <ID_> == <value> → add <generators>
103+
- …
104+
105+
Fixtures to add (under tools/test-flow/testdata/):
106+
- <timestamp>_<flow-id>_<variant>.json — covers <branch>
107+
- …
108+
109+
Proceed?
110+
```
111+
112+
Stop and ASK.
113+
114+
### 5. Create / modify generators
115+
116+
For each item in the Add list, run the `dot-add-generator` skill end-to-end (package layout, manifest, embedded `files/`, registration, doc, tests). For each item in the Modify list, apply the change with version bump + doc update.
117+
118+
Do this **before** writing the flow file — the flow's resolver references generators by name, and `make build` will fail if they don't exist yet.
119+
120+
### 6. Write `flows/<flow-id>.go`
121+
122+
Mirror the structure of `flows/init.go`:
123+
124+
```go
125+
package flows
126+
127+
import (
128+
"github.com/version14/dot/internal/flow"
129+
"github.com/version14/dot/internal/spec"
130+
)
131+
132+
// constants for stable answer values reused across the resolver
133+
const FOO_BAR = "foo-bar"
134+
135+
// <FlowID>Flow is the … flow. <one-paragraph description, including
136+
// the note that question IDs are stable for dot update.>
137+
func <FlowID>Flow() *FlowDef {
138+
confirmGenerate := &flow.ConfirmQuestion{
139+
QuestionBase: flow.QuestionBase{ID_: "confirm-generate"},
140+
Label: "Generate the project now?",
141+
Default: true,
142+
Then: &flow.Next{End: true},
143+
Else: &flow.Next{End: true},
144+
}
145+
146+
// … declare questions bottom-up …
147+
148+
return &FlowDef{
149+
ID: "<flow-id>",
150+
Title: "<Title>",
151+
Description: "<Description>",
152+
Root: <rootQuestion>,
153+
Generators: resolve<FlowID>Generators,
154+
}
155+
}
156+
157+
func resolve<FlowID>Generators(s *spec.ProjectSpec) []Invocation {
158+
if s == nil { return nil }
159+
out := []Invocation{{Name: "base_project"}}
160+
// … read s.Answers, append Invocations …
161+
return out
162+
}
163+
```
164+
165+
For loops use `LoopQuestion` + emit one `Invocation` per loop frame with `LoopStack`. See `flows/microservices.go` pattern (referenced in `docs/contributor/authoring-flows.md`).
166+
167+
### 7. Register the flow
168+
169+
Edit `flows/registry.go` — add `_ = r.Register(<FlowID>Flow())` in the `Default()` builder. The flow then appears in `dot flows` and `dot scaffold`.
170+
171+
### 8. Fixtures (full coverage)
172+
173+
Under `tools/test-flow/testdata/`, create one JSON file per distinct branch. Use timestamped filenames sorted lexicographically. Required fields (see `0_template.json`):
174+
175+
```json
176+
{
177+
"name": "<flow-id>_<variant>",
178+
"flow_id": "<flow-id>",
179+
"answers": { /* every required key, in the order the user would answer */ },
180+
"expected_visited": [ /* every ID_ visited, in order */ ],
181+
"skip_post_commands": false,
182+
"skip_test_commands": false
183+
}
184+
```
185+
186+
Minimum coverage matrix:
187+
188+
- Happy path (every default, simplest options)
189+
- Each architecture / ORM / auth / formatter variant the flow exposes
190+
- Loop variants (0 iterations if allowed, 1, N>1)
191+
- Boolean confirm questions: both `true` and `false` covered somewhere
192+
193+
### 9. Verify
194+
195+
```
196+
make build
197+
make validate
198+
make test-flows
199+
```
200+
201+
Iterate until green. If a fixture's `expected_visited` mismatches the flow, fix the flow or the fixture deliberately — never blanket-edit fixtures to silence failures.
202+
203+
### 10. Documentation
204+
205+
- Add a row to `README.md`'s "Built-in flows" table
206+
- Add a row to `docs/contributor/authoring-flows.md`'s "Built-in flows" table
207+
- If you added new generators, ensure `docs/contributor/generators/<name>.md` exists and `docs/README.md` lists each one
208+
209+
### 11. Commit
210+
211+
Conventional Commits, multiple commits:
212+
213+
- `feat(generators): add <name>` per new generator (with its doc)
214+
- `refactor(generators/<name>): <change>` per modified generator (with version bump)
215+
- `feat(flow): add <flow-id> flow` for the flow file + registration
216+
- `test(test-flow): add fixtures for <flow-id>` for the fixtures
217+
- `docs(flows): describe <flow-id> flow` if separate doc work was needed
218+
219+
Do **not** auto-commit — wait for explicit user instruction.
220+
221+
---
222+
223+
## Worked example skeleton (Go backend microservice flow)
224+
225+
Phase A — Generator plan:
226+
227+
```
228+
Reuse: base_project, postgres_docker_compose, postgres_env_example
229+
Modify: (none)
230+
Add:
231+
- go_module_base — go.mod + main.go + Dockerfile + healthcheck — DependsOn: base_project
232+
- go_chi_router — Chi router + middleware + /health — DependsOn: go_module_base
233+
- go_postgres_repo — pgx pool + repo skeleton — DependsOn: go_module_base, postgres_docker_compose
234+
- go_test_setup — go test scaffolding + testcontainers helper — DependsOn: go_module_base
235+
```
236+
237+
Phase B — Question plan:
238+
239+
```
240+
project_name (Text) → module_path (Text) → router_choice (Option: chi / stdlib)
241+
→ enable_db (Confirm)
242+
Then → db_type (Option: postgres) → confirm-generate
243+
Else → confirm-generate
244+
```
245+
246+
Then resolver pulls `go_module_base` always, `go_chi_router` when `chi`, plus postgres + `go_postgres_repo` when `enable_db && db_type == "postgres"`.
247+
248+
Fixtures:
249+
250+
- `..._go_chi_no_db.json`
251+
- `..._go_stdlib_no_db.json`
252+
- `..._go_chi_postgres.json`
253+
254+
---
255+
256+
## Common mistakes (do not make)
257+
258+
- Skipping Phase A or Phase B announcements
259+
- Adding a flow that depends on a generator that does not yet exist (build will fail)
260+
- Forgetting to register the flow in `flows/registry.go`
261+
- Inadequate fixture coverage — every branching choice must be exercised by some fixture
262+
- Renaming a question `ID_` after first commit (breaks `dot update`)
263+
- Modifying an existing generator without bumping its version and updating its doc
264+
- Putting a formatter ahead of architecture/feature generators in the resolver (instead set `DependsOn: ["*"]` on the formatter)
265+
266+
---
267+
268+
## Skill composition
269+
270+
This skill **delegates**:
271+
272+
- For each new generator → invoke / follow `dot-add-generator` end-to-end
273+
- For each question → follow `dot-add-question` discipline (announcement, fixture impact, version bumps)
274+
275+
It only owns: the flow file, the registry entry, the resolver, and the cross-cutting Phase A / Phase B announcements that make the whole thing reviewable in one pass.

0 commit comments

Comments
 (0)