forgecraft-mcp 1.2.0 → 1.3.2
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/README.md +525 -525
- package/dist/cli/help.js +44 -44
- package/dist/registry/renderer-skeletons.js +92 -92
- package/dist/shared/gs-score-logger.js +6 -6
- package/dist/tools/add-module.js +123 -123
- package/dist/tools/advice-registry.js +18 -18
- package/dist/tools/check-cascade-report.js +64 -64
- package/dist/tools/configure-mcp.d.ts +3 -0
- package/dist/tools/configure-mcp.d.ts.map +1 -1
- package/dist/tools/configure-mcp.js +10 -0
- package/dist/tools/configure-mcp.js.map +1 -1
- package/dist/tools/forgecraft-dispatch.d.ts.map +1 -1
- package/dist/tools/forgecraft-dispatch.js +3 -0
- package/dist/tools/forgecraft-dispatch.js.map +1 -1
- package/dist/tools/forgecraft-schema-params.d.ts +9 -0
- package/dist/tools/forgecraft-schema-params.d.ts.map +1 -1
- package/dist/tools/forgecraft-schema-params.js +21 -0
- package/dist/tools/forgecraft-schema-params.js.map +1 -1
- package/dist/tools/forgecraft-schema.d.ts +9 -0
- package/dist/tools/forgecraft-schema.d.ts.map +1 -1
- package/dist/tools/refresh-output.js +14 -14
- package/dist/tools/scaffold-spec-stubs.js +115 -115
- package/dist/tools/scaffold-templates.js +62 -62
- package/dist/tools/setup-artifact-writers.d.ts +30 -0
- package/dist/tools/setup-artifact-writers.d.ts.map +1 -1
- package/dist/tools/setup-artifact-writers.js +120 -8
- package/dist/tools/setup-artifact-writers.js.map +1 -1
- package/dist/tools/setup-phase1.d.ts +3 -0
- package/dist/tools/setup-phase1.d.ts.map +1 -1
- package/dist/tools/setup-phase1.js +79 -35
- package/dist/tools/setup-phase1.js.map +1 -1
- package/dist/tools/setup-phase2.d.ts +2 -0
- package/dist/tools/setup-phase2.d.ts.map +1 -1
- package/dist/tools/setup-phase2.js +10 -1
- package/dist/tools/setup-phase2.js.map +1 -1
- package/dist/tools/setup-project.d.ts +18 -0
- package/dist/tools/setup-project.d.ts.map +1 -1
- package/dist/tools/setup-project.js +77 -1
- package/dist/tools/setup-project.js.map +1 -1
- package/dist/tools/spec-parser-tags.d.ts +9 -0
- package/dist/tools/spec-parser-tags.d.ts.map +1 -1
- package/dist/tools/spec-parser-tags.js +92 -0
- package/dist/tools/spec-parser-tags.js.map +1 -1
- package/package.json +89 -86
- package/templates/analytics/instructions.yaml +37 -37
- package/templates/analytics/mcp-servers.yaml +11 -11
- package/templates/analytics/structure.yaml +25 -25
- package/templates/api/instructions.yaml +231 -231
- package/templates/api/mcp-servers.yaml +22 -13
- package/templates/api/nfr.yaml +23 -23
- package/templates/api/review.yaml +103 -103
- package/templates/api/structure.yaml +34 -34
- package/templates/api/verification.yaml +132 -132
- package/templates/cli/instructions.yaml +31 -31
- package/templates/cli/mcp-servers.yaml +11 -11
- package/templates/cli/review.yaml +53 -53
- package/templates/cli/structure.yaml +16 -16
- package/templates/data-lineage/instructions.yaml +28 -28
- package/templates/data-lineage/mcp-servers.yaml +22 -22
- package/templates/data-pipeline/instructions.yaml +84 -84
- package/templates/data-pipeline/mcp-servers.yaml +13 -13
- package/templates/data-pipeline/nfr.yaml +39 -39
- package/templates/data-pipeline/structure.yaml +23 -23
- package/templates/fintech/hooks.yaml +55 -55
- package/templates/fintech/instructions.yaml +112 -112
- package/templates/fintech/mcp-servers.yaml +13 -13
- package/templates/fintech/nfr.yaml +46 -46
- package/templates/fintech/playbook.yaml +210 -210
- package/templates/fintech/verification.yaml +239 -239
- package/templates/game/instructions.yaml +289 -289
- package/templates/game/mcp-servers.yaml +38 -38
- package/templates/game/nfr.yaml +64 -64
- package/templates/game/playbook.yaml +214 -214
- package/templates/game/review.yaml +97 -97
- package/templates/game/structure.yaml +67 -67
- package/templates/game/verification.yaml +174 -174
- package/templates/healthcare/instructions.yaml +42 -42
- package/templates/healthcare/mcp-servers.yaml +13 -13
- package/templates/healthcare/nfr.yaml +47 -47
- package/templates/hipaa/instructions.yaml +41 -41
- package/templates/hipaa/mcp-servers.yaml +13 -13
- package/templates/infra/instructions.yaml +104 -104
- package/templates/infra/mcp-servers.yaml +20 -20
- package/templates/infra/nfr.yaml +46 -46
- package/templates/infra/review.yaml +65 -65
- package/templates/infra/structure.yaml +25 -25
- package/templates/library/instructions.yaml +36 -36
- package/templates/library/mcp-servers.yaml +20 -20
- package/templates/library/review.yaml +56 -56
- package/templates/library/structure.yaml +19 -19
- package/templates/medallion-architecture/instructions.yaml +41 -41
- package/templates/medallion-architecture/mcp-servers.yaml +22 -22
- package/templates/ml/instructions.yaml +85 -85
- package/templates/ml/mcp-servers.yaml +11 -11
- package/templates/ml/nfr.yaml +39 -39
- package/templates/ml/structure.yaml +25 -25
- package/templates/ml/verification.yaml +156 -156
- package/templates/mobile/instructions.yaml +44 -44
- package/templates/mobile/mcp-servers.yaml +11 -11
- package/templates/mobile/nfr.yaml +49 -49
- package/templates/mobile/structure.yaml +27 -27
- package/templates/mobile/verification.yaml +121 -121
- package/templates/observability-xray/instructions.yaml +40 -40
- package/templates/observability-xray/mcp-servers.yaml +15 -15
- package/templates/realtime/instructions.yaml +42 -42
- package/templates/realtime/mcp-servers.yaml +13 -13
- package/templates/soc2/instructions.yaml +41 -41
- package/templates/soc2/mcp-servers.yaml +24 -24
- package/templates/social/instructions.yaml +43 -43
- package/templates/social/mcp-servers.yaml +24 -24
- package/templates/state-machine/instructions.yaml +42 -42
- package/templates/state-machine/mcp-servers.yaml +11 -11
- package/templates/tools-registry.yaml +164 -164
- package/templates/universal/hooks.yaml +531 -531
- package/templates/universal/instructions.yaml +1692 -1692
- package/templates/universal/mcp-servers.yaml +50 -50
- package/templates/universal/nfr.yaml +197 -197
- package/templates/universal/reference.yaml +326 -326
- package/templates/universal/review.yaml +204 -204
- package/templates/universal/skills.yaml +262 -262
- package/templates/universal/structure.yaml +67 -67
- package/templates/universal/verification.yaml +416 -416
- package/templates/web-react/hooks.yaml +44 -44
- package/templates/web-react/instructions.yaml +207 -207
- package/templates/web-react/mcp-servers.yaml +20 -20
- package/templates/web-react/nfr.yaml +27 -27
- package/templates/web-react/review.yaml +94 -94
- package/templates/web-react/structure.yaml +46 -46
- package/templates/web-react/verification.yaml +126 -126
- package/templates/web-static/instructions.yaml +115 -115
- package/templates/web-static/mcp-servers.yaml +20 -20
- package/templates/web3/instructions.yaml +44 -44
- package/templates/web3/mcp-servers.yaml +11 -11
- package/templates/web3/verification.yaml +159 -159
- package/templates/zero-trust/instructions.yaml +41 -41
- package/templates/zero-trust/mcp-servers.yaml +15 -15
|
@@ -7,20 +7,20 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
9
9
|
import { dirname } from "node:path";
|
|
10
|
-
export const USE_CASES_STUB = `<!-- UNFILLED: Use Cases -->
|
|
11
|
-
# Use Cases
|
|
12
|
-
|
|
13
|
-
## UC-01: [Name]
|
|
14
|
-
**Actor**: <!-- FILL: who? -->
|
|
15
|
-
**Precondition**: <!-- FILL: what must be true before? -->
|
|
16
|
-
**Steps**: <!-- FILL: numbered steps -->
|
|
17
|
-
**Success**: <!-- FILL: what changed? -->
|
|
18
|
-
|
|
19
|
-
## UC-02: [Name]
|
|
20
|
-
<!-- FILL -->
|
|
21
|
-
|
|
22
|
-
## UC-03: [Name]
|
|
23
|
-
<!-- FILL -->
|
|
10
|
+
export const USE_CASES_STUB = `<!-- UNFILLED: Use Cases -->
|
|
11
|
+
# Use Cases
|
|
12
|
+
|
|
13
|
+
## UC-01: [Name]
|
|
14
|
+
**Actor**: <!-- FILL: who? -->
|
|
15
|
+
**Precondition**: <!-- FILL: what must be true before? -->
|
|
16
|
+
**Steps**: <!-- FILL: numbered steps -->
|
|
17
|
+
**Success**: <!-- FILL: what changed? -->
|
|
18
|
+
|
|
19
|
+
## UC-02: [Name]
|
|
20
|
+
<!-- FILL -->
|
|
21
|
+
|
|
22
|
+
## UC-03: [Name]
|
|
23
|
+
<!-- FILL -->
|
|
24
24
|
`;
|
|
25
25
|
/**
|
|
26
26
|
* Build the UNFILLED stub content for docs/diagrams/c4-context.md.
|
|
@@ -29,16 +29,16 @@ export const USE_CASES_STUB = `<!-- UNFILLED: Use Cases -->
|
|
|
29
29
|
* @returns Stub content with UNFILLED markers
|
|
30
30
|
*/
|
|
31
31
|
export function buildC4ContextStub(projectName) {
|
|
32
|
-
return `<!-- UNFILLED: C4 Context Diagram -->
|
|
33
|
-
<!-- Run \`forgecraft generate_diagram\` to auto-generate from your spec -->
|
|
34
|
-
# System Context Diagram
|
|
35
|
-
\`\`\`mermaid
|
|
36
|
-
C4Context
|
|
37
|
-
title System Context: ${projectName}
|
|
38
|
-
Person(user, "User", "<!-- FILL: Who uses the system? -->")
|
|
39
|
-
System(system, "${projectName}", "<!-- FILL: What does the system do in one sentence? -->")
|
|
40
|
-
Rel(user, system, "<!-- FILL: Primary interaction -->")
|
|
41
|
-
\`\`\`
|
|
32
|
+
return `<!-- UNFILLED: C4 Context Diagram -->
|
|
33
|
+
<!-- Run \`forgecraft generate_diagram\` to auto-generate from your spec -->
|
|
34
|
+
# System Context Diagram
|
|
35
|
+
\`\`\`mermaid
|
|
36
|
+
C4Context
|
|
37
|
+
title System Context: ${projectName}
|
|
38
|
+
Person(user, "User", "<!-- FILL: Who uses the system? -->")
|
|
39
|
+
System(system, "${projectName}", "<!-- FILL: What does the system do in one sentence? -->")
|
|
40
|
+
Rel(user, system, "<!-- FILL: Primary interaction -->")
|
|
41
|
+
\`\`\`
|
|
42
42
|
`;
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
@@ -51,32 +51,32 @@ C4Context
|
|
|
51
51
|
* @returns Stub content with UNFILLED markers and structural Mermaid syntax
|
|
52
52
|
*/
|
|
53
53
|
export function buildSequenceDiagramStub(feature) {
|
|
54
|
-
return `<!-- UNFILLED: Sequence Diagram — ${feature} -->
|
|
55
|
-
<!-- Replace participant labels and messages with real actors and contracts -->
|
|
56
|
-
# Sequence Diagram: ${feature}
|
|
57
|
-
|
|
58
|
-
\`\`\`mermaid
|
|
59
|
-
sequenceDiagram
|
|
60
|
-
participant Client as <!-- FILL: initiating actor, e.g. Browser / CLI / Service -->
|
|
61
|
-
participant API as <!-- FILL: entry-point service, e.g. API Gateway -->
|
|
62
|
-
participant Service as <!-- FILL: domain service, e.g. AuthService -->
|
|
63
|
-
participant Store as <!-- FILL: persistence layer, e.g. Database -->
|
|
64
|
-
|
|
65
|
-
Note over Client,Store: <!-- FILL: describe the primary flow in one sentence -->
|
|
66
|
-
|
|
67
|
-
Client->>API: <!-- FILL: request, e.g. POST /login {credentials} -->
|
|
68
|
-
API->>Service: <!-- FILL: delegate, e.g. authenticate(credentials) -->
|
|
69
|
-
Service->>Store: <!-- FILL: query, e.g. findUserByEmail(email) -->
|
|
70
|
-
Store-->>Service: <!-- FILL: result, e.g. User | null -->
|
|
71
|
-
|
|
72
|
-
alt <!-- FILL: failure case, e.g. User not found or wrong password -->
|
|
73
|
-
Service-->>API: <!-- FILL: error response, e.g. AuthError -->
|
|
74
|
-
API-->>Client: <!-- FILL: HTTP error, e.g. 401 Unauthorized -->
|
|
75
|
-
else <!-- FILL: success case -->
|
|
76
|
-
Service-->>API: <!-- FILL: success result, e.g. JWT token -->
|
|
77
|
-
API-->>Client: <!-- FILL: HTTP success, e.g. 200 OK {token} -->
|
|
78
|
-
end
|
|
79
|
-
\`\`\`
|
|
54
|
+
return `<!-- UNFILLED: Sequence Diagram — ${feature} -->
|
|
55
|
+
<!-- Replace participant labels and messages with real actors and contracts -->
|
|
56
|
+
# Sequence Diagram: ${feature}
|
|
57
|
+
|
|
58
|
+
\`\`\`mermaid
|
|
59
|
+
sequenceDiagram
|
|
60
|
+
participant Client as <!-- FILL: initiating actor, e.g. Browser / CLI / Service -->
|
|
61
|
+
participant API as <!-- FILL: entry-point service, e.g. API Gateway -->
|
|
62
|
+
participant Service as <!-- FILL: domain service, e.g. AuthService -->
|
|
63
|
+
participant Store as <!-- FILL: persistence layer, e.g. Database -->
|
|
64
|
+
|
|
65
|
+
Note over Client,Store: <!-- FILL: describe the primary flow in one sentence -->
|
|
66
|
+
|
|
67
|
+
Client->>API: <!-- FILL: request, e.g. POST /login {credentials} -->
|
|
68
|
+
API->>Service: <!-- FILL: delegate, e.g. authenticate(credentials) -->
|
|
69
|
+
Service->>Store: <!-- FILL: query, e.g. findUserByEmail(email) -->
|
|
70
|
+
Store-->>Service: <!-- FILL: result, e.g. User | null -->
|
|
71
|
+
|
|
72
|
+
alt <!-- FILL: failure case, e.g. User not found or wrong password -->
|
|
73
|
+
Service-->>API: <!-- FILL: error response, e.g. AuthError -->
|
|
74
|
+
API-->>Client: <!-- FILL: HTTP error, e.g. 401 Unauthorized -->
|
|
75
|
+
else <!-- FILL: success case -->
|
|
76
|
+
Service-->>API: <!-- FILL: success result, e.g. JWT token -->
|
|
77
|
+
API-->>Client: <!-- FILL: HTTP success, e.g. 200 OK {token} -->
|
|
78
|
+
end
|
|
79
|
+
\`\`\`
|
|
80
80
|
`;
|
|
81
81
|
}
|
|
82
82
|
/**
|
|
@@ -90,30 +90,30 @@ sequenceDiagram
|
|
|
90
90
|
* @returns Stub content with UNFILLED markers and structural Mermaid syntax
|
|
91
91
|
*/
|
|
92
92
|
export function buildStateMachineDiagramStub(entityName) {
|
|
93
|
-
return `<!-- UNFILLED: State Machine — ${entityName} -->
|
|
94
|
-
<!-- Replace state names (Draft, Pending, Active, etc.) and transition labels -->
|
|
95
|
-
<!-- with the actual lifecycle states of your domain entity. -->
|
|
96
|
-
# State Machine: ${entityName}
|
|
97
|
-
|
|
98
|
-
\`\`\`mermaid
|
|
99
|
-
stateDiagram-v2
|
|
100
|
-
[*] --> Draft
|
|
101
|
-
|
|
102
|
-
Draft --> Pending: submit()
|
|
103
|
-
Pending --> Active: approve()
|
|
104
|
-
Pending --> Rejected: reject()
|
|
105
|
-
Active --> Completed: complete()
|
|
106
|
-
Active --> Cancelled: cancel()
|
|
107
|
-
|
|
108
|
-
Completed --> [*]
|
|
109
|
-
Rejected --> [*]
|
|
110
|
-
Cancelled --> [*]
|
|
111
|
-
|
|
112
|
-
note right of Active
|
|
113
|
-
FILL: add invariant or constraint
|
|
114
|
-
e.g. "requires valid payment method"
|
|
115
|
-
end note
|
|
116
|
-
\`\`\`
|
|
93
|
+
return `<!-- UNFILLED: State Machine — ${entityName} -->
|
|
94
|
+
<!-- Replace state names (Draft, Pending, Active, etc.) and transition labels -->
|
|
95
|
+
<!-- with the actual lifecycle states of your domain entity. -->
|
|
96
|
+
# State Machine: ${entityName}
|
|
97
|
+
|
|
98
|
+
\`\`\`mermaid
|
|
99
|
+
stateDiagram-v2
|
|
100
|
+
[*] --> Draft
|
|
101
|
+
|
|
102
|
+
Draft --> Pending: submit()
|
|
103
|
+
Pending --> Active: approve()
|
|
104
|
+
Pending --> Rejected: reject()
|
|
105
|
+
Active --> Completed: complete()
|
|
106
|
+
Active --> Cancelled: cancel()
|
|
107
|
+
|
|
108
|
+
Completed --> [*]
|
|
109
|
+
Rejected --> [*]
|
|
110
|
+
Cancelled --> [*]
|
|
111
|
+
|
|
112
|
+
note right of Active
|
|
113
|
+
FILL: add invariant or constraint
|
|
114
|
+
e.g. "requires valid payment method"
|
|
115
|
+
end note
|
|
116
|
+
\`\`\`
|
|
117
117
|
`;
|
|
118
118
|
}
|
|
119
119
|
/**
|
|
@@ -126,29 +126,29 @@ stateDiagram-v2
|
|
|
126
126
|
* @returns Stub content with UNFILLED markers and structural Mermaid syntax
|
|
127
127
|
*/
|
|
128
128
|
export function buildFlowDiagramStub(ucName) {
|
|
129
|
-
return `<!-- UNFILLED: Flow Diagram — ${ucName} -->
|
|
130
|
-
<!-- Replace node labels and edge conditions with real user journey steps -->
|
|
131
|
-
# Flow: ${ucName}
|
|
132
|
-
|
|
133
|
-
\`\`\`mermaid
|
|
134
|
-
flowchart TD
|
|
135
|
-
Start([<!-- FILL: trigger, e.g. User opens registration page -->])
|
|
136
|
-
|
|
137
|
-
Start --> Input[<!-- FILL: first action, e.g. Fill in name, email, password -->]
|
|
138
|
-
Input --> Validate{<!-- FILL: validation check, e.g. All fields valid? -->}
|
|
139
|
-
|
|
140
|
-
Validate -->|<!-- FILL: failure label, e.g. Invalid -->| Error[<!-- FILL: error action, e.g. Show validation errors -->]
|
|
141
|
-
Error --> Input
|
|
142
|
-
|
|
143
|
-
Validate -->|<!-- FILL: success label, e.g. Valid -->| Process[<!-- FILL: main action, e.g. Create account -->]
|
|
144
|
-
Process --> Check{<!-- FILL: guard check, e.g. Email already exists? -->}
|
|
145
|
-
|
|
146
|
-
Check -->|<!-- FILL: conflict label, e.g. Yes -->| Conflict[<!-- FILL: conflict action, e.g. Show duplicate email error -->]
|
|
147
|
-
Conflict --> End([<!-- FILL: exit label, e.g. User corrects email -->])
|
|
148
|
-
|
|
149
|
-
Check -->|<!-- FILL: proceed label, e.g. No -->| Success[<!-- FILL: success action, e.g. Send confirmation email -->]
|
|
150
|
-
Success --> End
|
|
151
|
-
\`\`\`
|
|
129
|
+
return `<!-- UNFILLED: Flow Diagram — ${ucName} -->
|
|
130
|
+
<!-- Replace node labels and edge conditions with real user journey steps -->
|
|
131
|
+
# Flow: ${ucName}
|
|
132
|
+
|
|
133
|
+
\`\`\`mermaid
|
|
134
|
+
flowchart TD
|
|
135
|
+
Start([<!-- FILL: trigger, e.g. User opens registration page -->])
|
|
136
|
+
|
|
137
|
+
Start --> Input[<!-- FILL: first action, e.g. Fill in name, email, password -->]
|
|
138
|
+
Input --> Validate{<!-- FILL: validation check, e.g. All fields valid? -->}
|
|
139
|
+
|
|
140
|
+
Validate -->|<!-- FILL: failure label, e.g. Invalid -->| Error[<!-- FILL: error action, e.g. Show validation errors -->]
|
|
141
|
+
Error --> Input
|
|
142
|
+
|
|
143
|
+
Validate -->|<!-- FILL: success label, e.g. Valid -->| Process[<!-- FILL: main action, e.g. Create account -->]
|
|
144
|
+
Process --> Check{<!-- FILL: guard check, e.g. Email already exists? -->}
|
|
145
|
+
|
|
146
|
+
Check -->|<!-- FILL: conflict label, e.g. Yes -->| Conflict[<!-- FILL: conflict action, e.g. Show duplicate email error -->]
|
|
147
|
+
Conflict --> End([<!-- FILL: exit label, e.g. User corrects email -->])
|
|
148
|
+
|
|
149
|
+
Check -->|<!-- FILL: proceed label, e.g. No -->| Success[<!-- FILL: success action, e.g. Send confirmation email -->]
|
|
150
|
+
Success --> End
|
|
151
|
+
\`\`\`
|
|
152
152
|
`;
|
|
153
153
|
}
|
|
154
154
|
/**
|
|
@@ -161,24 +161,24 @@ flowchart TD
|
|
|
161
161
|
* @returns Stub content with UNFILLED markers and structural Mermaid syntax
|
|
162
162
|
*/
|
|
163
163
|
export function buildC4ContainerStub(projectName) {
|
|
164
|
-
return `<!-- UNFILLED: C4 Container Diagram -->
|
|
165
|
-
<!-- Replace container labels, technology fields, and relations with your stack -->
|
|
166
|
-
# Container Diagram — ${projectName}
|
|
167
|
-
|
|
168
|
-
\`\`\`mermaid
|
|
169
|
-
C4Container
|
|
170
|
-
title Container Diagram: ${projectName}
|
|
171
|
-
|
|
172
|
-
Person(user, "<!-- FILL: actor name -->", "<!-- FILL: actor description -->")
|
|
173
|
-
|
|
174
|
-
Container(web, "<!-- FILL: frontend name, e.g. Web Application -->", "<!-- FILL: technology, e.g. React -->", "<!-- FILL: responsibility -->")
|
|
175
|
-
Container(api, "<!-- FILL: backend name, e.g. API Server -->", "<!-- FILL: technology, e.g. Node.js / Express -->", "<!-- FILL: responsibility -->")
|
|
176
|
-
Container(db, "<!-- FILL: database name, e.g. Primary Database -->", "<!-- FILL: technology, e.g. PostgreSQL -->", "<!-- FILL: responsibility -->")
|
|
177
|
-
|
|
178
|
-
Rel(user, web, "<!-- FILL: interaction, e.g. Uses -->", "<!-- FILL: protocol, e.g. HTTPS -->")
|
|
179
|
-
Rel(web, api, "<!-- FILL: call, e.g. API calls -->", "<!-- FILL: protocol, e.g. REST / JSON -->")
|
|
180
|
-
Rel(api, db, "<!-- FILL: query, e.g. Reads and writes -->", "<!-- FILL: protocol, e.g. SQL -->")
|
|
181
|
-
\`\`\`
|
|
164
|
+
return `<!-- UNFILLED: C4 Container Diagram -->
|
|
165
|
+
<!-- Replace container labels, technology fields, and relations with your stack -->
|
|
166
|
+
# Container Diagram — ${projectName}
|
|
167
|
+
|
|
168
|
+
\`\`\`mermaid
|
|
169
|
+
C4Container
|
|
170
|
+
title Container Diagram: ${projectName}
|
|
171
|
+
|
|
172
|
+
Person(user, "<!-- FILL: actor name -->", "<!-- FILL: actor description -->")
|
|
173
|
+
|
|
174
|
+
Container(web, "<!-- FILL: frontend name, e.g. Web Application -->", "<!-- FILL: technology, e.g. React -->", "<!-- FILL: responsibility -->")
|
|
175
|
+
Container(api, "<!-- FILL: backend name, e.g. API Server -->", "<!-- FILL: technology, e.g. Node.js / Express -->", "<!-- FILL: responsibility -->")
|
|
176
|
+
Container(db, "<!-- FILL: database name, e.g. Primary Database -->", "<!-- FILL: technology, e.g. PostgreSQL -->", "<!-- FILL: responsibility -->")
|
|
177
|
+
|
|
178
|
+
Rel(user, web, "<!-- FILL: interaction, e.g. Uses -->", "<!-- FILL: protocol, e.g. HTTPS -->")
|
|
179
|
+
Rel(web, api, "<!-- FILL: call, e.g. API calls -->", "<!-- FILL: protocol, e.g. REST / JSON -->")
|
|
180
|
+
Rel(api, db, "<!-- FILL: query, e.g. Reads and writes -->", "<!-- FILL: protocol, e.g. SQL -->")
|
|
181
|
+
\`\`\`
|
|
182
182
|
`;
|
|
183
183
|
}
|
|
184
184
|
/**
|
|
@@ -1,76 +1,76 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* scaffold-templates: Static template strings and render functions for scaffold_project.
|
|
3
3
|
*/
|
|
4
|
-
export const PROJECT_SPECIFIC_TEMPLATE = `# Project-Specific Rules
|
|
5
|
-
<!-- This file is owned by YOU. ForgeCraft will never overwrite it. -->
|
|
6
|
-
<!-- Add project-specific rules, framework choices, conventions, and corrections here. -->
|
|
7
|
-
<!-- The sentinel CLAUDE.md links here so any AI reading your project can find it. -->
|
|
8
|
-
|
|
9
|
-
## Framework & Stack Choices
|
|
10
|
-
<!-- e.g. We use Prisma for ORM. Deploy target is Railway. Python 3.11+. -->
|
|
11
|
-
|
|
12
|
-
## Custom Corrections Log
|
|
13
|
-
<!-- Log AI corrections so the pattern isn't repeated. -->
|
|
14
|
-
<!-- Format: - YYYY-MM-DD: [description of correction] -->
|
|
15
|
-
|
|
16
|
-
## Project-Specific Gates
|
|
17
|
-
<!-- Add quality rules specific to this project that don't belong in universal standards. -->
|
|
4
|
+
export const PROJECT_SPECIFIC_TEMPLATE = `# Project-Specific Rules
|
|
5
|
+
<!-- This file is owned by YOU. ForgeCraft will never overwrite it. -->
|
|
6
|
+
<!-- Add project-specific rules, framework choices, conventions, and corrections here. -->
|
|
7
|
+
<!-- The sentinel CLAUDE.md links here so any AI reading your project can find it. -->
|
|
8
|
+
|
|
9
|
+
## Framework & Stack Choices
|
|
10
|
+
<!-- e.g. We use Prisma for ORM. Deploy target is Railway. Python 3.11+. -->
|
|
11
|
+
|
|
12
|
+
## Custom Corrections Log
|
|
13
|
+
<!-- Log AI corrections so the pattern isn't repeated. -->
|
|
14
|
+
<!-- Format: - YYYY-MM-DD: [description of correction] -->
|
|
15
|
+
|
|
16
|
+
## Project-Specific Gates
|
|
17
|
+
<!-- Add quality rules specific to this project that don't belong in universal standards. -->
|
|
18
18
|
`;
|
|
19
19
|
export const EXCEPTIONS_TEMPLATE = JSON.stringify({
|
|
20
20
|
version: "1",
|
|
21
21
|
_comment: "Hook false-positive exceptions. Add entries here to prevent rediscovering the same false positive each session. Each entry: {id, hook, pattern, reason, addedAt, addedBy, adr?}",
|
|
22
22
|
exceptions: [],
|
|
23
23
|
}, null, 2) + "\n";
|
|
24
|
-
export const PROJECT_GATES_TEMPLATE = `version: "1"
|
|
25
|
-
# Project-specific quality gates.
|
|
26
|
-
# Gates you discover while working that should be enforced for this project.
|
|
27
|
-
# Set generalizable: true + fill in evidence to contribute to the community registry.
|
|
28
|
-
# See: https://github.com/jghiringhelli/quality-gates/issues/new?template=quality-gate-proposal.md
|
|
29
|
-
gates: []
|
|
24
|
+
export const PROJECT_GATES_TEMPLATE = `version: "1"
|
|
25
|
+
# Project-specific quality gates.
|
|
26
|
+
# Gates you discover while working that should be enforced for this project.
|
|
27
|
+
# Set generalizable: true + fill in evidence to contribute to the community registry.
|
|
28
|
+
# See: https://github.com/jghiringhelli/quality-gates/issues/new?template=quality-gate-proposal.md
|
|
29
|
+
gates: []
|
|
30
30
|
`;
|
|
31
|
-
export const SMOKE_TESTS_README = `# Smoke Tests
|
|
32
|
-
|
|
33
|
-
Generated by ForgeCraft scaffold. Fill in the critical paths from your tech spec.
|
|
34
|
-
|
|
35
|
-
## What smoke tests cover
|
|
36
|
-
- Every API entry point that serves real users
|
|
37
|
-
- Every critical user journey end-to-end
|
|
38
|
-
- Every DB migration (verify schema applied correctly)
|
|
39
|
-
- Every external integration handshake
|
|
40
|
-
|
|
41
|
-
## Format
|
|
42
|
-
Use the tool configured in forgecraft.yaml deployment.testing.smokeTool (or default to HTTP assertions).
|
|
43
|
-
All smoke tests must complete in < 60 seconds total.
|
|
44
|
-
|
|
45
|
-
## Running
|
|
46
|
-
See forgecraft.yaml tools.test or your project's test runner.
|
|
47
|
-
Results are written to .forgecraft/reports/smoke-latest.json.
|
|
48
|
-
|
|
49
|
-
## Required before deployment
|
|
50
|
-
All smoke tests must pass against staging before any production deploy.
|
|
51
|
-
See verification.yaml deployment-gates phase.
|
|
31
|
+
export const SMOKE_TESTS_README = `# Smoke Tests
|
|
32
|
+
|
|
33
|
+
Generated by ForgeCraft scaffold. Fill in the critical paths from your tech spec.
|
|
34
|
+
|
|
35
|
+
## What smoke tests cover
|
|
36
|
+
- Every API entry point that serves real users
|
|
37
|
+
- Every critical user journey end-to-end
|
|
38
|
+
- Every DB migration (verify schema applied correctly)
|
|
39
|
+
- Every external integration handshake
|
|
40
|
+
|
|
41
|
+
## Format
|
|
42
|
+
Use the tool configured in forgecraft.yaml deployment.testing.smokeTool (or default to HTTP assertions).
|
|
43
|
+
All smoke tests must complete in < 60 seconds total.
|
|
44
|
+
|
|
45
|
+
## Running
|
|
46
|
+
See forgecraft.yaml tools.test or your project's test runner.
|
|
47
|
+
Results are written to .forgecraft/reports/smoke-latest.json.
|
|
48
|
+
|
|
49
|
+
## Required before deployment
|
|
50
|
+
All smoke tests must pass against staging before any production deploy.
|
|
51
|
+
See verification.yaml deployment-gates phase.
|
|
52
52
|
`;
|
|
53
|
-
export const LOAD_TESTS_README = `# Load Tests
|
|
54
|
-
|
|
55
|
-
Generated by ForgeCraft scaffold. Fill in the parameters from your tech spec.
|
|
56
|
-
|
|
57
|
-
## Parameters (fill in from forgecraft.yaml deployment.testing.load)
|
|
58
|
-
- Concurrent users: [TODO: concurrentUsers from forgecraft.yaml]
|
|
59
|
-
- Target RPS: [TODO: targetRps from forgecraft.yaml]
|
|
60
|
-
- p99 ceiling: [TODO: p99CeilingMs ms]
|
|
61
|
-
- Duration: [TODO: durationSeconds seconds minimum]
|
|
62
|
-
|
|
63
|
-
## When these parameters are missing
|
|
64
|
-
Deploying without stated load test parameters is full deployment with manual monitoring.
|
|
65
|
-
The paper requires: parameters named in spec BEFORE the test runs, not after.
|
|
66
|
-
Add them to forgecraft.yaml deployment.testing.load before running.
|
|
67
|
-
|
|
68
|
-
## Tool
|
|
69
|
-
Use the tool configured in forgecraft.yaml deployment.testing.load.tool (k6, Artillery, Locust, etc.)
|
|
70
|
-
Results are written to .forgecraft/reports/load-latest.json.
|
|
71
|
-
|
|
72
|
-
## Required before pre-release
|
|
73
|
-
See verification.yaml pre-release-hardening phase, load-test step.
|
|
53
|
+
export const LOAD_TESTS_README = `# Load Tests
|
|
54
|
+
|
|
55
|
+
Generated by ForgeCraft scaffold. Fill in the parameters from your tech spec.
|
|
56
|
+
|
|
57
|
+
## Parameters (fill in from forgecraft.yaml deployment.testing.load)
|
|
58
|
+
- Concurrent users: [TODO: concurrentUsers from forgecraft.yaml]
|
|
59
|
+
- Target RPS: [TODO: targetRps from forgecraft.yaml]
|
|
60
|
+
- p99 ceiling: [TODO: p99CeilingMs ms]
|
|
61
|
+
- Duration: [TODO: durationSeconds seconds minimum]
|
|
62
|
+
|
|
63
|
+
## When these parameters are missing
|
|
64
|
+
Deploying without stated load test parameters is full deployment with manual monitoring.
|
|
65
|
+
The paper requires: parameters named in spec BEFORE the test runs, not after.
|
|
66
|
+
Add them to forgecraft.yaml deployment.testing.load before running.
|
|
67
|
+
|
|
68
|
+
## Tool
|
|
69
|
+
Use the tool configured in forgecraft.yaml deployment.testing.load.tool (k6, Artillery, Locust, etc.)
|
|
70
|
+
Results are written to .forgecraft/reports/load-latest.json.
|
|
71
|
+
|
|
72
|
+
## Required before pre-release
|
|
73
|
+
See verification.yaml pre-release-hardening phase, load-test step.
|
|
74
74
|
`;
|
|
75
75
|
/**
|
|
76
76
|
* Render the bootstrap README for docs/adrs/.
|
|
@@ -3,6 +3,23 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { CascadeDecision } from "../shared/types.js";
|
|
5
5
|
import { deriveDefaultCascadeDecisions } from "./cascade-defaults.js";
|
|
6
|
+
/**
|
|
7
|
+
* Result of a pre-flight git environment check.
|
|
8
|
+
*
|
|
9
|
+
* - `repo` — a `.git` directory exists; all good.
|
|
10
|
+
* - `no-repo` — git is installed but no repository exists yet; ForgeCraft will init one.
|
|
11
|
+
* - `no-git` — git binary not found; user must install git before setup can proceed.
|
|
12
|
+
*/
|
|
13
|
+
export type GitStatus = "repo" | "no-repo" | "no-git";
|
|
14
|
+
/**
|
|
15
|
+
* Check whether a git repository and the git binary are present.
|
|
16
|
+
*
|
|
17
|
+
* Does NOT modify the filesystem. Safe to call at any time.
|
|
18
|
+
*
|
|
19
|
+
* @param projectDir - Absolute path to the project root
|
|
20
|
+
* @returns Current git status for the directory
|
|
21
|
+
*/
|
|
22
|
+
export declare function checkGitStatus(projectDir: string): GitStatus;
|
|
6
23
|
/**
|
|
7
24
|
* Initialise a git repository in projectDir if one does not already exist.
|
|
8
25
|
* Falls back gracefully when git is not installed.
|
|
@@ -60,6 +77,19 @@ export declare function writePrd(projectDir: string, projectName: string, aiFiel
|
|
|
60
77
|
*/
|
|
61
78
|
export declare function writeUseCases(projectDir: string, projectName: string, aiFields: AiExtractedFields, _specContent: string | null): boolean;
|
|
62
79
|
export { deriveDefaultCascadeDecisions };
|
|
80
|
+
/**
|
|
81
|
+
* Write docs/sample-outcome.md — a stub for the first real deliverable of
|
|
82
|
+
* a generative tool. Created when Phase 2 receives tool_sample_split = "tool_and_sample".
|
|
83
|
+
*
|
|
84
|
+
* The AI assistant should fill in the sections from the creative content
|
|
85
|
+
* described in the spec (the book, song, game, artwork, etc.).
|
|
86
|
+
* Never overwrites an existing file.
|
|
87
|
+
*
|
|
88
|
+
* @param projectDir - Project root
|
|
89
|
+
* @param toolName - Name of the core generative tool
|
|
90
|
+
* @returns True if the file was written
|
|
91
|
+
*/
|
|
92
|
+
export declare function writeSampleOutcome(projectDir: string, toolName: string): boolean;
|
|
63
93
|
/**
|
|
64
94
|
* Load cascade decisions from forgecraft.yaml (convenience re-used in writers).
|
|
65
95
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup-artifact-writers.d.ts","sourceRoot":"","sources":["../../src/tools/setup-artifact-writers.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"setup-artifact-writers.d.ts","sourceRoot":"","sources":["../../src/tools/setup-artifact-writers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AAItE;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEtD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAQ5D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAwBtD;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EAAE,EACd,SAAS,EAAE,eAAe,EAAE,EAC5B,aAAa,CAAC,EAAE,OAAO,EACvB,UAAU,CAAC,EAAE,OAAO,GACnB,OAAO,CA8BT;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAwBpE;AAID,gDAAgD;AAChD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CACtB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,GAC1B,OAAO,CAMT;AAwBD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,GAC1B,OAAO,CAUT;AAuDD,OAAO,EAAE,6BAA6B,EAAE,CAAC;AAIzC;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CA4CT;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,MAAM,GACjB,eAAe,EAAE,GAAG,IAAI,CAY1B"}
|
|
@@ -1,12 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* setup-artifact-writers: Writers for forgecraft.yaml, PRD, use-cases, and git init.
|
|
3
3
|
*/
|
|
4
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import { execSync } from "node:child_process";
|
|
7
7
|
import yaml from "js-yaml";
|
|
8
8
|
import { deriveDefaultCascadeDecisions } from "./cascade-defaults.js";
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Check whether a git repository and the git binary are present.
|
|
11
|
+
*
|
|
12
|
+
* Does NOT modify the filesystem. Safe to call at any time.
|
|
13
|
+
*
|
|
14
|
+
* @param projectDir - Absolute path to the project root
|
|
15
|
+
* @returns Current git status for the directory
|
|
16
|
+
*/
|
|
17
|
+
export function checkGitStatus(projectDir) {
|
|
18
|
+
if (existsSync(join(projectDir, ".git")))
|
|
19
|
+
return "repo";
|
|
20
|
+
try {
|
|
21
|
+
execSync("git --version", { stdio: "ignore" });
|
|
22
|
+
return "no-repo";
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return "no-git";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
10
28
|
/**
|
|
11
29
|
* Initialise a git repository in projectDir if one does not already exist.
|
|
12
30
|
* Falls back gracefully when git is not installed.
|
|
@@ -127,7 +145,12 @@ export function writePrd(projectDir, projectName, aiFields, _specContent) {
|
|
|
127
145
|
}
|
|
128
146
|
function buildPrdContent(projectName, aiFields) {
|
|
129
147
|
const fill = (placeholder) => `<!-- FILL: ${placeholder} -->`;
|
|
130
|
-
const listOrFill = (csv, placeholder) => csv
|
|
148
|
+
const listOrFill = (csv, placeholder) => csv
|
|
149
|
+
? csv
|
|
150
|
+
.split(",")
|
|
151
|
+
.map((s) => `- ${s.trim()}`)
|
|
152
|
+
.join("\n")
|
|
153
|
+
: fill(placeholder);
|
|
131
154
|
return [
|
|
132
155
|
`# ${projectName}\n`,
|
|
133
156
|
`## Problem\n\n${aiFields.problemStatement ?? fill("describe the problem this project solves")}\n`,
|
|
@@ -157,18 +180,107 @@ export function writeUseCases(projectDir, projectName, aiFields, _specContent) {
|
|
|
157
180
|
}
|
|
158
181
|
function buildUseCasesContent(projectName, aiFields) {
|
|
159
182
|
const fill = (placeholder) => `<!-- FILL: ${placeholder} -->`;
|
|
160
|
-
const actors = aiFields.primaryUsers
|
|
183
|
+
const actors = aiFields.primaryUsers
|
|
184
|
+
? aiFields.primaryUsers.split(",").map((s) => s.trim())
|
|
185
|
+
: [];
|
|
161
186
|
const primaryActor = actors[0] ?? fill("primary actor");
|
|
162
187
|
const secondaryActor = actors[1] ?? actors[0] ?? fill("secondary actor");
|
|
163
188
|
const thirdActor = actors[2] ?? actors[0] ?? fill("actor");
|
|
164
|
-
const problemContext = aiFields.problemStatement
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const
|
|
189
|
+
const problemContext = aiFields.problemStatement
|
|
190
|
+
? aiFields.problemStatement.slice(0, 150).replace(/\n/g, " ")
|
|
191
|
+
: fill("problem context");
|
|
192
|
+
const uc1 = [
|
|
193
|
+
`## UC-001: Accomplish Primary Goal`,
|
|
194
|
+
``,
|
|
195
|
+
`**Actor**: ${primaryActor}`,
|
|
196
|
+
`**Precondition**: Actor is authenticated and the system is operational.`,
|
|
197
|
+
`**Steps**:`,
|
|
198
|
+
`1. Actor initiates the primary workflow.`,
|
|
199
|
+
`2. System validates the request and processes the input.`,
|
|
200
|
+
`3. System returns the result confirming the action was completed.`,
|
|
201
|
+
`**Outcome**: The actor's goal is achieved. Context: ${problemContext}`,
|
|
202
|
+
].join("\n");
|
|
203
|
+
const uc2 = [
|
|
204
|
+
`## UC-002: Configure and Manage`,
|
|
205
|
+
``,
|
|
206
|
+
`**Actor**: ${secondaryActor}`,
|
|
207
|
+
`**Precondition**: Actor has appropriate permissions.`,
|
|
208
|
+
`**Steps**:`,
|
|
209
|
+
`1. Actor selects the configuration option.`,
|
|
210
|
+
`2. System presents available options and current state.`,
|
|
211
|
+
`3. Actor applies changes; system persists the configuration.`,
|
|
212
|
+
`**Outcome**: Configuration is updated and takes effect immediately.`,
|
|
213
|
+
].join("\n");
|
|
214
|
+
const uc3 = [
|
|
215
|
+
`## UC-003: Review and Observe`,
|
|
216
|
+
``,
|
|
217
|
+
`**Actor**: ${thirdActor}`,
|
|
218
|
+
`**Precondition**: At least one operation has been completed.`,
|
|
219
|
+
`**Steps**:`,
|
|
220
|
+
`1. Actor navigates to the overview section.`,
|
|
221
|
+
`2. System retrieves and displays the current state and history.`,
|
|
222
|
+
`3. Actor reviews the information and takes appropriate action.`,
|
|
223
|
+
`**Outcome**: Actor has a clear picture of the current system state.`,
|
|
224
|
+
].join("\n");
|
|
168
225
|
return [`# Use Cases — ${projectName}`, ``, uc1, ``, uc2, ``, uc3, ``].join("\n");
|
|
169
226
|
}
|
|
170
227
|
// ── Re-export deriveDefaultCascadeDecisions for convenience ──────────
|
|
171
228
|
export { deriveDefaultCascadeDecisions };
|
|
229
|
+
// ── Sample-outcome writer ─────────────────────────────────────────────
|
|
230
|
+
/**
|
|
231
|
+
* Write docs/sample-outcome.md — a stub for the first real deliverable of
|
|
232
|
+
* a generative tool. Created when Phase 2 receives tool_sample_split = "tool_and_sample".
|
|
233
|
+
*
|
|
234
|
+
* The AI assistant should fill in the sections from the creative content
|
|
235
|
+
* described in the spec (the book, song, game, artwork, etc.).
|
|
236
|
+
* Never overwrites an existing file.
|
|
237
|
+
*
|
|
238
|
+
* @param projectDir - Project root
|
|
239
|
+
* @param toolName - Name of the core generative tool
|
|
240
|
+
* @returns True if the file was written
|
|
241
|
+
*/
|
|
242
|
+
export function writeSampleOutcome(projectDir, toolName) {
|
|
243
|
+
const outcomePath = join(projectDir, "docs", "sample-outcome.md");
|
|
244
|
+
if (existsSync(outcomePath))
|
|
245
|
+
return false;
|
|
246
|
+
mkdirSync(join(projectDir, "docs"), { recursive: true });
|
|
247
|
+
const fill = (placeholder) => `<!-- FILL: ${placeholder} -->`;
|
|
248
|
+
const content = [
|
|
249
|
+
`# Sample Outcome — First Real Deliverable`,
|
|
250
|
+
``,
|
|
251
|
+
`> **What this file is:** The core tool is **${toolName}**. This file captures the`,
|
|
252
|
+
`> first specific creative work the tool will produce — the proof that the tool works.`,
|
|
253
|
+
`> It is an acceptance test, not a deliverable in itself.`,
|
|
254
|
+
`> Read the original spec and extract the creative content details into the sections below.`,
|
|
255
|
+
``,
|
|
256
|
+
`## The Work`,
|
|
257
|
+
``,
|
|
258
|
+
`**Title / Name**: ${fill("name of the book, song, game, artwork, etc.")}`,
|
|
259
|
+
`**Type**: ${fill("novel | music track | game | artwork | script | other")}`,
|
|
260
|
+
``,
|
|
261
|
+
`## Description`,
|
|
262
|
+
``,
|
|
263
|
+
fill("brief description of what this creative work is — 2-3 sentences from the spec"),
|
|
264
|
+
``,
|
|
265
|
+
`## Key Elements`,
|
|
266
|
+
``,
|
|
267
|
+
fill("characters, themes, setting, style, structure — the specifics from the spec"),
|
|
268
|
+
``,
|
|
269
|
+
`## Acceptance Criteria`,
|
|
270
|
+
``,
|
|
271
|
+
`The tool has succeeded with this first outcome when:`,
|
|
272
|
+
``,
|
|
273
|
+
`- [ ] ${fill("first measurable criterion — e.g. 'generates a coherent chapter 1'")}`,
|
|
274
|
+
`- [ ] ${fill("second criterion")}`,
|
|
275
|
+
`- [ ] ${fill("third criterion")}`,
|
|
276
|
+
``,
|
|
277
|
+
`## Notes`,
|
|
278
|
+
``,
|
|
279
|
+
fill("anything else from the spec about this specific creative work"),
|
|
280
|
+
].join("\n");
|
|
281
|
+
writeFileSync(outcomePath, content, "utf-8");
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
172
284
|
/**
|
|
173
285
|
* Load cascade decisions from forgecraft.yaml (convenience re-used in writers).
|
|
174
286
|
*/
|