@khanhspring/forge-spec 1.0.0 → 1.1.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/bin/install.js CHANGED
@@ -2,12 +2,11 @@
2
2
 
3
3
  import { cpSync, mkdirSync } from 'fs';
4
4
  import { join, dirname } from 'path';
5
- import { homedir } from 'os';
6
5
  import { fileURLToPath } from 'url';
7
6
 
8
7
  const __dirname = dirname(fileURLToPath(import.meta.url));
9
8
  const ROOT = join(__dirname, '..');
10
- const SKILLS_DIR = join(homedir(), '.claude', 'skills');
9
+ const SKILLS_DIR = join(process.cwd(), '.claude', 'skills');
11
10
 
12
11
  const SKILLS = [
13
12
  'forge-brainstorm',
@@ -25,9 +24,9 @@ console.log('Installing @forge-workflow/spec skills...\n');
25
24
  mkdirSync(SKILLS_DIR, { recursive: true });
26
25
 
27
26
  for (const skill of SKILLS) {
28
- cpSync(join(ROOT, skill), join(SKILLS_DIR, skill), { recursive: true, force: true });
27
+ cpSync(join(ROOT, 'skills', skill), join(SKILLS_DIR, skill), { recursive: true, force: true });
29
28
  console.log(` ✓ ${skill}`);
30
29
  }
31
30
 
32
- console.log(`\nInstalled to ${SKILLS_DIR}`);
31
+ console.log(`\nInstalled to ${SKILLS_DIR} (project-local)`)
33
32
  console.log('Restart Claude Code, then run /forge-init in your spec repo.');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanhspring/forge-spec",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Forge spec repo skills for Claude Code — brainstorm, spec, tasks, contract, and more",
5
5
  "type": "module",
6
6
  "bin": {
@@ -8,14 +8,7 @@
8
8
  },
9
9
  "files": [
10
10
  "bin",
11
- "forge-brainstorm",
12
- "forge-close",
13
- "forge-config",
14
- "forge-contract",
15
- "forge-init",
16
- "forge-spec",
17
- "forge-status",
18
- "forge-tasks"
11
+ "skills"
19
12
  ],
20
13
  "keywords": ["claude-code", "skills", "ai", "workflow", "microservices"],
21
14
  "license": "MIT"
@@ -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 ONLY file this skill writes is `features/{slug}/brainstorm.md`, and only AFTER
22
- the user has explicitly approved the Brainstorm Summary at the gate (Step 7).
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:
@@ -57,7 +83,8 @@ Then check scope:
57
83
  ## Step 2 — Mandatory questions (one at a time)
58
84
 
59
85
  These MUST all be answered before moving to Step 4. Ask one at a time.
60
- Skip any sub-question already answered by your research in Step 1.
86
+ **Skip any area already covered by Step 0 extraction or Step 1 research.**
87
+ Only ask about genuine gaps — never re-ask what the user already provided.
61
88
 
62
89
  **If a question hits an unknown** — something the user can't answer without researching —
63
90
  use the Research Flag pattern (see Research Handling below).
@@ -302,8 +329,17 @@ If (b), convert each item to an explicit assumption in the summary.
302
329
 
303
330
  ## Step 8 — Persist the summary (after approval only)
304
331
 
305
- Once the user says **yes**, write the approved summary to `features/{slug}/brainstorm.md`
306
- so it survives across sessions and forge-spec can pick it up later.
332
+ Once the user says **yes**:
333
+
334
+ **8a — Assign sequence number and ask about dependencies**
335
+
336
+ Read `features/CHANGELOG.md`. Count existing rows to get the next `#`.
337
+
338
+ Ask (one message):
339
+ > "Does this feature depend on any other feature being shipped first?
340
+ > _(Enter slugs like `user-registration`, or 'none')_"
341
+
342
+ **8b — Write `features/{slug}/brainstorm.md`**
307
343
 
308
344
  ```markdown
309
345
  # Brainstorm: {Feature Name}
@@ -315,18 +351,26 @@ so it survives across sessions and forge-spec can pick it up later.
315
351
  {the full Brainstorm Summary body from Step 6 — all sections}
316
352
  ```
317
353
 
354
+ **8c — Append row to `features/CHANGELOG.md`**
355
+
356
+ Add a new row — status `Brainstormed`, modules left blank until forge-spec fills them:
357
+ ```
358
+ | {n} | {slug} | {one-line from Problem section} | Brainstormed | — | {depends or —} |
359
+ ```
360
+
318
361
  Then hand off:
319
- > "Saved to `features/{slug}/brainstorm.md`. Run `/forge-spec {slug}` to write the spec."
362
+ > "Saved to `features/{slug}/brainstorm.md` and added to the changelog as #{n}.
363
+ > Run `/forge-spec {slug}` to write the spec."
320
364
 
321
365
  ---
322
366
 
323
367
  ## Rules
324
368
  - One question per message — never list multiple at once
325
369
  - Prefer multiple-choice when options are predictable
326
- - Never skip Step 2 mandatory areas — even for "simple" features
327
- - Never skip the challenge round (Step 4)
328
- - Never skip the approaches step (Step 5)
370
+ - Cover all Step 2 mandatory areas — but fill from Step 0 extraction first; only ask for genuine gaps
371
+ - Never skip the challenge round (Step 4) — even when a doc covers everything, challenge it
372
+ - Never skip the approaches step (Step 5) — a doc may have a chosen approach but alternatives should still be surfaced
329
373
  - YAGNI: move anything non-core to Out of Scope
330
374
  - The ONLY file written is `features/{slug}/brainstorm.md`, and only after approval (Step 8)
331
375
  - 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
376
+ - 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
 
@@ -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` — get module names, ports, stacks.
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
@@ -53,16 +53,39 @@ For each module, ask these in order (one question per message):
53
53
  2. **Type** — "Is `{name}` a backend service, frontend app, or something else?
54
54
  _(backend / frontend / worker / gateway)_"
55
55
  3. **Stack** — "What's the tech stack for `{name}`? (e.g. `Spring Boot 3, Java 21` or `React, TypeScript`)"
56
- 4. **Port** — "What port does `{name}` run on locally?"
57
- 5. **Repo URL** — "What's the git repo URL for `{name}`?
56
+ 4. **Repo URL** — "What's the git repo URL for `{name}`?
58
57
  _(Skip with 'none' if not set up yet)_"
59
- 6. **Description** — "One sentence: what does `{name}` do?
60
- _(Skip with 'none')_"
61
-
62
- After collecting all fields for a module, confirm it back:
58
+ 5. **Submodules** — scan the user's answers so far for signals: words like "monorepo", "multi-module",
59
+ "Gradle modules", a comma-separated list of app names, etc.
60
+ **If signals present**, ask:
61
+ > "It sounds like `{name}` contains multiple submodules ({detected names if any}).
62
+ > Should I configure them separately? (yes / no)"
63
+ **If yes** → collect submodules one at a time (see below). Skip step 6 — port belongs to each submodule, not the parent.
64
+ **If no or no signals** → continue to step 6.
65
+ 6. **Port** _(skip when module has submodules)_ — "What port does `{name}` run on locally?"
66
+ 7. **Description** — "One sentence: what does `{name}` do? _(Skip with 'none')_"
67
+
68
+ **Submodule collection** (repeat for each):
69
+ - "Submodule name? (kebab-case)"
70
+ - "Type? (backend / frontend / worker)"
71
+ - "Stack?"
72
+ - "Port?"
73
+ - "Path within the `{name}` repo? (e.g. `apps/admin` or `auth-ui`)"
74
+ - "One sentence: what does it do? _(Skip with 'none')_"
75
+
76
+ Confirm each: "`{sub}` — {type} — {stack} — :{port} — path: {path}. Another submodule? (yes / no)"
77
+
78
+ > **Rules for submodules:**
79
+ > - No `repo` field — submodules share the parent module's repo
80
+ > - No `port` on the parent module — port belongs to each submodule
81
+ > - `type` and `stack` are per-submodule (may differ from the parent)
82
+
83
+ After collecting all submodules (or just module fields), confirm:
63
84
 
64
85
  > "Got it:
65
- > `{name}` — {type} — {stack} — :{port} — {repo or 'no repo yet'}
86
+ > `{name}` — {type} — {repo or 'no repo yet'}
87
+ > {if no submodules: stack + port}
88
+ > {if submodules: list each as ` ↳ {sub} — {type} — {stack} — :{port} — {path}`}
66
89
  > {description}
67
90
  > Is that right?"
68
91
 
@@ -112,7 +135,7 @@ CLAUDE.md
112
135
  Conventions: {list or "none yet"}
113
136
  Out of scope: {list or "none yet"}
114
137
 
115
- features/.gitkeep
138
+ features/CHANGELOG.md
116
139
  contracts/.gitkeep
117
140
  .gitignore ← append Forge entries
118
141
  ```
@@ -126,6 +149,8 @@ Wait for confirmation. Do not write anything before the user says yes.
126
149
  ## Phase 5 — Write files
127
150
 
128
151
  Write `.forge/project.json`:
152
+
153
+ Module **without** submodules — `port` and `stack` on the module itself:
129
154
  ```json
130
155
  {
131
156
  "project": "{project-name}",
@@ -146,6 +171,35 @@ Write `.forge/project.json`:
146
171
  }
147
172
  ```
148
173
 
174
+ Module **with** submodules — no `port` on the module; each submodule owns its `port`, `stack`,
175
+ `type`, and `path`; no `repo` on submodules (they share the parent's repo):
176
+ ```json
177
+ {
178
+ "project": "{project-name}",
179
+ "version": "1.0",
180
+ "modules": [
181
+ {
182
+ "name": "{module-name}",
183
+ "repo": "{repo-url}",
184
+ "description": "{description}",
185
+ "submodules": [
186
+ {
187
+ "name": "{sub-name}",
188
+ "type": "backend|frontend|worker",
189
+ "stack": ["{stack}"],
190
+ "port": {port},
191
+ "path": "{relative-path-in-repo}",
192
+ "description": "{description}"
193
+ }
194
+ ]
195
+ }
196
+ ],
197
+ "spec_repo": "{spec-repo-url}",
198
+ "contract_format": "openapi3",
199
+ "contract_tool": "specmatic"
200
+ }
201
+ ```
202
+
149
203
  Write `CLAUDE.md`:
150
204
  ```markdown
151
205
  # {project-name}
@@ -157,6 +211,14 @@ Write `CLAUDE.md`:
157
211
  |------|------|-------|------|
158
212
  | {name} | {type} | {stack} | {port} |
159
213
 
214
+ _(For modules with submodules, expand the table with one row per submodule.
215
+ Indent the submodule name with `↳` and omit port/stack from the parent row.)_
216
+
217
+ | Name | Type | Stack | Port | Path |
218
+ |------|------|-------|------|------|
219
+ | {module} | — | — | — | — |
220
+ | ↳ {sub} | {type} | {stack} | {port} | {path} |
221
+
160
222
  ## Forge Workflow
161
223
  1. `/forge-brainstorm` — explore and define a feature
162
224
  2. `/forge-spec` — write the spec
@@ -182,8 +244,18 @@ Utilities: `/forge-status` (feature dashboard) · `/forge-config` (edit modules/
182
244
  - `contracts/{module}/{slug}.yaml` + `schemas/` + `shared/` — Specmatic OpenAPI 3.0 contracts
183
245
  ```
184
246
 
247
+ Create `features/CHANGELOG.md`:
248
+ ```markdown
249
+ # Feature Changelog
250
+
251
+ Ordered list of all features. Add entries via `/forge-brainstorm`; update via `/forge-spec`,
252
+ `/forge-contract`, and `/forge-close`. Use `Depends on` to declare what must ship first.
253
+
254
+ | # | Slug | Description | Status | Modules | Depends on |
255
+ |---|------|-------------|--------|---------|------------|
256
+ ```
257
+
185
258
  Create:
186
- - `features/.gitkeep`
187
259
  - `contracts/.gitkeep`
188
260
 
189
261
  Append to `.gitignore` if not present:
@@ -202,4 +274,8 @@ Run `git status` and confirm:
202
274
  - Never write files before the user says yes in Phase 4
203
275
  - Never overwrite existing files
204
276
  - All written files must be complete — no unfilled placeholders
277
+ - **Extract, don't re-ask**: if the user's answer contains information for upcoming fields
278
+ (e.g. "user-service, Spring Boot 3, port 8080, backend"), extract and fill those fields
279
+ silently — only ask about what is genuinely missing. Never ask a question the user has
280
+ already answered, even indirectly.
205
281
  - If the user provides multiple answers in one message, accept them gracefully and move forward
@@ -270,9 +270,16 @@ Cross-module data: {what is shared with or derived from other modules — or "No
270
270
 
271
271
  ---
272
272
 
273
- ## Step 7 — Gate
273
+ ## Step 7 — Update changelog & gate
274
274
 
275
- After writing, say:
275
+ After writing `spec.md`, update `features/CHANGELOG.md`:
276
+ - Find the row where `Slug` = `{slug}`
277
+ - Update `Status` → `Draft`
278
+ - Update `Modules` → comma-separated list of modules from the spec's **Modules** header
279
+ - If the row doesn't exist (spec written without going through forge-brainstorm), append it:
280
+ `| — | {slug} | {overview first sentence} | Draft | {modules} | — |`
281
+
282
+ Then say:
276
283
  > "Spec written to `features/{slug}/spec.md`. Review it and say **yes** to generate the task breakdown."
277
284
 
278
285
  Do NOT add tasks to spec.md — tasks go in `features/{slug}/tasks.md` via `/forge-tasks`.
@@ -0,0 +1,63 @@
1
+ ---
2
+ name: "forge-status"
3
+ description: "Scans features/ and shows phase status for every feature: 🔵 brainstorming, 🟡 spec written, 🟠 tasks ready, ✅ contract complete. Suggests the next forge command for each in-progress feature."
4
+ argument-hint: ""
5
+ compatibility: "Requires spec repo with .forge/project.json"
6
+ metadata:
7
+ author: "forge-workflow"
8
+ source: "spec-skills/forge-status/SKILL.md"
9
+ user-invocable: true
10
+ disable-model-invocation: true
11
+ ---
12
+
13
+ # Forge Status
14
+
15
+ Show the current status of all features in this spec repo, in changelog order.
16
+
17
+ ## Steps
18
+
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`.
22
+
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):
25
+
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 |
34
+
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 ⚠️.
39
+
40
+ ## Output Format
41
+
42
+ ```
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
54
+ ```
55
+
56
+ The ⚠️ flag means "this feature's dependency is not yet Done — reconsider starting it."
57
+
58
+ ## What to Show Next
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
- - Group tasks by module using `### {module-name}` headings (use module names from `.forge/project.json`)
26
- - Each task gets a unique ID: `TASK-N` (sequential across all modules)
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 module by dependency (what must be done first)
30
- - For frontend/consumer modules, reference the backend endpoint they integrate against
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
- ### {module-name} ({type})
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
- ### {module-name} ({type})
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
- ### web-app (frontend)
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 2 modules
81
+ 3 tasks across 3 targets
74
82
  ```
75
83
 
76
84
  ## Gate
@@ -1,55 +0,0 @@
1
- ---
2
- name: "forge-status"
3
- description: "Scans features/ and shows phase status for every feature: 🔵 brainstorming, 🟡 spec written, 🟠 tasks ready, ✅ contract complete. Suggests the next forge command for each in-progress feature."
4
- argument-hint: ""
5
- compatibility: "Requires spec repo with .forge/project.json"
6
- metadata:
7
- author: "forge-workflow"
8
- source: "spec-skills/forge-status/SKILL.md"
9
- user-invocable: true
10
- disable-model-invocation: true
11
- ---
12
-
13
- # Forge Status
14
-
15
- Show the current status of all features in this spec repo.
16
-
17
- ## Steps
18
-
19
- 1. Scan the `features/` directory. If empty or missing, say "No features yet. Run `/forge-brainstorm` to plan your first feature."
20
-
21
- 2. For each feature folder, determine its state (check in order, top to bottom):
22
- - No `brainstorm.md` and no `spec.md` → 🔵 Brainstorming
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
28
-
29
- 3. For features in Implementing, read `tasks.md` and compute per-module completion
30
- (ticked vs total under each `### {module}` heading) for the detail line.
31
-
32
- 4. Also check `contracts/` for orphaned contracts (contract file exists but no matching feature folder) and flag them.
33
-
34
- ## Output Format
35
-
36
- ```
37
- Feature Status — {project} spec repo
38
- ══════════════════════════════════════════════════════
39
-
40
- ✅ user-auth Done — all modules complete
41
- 🟣 payment-flow Implementing — user-service 2/3, web-app 0/2
42
- 🟠 notification-prefs Tasks ready — contract pending
43
- 🟡 search-filters Spec written — tasks pending
44
- 🔵 bulk-export Brainstormed — spec pending
45
-
46
- ══════════════════════════════════════════════════════
47
- 5 features · 1 done · 1 implementing · 3 planning
48
- ```
49
-
50
- ## What to Show Next
51
- After the table, suggest the next action for each non-done feature:
52
- - Brainstorming/Brainstormed → "Run `/forge-spec {slug}` to write the spec"
53
- - Spec written → "Run `/forge-tasks {slug}` to generate the task breakdown"
54
- - Tasks ready → "Run `/forge-contract {slug}` to generate the API contract"
55
- - Implementing → "Module repos run `/forge-implement {slug}`, then `/forge-done` → `/forge-close {slug} {module}`"
File without changes