@khanhspring/forge-spec 1.0.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 ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { cpSync, mkdirSync } from 'fs';
4
+ import { join, dirname } from 'path';
5
+ import { homedir } from 'os';
6
+ import { fileURLToPath } from 'url';
7
+
8
+ const __dirname = dirname(fileURLToPath(import.meta.url));
9
+ const ROOT = join(__dirname, '..');
10
+ const SKILLS_DIR = join(homedir(), '.claude', 'skills');
11
+
12
+ const SKILLS = [
13
+ 'forge-brainstorm',
14
+ 'forge-close',
15
+ 'forge-config',
16
+ 'forge-contract',
17
+ 'forge-init',
18
+ 'forge-spec',
19
+ 'forge-status',
20
+ 'forge-tasks',
21
+ ];
22
+
23
+ console.log('Installing @forge-workflow/spec skills...\n');
24
+
25
+ mkdirSync(SKILLS_DIR, { recursive: true });
26
+
27
+ for (const skill of SKILLS) {
28
+ cpSync(join(ROOT, skill), join(SKILLS_DIR, skill), { recursive: true, force: true });
29
+ console.log(` ✓ ${skill}`);
30
+ }
31
+
32
+ console.log(`\nInstalled to ${SKILLS_DIR}`);
33
+ console.log('Restart Claude Code, then run /forge-init in your spec repo.');
@@ -0,0 +1,332 @@
1
+ ---
2
+ name: "forge-brainstorm"
3
+ description: "Phase 1 of 4. Interrogates a feature idea through structured questioning, a challenge round, and 2–3 design approaches before writing a gated summary. Proactively researches existing context and surfaces research-blocked items before writing the spec."
4
+ argument-hint: "Feature idea to brainstorm (e.g. 'user notifications')"
5
+ compatibility: "Requires spec repo with .forge/project.json"
6
+ metadata:
7
+ author: "forge-workflow"
8
+ source: "spec-skills/forge-brainstorm/SKILL.md"
9
+ user-invocable: true
10
+ disable-model-invocation: true
11
+ ---
12
+
13
+ # Forge Brainstorm
14
+
15
+ Phase 1 of 4. Your job is to fully understand a feature before any spec is written.
16
+ The goal is zero ambiguity — every concern surfaced, every edge case accounted for,
17
+ every unknown either resolved or explicitly accepted as an assumption.
18
+
19
+ <HARD-GATE>
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).
23
+ "Simple" features are where unexamined assumptions cause the most wasted work — no feature
24
+ skips this phase.
25
+ </HARD-GATE>
26
+
27
+ ---
28
+
29
+ ## Step 1 — Load & Research Context
30
+
31
+ Before asking the user anything, research the existing codebase silently:
32
+
33
+ 1. Read `.forge/project.json` — note module names, types, stacks, ports.
34
+ 2. Scan `features/*/spec.md` — are there related or similar features already specced?
35
+ Note any patterns, naming conventions, or prior decisions relevant to this idea.
36
+ 3. Scan `contracts/*/` — are there existing API contracts this feature will touch or extend?
37
+ Note existing endpoint shapes, error formats, auth patterns.
38
+ 4. Read `CLAUDE.md` — note project principles, conventions, and forbidden patterns
39
+ that will constrain design choices.
40
+
41
+ Report your findings before starting questions:
42
+
43
+ > "Before we dive in, here's what I found in the codebase:
44
+ > - [relevant existing feature or contract, or "No related features found"]
45
+ > - [relevant principle from CLAUDE.md, or "No constraints found"]
46
+ >
47
+ > I'll use this as context. Here's my understanding of the feature: {1–2 sentence restatement}
48
+ > Is that right?"
49
+
50
+ Then check scope:
51
+
52
+ > If the idea spans multiple unrelated concerns: "This sounds like 2–3 separate features.
53
+ > Shall we split and brainstorm each one, or treat it as a single feature?"
54
+
55
+ ---
56
+
57
+ ## Step 2 — Mandatory questions (one at a time)
58
+
59
+ 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.
61
+
62
+ **If a question hits an unknown** — something the user can't answer without researching —
63
+ use the Research Flag pattern (see Research Handling below).
64
+
65
+ **1. Problem & users**
66
+ - What specific pain does this solve?
67
+ - Who experiences it, and how often?
68
+ - What happens today without this feature?
69
+
70
+ **2. Actors & permissions**
71
+ - Who are the actors? (end user / admin / system / external service)
72
+ - Does each actor have different access levels or see different data?
73
+ - Is any part restricted by role or ownership? (e.g. "users can only edit their own records")
74
+
75
+ **3. Happy path**
76
+ - Walk through the exact steps from trigger to completion.
77
+ - What does the user see/receive at the end?
78
+
79
+ **4. Data & state**
80
+ - What data is created, read, updated, or deleted?
81
+ - What persists after the action completes?
82
+ - Is any of this shared with or derived from other modules?
83
+
84
+ **5. Failure cases** — ask explicitly about each:
85
+ - Invalid or missing input → what happens?
86
+ - The same request submitted twice (idempotency)?
87
+ - A downstream service or dependency is unavailable?
88
+ - The user doesn't have permission?
89
+ - Partial failure mid-flow — is rollback needed?
90
+
91
+ **6. Modules & APIs**
92
+ - Which modules are involved?
93
+ - Does this extend existing APIs or is it net-new?
94
+ - Does anything need to be deprecated or changed?
95
+
96
+ ---
97
+
98
+ ## Step 3 — Conditional questions (ask if not already answered)
99
+
100
+ - **Integrations** — emails, push notifications, webhooks, third-party APIs?
101
+ - **Async / background work** — any deferred or eventually consistent parts?
102
+ - **Scale & performance** — volume expectations or SLA requirements?
103
+ - **Consistency** — similar existing feature to follow for patterns?
104
+
105
+ Skip any that are clearly irrelevant.
106
+
107
+ ---
108
+
109
+ ## Research Handling
110
+
111
+ Use this pattern whenever a question surfaces something that cannot be answered
112
+ through discussion alone.
113
+
114
+ ### When the user doesn't know the answer
115
+
116
+ > "🔍 **Research needed:** {what needs to be found out}
117
+ >
118
+ > To answer this, you'd need to: {specific action — e.g. 'check if Stripe supports partial
119
+ > refunds in your plan', 'ask the product team what the UX should be', 'look at how
120
+ > user-service currently handles token expiry'}
121
+ >
122
+ > How do you want to proceed?
123
+ > **(a) Pause here** — I'll give you a research checklist and we resume when you have answers
124
+ > **(b) Proceed with an assumption** — I'll state an explicit assumption and flag it for validation
125
+ > **(c) Keep going** — we'll leave this as an open question and resolve it before writing the spec"
126
+
127
+ ### When Claude can research it
128
+
129
+ If the answer can be found by reading existing files in the repo:
130
+
131
+ > "🔍 Let me check the existing codebase for this — one moment."
132
+
133
+ Read the relevant file(s), then report what you found and whether it resolves the question.
134
+
135
+ ### Research pause
136
+
137
+ If the user chooses **(a) Pause**:
138
+
139
+ Output a research checklist:
140
+
141
+ ```
142
+ ⏸ Brainstorm paused — research needed before continuing.
143
+
144
+ Research checklist:
145
+ □ {item 1} — {where to look / who to ask}
146
+ □ {item 2} — {where to look / who to ask}
147
+
148
+ Resume by coming back and saying: "forge-brainstorm {slug} — resuming with answers:
149
+ - {item 1}: [your answer]
150
+ - {item 2}: [your answer]"
151
+ ```
152
+
153
+ Stop here. Do not continue the brainstorm until the user resumes with answers.
154
+
155
+ ### Proceed with assumption
156
+
157
+ If the user chooses **(b) Assumption**:
158
+
159
+ State it explicitly and add it to the Assumptions section in the summary:
160
+
161
+ > "✅ Assumption recorded: {clear statement of what we're assuming}
162
+ > This will need validation before or during implementation."
163
+
164
+ ---
165
+
166
+ ## Step 4 — Challenge round
167
+
168
+ Actively probe for hidden problems. Raise at least 2 concerns specific to the answers given:
169
+
170
+ > "Before I propose approaches, I want to flag a couple of things:
171
+ >
172
+ > **[Concern 1]:** {specific concern from the conversation}
173
+ >
174
+ > **[Concern 2]:** {specific concern from the conversation}
175
+ >
176
+ > How should these be handled?"
177
+
178
+ Wait for resolution before moving on. If a concern can't be resolved without research,
179
+ apply the Research Handling pattern.
180
+
181
+ ---
182
+
183
+ ## Step 5 — Propose approaches
184
+
185
+ 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 CLAUDE.md principles.
187
+
188
+ ```
189
+ I see 2–3 ways to approach this:
190
+
191
+ **Option A (Recommended): {name}**
192
+ {1–2 sentences}
193
+ ✓ {pro} ✗ {con}
194
+ {note if consistent/inconsistent with existing patterns}
195
+
196
+ **Option B: {name}**
197
+ {1–2 sentences}
198
+ ✓ {pro} ✗ {con}
199
+
200
+ **Option C: {name}** (if relevant)
201
+ {1–2 sentences}
202
+ ✓ {pro} ✗ {con}
203
+
204
+ I'd go with Option A because {reason}. What do you think?
205
+ ```
206
+
207
+ After the user picks, ask one follow-up:
208
+ > "What's the main risk you see with this approach? Anything that makes you hesitant?"
209
+
210
+ Resolve concerns before moving on.
211
+
212
+ ---
213
+
214
+ ## Step 6 — Synthesize
215
+
216
+ Write the brainstorm summary in the conversation (no file):
217
+
218
+ ```
219
+ ## Brainstorm Summary: {Feature Name}
220
+ **Slug:** {kebab-case-slug}
221
+ **Approach:** {chosen option name}
222
+
223
+ ### Problem
224
+ {1–2 sentences}
225
+
226
+ ### Actors & Permissions
227
+ - **{Role}**: {what they do and what they can access}
228
+
229
+ ### Happy Path
230
+ 1. {step}
231
+ 2. {step}
232
+
233
+ ### Data & State
234
+ - {what is created/read/updated/deleted}
235
+ - {what persists and where}
236
+
237
+ ### Edge Cases & Failures
238
+ - **{case}**: {handling}
239
+
240
+ ### Constraints
241
+ - {constraint — or "None identified"}
242
+
243
+ ### Modules Involved
244
+ - **{module-name}** ({type}): {responsibility in this feature}
245
+
246
+ ### Out of Scope
247
+ - {explicitly excluded items}
248
+
249
+ ### Assumptions
250
+ - {assumption}: {what it means if this is wrong}
251
+ - (empty if no assumptions were made)
252
+
253
+ ### Research Needed
254
+ - {item}: {what to check and where}
255
+ - (empty if nothing is pending)
256
+
257
+ ### Open Questions
258
+ - {unresolved concern — must be empty or moved to Research Needed before spec is written}
259
+ ```
260
+
261
+ **Self-review before presenting:**
262
+ - Any requirement readable two ways → pick one interpretation, state it explicitly
263
+ - Any happy path step with no failure case → add it
264
+ - Any "nice to have" → move to Out of Scope
265
+ - Any contradiction between sections → resolve it
266
+ - Anything in Open Questions that's actually a research item → move it to Research Needed
267
+ - Open Questions not truly empty → do not write "None"
268
+
269
+ Do not mention the self-review to the user.
270
+
271
+ ---
272
+
273
+ ## Step 7 — Gate
274
+
275
+ Check all three blocking sections before accepting "yes":
276
+
277
+ **If Open Questions is not empty:**
278
+ > "Let's resolve these before writing the spec:
279
+ > - {question}
280
+ > How would you handle each?"
281
+ Do NOT proceed until resolved.
282
+
283
+ **If Research Needed is not empty:**
284
+ > "There are items that need research before the spec can be finalized:
285
+ > - {item}: {where to look}
286
+ >
287
+ > Do you want to:
288
+ > **(a) Pause and research first** — I'll give you the checklist
289
+ > **(b) Proceed and treat these as assumptions** — I'll add them to the spec as risks to validate"
290
+
291
+ Wait for the user's choice. If (a), output the research checklist and stop.
292
+ If (b), convert each item to an explicit assumption in the summary.
293
+
294
+ **If Assumptions is not empty, warn:**
295
+ > "Note: this spec will include {n} assumption(s) that need validation:
296
+ > - {assumption}: {risk if wrong}"
297
+
298
+ **Once all three sections are resolved or accepted:**
299
+ > "Does this capture the feature correctly? Clarify anything above, or say **yes** to save it and move to the spec."
300
+
301
+ ---
302
+
303
+ ## Step 8 — Persist the summary (after approval only)
304
+
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.
307
+
308
+ ```markdown
309
+ # Brainstorm: {Feature Name}
310
+
311
+ **Slug:** {slug}
312
+ **Approach:** {chosen option name}
313
+ **Captured:** {YYYY-MM-DD}
314
+
315
+ {the full Brainstorm Summary body from Step 6 — all sections}
316
+ ```
317
+
318
+ Then hand off:
319
+ > "Saved to `features/{slug}/brainstorm.md`. Run `/forge-spec {slug}` to write the spec."
320
+
321
+ ---
322
+
323
+ ## Rules
324
+ - One question per message — never list multiple at once
325
+ - 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)
329
+ - YAGNI: move anything non-core to Out of Scope
330
+ - The ONLY file written is `features/{slug}/brainstorm.md`, and only after approval (Step 8)
331
+ - 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
@@ -0,0 +1,129 @@
1
+ ---
2
+ name: "forge-close"
3
+ description: "Marks a module's tasks as done in features/{slug}/tasks.md, generates the spec repo commit message, and checks whether all modules have completed — closing the feature if so."
4
+ argument-hint: "Feature slug and module name (e.g. 'user-registration user-service')"
5
+ compatibility: "Requires spec repo with .forge/project.json and features/{slug}/tasks.md"
6
+ metadata:
7
+ author: "forge-workflow"
8
+ source: "spec-skills/forge-close/SKILL.md"
9
+ user-invocable: true
10
+ disable-model-invocation: true
11
+ ---
12
+
13
+ # Forge Close — Spec Repo
14
+
15
+ Mark a module's implementation tasks as done in the spec repo.
16
+ Run this after `/forge-done` in the module repo.
17
+
18
+ ---
19
+
20
+ ## Pre-check
21
+
22
+ - Read `.forge/project.json` — get module list.
23
+ If missing: "Run `/forge-init` to set up this spec repo first."
24
+ - Parse $ARGUMENTS:
25
+ - First word → feature slug
26
+ - Second word → module name
27
+ - If slug missing → ask: "Which feature are you closing?"
28
+ - If module missing → ask: "Which module are you marking as done?
29
+ _(Available modules: {list from project.json})_"
30
+ - Read `features/{slug}/tasks.md` — must exist.
31
+ If missing: "No tasks file found. Run `/forge-tasks {slug}` first."
32
+ - Validate module name exists in `### {module}` section of tasks.md.
33
+ If not found: "No tasks for `{module}` in `{slug}`. Check the module name matches exactly."
34
+
35
+ ---
36
+
37
+ ## Step 1 — Show current task state
38
+
39
+ Display the module's current tasks:
40
+
41
+ ```
42
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
43
+ Closing: {module} / {feature-slug}
44
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
45
+ - [ ] TASK-1 [api] POST /users/register endpoint
46
+ - [ ] TASK-2 [feat] Password hashing + validation
47
+ - [x] TASK-3 [test] Unit tests for UserService
48
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
49
+ ```
50
+
51
+ If all tasks are already ticked:
52
+ > "All tasks for `{module}` are already marked done. Nothing to update."
53
+ Check overall feature status (Step 3) and stop.
54
+
55
+ Otherwise ask:
56
+ > "Mark all {n} tasks for `{module}` as done? Say **yes** to update, or tell me which ones to skip."
57
+
58
+ Wait for confirmation before writing.
59
+
60
+ ---
61
+
62
+ ## Step 2 — Update tasks.md
63
+
64
+ In `features/{slug}/tasks.md`, tick all confirmed tasks under `### {module}`:
65
+ - Change `- [ ]` → `- [x]` for each confirmed task
66
+ - Leave any explicitly skipped tasks untouched
67
+ - Update the `**Last updated:**` date at the top of the file to today
68
+
69
+ Show a diff summary:
70
+ ```
71
+ Updated features/{slug}/tasks.md:
72
+ - [x] TASK-1 [api] POST /users/register endpoint ← ticked
73
+ - [x] TASK-2 [feat] Password hashing + validation ← ticked
74
+ - [x] TASK-3 [test] Unit tests for UserService (was already done)
75
+ ```
76
+
77
+ ---
78
+
79
+ ## Step 3 — Check overall feature completion
80
+
81
+ Scan ALL `### {module}` sections in `tasks.md`.
82
+ Count ticked vs unticked tasks per module:
83
+
84
+ ```
85
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
86
+ Feature progress: {feature-slug}
87
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
88
+ - [x] user-service — 3/3 tasks done
89
+ - [ ] web-app — 0/2 tasks done
90
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
91
+ ```
92
+
93
+ **If all modules are complete:**
94
+ Update `features/{slug}/tasks.md` header status to `Done`
95
+ and `features/{slug}/spec.md` header status to `Done`.
96
+
97
+ > "🎉 All modules done — feature `{slug}` is complete."
98
+
99
+ **If modules still remain:**
100
+
101
+ List what's left:
102
+ > "{module} still has {n} task(s) remaining.
103
+ > Once they run `/forge-done {slug}` in their module repo,
104
+ > they can run `/forge-close {slug} {module}` here to close out."
105
+
106
+ ---
107
+
108
+ ## Step 4 — Generate commit message
109
+
110
+ ```
111
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
112
+ Commit message
113
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
114
+ chore(tasks): mark {module} done for {feature-slug}
115
+
116
+ Completed tasks:
117
+ - TASK-1: {title}
118
+ - TASK-2: {title}
119
+ - TASK-3: {title}
120
+
121
+ {if all modules done}
122
+ Feature {feature-slug} fully implemented across all modules.
123
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
124
+ ```
125
+
126
+ Then remind:
127
+ > "After committing and pushing, module repos should run:
128
+ > `git submodule update --remote specs`
129
+ > to sync the updated task status."
@@ -0,0 +1,113 @@
1
+ ---
2
+ name: "forge-config"
3
+ description: "View and interactively update .forge/project.json: add or remove modules, update ports, change stack info, or update the spec repo URL. Asks one question at a time and previews changes before writing."
4
+ argument-hint: "Optional hint: 'add module', 'update user-service port', 'remove web-app'"
5
+ compatibility: "Requires spec repo with .forge/project.json"
6
+ metadata:
7
+ author: "forge-workflow"
8
+ source: "spec-skills/forge-config/SKILL.md"
9
+ user-invocable: true
10
+ disable-model-invocation: true
11
+ ---
12
+
13
+ # Forge Config
14
+
15
+ View and update the project configuration at `.forge/project.json`.
16
+
17
+ ## Step 1 — Load & display
18
+
19
+ Read `.forge/project.json`.
20
+ If missing: "No project config found. Run `/forge-init` to set up this repo first."
21
+
22
+ Display the current config:
23
+
24
+ ```
25
+ Project: {project-name}
26
+ Spec repo: {spec_repo}
27
+ Contract tool: {contract_tool}
28
+
29
+ Modules ({n}):
30
+ · user-service backend Spring Boot 3, Java 21 :8081
31
+ · web-app frontend React, TypeScript :3000
32
+ ```
33
+
34
+ ## Step 2 — Determine the change
35
+
36
+ From $ARGUMENTS, infer the intent if given (e.g. "add module", "update user-service port").
37
+ If empty, ask: "What do you want to change? (add a module / remove a module / update a field / change spec repo URL)"
38
+
39
+ ## Step 3 — Collect details (one question at a time)
40
+
41
+ Ask one question per message — never batch.
42
+
43
+ **Adding a module** — ask in order, one at a time:
44
+ 1. "Module name? (kebab-case, must be unique)"
45
+ 2. "Type? (backend / frontend / worker / gateway)"
46
+ 3. "Tech stack? (e.g. 'Spring Boot 3, Java 21')"
47
+ 4. "Local dev port?"
48
+ 5. "Git repo URL? (or 'none')"
49
+ 6. "One-sentence description? (or 'none')"
50
+
51
+ **Removing a module:**
52
+ - Check whether any `features/*/tasks.md` has a `### {module}` section.
53
+ If so, warn: "`{module}` has tasks in {feature(s)}. Removing it from config won't delete those tasks. Remove anyway? (yes/no)"
54
+ - Otherwise confirm: "Remove `{module}` from the project? (yes/no)"
55
+
56
+ **Updating a field:**
57
+ - Show the current value, then ask for the new one:
58
+ "`{module}.{field}` is currently `{old}`. What should it be?"
59
+
60
+ **Changing spec repo URL:**
61
+ - "Current spec_repo is `{old}`. New URL?"
62
+
63
+ ## Step 4 — Preview & gate
64
+
65
+ Show the before/after of exactly what will change:
66
+
67
+ ```
68
+ Change preview:
69
+ modules[user-service].port: 8081 → 8090
70
+ ```
71
+
72
+ > "Apply this change to `.forge/project.json`? Say **yes** to write, or tell me what to adjust."
73
+
74
+ Wait for confirmation. Do not write before the user says yes.
75
+
76
+ ## Step 5 — Write & confirm
77
+
78
+ Apply the change, preserving all other fields and formatting.
79
+ Confirm: "Updated `.forge/project.json` — {summary of what changed}."
80
+
81
+ If a module name changed, warn:
82
+ > "Heads up: `{module}` is referenced by the module repo's `.forge/module.json` and by
83
+ > `### {module}` headings in tasks.md. Update those to match, or `/forge-implement` and
84
+ > `/forge-close` will break."
85
+
86
+ ## Schema Reference
87
+
88
+ ```jsonc
89
+ {
90
+ "project": "my-project", // short slug, no spaces
91
+ "version": "1.0",
92
+ "modules": [
93
+ {
94
+ "name": "user-service", // kebab-case, matches module.json in module repos
95
+ "repo": "git@github.com:org/user-service.git",
96
+ "type": "backend", // backend | frontend | worker | gateway
97
+ "stack": ["Spring Boot 3", "Java 21"],
98
+ "port": 8081,
99
+ "description": "" // optional, one sentence
100
+ }
101
+ ],
102
+ "spec_repo": "git@github.com:org/specs.git",
103
+ "contract_format": "openapi3",
104
+ "contract_tool": "specmatic"
105
+ }
106
+ ```
107
+
108
+ ## Rules
109
+ - One question per message — never batch
110
+ - Never write before the user confirms the preview in Step 4
111
+ - `module.name` must be kebab-case and unique
112
+ - `module.name` must match the `module` field in the module repo's `.forge/module.json`
113
+ - Never silently remove a module that has tasks referencing it — warn first