@khanhspring/forge-module 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 +30 -0
- package/forge-contract-test/SKILL.md +60 -0
- package/forge-done/SKILL.md +87 -0
- package/forge-implement/SKILL.md +188 -0
- package/forge-init/SKILL.md +240 -0
- package/forge-tasks/SKILL.md +49 -0
- package/package.json +19 -0
package/bin/install.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
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-contract-test',
|
|
14
|
+
'forge-done',
|
|
15
|
+
'forge-implement',
|
|
16
|
+
'forge-init',
|
|
17
|
+
'forge-tasks',
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
console.log('Installing @forge-workflow/module skills...\n');
|
|
21
|
+
|
|
22
|
+
mkdirSync(SKILLS_DIR, { recursive: true });
|
|
23
|
+
|
|
24
|
+
for (const skill of SKILLS) {
|
|
25
|
+
cpSync(join(ROOT, skill), join(SKILLS_DIR, skill), { recursive: true, force: true });
|
|
26
|
+
console.log(` ✓ ${skill}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
console.log(`\nInstalled to ${SKILLS_DIR}`);
|
|
30
|
+
console.log('Restart Claude Code, then run /forge-init in your module repo.');
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "forge-contract-test"
|
|
3
|
+
description: "Outputs the specmatic test command to verify the running service against its contracts. If test output is pasted as argument, analyzes each failure with endpoint, mismatch type, and a one-line fix."
|
|
4
|
+
argument-hint: "Paste specmatic test failure output to analyze, or leave empty to get the test command"
|
|
5
|
+
compatibility: "Requires module repo with .forge/module.json; service must be running at test_base_url for live testing"
|
|
6
|
+
metadata:
|
|
7
|
+
author: "forge-workflow"
|
|
8
|
+
source: "module-skills/forge-contract-test/SKILL.md"
|
|
9
|
+
user-invocable: true
|
|
10
|
+
disable-model-invocation: true
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Forge Contract Test
|
|
14
|
+
|
|
15
|
+
Run or analyze Specmatic contract tests for this module.
|
|
16
|
+
|
|
17
|
+
## Pre-check
|
|
18
|
+
- Read `.forge/module.json` for `contract_glob` and `test_base_url`.
|
|
19
|
+
If missing, say "Run forge-init to set up this module repo first."
|
|
20
|
+
|
|
21
|
+
## If $ARGUMENTS is empty — Output the test command
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
25
|
+
Contract Tests: {module}
|
|
26
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
27
|
+
|
|
28
|
+
Make sure your server is running at {test_base_url}, then run:
|
|
29
|
+
|
|
30
|
+
specmatic test \
|
|
31
|
+
--contract "{contract_glob}" \
|
|
32
|
+
--testBaseURL {test_base_url}
|
|
33
|
+
|
|
34
|
+
Contracts under test:
|
|
35
|
+
{list files matching contract_glob}
|
|
36
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## If $ARGUMENTS contains test output — Analyze failures
|
|
40
|
+
|
|
41
|
+
For each failure, provide:
|
|
42
|
+
1. Which endpoint failed (method + path)
|
|
43
|
+
2. What the mismatch is (missing field / wrong type / wrong status code / unexpected field)
|
|
44
|
+
3. Where to fix it in the implementation (specific file/method if determinable from stack)
|
|
45
|
+
4. One-line fix suggestion
|
|
46
|
+
|
|
47
|
+
Format:
|
|
48
|
+
```
|
|
49
|
+
❌ POST /api/v1/users/register
|
|
50
|
+
Issue: Response missing required field `createdAt` (string, date-time)
|
|
51
|
+
Fix: Add `createdAt` to the RegisterResponse DTO and include it in the response
|
|
52
|
+
|
|
53
|
+
❌ GET /api/v1/users/{id}
|
|
54
|
+
Issue: Returns 200 when user not found — contract expects 404
|
|
55
|
+
Fix: Add a not-found check before returning the response
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Rule
|
|
59
|
+
Never suggest changing the contract to fix a failing test.
|
|
60
|
+
If the contract looks wrong: "Raise this in the spec repo — don't work around it here."
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "forge-done"
|
|
3
|
+
description: "Confirms all tasks for this module are complete and generates the module repo commit message. Module repo only — run /forge-close in the spec repo afterward to mark tasks done there."
|
|
4
|
+
argument-hint: "Feature slug (e.g. 'user-registration')"
|
|
5
|
+
compatibility: "Requires module repo with .forge/module.json and an initialized specs/ git submodule"
|
|
6
|
+
metadata:
|
|
7
|
+
author: "forge-workflow"
|
|
8
|
+
source: "module-skills/forge-done/SKILL.md"
|
|
9
|
+
user-invocable: true
|
|
10
|
+
disable-model-invocation: true
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Forge Done — Module Repo
|
|
14
|
+
|
|
15
|
+
Close out the implementation side of a feature: confirm all tasks are complete
|
|
16
|
+
and generate the module repo commit message.
|
|
17
|
+
|
|
18
|
+
This skill owns the module repo only. Updating task checkboxes in the spec repo
|
|
19
|
+
is handled separately by `/forge-close` in the spec repo.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Pre-check
|
|
24
|
+
|
|
25
|
+
- Read `.forge/module.json` for `module` and `spec_submodule_path`.
|
|
26
|
+
If missing, say "Run `/forge-init` to set up this module repo first."
|
|
27
|
+
- Feature slug from $ARGUMENTS. If empty, ask: "Which feature are you done with?"
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Step 1 — Read task list (read-only from submodule)
|
|
32
|
+
|
|
33
|
+
Read `{spec_submodule_path}/features/{slug}/tasks.md`.
|
|
34
|
+
Find the `### {module}` section. Extract all tasks with their checkbox state.
|
|
35
|
+
|
|
36
|
+
If `tasks.md` is missing:
|
|
37
|
+
> "No tasks file found at `specs/features/{slug}/tasks.md`.
|
|
38
|
+
> Run `/forge-tasks {slug}` in the spec repo first."
|
|
39
|
+
|
|
40
|
+
Note: the submodule is read-only — task checkboxes cannot be updated from here.
|
|
41
|
+
That is handled by `/forge-close` in the spec repo.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Step 2 — Confirm completion
|
|
46
|
+
|
|
47
|
+
Show the task list:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
51
|
+
Tasks: {module} / {feature-slug}
|
|
52
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
53
|
+
- [x] TASK-1 [api] POST /users/register endpoint
|
|
54
|
+
- [ ] TASK-2 [feat] Password hashing + validation
|
|
55
|
+
- [x] TASK-3 [test] Unit tests for UserService
|
|
56
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- All already ticked in submodule → note it and proceed.
|
|
60
|
+
- Some unticked → ask: "Are these actually finished? Say **yes** to proceed or tell me what's still in progress."
|
|
61
|
+
|
|
62
|
+
Wait for confirmation before continuing.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Step 3 — Generate commit message
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
70
|
+
Commit message
|
|
71
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
72
|
+
feat({module}): implement {feature-slug}
|
|
73
|
+
|
|
74
|
+
- TASK-1: {title}
|
|
75
|
+
- TASK-2: {title}
|
|
76
|
+
- TASK-3: {title}
|
|
77
|
+
|
|
78
|
+
Spec: specs/features/{slug}/spec.md
|
|
79
|
+
Tasks: specs/features/{slug}/tasks.md
|
|
80
|
+
Contract: specs/contracts/{module}/{slug}.yaml
|
|
81
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Then remind:
|
|
85
|
+
> "Once committed and pushed, go to the spec repo and run:
|
|
86
|
+
> `/forge-close {slug} {module}`
|
|
87
|
+
> to mark your tasks as done and check if the feature is fully complete."
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "forge-implement"
|
|
3
|
+
description: "Researches existing codebase patterns, clears ambiguities one at a time, challenges implementation concerns, then guides task-by-task implementation scoped to this module. No code written until plan is confirmed."
|
|
4
|
+
argument-hint: "Feature slug (e.g. 'user-registration')"
|
|
5
|
+
compatibility: "Requires module repo with .forge/module.json and an initialized specs/ git submodule"
|
|
6
|
+
metadata:
|
|
7
|
+
author: "forge-workflow"
|
|
8
|
+
source: "module-skills/forge-implement/SKILL.md"
|
|
9
|
+
user-invocable: true
|
|
10
|
+
disable-model-invocation: true
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Forge Implement
|
|
14
|
+
|
|
15
|
+
Understand the feature fully before writing a single line of code. Research existing
|
|
16
|
+
patterns, surface ambiguities, flag conflicts — then implement with confidence.
|
|
17
|
+
|
|
18
|
+
<HARD-GATE>
|
|
19
|
+
Do NOT write any code, create any files, or modify any existing files until you have
|
|
20
|
+
presented the Implementation Plan and the user has explicitly confirmed it.
|
|
21
|
+
</HARD-GATE>
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Pre-check
|
|
26
|
+
|
|
27
|
+
- Read `.forge/module.json` — if missing, say "Run `/forge-init` to set up this module repo first."
|
|
28
|
+
- Get `module`, `spec_submodule_path`, `test_base_url`, `contract_glob` from module.json.
|
|
29
|
+
- Feature slug from $ARGUMENTS.
|
|
30
|
+
- If empty, scan `{spec_submodule_path}/features/*/tasks.md` for `### {module}` sections,
|
|
31
|
+
list features with pending tasks, ask which to implement.
|
|
32
|
+
- Check `git submodule status` — if specs/ is out of date, say:
|
|
33
|
+
> "Your specs submodule may be out of date. Run `git submodule update --remote specs` first, or continue with the current version?"
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Step 1 — Load & Research Context
|
|
38
|
+
|
|
39
|
+
Load the feature documents silently:
|
|
40
|
+
- `{spec_submodule_path}/features/{slug}/spec.md` — requirements and flows
|
|
41
|
+
- `{spec_submodule_path}/features/{slug}/tasks.md` — task list for this module
|
|
42
|
+
|
|
43
|
+
If `tasks.md` is missing → stop: "No tasks found. Run `/forge-tasks {slug}` in the spec repo first."
|
|
44
|
+
|
|
45
|
+
**Determine which contract(s) apply to this module:**
|
|
46
|
+
- Look for an own-module contract: `{spec_submodule_path}/contracts/{module}/{slug}.yaml`.
|
|
47
|
+
- **If it exists** → this module *provides* the API. Use it as the source of truth for the
|
|
48
|
+
endpoints you implement.
|
|
49
|
+
- **If it does NOT exist** (typical for frontend/consumer modules) → scan
|
|
50
|
+
`{spec_submodule_path}/contracts/*/{slug}.yaml` for sibling contracts. These are the APIs
|
|
51
|
+
this module *consumes*. Report:
|
|
52
|
+
> "No contract for `{module}` — this module consumes APIs from: {list backend modules}.
|
|
53
|
+
> I'll use their contracts as the integration source of truth."
|
|
54
|
+
- If no contract exists anywhere for this feature → note it and continue with spec + tasks only.
|
|
55
|
+
|
|
56
|
+
Then research the existing codebase — do this before asking any questions:
|
|
57
|
+
|
|
58
|
+
1. **Read `CLAUDE.md`** — note architectural principles, conventions, and forbidden patterns.
|
|
59
|
+
2. **Find similar existing endpoints** — look for controllers/routes with similar patterns to what the contract defines. Note how they're structured.
|
|
60
|
+
3. **Find existing service/repository patterns** — how are services and data access layers organized in this codebase?
|
|
61
|
+
4. **Find existing test patterns** — how are unit and integration tests structured? What test utilities exist?
|
|
62
|
+
5. **Find existing error handling** — how does this service return errors? Does it match the `ApiError` schema (`shared/api-error.yaml`) in the contract — `code`, `message`, `traceId`, `details[]`?
|
|
63
|
+
6. **Find existing auth/middleware** — how is authentication enforced on existing endpoints?
|
|
64
|
+
|
|
65
|
+
Report findings before asking questions:
|
|
66
|
+
|
|
67
|
+
> "Before we start, here's what I found in the codebase:
|
|
68
|
+
> - Existing pattern: {e.g. 'Controllers use @RestController with @RequestMapping, services are injected via constructor'}
|
|
69
|
+
> - Test pattern: {e.g. 'Integration tests use @SpringBootTest with TestContainers'}
|
|
70
|
+
> - Error handling: {e.g. 'GlobalExceptionHandler returns ApiError with code + message + traceId — matches contract'}
|
|
71
|
+
> - Auth: {e.g. 'JwtAuthFilter applied to all /api/v1/** routes via SecurityConfig'}
|
|
72
|
+
> - Potential conflict: {any mismatch found — or 'None found'}
|
|
73
|
+
>
|
|
74
|
+
> I'll follow these patterns in the implementation."
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Step 2 — Clarifying Questions (one at a time)
|
|
79
|
+
|
|
80
|
+
Ask questions ONE at a time. Only ask about things that are genuinely ambiguous or
|
|
81
|
+
missing — do not ask about things already answered by the spec, contract, or codebase.
|
|
82
|
+
|
|
83
|
+
Areas to clarify if unclear:
|
|
84
|
+
|
|
85
|
+
- **Ambiguous acceptance criteria** — any task AC that could be implemented multiple ways
|
|
86
|
+
- **Missing dependencies** — e.g. "TASK-3 requires sending an email but I don't see an email service in the codebase — is this in scope or should it be stubbed?"
|
|
87
|
+
- **Conflicting patterns** — e.g. "The contract uses snake_case field names but all existing DTOs use camelCase — which should we follow?"
|
|
88
|
+
- **Task ordering** — if task dependencies aren't obvious from the task list
|
|
89
|
+
- **Data ownership** — if the feature touches data owned by another module, how should that be accessed?
|
|
90
|
+
|
|
91
|
+
If a question cannot be answered without research outside this conversation, use the
|
|
92
|
+
research flag pattern:
|
|
93
|
+
|
|
94
|
+
> "🔍 **Research needed:** {what needs to be found out — e.g. 'whether the payment service supports idempotency keys'}
|
|
95
|
+
> Want to (a) pause and check, (b) proceed with an assumption, or (c) flag it and move on?"
|
|
96
|
+
|
|
97
|
+
If all tasks and the contract are clear, skip this step and say so.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Step 3 — Challenge Round
|
|
102
|
+
|
|
103
|
+
Before presenting the plan, flag at least 2 implementation concerns specific to what
|
|
104
|
+
you've read. These should be real conflicts or risks, not generic warnings.
|
|
105
|
+
|
|
106
|
+
> "Before I lay out the plan, a couple of things to flag:
|
|
107
|
+
>
|
|
108
|
+
> **[Concern 1]:** {e.g. 'The contract requires `createdAt` as date-time in the response,
|
|
109
|
+
> but the existing User entity doesn't have this field — we'll need to add it or compute it.
|
|
110
|
+
> Does that sound right?'}
|
|
111
|
+
>
|
|
112
|
+
> **[Concern 2]:** {e.g. 'TASK-2 (password hashing) and TASK-1 (register endpoint) are listed
|
|
113
|
+
> independently, but TASK-1 depends on TASK-2 being done first. I'll do TASK-2 first — agreed?'}
|
|
114
|
+
>
|
|
115
|
+
> How should these be handled?"
|
|
116
|
+
|
|
117
|
+
Wait for resolution before presenting the plan.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Step 4 — Implementation Plan & Gate
|
|
122
|
+
|
|
123
|
+
Present the full plan and wait for confirmation before writing any code:
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
127
|
+
Implementation Plan: {Feature Name}
|
|
128
|
+
Module: {module}
|
|
129
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
130
|
+
|
|
131
|
+
TASKS (in order)
|
|
132
|
+
1. TASK-2 [feat] Password hashing + validation
|
|
133
|
+
→ {implementation approach}
|
|
134
|
+
2. TASK-1 [api] POST /users/register endpoint
|
|
135
|
+
→ {implementation approach, files to touch}
|
|
136
|
+
3. TASK-3 [test] Unit tests for UserService
|
|
137
|
+
→ {what will be tested}
|
|
138
|
+
|
|
139
|
+
KEY DECISIONS
|
|
140
|
+
- {pattern chosen and why, e.g. 'Following existing constructor injection pattern'}
|
|
141
|
+
- {any assumption recorded}
|
|
142
|
+
|
|
143
|
+
FILES TO TOUCH
|
|
144
|
+
- {file path} — {what changes}
|
|
145
|
+
- {file path} — {what changes}
|
|
146
|
+
|
|
147
|
+
CONTRACT ({provide | consume})
|
|
148
|
+
{METHOD} {path} — {key fields to implement, or to send/expect when consuming}
|
|
149
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
End with:
|
|
153
|
+
> "Does this plan look right? Say **yes** to start, or tell me what to change."
|
|
154
|
+
|
|
155
|
+
Do NOT write any code until the user confirms.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Step 5 — Implement Task by Task
|
|
160
|
+
|
|
161
|
+
Work through tasks in the agreed order. For each task:
|
|
162
|
+
|
|
163
|
+
- State which task you're starting: "Starting TASK-2: {title}"
|
|
164
|
+
- Use the contract YAML for exact field names, types, and response shapes
|
|
165
|
+
- Follow the patterns found in Step 1 — no new patterns unless discussed
|
|
166
|
+
- Write tests alongside the implementation, not after
|
|
167
|
+
- When a task is done, confirm: "TASK-2 done. Moving to TASK-1 — ready?"
|
|
168
|
+
|
|
169
|
+
If a new ambiguity surfaces mid-implementation:
|
|
170
|
+
> "Unexpected: {what came up}. I'd suggest {option A} or {option B}. Which do you prefer?"
|
|
171
|
+
Wait for the answer before continuing.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Rules
|
|
176
|
+
- Contract is the source of truth for API shape — never change it to fix a failing test
|
|
177
|
+
- When **providing** an API: match the contract's request/response exactly
|
|
178
|
+
- When **consuming** an API (frontend/client): send requests and parse responses exactly as the
|
|
179
|
+
consumed contract defines — treat its shapes as fixed, code defensively against its error responses
|
|
180
|
+
- If the contract looks wrong: "This looks like a contract issue — raise a PR in the spec repo"
|
|
181
|
+
- Only implement tasks under `### {module}` in tasks.md — flag any cross-module work
|
|
182
|
+
- Follow existing codebase patterns found in Step 1 — consistency over personal preference
|
|
183
|
+
- No code before the user confirms the plan in Step 4
|
|
184
|
+
|
|
185
|
+
## Parallel FE+BE Flow (mention when relevant)
|
|
186
|
+
If a consumer module needs the API before the provider has built it:
|
|
187
|
+
> "The provider's contract at `specs/contracts/{backend-module}/{slug}.yaml` fully defines the
|
|
188
|
+
> API — you can build and test against it (e.g. a stub server) before the backend is ready."
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "forge-init"
|
|
3
|
+
description: "One-time initialization for a Forge module repo (backend or frontend). Researches existing repo state, then walks through setup conversationally one question at a time before writing any files."
|
|
4
|
+
argument-hint: "Optional: module name to skip the first prompt"
|
|
5
|
+
compatibility: "Run once in a module repo before any other forge skills. Safe to re-run — never overwrites existing files."
|
|
6
|
+
when_to_use: >
|
|
7
|
+
ALWAYS activate when any of the following occur:
|
|
8
|
+
- User says init, initialize, setup, set up, bootstrap, configure + repo/forge/project
|
|
9
|
+
- User says "set this up", "get this started", "prepare this repo"
|
|
10
|
+
- No .forge/module.json exists AND user wants to start implementing specs
|
|
11
|
+
- User says "this is a new module repo" (or "service repo" / "code repo") or "add forge to this project"
|
|
12
|
+
Do NOT activate if .forge/module.json already exists — repo is already initialized.
|
|
13
|
+
metadata:
|
|
14
|
+
author: "forge-workflow"
|
|
15
|
+
source: "module-skills/forge-init/SKILL.md"
|
|
16
|
+
user-invocable: true
|
|
17
|
+
disable-model-invocation: false
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# Forge Init — Module Repo
|
|
21
|
+
|
|
22
|
+
Initialize this repo as a Forge module repo (one module — backend or frontend).
|
|
23
|
+
Research what's already in the codebase first, then ask one question at a time —
|
|
24
|
+
pre-filling anything already detectable. Write all files in one go after confirmation.
|
|
25
|
+
|
|
26
|
+
## Pre-check
|
|
27
|
+
If `.forge/module.json` already exists → say "Module repo already initialized." and stop.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Step 1 — Research existing repo state
|
|
32
|
+
|
|
33
|
+
Before asking anything, silently scan the repo and note:
|
|
34
|
+
|
|
35
|
+
1. **Stack detection** — does `pom.xml`, `build.gradle`, `package.json`, `go.mod`, `requirements.txt`, or similar exist? What versions are declared?
|
|
36
|
+
2. **Port detection** — is a port configured in `application.yml`, `application.properties`, `.env`, `.env.example`, or `docker-compose.yml`?
|
|
37
|
+
3. **Submodule** — does `specs/` already exist as a directory or submodule?
|
|
38
|
+
4. **CI** — does `.github/workflows/` already exist? Any contract test workflow present?
|
|
39
|
+
5. **Existing CLAUDE.md** — already has project context written?
|
|
40
|
+
|
|
41
|
+
Report findings before asking anything:
|
|
42
|
+
|
|
43
|
+
> "Here's what I found in this repo:
|
|
44
|
+
> - Stack: {detected stack — or 'not detected'}
|
|
45
|
+
> - Port: {detected port — or 'not found in config'}
|
|
46
|
+
> - specs/ submodule: {exists / not present}
|
|
47
|
+
> - GitHub Actions: {exists / not present}
|
|
48
|
+
>
|
|
49
|
+
> I'll use these as defaults — just confirm or correct as we go."
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Step 2 — Questions (one at a time)
|
|
54
|
+
|
|
55
|
+
Ask one question per message. Wait for the answer before asking the next.
|
|
56
|
+
Where research already gives a confident answer, present it as a default to confirm
|
|
57
|
+
rather than asking from scratch.
|
|
58
|
+
|
|
59
|
+
**Q1 — Module name**
|
|
60
|
+
> "What's the module name for this repo?
|
|
61
|
+
> _(Must exactly match a `name` entry in the spec repo's `.forge/project.json`)_"
|
|
62
|
+
|
|
63
|
+
Do not suggest a default — module names must be exact matches. Warn clearly:
|
|
64
|
+
> "This name must match exactly. A mismatch will break `/forge-implement` and `/forge-done`."
|
|
65
|
+
|
|
66
|
+
**Q2 — Module description**
|
|
67
|
+
> "What does this module do? (one sentence)"
|
|
68
|
+
|
|
69
|
+
**Q3 — Spec repo URL**
|
|
70
|
+
|
|
71
|
+
If `specs/` already exists:
|
|
72
|
+
> "I see a `specs/` directory already — is that the spec repo submodule? (yes/no)
|
|
73
|
+
> If yes, what's the remote URL? (run `git remote -v` in `specs/` if unsure)"
|
|
74
|
+
|
|
75
|
+
If not:
|
|
76
|
+
> "What's the spec repo URL? (it will be added as a git submodule at `specs/`)"
|
|
77
|
+
|
|
78
|
+
**Q4 — Port**
|
|
79
|
+
|
|
80
|
+
If port was detected in Step 1:
|
|
81
|
+
> "I found port `{port}` in your config — is that the right local dev port? (yes / enter different port)"
|
|
82
|
+
|
|
83
|
+
If not detected:
|
|
84
|
+
> "What port does this module run on locally?"
|
|
85
|
+
|
|
86
|
+
**Q5 — Tech stack**
|
|
87
|
+
|
|
88
|
+
If stack was detected in Step 1:
|
|
89
|
+
> "Looks like this is a `{detected stack}` module — is that right? Anything to add?"
|
|
90
|
+
|
|
91
|
+
If not detected:
|
|
92
|
+
> "What's the tech stack? (e.g. 'Spring Boot 3, Java 21' or 'React, TypeScript')"
|
|
93
|
+
|
|
94
|
+
**Q6 — Principles**
|
|
95
|
+
> "What are the key architectural principles for this module?
|
|
96
|
+
> _(e.g. 'stateless', 'no business logic in controllers', 'repository pattern for DB access')
|
|
97
|
+
> Say 'none yet' to skip._"
|
|
98
|
+
|
|
99
|
+
**Q7 — Conventions**
|
|
100
|
+
> "Any coding conventions the team follows in this repo?
|
|
101
|
+
> _(e.g. 'constructor injection only', 'all public methods must have unit tests', 'no magic strings')
|
|
102
|
+
> Say 'none yet' to skip._"
|
|
103
|
+
|
|
104
|
+
**Q8 — Never**
|
|
105
|
+
> "Anything developers should never do in this codebase?
|
|
106
|
+
> _(e.g. 'no direct DB calls from the API layer', 'never change a contract to fix a failing test')
|
|
107
|
+
> Say 'none yet' to skip._"
|
|
108
|
+
|
|
109
|
+
**Q9 — GitHub Actions CI**
|
|
110
|
+
|
|
111
|
+
If `.github/workflows/` already exists with a contract test:
|
|
112
|
+
> "I see a CI workflow already exists — skip adding another? (yes to skip)"
|
|
113
|
+
|
|
114
|
+
If not present:
|
|
115
|
+
> "Add a GitHub Actions contract test workflow? (yes/no)"
|
|
116
|
+
> _(Backend modules that serve an API benefit most; a frontend that only consumes can skip.)_
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Step 3 — Preview & gate
|
|
121
|
+
|
|
122
|
+
Show a full preview of everything that will be created or run:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
Ready to initialize. Here's what I'll do:
|
|
126
|
+
|
|
127
|
+
{if specs/ not present}
|
|
128
|
+
git submodule add {spec-repo-url} specs
|
|
129
|
+
git submodule update --init --recursive
|
|
130
|
+
|
|
131
|
+
.forge/module.json
|
|
132
|
+
module: {module-name}
|
|
133
|
+
test_base_url: http://localhost:{port}
|
|
134
|
+
contract_glob: specs/contracts/{module-name}/*.yaml
|
|
135
|
+
|
|
136
|
+
CLAUDE.md
|
|
137
|
+
Module: {module-name}
|
|
138
|
+
Description: {description}
|
|
139
|
+
Stack: {stack} Port: {port}
|
|
140
|
+
Principles: {list or "none yet"}
|
|
141
|
+
Conventions: {list or "none yet"}
|
|
142
|
+
Never: {list or "none yet"}
|
|
143
|
+
|
|
144
|
+
{if yes} .github/workflows/contract-test.yml
|
|
145
|
+
.gitignore ← append Forge entries
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
End with:
|
|
149
|
+
> "Does this look right? Say **yes** to initialize, or tell me what to change."
|
|
150
|
+
|
|
151
|
+
Wait for confirmation. Do not write files or run git commands before the user says yes.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Step 4 — Write files
|
|
156
|
+
|
|
157
|
+
Run (if specs/ not already present):
|
|
158
|
+
```bash
|
|
159
|
+
git submodule add {spec-repo-url} specs
|
|
160
|
+
git submodule update --init --recursive
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Write `.forge/module.json`:
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"module": "{module-name}",
|
|
167
|
+
"spec_submodule_path": "specs",
|
|
168
|
+
"specmatic_version": "2.x",
|
|
169
|
+
"test_base_url": "http://localhost:{port}",
|
|
170
|
+
"contract_glob": "specs/contracts/{module-name}/*.yaml"
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Write `CLAUDE.md`:
|
|
175
|
+
```markdown
|
|
176
|
+
# {module-name}
|
|
177
|
+
|
|
178
|
+
{description}
|
|
179
|
+
|
|
180
|
+
**Stack:** {stack}
|
|
181
|
+
**Port:** {port}
|
|
182
|
+
|
|
183
|
+
## Forge Workflow
|
|
184
|
+
1. `/forge-tasks` — see all pending tasks for this module
|
|
185
|
+
2. `/forge-implement` — implement a feature task by task
|
|
186
|
+
3. `/forge-contract-test` — run Specmatic contract tests
|
|
187
|
+
4. `/forge-done` — confirm tasks done + generate commit message
|
|
188
|
+
5. (then in the spec repo) `/forge-close {slug} {module}` — mark tasks done there
|
|
189
|
+
|
|
190
|
+
## Spec repo
|
|
191
|
+
Linked via git submodule at `specs/`.
|
|
192
|
+
Run `git submodule update --remote specs` before starting a new feature,
|
|
193
|
+
and again after `/forge-close` is run in the spec repo to sync task status.
|
|
194
|
+
|
|
195
|
+
## Principles
|
|
196
|
+
{list each as a bullet — or "None defined yet."}
|
|
197
|
+
|
|
198
|
+
## Conventions
|
|
199
|
+
{list each as a bullet — or "None defined yet."}
|
|
200
|
+
|
|
201
|
+
## Never
|
|
202
|
+
{list each as a bullet — or "None defined yet."}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
If GitHub Actions was requested, write `.github/workflows/contract-test.yml`:
|
|
206
|
+
```yaml
|
|
207
|
+
name: Contract Tests
|
|
208
|
+
on: [push, pull_request]
|
|
209
|
+
jobs:
|
|
210
|
+
contract-test:
|
|
211
|
+
runs-on: ubuntu-latest
|
|
212
|
+
steps:
|
|
213
|
+
- uses: actions/checkout@v4
|
|
214
|
+
with:
|
|
215
|
+
submodules: recursive
|
|
216
|
+
- name: Run contract tests
|
|
217
|
+
run: |
|
|
218
|
+
specmatic test \
|
|
219
|
+
--contract "specs/contracts/{module-name}/*.yaml" \
|
|
220
|
+
--testBaseURL ${{ env.SERVICE_URL }}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Append to `.gitignore` if not present:
|
|
224
|
+
```
|
|
225
|
+
# Forge
|
|
226
|
+
.forge/secrets
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Run `git status` and confirm:
|
|
230
|
+
> "Module repo initialized. Run `/forge-tasks` to see what needs to be built."
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Rules
|
|
235
|
+
- One question per message — never ask multiple questions at once
|
|
236
|
+
- Never write files or run git commands before the user says yes in Step 3
|
|
237
|
+
- Never overwrite existing files
|
|
238
|
+
- All written files must be complete — no unfilled placeholders
|
|
239
|
+
- `module` in module.json must exactly match the name in the spec repo's project.json
|
|
240
|
+
- If the user provides multiple answers in one message, accept them gracefully and move forward
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "forge-tasks"
|
|
3
|
+
description: "Lists all tasks assigned to this module across every feature, with completion status, by scanning the spec submodule. Module repo task dashboard."
|
|
4
|
+
argument-hint: ""
|
|
5
|
+
compatibility: "Requires module repo with .forge/module.json and an initialized specs/ git submodule"
|
|
6
|
+
metadata:
|
|
7
|
+
author: "forge-workflow"
|
|
8
|
+
source: "module-skills/forge-tasks/SKILL.md"
|
|
9
|
+
user-invocable: true
|
|
10
|
+
disable-model-invocation: true
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Forge Tasks — Module Repo
|
|
14
|
+
|
|
15
|
+
Show all tasks assigned to this module across all features.
|
|
16
|
+
|
|
17
|
+
## Pre-check
|
|
18
|
+
- Read `.forge/module.json` for `module` and `spec_submodule_path`.
|
|
19
|
+
If missing: "Run `/forge-init` to set up this module repo first."
|
|
20
|
+
- If `specs/` is not initialized: suggest `git submodule update --init --recursive`
|
|
21
|
+
- Optionally suggest `git submodule update --remote specs` to get the latest task status.
|
|
22
|
+
|
|
23
|
+
## Steps
|
|
24
|
+
|
|
25
|
+
Scan `{spec_submodule_path}/features/*/tasks.md` → find `### {module}` sections → extract tasks
|
|
26
|
+
with their checkbox state and the parent feature's `Status`.
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
30
|
+
Tasks for: {module}
|
|
31
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
32
|
+
|
|
33
|
+
Feature: user-registration [Open]
|
|
34
|
+
- [ ] TASK-1 [api] POST /users/register endpoint
|
|
35
|
+
- [ ] TASK-2 [feat] Password hashing + validation
|
|
36
|
+
- [x] TASK-3 [test] Unit tests for UserService
|
|
37
|
+
|
|
38
|
+
Feature: user-profile [Open]
|
|
39
|
+
- [ ] TASK-5 [api] GET /users/{id} endpoint
|
|
40
|
+
|
|
41
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
42
|
+
2 features · 4 remaining · 1 done
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
If no tasks reference this module across any feature:
|
|
46
|
+
> "No tasks found for `{module}`. Either no feature targets this module yet, or the specs
|
|
47
|
+
> submodule is out of date — try `git submodule update --remote specs`."
|
|
48
|
+
|
|
49
|
+
After showing: "Tell me which feature to implement, or run `/forge-implement {slug}`."
|
package/package.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@khanhspring/forge-module",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Forge module repo skills for Claude Code — implement, contract-test, done, and more",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"forge-module": "bin/install.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"forge-contract-test",
|
|
12
|
+
"forge-done",
|
|
13
|
+
"forge-implement",
|
|
14
|
+
"forge-init",
|
|
15
|
+
"forge-tasks"
|
|
16
|
+
],
|
|
17
|
+
"keywords": ["claude-code", "skills", "ai", "workflow", "microservices"],
|
|
18
|
+
"license": "MIT"
|
|
19
|
+
}
|