@khanhspring/forge-spec 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/forge-brainstorm/SKILL.md +59 -14
- package/skills/forge-close/SKILL.md +1 -0
- package/skills/forge-config/SKILL.md +118 -25
- package/skills/forge-contract/SKILL.md +7 -1
- package/skills/forge-init/SKILL.md +185 -30
- package/skills/forge-spec/SKILL.md +12 -4
- package/skills/forge-status/SKILL.md +36 -28
- package/skills/forge-tasks/SKILL.md +16 -8
package/package.json
CHANGED
|
@@ -18,14 +18,40 @@ every unknown either resolved or explicitly accepted as an assumption.
|
|
|
18
18
|
|
|
19
19
|
<HARD-GATE>
|
|
20
20
|
Do NOT generate a spec, break down tasks, or write any contracts in this phase.
|
|
21
|
-
The
|
|
22
|
-
the user has explicitly approved the Brainstorm
|
|
21
|
+
The only files this skill writes are `features/{slug}/brainstorm.md` and one row in
|
|
22
|
+
`features/CHANGELOG.md`, and only AFTER the user has explicitly approved the Brainstorm
|
|
23
|
+
Summary at the gate (Step 7).
|
|
23
24
|
"Simple" features are where unexamined assumptions cause the most wasted work — no feature
|
|
24
25
|
skips this phase.
|
|
25
26
|
</HARD-GATE>
|
|
26
27
|
|
|
27
28
|
---
|
|
28
29
|
|
|
30
|
+
## Step 0 — Check for existing external context
|
|
31
|
+
|
|
32
|
+
Before anything else, check if the user has provided external content to work from.
|
|
33
|
+
Signals: they paste a block of text, mention "we have a Confluence page / Google Doc / proposal /
|
|
34
|
+
PRD / design doc", or say "here's the draft".
|
|
35
|
+
|
|
36
|
+
**If external content is present (pasted inline):**
|
|
37
|
+
Extract everything you can from it — map it to the mandatory question areas in Step 2.
|
|
38
|
+
Note what is covered, what is missing, and what is ambiguous.
|
|
39
|
+
Report back:
|
|
40
|
+
> "I've read your {doc type}. Here's what I extracted:
|
|
41
|
+
> ✅ Covered: {list of areas — problem, actors, happy path, etc.}
|
|
42
|
+
> ❓ Missing or unclear: {list of gaps}
|
|
43
|
+
> ⚠️ Ambiguous: {anything that could be read two ways}
|
|
44
|
+
>
|
|
45
|
+
> I'll ask only about the gaps. Sound good?"
|
|
46
|
+
|
|
47
|
+
**If the user mentions a doc but hasn't pasted it:**
|
|
48
|
+
> "I can't access external URLs directly — could you paste the relevant content here?
|
|
49
|
+
> Even a rough copy-paste is fine; I'll extract what I need."
|
|
50
|
+
|
|
51
|
+
**If no external content** — proceed straight to Step 1.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
29
55
|
## Step 1 — Load & Research Context
|
|
30
56
|
|
|
31
57
|
Before asking the user anything, research the existing codebase silently:
|
|
@@ -35,14 +61,15 @@ Before asking the user anything, research the existing codebase silently:
|
|
|
35
61
|
Note any patterns, naming conventions, or prior decisions relevant to this idea.
|
|
36
62
|
3. Scan `contracts/*/` — are there existing API contracts this feature will touch or extend?
|
|
37
63
|
Note existing endpoint shapes, error formats, auth patterns.
|
|
38
|
-
4. Read `
|
|
39
|
-
that will constrain design choices.
|
|
64
|
+
4. Read `CONTEXT.md` — note the actors, domain glossary, principles, conventions, and
|
|
65
|
+
forbidden patterns that will constrain design choices. Use glossary terms verbatim
|
|
66
|
+
in your questions and in the summary — never invent synonyms for existing domain terms.
|
|
40
67
|
|
|
41
68
|
Report your findings before starting questions:
|
|
42
69
|
|
|
43
70
|
> "Before we dive in, here's what I found in the codebase:
|
|
44
71
|
> - [relevant existing feature or contract, or "No related features found"]
|
|
45
|
-
> - [relevant principle from
|
|
72
|
+
> - [relevant principle or constraint from CONTEXT.md, or "No constraints found"]
|
|
46
73
|
>
|
|
47
74
|
> I'll use this as context. Here's my understanding of the feature: {1–2 sentence restatement}
|
|
48
75
|
> Is that right?"
|
|
@@ -57,7 +84,8 @@ Then check scope:
|
|
|
57
84
|
## Step 2 — Mandatory questions (one at a time)
|
|
58
85
|
|
|
59
86
|
These MUST all be answered before moving to Step 4. Ask one at a time.
|
|
60
|
-
Skip any
|
|
87
|
+
**Skip any area already covered by Step 0 extraction or Step 1 research.**
|
|
88
|
+
Only ask about genuine gaps — never re-ask what the user already provided.
|
|
61
89
|
|
|
62
90
|
**If a question hits an unknown** — something the user can't answer without researching —
|
|
63
91
|
use the Research Flag pattern (see Research Handling below).
|
|
@@ -183,7 +211,7 @@ apply the Research Handling pattern.
|
|
|
183
211
|
## Step 5 — Propose approaches
|
|
184
212
|
|
|
185
213
|
Propose **2–3 design approaches** with trade-offs. Base them on the researched context
|
|
186
|
-
from Step 1 — flag if an approach conflicts with existing patterns or
|
|
214
|
+
from Step 1 — flag if an approach conflicts with existing patterns or CONTEXT.md principles.
|
|
187
215
|
|
|
188
216
|
```
|
|
189
217
|
I see 2–3 ways to approach this:
|
|
@@ -302,8 +330,17 @@ If (b), convert each item to an explicit assumption in the summary.
|
|
|
302
330
|
|
|
303
331
|
## Step 8 — Persist the summary (after approval only)
|
|
304
332
|
|
|
305
|
-
Once the user says **yes
|
|
306
|
-
|
|
333
|
+
Once the user says **yes**:
|
|
334
|
+
|
|
335
|
+
**8a — Assign sequence number and ask about dependencies**
|
|
336
|
+
|
|
337
|
+
Read `features/CHANGELOG.md`. Count existing rows to get the next `#`.
|
|
338
|
+
|
|
339
|
+
Ask (one message):
|
|
340
|
+
> "Does this feature depend on any other feature being shipped first?
|
|
341
|
+
> _(Enter slugs like `user-registration`, or 'none')_"
|
|
342
|
+
|
|
343
|
+
**8b — Write `features/{slug}/brainstorm.md`**
|
|
307
344
|
|
|
308
345
|
```markdown
|
|
309
346
|
# Brainstorm: {Feature Name}
|
|
@@ -315,18 +352,26 @@ so it survives across sessions and forge-spec can pick it up later.
|
|
|
315
352
|
{the full Brainstorm Summary body from Step 6 — all sections}
|
|
316
353
|
```
|
|
317
354
|
|
|
355
|
+
**8c — Append row to `features/CHANGELOG.md`**
|
|
356
|
+
|
|
357
|
+
Add a new row — status `Brainstormed`, modules left blank until forge-spec fills them:
|
|
358
|
+
```
|
|
359
|
+
| {n} | {slug} | {one-line from Problem section} | Brainstormed | — | {depends or —} |
|
|
360
|
+
```
|
|
361
|
+
|
|
318
362
|
Then hand off:
|
|
319
|
-
> "Saved to `features/{slug}/brainstorm.md
|
|
363
|
+
> "Saved to `features/{slug}/brainstorm.md` and added to the changelog as #{n}.
|
|
364
|
+
> Run `/forge-spec {slug}` to write the spec."
|
|
320
365
|
|
|
321
366
|
---
|
|
322
367
|
|
|
323
368
|
## Rules
|
|
324
369
|
- One question per message — never list multiple at once
|
|
325
370
|
- Prefer multiple-choice when options are predictable
|
|
326
|
-
-
|
|
327
|
-
- Never skip the challenge round (Step 4)
|
|
328
|
-
- Never skip the approaches step (Step 5)
|
|
371
|
+
- Cover all Step 2 mandatory areas — but fill from Step 0 extraction first; only ask for genuine gaps
|
|
372
|
+
- Never skip the challenge round (Step 4) — even when a doc covers everything, challenge it
|
|
373
|
+
- Never skip the approaches step (Step 5) — a doc may have a chosen approach but alternatives should still be surfaced
|
|
329
374
|
- YAGNI: move anything non-core to Out of Scope
|
|
330
375
|
- The ONLY file written is `features/{slug}/brainstorm.md`, and only after approval (Step 8)
|
|
331
376
|
- Do NOT skip Step 1 research — always check existing context first
|
|
332
|
-
- Do NOT ask questions that could be answered by reading the existing codebase
|
|
377
|
+
- Do NOT ask questions that could be answered by reading the existing codebase or the pasted doc
|
|
@@ -93,6 +93,7 @@ Feature progress: {feature-slug}
|
|
|
93
93
|
**If all modules are complete:**
|
|
94
94
|
Update `features/{slug}/tasks.md` header status to `Done`
|
|
95
95
|
and `features/{slug}/spec.md` header status to `Done`.
|
|
96
|
+
Update `features/CHANGELOG.md`: find the row for `{slug}` and set `Status` → `Done`.
|
|
96
97
|
|
|
97
98
|
> "🎉 All modules done — feature `{slug}` is complete."
|
|
98
99
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "forge-config"
|
|
3
|
-
description: "View and interactively update .forge/project.json
|
|
4
|
-
argument-hint: "Optional hint: 'add module', 'update user-service port', '
|
|
3
|
+
description: "View and interactively update .forge/project.json (add/remove modules and submodules, ports, stack, spec repo URL) and CONTEXT.md (actors, glossary, principles, conventions). Asks one question at a time and previews changes before writing."
|
|
4
|
+
argument-hint: "Optional hint: 'add module', 'add submodule to webapps', 'update user-service port', 'edit principles'"
|
|
5
5
|
compatibility: "Requires spec repo with .forge/project.json"
|
|
6
6
|
metadata:
|
|
7
7
|
author: "forge-workflow"
|
|
@@ -12,14 +12,16 @@ disable-model-invocation: true
|
|
|
12
12
|
|
|
13
13
|
# Forge Config
|
|
14
14
|
|
|
15
|
-
View and update the project configuration at `.forge/project.json
|
|
15
|
+
View and update the project configuration at `.forge/project.json`, and the
|
|
16
|
+
project-wide domain context at `CONTEXT.md`.
|
|
16
17
|
|
|
17
18
|
## Step 1 — Load & display
|
|
18
19
|
|
|
19
20
|
Read `.forge/project.json`.
|
|
20
21
|
If missing: "No project config found. Run `/forge-init` to set up this repo first."
|
|
21
22
|
|
|
22
|
-
Display the current config
|
|
23
|
+
Display the current config. Modules with submodules show one indented `↳` row per
|
|
24
|
+
submodule — the parent row has no port/stack (those belong to each submodule):
|
|
23
25
|
|
|
24
26
|
```
|
|
25
27
|
Project: {project-name}
|
|
@@ -28,13 +30,19 @@ Contract tool: {contract_tool}
|
|
|
28
30
|
|
|
29
31
|
Modules ({n}):
|
|
30
32
|
· user-service backend Spring Boot 3, Java 21 :8081
|
|
31
|
-
·
|
|
33
|
+
· webapps (3 submodules)
|
|
34
|
+
↳ admin frontend React :3001 apps/admin
|
|
35
|
+
↳ landing frontend Next.js :3000 apps/landing
|
|
36
|
+
↳ portal frontend React :3002 apps/portal
|
|
32
37
|
```
|
|
33
38
|
|
|
34
39
|
## Step 2 — Determine the change
|
|
35
40
|
|
|
36
|
-
From $ARGUMENTS, infer the intent if given (e.g. "add module", "
|
|
37
|
-
|
|
41
|
+
From $ARGUMENTS, infer the intent if given (e.g. "add module", "add submodule to webapps",
|
|
42
|
+
"update user-service port", "edit principles").
|
|
43
|
+
If empty, ask: "What do you want to change? (add a module / add a submodule to an existing
|
|
44
|
+
module / remove a module or submodule / update a field / change spec repo URL / edit project
|
|
45
|
+
context — actors, glossary, principles, conventions)"
|
|
38
46
|
|
|
39
47
|
## Step 3 — Collect details (one question at a time)
|
|
40
48
|
|
|
@@ -44,22 +52,68 @@ Ask one question per message — never batch.
|
|
|
44
52
|
1. "Module name? (kebab-case, must be unique)"
|
|
45
53
|
2. "Type? (backend / frontend / worker / gateway)"
|
|
46
54
|
3. "Tech stack? (e.g. 'Spring Boot 3, Java 21')"
|
|
47
|
-
4. "
|
|
48
|
-
5. "
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
4. "Git repo URL? (or 'none')"
|
|
56
|
+
5. "Does `{name}` contain multiple submodules — e.g. a monorepo with several apps,
|
|
57
|
+
or a Gradle multi-module build? (yes / no)"
|
|
58
|
+
- **If yes** → collect submodules one at a time (see below). Skip step 6 —
|
|
59
|
+
port and stack belong to each submodule, not the parent; drop the stack from step 3
|
|
60
|
+
if it was given for the parent.
|
|
61
|
+
- **If no** → continue.
|
|
62
|
+
6. "Local dev port?" _(skip when the module has submodules)_
|
|
63
|
+
7. "One-sentence description? (or 'none')"
|
|
64
|
+
|
|
65
|
+
**Adding a submodule** (to an existing module) — ask which module first if not given.
|
|
66
|
+
|
|
67
|
+
- If the parent is currently a **simple module** (no `submodules[]`), warn before converting:
|
|
68
|
+
> "`{module}` is currently a standalone module. Adding a submodule converts it:
|
|
69
|
+
> its `port` and `stack` move to the submodules — the parent keeps only `name`,
|
|
70
|
+
> `repo`, and `description`. If `{module}` already has tasks or contracts under its
|
|
71
|
+
> own name, those stay as-is and won't match a submodule name. Convert? (yes/no)"
|
|
72
|
+
If yes, ask whether the existing port/stack should become the first submodule
|
|
73
|
+
(asking for its `name` and `path`) or be discarded.
|
|
74
|
+
- Then collect each new submodule, one field at a time (same as `/forge-init`):
|
|
75
|
+
1. "Submodule name? (kebab-case, unique across the whole project — not just within `{module}`)"
|
|
76
|
+
2. "Type? (backend / frontend / worker)"
|
|
77
|
+
3. "Stack?"
|
|
78
|
+
4. "Port?"
|
|
79
|
+
5. "Path within the `{module}` repo? (e.g. `apps/admin` or `auth-ui`)"
|
|
80
|
+
6. "One sentence: what does it do? _(Skip with 'none')_"
|
|
81
|
+
- Confirm each: "`{sub}` — {type} — {stack} — :{port} — path: {path}. Another submodule? (yes / no)"
|
|
82
|
+
|
|
83
|
+
> **Submodule rules (same as `/forge-init`):**
|
|
84
|
+
> - No `repo` field on a submodule — it shares the parent module's repo
|
|
85
|
+
> - No `port` or `stack` on a parent that has submodules
|
|
86
|
+
> - Submodule names must be unique across the whole project — contracts live at
|
|
87
|
+
> `contracts/{submodule}/` and tasks.md uses `### {submodule}` headings directly
|
|
88
|
+
|
|
89
|
+
**Removing a module or submodule:**
|
|
90
|
+
- Check whether any `features/*/tasks.md` has a `### {name}` section (module name for
|
|
91
|
+
simple modules, submodule name for submodules).
|
|
92
|
+
If so, warn: "`{name}` has tasks in {feature(s)}. Removing it from config won't delete those tasks. Remove anyway? (yes/no)"
|
|
93
|
+
- Otherwise confirm: "Remove `{name}` from the project? (yes/no)"
|
|
94
|
+
- If removing the **last submodule** of a module, ask: "That's the last submodule of
|
|
95
|
+
`{module}`. Convert it back to a standalone module (needs a port and stack), or remove
|
|
96
|
+
the whole module?"
|
|
55
97
|
|
|
56
98
|
**Updating a field:**
|
|
57
99
|
- Show the current value, then ask for the new one:
|
|
58
100
|
"`{module}.{field}` is currently `{old}`. What should it be?"
|
|
101
|
+
- Submodule fields use the path `{module}.submodules[{sub}].{field}` — e.g.
|
|
102
|
+
"`webapps.submodules[admin].port` is currently `3001`. What should it be?"
|
|
103
|
+
- Refuse to set `port` or `stack` on a parent with submodules, or `repo` on a
|
|
104
|
+
submodule — explain the rule instead.
|
|
59
105
|
|
|
60
106
|
**Changing spec repo URL:**
|
|
61
107
|
- "Current spec_repo is `{old}`. New URL?"
|
|
62
108
|
|
|
109
|
+
**Editing project context (`CONTEXT.md`):**
|
|
110
|
+
- Read `CONTEXT.md`. If missing, offer to create it with the template from `/forge-init`
|
|
111
|
+
Phase 6, asking the Phase 2 and Phase 4 questions to fill it.
|
|
112
|
+
- Ask which section: "Which section? (What This Project Is / Business Goal / Actors /
|
|
113
|
+
Domain Glossary / Current State / Principles / Conventions / Out of Scope)"
|
|
114
|
+
- Show the section's current content, then ask what to add, change, or remove.
|
|
115
|
+
- Context edits go to `CONTEXT.md` only — never to CLAUDE.md or project.json.
|
|
116
|
+
|
|
63
117
|
## Step 4 — Preview & gate
|
|
64
118
|
|
|
65
119
|
Show the before/after of exactly what will change:
|
|
@@ -69,19 +123,36 @@ Change preview:
|
|
|
69
123
|
modules[user-service].port: 8081 → 8090
|
|
70
124
|
```
|
|
71
125
|
|
|
72
|
-
|
|
126
|
+
Adding a submodule:
|
|
127
|
+
```
|
|
128
|
+
Change preview:
|
|
129
|
+
modules[webapps].submodules + { name: reports, type: frontend,
|
|
130
|
+
stack: [React], port: 3003, path: apps/reports }
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Converting a simple module to one with submodules, show the moved fields too:
|
|
134
|
+
```
|
|
135
|
+
Change preview:
|
|
136
|
+
modules[webapps].port 3000 → (removed — moves to submodules)
|
|
137
|
+
modules[webapps].stack [React] → (removed — moves to submodules)
|
|
138
|
+
modules[webapps].submodules + { name: admin, ... }
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
For CONTEXT.md edits, show the section before/after instead.
|
|
142
|
+
|
|
143
|
+
> "Apply this change to `{file}`? Say **yes** to write, or tell me what to adjust."
|
|
73
144
|
|
|
74
145
|
Wait for confirmation. Do not write before the user says yes.
|
|
75
146
|
|
|
76
147
|
## Step 5 — Write & confirm
|
|
77
148
|
|
|
78
|
-
Apply the change, preserving all other fields and formatting.
|
|
79
|
-
Confirm: "Updated
|
|
149
|
+
Apply the change, preserving all other fields, sections, and formatting.
|
|
150
|
+
Confirm: "Updated `{file}` — {summary of what changed}."
|
|
80
151
|
|
|
81
|
-
If a module name changed, warn:
|
|
82
|
-
> "Heads up: `{
|
|
83
|
-
> `### {
|
|
84
|
-
> `/forge-close` will break."
|
|
152
|
+
If a module or submodule name changed, warn:
|
|
153
|
+
> "Heads up: `{name}` is referenced by the module repo's `.forge/module.json`, by
|
|
154
|
+
> `### {name}` headings in tasks.md, and by the `contracts/{name}/` folder. Update
|
|
155
|
+
> those to match, or `/forge-implement` and `/forge-close` will break."
|
|
85
156
|
|
|
86
157
|
## Schema Reference
|
|
87
158
|
|
|
@@ -90,6 +161,7 @@ If a module name changed, warn:
|
|
|
90
161
|
"project": "my-project", // short slug, no spaces
|
|
91
162
|
"version": "1.0",
|
|
92
163
|
"modules": [
|
|
164
|
+
// Module WITHOUT submodules — port and stack on the module itself:
|
|
93
165
|
{
|
|
94
166
|
"name": "user-service", // kebab-case, matches module.json in module repos
|
|
95
167
|
"repo": "git@github.com:org/user-service.git",
|
|
@@ -97,6 +169,23 @@ If a module name changed, warn:
|
|
|
97
169
|
"stack": ["Spring Boot 3", "Java 21"],
|
|
98
170
|
"port": 8081,
|
|
99
171
|
"description": "" // optional, one sentence
|
|
172
|
+
},
|
|
173
|
+
// Module WITH submodules — NO port/stack/type on the parent;
|
|
174
|
+
// each submodule owns type, stack, port, path; NO repo on submodules:
|
|
175
|
+
{
|
|
176
|
+
"name": "webapps",
|
|
177
|
+
"repo": "git@github.com:org/webapps.git",
|
|
178
|
+
"description": "Web app mono-repo",
|
|
179
|
+
"submodules": [
|
|
180
|
+
{
|
|
181
|
+
"name": "admin", // kebab-case, unique across the WHOLE project
|
|
182
|
+
"type": "frontend", // backend | frontend | worker
|
|
183
|
+
"stack": ["React"],
|
|
184
|
+
"port": 3001,
|
|
185
|
+
"path": "apps/admin", // relative path inside the parent repo
|
|
186
|
+
"description": "" // optional, one sentence
|
|
187
|
+
}
|
|
188
|
+
]
|
|
100
189
|
}
|
|
101
190
|
],
|
|
102
191
|
"spec_repo": "git@github.com:org/specs.git",
|
|
@@ -108,6 +197,10 @@ If a module name changed, warn:
|
|
|
108
197
|
## Rules
|
|
109
198
|
- One question per message — never batch
|
|
110
199
|
- Never write before the user confirms the preview in Step 4
|
|
111
|
-
- `module.name` must be kebab-case and unique
|
|
112
|
-
|
|
113
|
-
-
|
|
200
|
+
- `module.name` must be kebab-case and unique; submodule names must be unique across
|
|
201
|
+
the whole project (contracts and task headings use the submodule name directly)
|
|
202
|
+
- `module.name` must match the `module` field in the module repo's `.forge/module.json`;
|
|
203
|
+
submodule names must match the `submodules[].name` entries there
|
|
204
|
+
- A module has EITHER `port`+`stack` OR `submodules[]` — never both; submodules never
|
|
205
|
+
have a `repo` field
|
|
206
|
+
- Never silently remove a module or submodule that has tasks referencing it — warn first
|
|
@@ -28,7 +28,11 @@ and the user has explicitly confirmed it.
|
|
|
28
28
|
- Feature slug from $ARGUMENTS, or ask: "Which feature do you want to generate a contract for?"
|
|
29
29
|
- Read `features/{slug}/spec.md` — must exist, otherwise stop.
|
|
30
30
|
- Read `features/{slug}/tasks.md` — must exist, otherwise say "Run `/forge-tasks {slug}` first."
|
|
31
|
-
- Read `.forge/project.json` —
|
|
31
|
+
- Read `.forge/project.json` — build a flat list of **contract targets**:
|
|
32
|
+
- Module with no submodules → target name = `{module.name}`, contract path = `contracts/{module.name}/`
|
|
33
|
+
- Module with submodules → target name = each `{submodule.name}`, contract path = `contracts/{submodule.name}/`
|
|
34
|
+
- Submodules use their own name as the target — identical to a standalone module — so they can be
|
|
35
|
+
promoted to a separate repo later with no contract path changes.
|
|
32
36
|
|
|
33
37
|
---
|
|
34
38
|
|
|
@@ -207,6 +211,8 @@ Update the API Endpoints table in `features/{slug}/spec.md`:
|
|
|
207
211
|
Also advance the spec status: change the `**Status:**` line in `features/{slug}/spec.md`
|
|
208
212
|
from `Draft` to `Ready` (planning complete — ready for implementation).
|
|
209
213
|
|
|
214
|
+
Update `features/CHANGELOG.md`: find the row for `{slug}` and set `Status` → `Ready`.
|
|
215
|
+
|
|
210
216
|
---
|
|
211
217
|
|
|
212
218
|
## Step 7 — Completion
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "forge-init"
|
|
3
|
-
description: "One-time initialization for a Forge spec repo. Walks through setup conversationally one question at a time, then writes .forge/project.json, CLAUDE.md, and directory scaffolding on confirmation."
|
|
3
|
+
description: "One-time initialization for a Forge spec repo. Walks through setup conversationally one question at a time — project identity, project details, modules, principles — then writes .forge/project.json, CONTEXT.md, CLAUDE.md, and directory scaffolding on confirmation."
|
|
4
4
|
argument-hint: "Optional: project name to skip the first prompt"
|
|
5
5
|
compatibility: "Run once in a spec repo before any other forge skills. Safe to re-run — never overwrites existing files."
|
|
6
6
|
when_to_use: >
|
|
@@ -40,7 +40,40 @@ _(Skip with 'none' if it's not set up yet — you can add it later with `/forge-
|
|
|
40
40
|
|
|
41
41
|
---
|
|
42
42
|
|
|
43
|
-
## Phase 2 —
|
|
43
|
+
## Phase 2 — Project details
|
|
44
|
+
|
|
45
|
+
These answers become `CONTEXT.md` — the project-wide domain context that
|
|
46
|
+
`/forge-brainstorm` and `/forge-spec` read before planning, and that module repos
|
|
47
|
+
see at `specs/CONTEXT.md` during implementation. Getting this right once saves
|
|
48
|
+
re-explaining the project in every feature conversation.
|
|
49
|
+
|
|
50
|
+
Start by offering the shortcut:
|
|
51
|
+
> "If you have a project overview doc (README, pitch doc, Confluence page), paste it
|
|
52
|
+
> and I'll extract these answers — otherwise I'll ask a few short questions."
|
|
53
|
+
|
|
54
|
+
If a doc is pasted, extract what's covered and ask only about genuine gaps.
|
|
55
|
+
Otherwise ask one question at a time:
|
|
56
|
+
|
|
57
|
+
**Q1.** "Who uses this system? List the actors/roles and what each one does.
|
|
58
|
+
_(e.g. 'customer — places orders; admin — manages the catalog; billing-worker — system actor')_"
|
|
59
|
+
|
|
60
|
+
**Q2.** "What are the core domain concepts, in your team's own words?
|
|
61
|
+
_(e.g. 'Order, Quote, Fulfillment — a Quote becomes an Order when accepted')_
|
|
62
|
+
These become the domain glossary — the exact terms specs and contracts will use."
|
|
63
|
+
|
|
64
|
+
**Q3.** "What's the business goal — what does success look like for this project?
|
|
65
|
+
_(1–2 sentences, or 'skip')_"
|
|
66
|
+
|
|
67
|
+
**Q4.** "What's the current state? Greenfield, or are there existing systems this
|
|
68
|
+
replaces or integrates with?
|
|
69
|
+
_(e.g. 'replacing a legacy PHP monolith; auth stays in Keycloak')_"
|
|
70
|
+
|
|
71
|
+
Keep this phase capped at these four areas — deep per-feature questioning is
|
|
72
|
+
`/forge-brainstorm`'s job, not init's.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Phase 3 — Modules
|
|
44
77
|
|
|
45
78
|
Collect modules one at a time. Each module is gathered field by field.
|
|
46
79
|
|
|
@@ -53,16 +86,39 @@ For each module, ask these in order (one question per message):
|
|
|
53
86
|
2. **Type** — "Is `{name}` a backend service, frontend app, or something else?
|
|
54
87
|
_(backend / frontend / worker / gateway)_"
|
|
55
88
|
3. **Stack** — "What's the tech stack for `{name}`? (e.g. `Spring Boot 3, Java 21` or `React, TypeScript`)"
|
|
56
|
-
4. **
|
|
57
|
-
5. **Repo URL** — "What's the git repo URL for `{name}`?
|
|
89
|
+
4. **Repo URL** — "What's the git repo URL for `{name}`?
|
|
58
90
|
_(Skip with 'none' if not set up yet)_"
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
91
|
+
5. **Submodules** — scan the user's answers so far for signals: words like "monorepo", "multi-module",
|
|
92
|
+
"Gradle modules", a comma-separated list of app names, etc.
|
|
93
|
+
**If signals present**, ask:
|
|
94
|
+
> "It sounds like `{name}` contains multiple submodules ({detected names if any}).
|
|
95
|
+
> Should I configure them separately? (yes / no)"
|
|
96
|
+
**If yes** → collect submodules one at a time (see below). Skip step 6 — port belongs to each submodule, not the parent.
|
|
97
|
+
**If no or no signals** → continue to step 6.
|
|
98
|
+
6. **Port** _(skip when module has submodules)_ — "What port does `{name}` run on locally?"
|
|
99
|
+
7. **Description** — "One sentence: what does `{name}` do? _(Skip with 'none')_"
|
|
100
|
+
|
|
101
|
+
**Submodule collection** (repeat for each):
|
|
102
|
+
- "Submodule name? (kebab-case)"
|
|
103
|
+
- "Type? (backend / frontend / worker)"
|
|
104
|
+
- "Stack?"
|
|
105
|
+
- "Port?"
|
|
106
|
+
- "Path within the `{name}` repo? (e.g. `apps/admin` or `auth-ui`)"
|
|
107
|
+
- "One sentence: what does it do? _(Skip with 'none')_"
|
|
108
|
+
|
|
109
|
+
Confirm each: "`{sub}` — {type} — {stack} — :{port} — path: {path}. Another submodule? (yes / no)"
|
|
110
|
+
|
|
111
|
+
> **Rules for submodules:**
|
|
112
|
+
> - No `repo` field — submodules share the parent module's repo
|
|
113
|
+
> - No `port` on the parent module — port belongs to each submodule
|
|
114
|
+
> - `type` and `stack` are per-submodule (may differ from the parent)
|
|
115
|
+
|
|
116
|
+
After collecting all submodules (or just module fields), confirm:
|
|
63
117
|
|
|
64
118
|
> "Got it:
|
|
65
|
-
> `{name}` — {type} — {
|
|
119
|
+
> `{name}` — {type} — {repo or 'no repo yet'}
|
|
120
|
+
> {if no submodules: stack + port}
|
|
121
|
+
> {if submodules: list each as ` ↳ {sub} — {type} — {stack} — :{port} — {path}`}
|
|
66
122
|
> {description}
|
|
67
123
|
> Is that right?"
|
|
68
124
|
|
|
@@ -70,11 +126,11 @@ Then ask:
|
|
|
70
126
|
> "Any more modules to add? (yes / no)"
|
|
71
127
|
|
|
72
128
|
If yes, repeat from step 1 of this phase for the next module.
|
|
73
|
-
If no, move to Phase
|
|
129
|
+
If no, move to Phase 4.
|
|
74
130
|
|
|
75
131
|
---
|
|
76
132
|
|
|
77
|
-
## Phase
|
|
133
|
+
## Phase 4 — Principles & conventions
|
|
78
134
|
|
|
79
135
|
Ask one at a time. "None" or "not yet" are valid answers — these sections can be filled
|
|
80
136
|
in later with `/forge-config`.
|
|
@@ -93,7 +149,7 @@ Say 'none yet' to skip._"
|
|
|
93
149
|
|
|
94
150
|
---
|
|
95
151
|
|
|
96
|
-
## Phase
|
|
152
|
+
## Phase 5 — Preview & gate
|
|
97
153
|
|
|
98
154
|
Show a full preview of what will be written:
|
|
99
155
|
|
|
@@ -105,14 +161,21 @@ Ready to initialize. Here's what I'll create:
|
|
|
105
161
|
modules: {n} module(s): {comma-separated names}
|
|
106
162
|
spec_repo: {url or "not set"}
|
|
107
163
|
|
|
108
|
-
|
|
164
|
+
CONTEXT.md
|
|
109
165
|
Description: {description}
|
|
110
|
-
|
|
166
|
+
Actors: {n} listed
|
|
167
|
+
Domain glossary: {n} terms
|
|
168
|
+
Business goal: {one line or "skipped"}
|
|
169
|
+
Current state: {one line}
|
|
111
170
|
Principles: {list or "none yet"}
|
|
112
171
|
Conventions: {list or "none yet"}
|
|
113
172
|
Out of scope: {list or "none yet"}
|
|
114
173
|
|
|
115
|
-
|
|
174
|
+
CLAUDE.md
|
|
175
|
+
Modules: {n} listed
|
|
176
|
+
Forge workflow + structure + pointer to CONTEXT.md
|
|
177
|
+
|
|
178
|
+
features/CHANGELOG.md
|
|
116
179
|
contracts/.gitkeep
|
|
117
180
|
.gitignore ← append Forge entries
|
|
118
181
|
```
|
|
@@ -123,9 +186,11 @@ Wait for confirmation. Do not write anything before the user says yes.
|
|
|
123
186
|
|
|
124
187
|
---
|
|
125
188
|
|
|
126
|
-
## Phase
|
|
189
|
+
## Phase 6 — Write files
|
|
127
190
|
|
|
128
191
|
Write `.forge/project.json`:
|
|
192
|
+
|
|
193
|
+
Module **without** submodules — `port` and `stack` on the module itself:
|
|
129
194
|
```json
|
|
130
195
|
{
|
|
131
196
|
"project": "{project-name}",
|
|
@@ -146,17 +211,98 @@ Write `.forge/project.json`:
|
|
|
146
211
|
}
|
|
147
212
|
```
|
|
148
213
|
|
|
149
|
-
|
|
214
|
+
Module **with** submodules — no `port` on the module; each submodule owns its `port`, `stack`,
|
|
215
|
+
`type`, and `path`; no `repo` on submodules (they share the parent's repo):
|
|
216
|
+
```json
|
|
217
|
+
{
|
|
218
|
+
"project": "{project-name}",
|
|
219
|
+
"version": "1.0",
|
|
220
|
+
"modules": [
|
|
221
|
+
{
|
|
222
|
+
"name": "{module-name}",
|
|
223
|
+
"repo": "{repo-url}",
|
|
224
|
+
"description": "{description}",
|
|
225
|
+
"submodules": [
|
|
226
|
+
{
|
|
227
|
+
"name": "{sub-name}",
|
|
228
|
+
"type": "backend|frontend|worker",
|
|
229
|
+
"stack": ["{stack}"],
|
|
230
|
+
"port": {port},
|
|
231
|
+
"path": "{relative-path-in-repo}",
|
|
232
|
+
"description": "{description}"
|
|
233
|
+
}
|
|
234
|
+
]
|
|
235
|
+
}
|
|
236
|
+
],
|
|
237
|
+
"spec_repo": "{spec-repo-url}",
|
|
238
|
+
"contract_format": "openapi3",
|
|
239
|
+
"contract_tool": "specmatic"
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Write `CONTEXT.md` — the single source of truth for project-wide domain context.
|
|
244
|
+
Fill every section from the Phase 1, 2, and 4 answers; write "None defined yet." only
|
|
245
|
+
where the user explicitly skipped:
|
|
246
|
+
```markdown
|
|
247
|
+
# {project-name} — Project Context
|
|
248
|
+
|
|
249
|
+
> Domain context for all planning and implementation. `/forge-brainstorm` and
|
|
250
|
+
> `/forge-spec` read this before any feature work; module repos see it at
|
|
251
|
+
> `specs/CONTEXT.md`. Keep it current via `/forge-config`.
|
|
252
|
+
|
|
253
|
+
## What This Project Is
|
|
254
|
+
{description — 2–4 sentences built from the user's answers, not just the one-liner}
|
|
255
|
+
|
|
256
|
+
## Business Goal
|
|
257
|
+
{goal — or "Not defined yet."}
|
|
258
|
+
|
|
259
|
+
## Actors
|
|
260
|
+
| Actor | Who they are | What they do in the system |
|
|
261
|
+
|-------|--------------|----------------------------|
|
|
262
|
+
| {role} | {description} | {responsibilities} |
|
|
263
|
+
|
|
264
|
+
## Domain Glossary
|
|
265
|
+
| Term | Meaning |
|
|
266
|
+
|------|---------|
|
|
267
|
+
| {term} | {definition in the team's own words} |
|
|
268
|
+
|
|
269
|
+
## Current State
|
|
270
|
+
{greenfield / existing systems, integrations, migration notes}
|
|
271
|
+
|
|
272
|
+
## Principles
|
|
273
|
+
{list each as a bullet — or "None defined yet."}
|
|
274
|
+
|
|
275
|
+
## Conventions
|
|
276
|
+
{list each as a bullet — or "None defined yet."}
|
|
277
|
+
|
|
278
|
+
## Out of Scope / Forbidden
|
|
279
|
+
{list each as a bullet — or "None defined yet."}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Write `CLAUDE.md` — operational only; domain context lives in `CONTEXT.md`, never
|
|
283
|
+
duplicate it here:
|
|
150
284
|
```markdown
|
|
151
285
|
# {project-name}
|
|
152
286
|
|
|
153
|
-
{description}
|
|
287
|
+
{description — the 1–2 sentence version}
|
|
288
|
+
|
|
289
|
+
## Project Context
|
|
290
|
+
Actors, domain glossary, principles, and conventions live in `CONTEXT.md`.
|
|
291
|
+
Read it before any brainstorm, spec, or planning work.
|
|
154
292
|
|
|
155
293
|
## Modules
|
|
156
294
|
| Name | Type | Stack | Port |
|
|
157
295
|
|------|------|-------|------|
|
|
158
296
|
| {name} | {type} | {stack} | {port} |
|
|
159
297
|
|
|
298
|
+
_(For modules with submodules, expand the table with one row per submodule.
|
|
299
|
+
Indent the submodule name with `↳` and omit port/stack from the parent row.)_
|
|
300
|
+
|
|
301
|
+
| Name | Type | Stack | Port | Path |
|
|
302
|
+
|------|------|-------|------|------|
|
|
303
|
+
| {module} | — | — | — | — |
|
|
304
|
+
| ↳ {sub} | {type} | {stack} | {port} | {path} |
|
|
305
|
+
|
|
160
306
|
## Forge Workflow
|
|
161
307
|
1. `/forge-brainstorm` — explore and define a feature
|
|
162
308
|
2. `/forge-spec` — write the spec
|
|
@@ -164,26 +310,28 @@ Write `CLAUDE.md`:
|
|
|
164
310
|
4. `/forge-contract` — generate Specmatic OpenAPI contracts
|
|
165
311
|
5. `/forge-close {slug} {module}` — mark a module's tasks done (after module repo ships)
|
|
166
312
|
|
|
167
|
-
Utilities: `/forge-status` (feature dashboard) · `/forge-config` (edit modules/ports)
|
|
168
|
-
|
|
169
|
-
## Principles
|
|
170
|
-
{list each as a bullet — or "None defined yet."}
|
|
171
|
-
|
|
172
|
-
## Conventions
|
|
173
|
-
{list each as a bullet — or "None defined yet."}
|
|
174
|
-
|
|
175
|
-
## Out of Scope / Forbidden
|
|
176
|
-
{list each as a bullet — or "None defined yet."}
|
|
313
|
+
Utilities: `/forge-status` (feature dashboard) · `/forge-config` (edit modules/ports/context)
|
|
177
314
|
|
|
178
315
|
## Structure
|
|
316
|
+
- `CONTEXT.md` — project-wide domain context (actors, glossary, principles)
|
|
179
317
|
- `features/{slug}/brainstorm.md` — approved brainstorm summary
|
|
180
318
|
- `features/{slug}/spec.md` — requirements, flows, API list
|
|
181
319
|
- `features/{slug}/tasks.md` — per-module task breakdown with checkboxes
|
|
182
320
|
- `contracts/{module}/{slug}.yaml` + `schemas/` + `shared/` — Specmatic OpenAPI 3.0 contracts
|
|
183
321
|
```
|
|
184
322
|
|
|
323
|
+
Create `features/CHANGELOG.md`:
|
|
324
|
+
```markdown
|
|
325
|
+
# Feature Changelog
|
|
326
|
+
|
|
327
|
+
Ordered list of all features. Add entries via `/forge-brainstorm`; update via `/forge-spec`,
|
|
328
|
+
`/forge-contract`, and `/forge-close`. Use `Depends on` to declare what must ship first.
|
|
329
|
+
|
|
330
|
+
| # | Slug | Description | Status | Modules | Depends on |
|
|
331
|
+
|---|------|-------------|--------|---------|------------|
|
|
332
|
+
```
|
|
333
|
+
|
|
185
334
|
Create:
|
|
186
|
-
- `features/.gitkeep`
|
|
187
335
|
- `contracts/.gitkeep`
|
|
188
336
|
|
|
189
337
|
Append to `.gitignore` if not present:
|
|
@@ -199,7 +347,14 @@ Run `git status` and confirm:
|
|
|
199
347
|
|
|
200
348
|
## Rules
|
|
201
349
|
- One question per message — never ask multiple questions at once
|
|
202
|
-
- Never write files before the user says yes in Phase
|
|
350
|
+
- Never write files before the user says yes in Phase 5
|
|
351
|
+
- Each fact lives in exactly one file: domain context in `CONTEXT.md`, machine config
|
|
352
|
+
in `.forge/project.json`, workflow instructions in `CLAUDE.md` — never duplicate
|
|
353
|
+
content across them
|
|
203
354
|
- Never overwrite existing files
|
|
204
355
|
- All written files must be complete — no unfilled placeholders
|
|
356
|
+
- **Extract, don't re-ask**: if the user's answer contains information for upcoming fields
|
|
357
|
+
(e.g. "user-service, Spring Boot 3, port 8080, backend"), extract and fill those fields
|
|
358
|
+
silently — only ask about what is genuinely missing. Never ask a question the user has
|
|
359
|
+
already answered, even indirectly.
|
|
205
360
|
- If the user provides multiple answers in one message, accept them gracefully and move forward
|
|
@@ -44,9 +44,10 @@ Before asking anything, research silently:
|
|
|
44
44
|
- How Non-Functional requirements are typically written
|
|
45
45
|
- Any related feature whose requirements this feature extends or depends on
|
|
46
46
|
|
|
47
|
-
2. **
|
|
47
|
+
2. **CONTEXT.md** — note the actors, domain glossary, principles, and conventions.
|
|
48
48
|
Any principle that implies a requirement for this feature?
|
|
49
49
|
(e.g. "API contract before implementation" → this feature needs a contract requirement)
|
|
50
|
+
Use glossary terms verbatim in requirements — never invent synonyms for existing domain terms.
|
|
50
51
|
|
|
51
52
|
3. **Brainstorm open items** — extract from the brainstorm summary:
|
|
52
53
|
- Any item listed under **Open Questions** that wasn't resolved
|
|
@@ -58,7 +59,7 @@ Report findings:
|
|
|
58
59
|
> "Before drafting, here's what I found:
|
|
59
60
|
> - Related features: {list or 'none'}
|
|
60
61
|
> - Unresolved from brainstorm: {open questions / assumptions — or 'none, all clear'}
|
|
61
|
-
> -
|
|
62
|
+
> - CONTEXT.md principles that apply: {list or 'none'}
|
|
62
63
|
> - Naming convention: {e.g. 'REQ-N restarts per feature'}"
|
|
63
64
|
|
|
64
65
|
---
|
|
@@ -270,9 +271,16 @@ Cross-module data: {what is shared with or derived from other modules — or "No
|
|
|
270
271
|
|
|
271
272
|
---
|
|
272
273
|
|
|
273
|
-
## Step 7 —
|
|
274
|
+
## Step 7 — Update changelog & gate
|
|
274
275
|
|
|
275
|
-
After writing
|
|
276
|
+
After writing `spec.md`, update `features/CHANGELOG.md`:
|
|
277
|
+
- Find the row where `Slug` = `{slug}`
|
|
278
|
+
- Update `Status` → `Draft`
|
|
279
|
+
- Update `Modules` → comma-separated list of modules from the spec's **Modules** header
|
|
280
|
+
- If the row doesn't exist (spec written without going through forge-brainstorm), append it:
|
|
281
|
+
`| — | {slug} | {overview first sentence} | Draft | {modules} | — |`
|
|
282
|
+
|
|
283
|
+
Then say:
|
|
276
284
|
> "Spec written to `features/{slug}/spec.md`. Review it and say **yes** to generate the task breakdown."
|
|
277
285
|
|
|
278
286
|
Do NOT add tasks to spec.md — tasks go in `features/{slug}/tasks.md` via `/forge-tasks`.
|
|
@@ -12,44 +12,52 @@ disable-model-invocation: true
|
|
|
12
12
|
|
|
13
13
|
# Forge Status
|
|
14
14
|
|
|
15
|
-
Show the current status of all features in this spec repo.
|
|
15
|
+
Show the current status of all features in this spec repo, in changelog order.
|
|
16
16
|
|
|
17
17
|
## Steps
|
|
18
18
|
|
|
19
|
-
1.
|
|
19
|
+
1. Read `features/CHANGELOG.md`.
|
|
20
|
+
- If missing or empty (no data rows): "No features yet. Run `/forge-brainstorm` to plan your first feature."
|
|
21
|
+
- Parse each row: `#`, `slug`, `description`, `status`, `modules`, `depends on`.
|
|
20
22
|
|
|
21
|
-
2. For each
|
|
22
|
-
|
|
23
|
-
- `brainstorm.md` exists, no `spec.md` → 🔵 Brainstormed
|
|
24
|
-
- `spec.md` exists, no `tasks.md` → 🟡 Spec written
|
|
25
|
-
- `tasks.md` exists, no contract file in `contracts/{any-module}/{slug}.yaml` → 🟠 Tasks ready
|
|
26
|
-
- Contract exists, but `tasks.md` has unchecked tasks → 🟣 Implementing
|
|
27
|
-
- Contract exists and all tasks in `tasks.md` are checked → ✅ Done
|
|
23
|
+
2. For each row — in changelog order — determine its **live state** by checking the files
|
|
24
|
+
(overrides the stored status for in-progress detail):
|
|
28
25
|
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
| Files present | Live state |
|
|
27
|
+
|---|---|
|
|
28
|
+
| Nothing in `features/{slug}/` | 🔵 Brainstormed |
|
|
29
|
+
| `brainstorm.md` only | 🔵 Brainstormed |
|
|
30
|
+
| `spec.md` exists, no `tasks.md` | 🟡 Draft |
|
|
31
|
+
| `tasks.md` exists, no contract | 🟠 Open |
|
|
32
|
+
| Contract exists, unchecked tasks remain | 🟣 Implementing |
|
|
33
|
+
| All tasks checked (or `Status: Done` in tasks.md) | ✅ Done |
|
|
31
34
|
|
|
32
|
-
|
|
35
|
+
3. For 🟣 Implementing features, read `tasks.md` and compute per-module completion
|
|
36
|
+
(ticked vs total under each `### {target}` heading).
|
|
37
|
+
|
|
38
|
+
4. Flag any `Depends on` entries where the dependency is not yet ✅ Done — mark with ⚠️.
|
|
33
39
|
|
|
34
40
|
## Output Format
|
|
35
41
|
|
|
36
42
|
```
|
|
37
|
-
Feature Status — {project}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
5 features · 1 done · 1 implementing · 3 planning
|
|
43
|
+
Feature Status — {project}
|
|
44
|
+
══════════════════════════════════════════════════════════════════
|
|
45
|
+
# Slug Status Modules Depends on
|
|
46
|
+
──────────────────────────────────────────────────────────────────
|
|
47
|
+
1 user-auth ✅ Done user-service —
|
|
48
|
+
2 payment-flow 🟣 Implementing user-service 2/3 #1
|
|
49
|
+
3 notification-prefs 🟠 Open user-service #1
|
|
50
|
+
4 search-filters 🟡 Draft user-service —
|
|
51
|
+
5 bulk-export 🔵 Brainstormed — #3 ⚠️ not done yet
|
|
52
|
+
══════════════════════════════════════════════════════════════════
|
|
53
|
+
5 features · 1 done · 1 implementing · 3 in planning
|
|
48
54
|
```
|
|
49
55
|
|
|
56
|
+
The ⚠️ flag means "this feature's dependency is not yet Done — reconsider starting it."
|
|
57
|
+
|
|
50
58
|
## What to Show Next
|
|
51
|
-
After the table, suggest the next action for each non-done feature:
|
|
52
|
-
-
|
|
53
|
-
-
|
|
54
|
-
-
|
|
55
|
-
- Implementing → "Module repos
|
|
59
|
+
After the table, suggest the next action for each non-done feature (in changelog order):
|
|
60
|
+
- 🔵 Brainstormed → `/forge-spec {slug}`
|
|
61
|
+
- 🟡 Draft → `/forge-tasks {slug}`
|
|
62
|
+
- 🟠 Open → `/forge-contract {slug}`
|
|
63
|
+
- 🟣 Implementing → "Module repos: `/forge-implement {slug}` → `/forge-done` → `/forge-close {slug} {module}`"
|
|
@@ -22,12 +22,20 @@ Generate the task breakdown for a feature and write it to a dedicated file.
|
|
|
22
22
|
- If no → generate and write.
|
|
23
23
|
|
|
24
24
|
## Task breakdown rules
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
|
|
26
|
+
Read `.forge/project.json` and build a flat list of **task targets** — the names used as `###` headings:
|
|
27
|
+
- For a module with **no submodules** → the target is `{module.name}`
|
|
28
|
+
- For a module **with submodules** → the targets are each `{submodule.name}` (the parent module name
|
|
29
|
+
is NOT used as a heading; submodules are treated exactly like standalone modules here)
|
|
30
|
+
|
|
31
|
+
This means a submodule can later be promoted to its own repo with zero changes to `tasks.md`.
|
|
32
|
+
|
|
33
|
+
- Group tasks by target using `### {target-name}` headings
|
|
34
|
+
- Each task gets a unique ID: `TASK-N` (sequential across all targets)
|
|
27
35
|
- Tag each task with type: `[api]` / `[feat]` / `[ui]` / `[test]` / `[infra]`
|
|
28
36
|
- Write 1–3 acceptance criteria under each task
|
|
29
|
-
- Order tasks within each
|
|
30
|
-
- For frontend/consumer
|
|
37
|
+
- Order tasks within each target by dependency (what must be done first)
|
|
38
|
+
- For frontend/consumer targets, reference the backend endpoint they integrate against
|
|
31
39
|
|
|
32
40
|
## Output file: `features/{slug}/tasks.md`
|
|
33
41
|
|
|
@@ -41,7 +49,7 @@ _(Status lifecycle: Open → Done, set by `/forge-close` when all modules finish
|
|
|
41
49
|
|
|
42
50
|
---
|
|
43
51
|
|
|
44
|
-
### {
|
|
52
|
+
### {target-name} ({type})
|
|
45
53
|
|
|
46
54
|
- [ ] TASK-1 [api] {task title}
|
|
47
55
|
- {acceptance criterion}
|
|
@@ -52,7 +60,7 @@ _(Status lifecycle: Open → Done, set by `/forge-close` when all modules finish
|
|
|
52
60
|
|
|
53
61
|
---
|
|
54
62
|
|
|
55
|
-
### {
|
|
63
|
+
### {target-name} ({type})
|
|
56
64
|
|
|
57
65
|
- [ ] TASK-3 [ui] {task title}
|
|
58
66
|
- {acceptance criterion}
|
|
@@ -67,10 +75,10 @@ Tasks: {feature-slug}
|
|
|
67
75
|
- [ ] TASK-1 [api] POST /users/register
|
|
68
76
|
- [ ] TASK-2 [feat] Password hashing
|
|
69
77
|
|
|
70
|
-
###
|
|
78
|
+
### admin (frontend) ← submodule of webapps, but headed by its own name
|
|
71
79
|
- [ ] TASK-3 [ui] Registration form component
|
|
72
80
|
══════════════════════════════════════════
|
|
73
|
-
3 tasks across
|
|
81
|
+
3 tasks across 3 targets
|
|
74
82
|
```
|
|
75
83
|
|
|
76
84
|
## Gate
|