@khanhspring/forge-spec 1.1.0 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanhspring/forge-spec",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Forge spec repo skills for Claude Code — brainstorm, spec, tasks, contract, and more",
5
5
  "type": "module",
6
6
  "bin": {
@@ -61,14 +61,15 @@ Before asking the user anything, research the existing codebase silently:
61
61
  Note any patterns, naming conventions, or prior decisions relevant to this idea.
62
62
  3. Scan `contracts/*/` — are there existing API contracts this feature will touch or extend?
63
63
  Note existing endpoint shapes, error formats, auth patterns.
64
- 4. Read `CLAUDE.md` — note project principles, conventions, and forbidden patterns
65
- 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.
66
67
 
67
68
  Report your findings before starting questions:
68
69
 
69
70
  > "Before we dive in, here's what I found in the codebase:
70
71
  > - [relevant existing feature or contract, or "No related features found"]
71
- > - [relevant principle from CLAUDE.md, or "No constraints found"]
72
+ > - [relevant principle or constraint from CONTEXT.md, or "No constraints found"]
72
73
  >
73
74
  > I'll use this as context. Here's my understanding of the feature: {1–2 sentence restatement}
74
75
  > Is that right?"
@@ -210,7 +211,7 @@ apply the Research Handling pattern.
210
211
  ## Step 5 — Propose approaches
211
212
 
212
213
  Propose **2–3 design approaches** with trade-offs. Base them on the researched context
213
- from Step 1 — flag if an approach conflicts with existing patterns or CLAUDE.md principles.
214
+ from Step 1 — flag if an approach conflicts with existing patterns or CONTEXT.md principles.
214
215
 
215
216
  ```
216
217
  I see 2–3 ways to approach this:
@@ -1,7 +1,7 @@
1
1
  ---
2
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'"
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
- · web-app frontend React, TypeScript :3000
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", "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)"
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. "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
+ 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
- > "Apply this change to `.forge/project.json`? Say **yes** to write, or tell me what to adjust."
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 `.forge/project.json` — {summary of what changed}."
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: `{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."
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
- - `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
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
@@ -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 — Modules
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
 
@@ -93,11 +126,11 @@ Then ask:
93
126
  > "Any more modules to add? (yes / no)"
94
127
 
95
128
  If yes, repeat from step 1 of this phase for the next module.
96
- If no, move to Phase 3.
129
+ If no, move to Phase 4.
97
130
 
98
131
  ---
99
132
 
100
- ## Phase 3 — Principles & conventions
133
+ ## Phase 4 — Principles & conventions
101
134
 
102
135
  Ask one at a time. "None" or "not yet" are valid answers — these sections can be filled
103
136
  in later with `/forge-config`.
@@ -116,7 +149,7 @@ Say 'none yet' to skip._"
116
149
 
117
150
  ---
118
151
 
119
- ## Phase 4 — Preview & gate
152
+ ## Phase 5 — Preview & gate
120
153
 
121
154
  Show a full preview of what will be written:
122
155
 
@@ -128,13 +161,20 @@ Ready to initialize. Here's what I'll create:
128
161
  modules: {n} module(s): {comma-separated names}
129
162
  spec_repo: {url or "not set"}
130
163
 
131
- CLAUDE.md
164
+ CONTEXT.md
132
165
  Description: {description}
133
- Modules: {n} listed
166
+ Actors: {n} listed
167
+ Domain glossary: {n} terms
168
+ Business goal: {one line or "skipped"}
169
+ Current state: {one line}
134
170
  Principles: {list or "none yet"}
135
171
  Conventions: {list or "none yet"}
136
172
  Out of scope: {list or "none yet"}
137
173
 
174
+ CLAUDE.md
175
+ Modules: {n} listed
176
+ Forge workflow + structure + pointer to CONTEXT.md
177
+
138
178
  features/CHANGELOG.md
139
179
  contracts/.gitkeep
140
180
  .gitignore ← append Forge entries
@@ -146,7 +186,7 @@ Wait for confirmation. Do not write anything before the user says yes.
146
186
 
147
187
  ---
148
188
 
149
- ## Phase 5 — Write files
189
+ ## Phase 6 — Write files
150
190
 
151
191
  Write `.forge/project.json`:
152
192
 
@@ -200,11 +240,55 @@ Module **with** submodules — no `port` on the module; each submodule owns its
200
240
  }
201
241
  ```
202
242
 
203
- Write `CLAUDE.md`:
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:
204
284
  ```markdown
205
285
  # {project-name}
206
286
 
207
- {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.
208
292
 
209
293
  ## Modules
210
294
  | Name | Type | Stack | Port |
@@ -226,18 +310,10 @@ Indent the submodule name with `↳` and omit port/stack from the parent row.)_
226
310
  4. `/forge-contract` — generate Specmatic OpenAPI contracts
227
311
  5. `/forge-close {slug} {module}` — mark a module's tasks done (after module repo ships)
228
312
 
229
- Utilities: `/forge-status` (feature dashboard) · `/forge-config` (edit modules/ports)
230
-
231
- ## Principles
232
- {list each as a bullet — or "None defined yet."}
233
-
234
- ## Conventions
235
- {list each as a bullet — or "None defined yet."}
236
-
237
- ## Out of Scope / Forbidden
238
- {list each as a bullet — or "None defined yet."}
313
+ Utilities: `/forge-status` (feature dashboard) · `/forge-config` (edit modules/ports/context)
239
314
 
240
315
  ## Structure
316
+ - `CONTEXT.md` — project-wide domain context (actors, glossary, principles)
241
317
  - `features/{slug}/brainstorm.md` — approved brainstorm summary
242
318
  - `features/{slug}/spec.md` — requirements, flows, API list
243
319
  - `features/{slug}/tasks.md` — per-module task breakdown with checkboxes
@@ -271,7 +347,10 @@ Run `git status` and confirm:
271
347
 
272
348
  ## Rules
273
349
  - One question per message — never ask multiple questions at once
274
- - Never write files before the user says yes in Phase 4
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
275
354
  - Never overwrite existing files
276
355
  - All written files must be complete — no unfilled placeholders
277
356
  - **Extract, don't re-ask**: if the user's answer contains information for upcoming fields
@@ -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. **CLAUDE.md** — note project principles and conventions.
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
- > - CLAUDE.md principles that apply: {list or 'none'}
62
+ > - CONTEXT.md principles that apply: {list or 'none'}
62
63
  > - Naming convention: {e.g. 'REQ-N restarts per feature'}"
63
64
 
64
65
  ---