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.
Files changed (136) hide show
  1. package/README.md +525 -525
  2. package/dist/cli/help.js +44 -44
  3. package/dist/registry/renderer-skeletons.js +92 -92
  4. package/dist/shared/gs-score-logger.js +6 -6
  5. package/dist/tools/add-module.js +123 -123
  6. package/dist/tools/advice-registry.js +18 -18
  7. package/dist/tools/check-cascade-report.js +64 -64
  8. package/dist/tools/configure-mcp.d.ts +3 -0
  9. package/dist/tools/configure-mcp.d.ts.map +1 -1
  10. package/dist/tools/configure-mcp.js +10 -0
  11. package/dist/tools/configure-mcp.js.map +1 -1
  12. package/dist/tools/forgecraft-dispatch.d.ts.map +1 -1
  13. package/dist/tools/forgecraft-dispatch.js +3 -0
  14. package/dist/tools/forgecraft-dispatch.js.map +1 -1
  15. package/dist/tools/forgecraft-schema-params.d.ts +9 -0
  16. package/dist/tools/forgecraft-schema-params.d.ts.map +1 -1
  17. package/dist/tools/forgecraft-schema-params.js +21 -0
  18. package/dist/tools/forgecraft-schema-params.js.map +1 -1
  19. package/dist/tools/forgecraft-schema.d.ts +9 -0
  20. package/dist/tools/forgecraft-schema.d.ts.map +1 -1
  21. package/dist/tools/refresh-output.js +14 -14
  22. package/dist/tools/scaffold-spec-stubs.js +115 -115
  23. package/dist/tools/scaffold-templates.js +62 -62
  24. package/dist/tools/setup-artifact-writers.d.ts +30 -0
  25. package/dist/tools/setup-artifact-writers.d.ts.map +1 -1
  26. package/dist/tools/setup-artifact-writers.js +120 -8
  27. package/dist/tools/setup-artifact-writers.js.map +1 -1
  28. package/dist/tools/setup-phase1.d.ts +3 -0
  29. package/dist/tools/setup-phase1.d.ts.map +1 -1
  30. package/dist/tools/setup-phase1.js +79 -35
  31. package/dist/tools/setup-phase1.js.map +1 -1
  32. package/dist/tools/setup-phase2.d.ts +2 -0
  33. package/dist/tools/setup-phase2.d.ts.map +1 -1
  34. package/dist/tools/setup-phase2.js +10 -1
  35. package/dist/tools/setup-phase2.js.map +1 -1
  36. package/dist/tools/setup-project.d.ts +18 -0
  37. package/dist/tools/setup-project.d.ts.map +1 -1
  38. package/dist/tools/setup-project.js +77 -1
  39. package/dist/tools/setup-project.js.map +1 -1
  40. package/dist/tools/spec-parser-tags.d.ts +9 -0
  41. package/dist/tools/spec-parser-tags.d.ts.map +1 -1
  42. package/dist/tools/spec-parser-tags.js +92 -0
  43. package/dist/tools/spec-parser-tags.js.map +1 -1
  44. package/package.json +89 -86
  45. package/templates/analytics/instructions.yaml +37 -37
  46. package/templates/analytics/mcp-servers.yaml +11 -11
  47. package/templates/analytics/structure.yaml +25 -25
  48. package/templates/api/instructions.yaml +231 -231
  49. package/templates/api/mcp-servers.yaml +22 -13
  50. package/templates/api/nfr.yaml +23 -23
  51. package/templates/api/review.yaml +103 -103
  52. package/templates/api/structure.yaml +34 -34
  53. package/templates/api/verification.yaml +132 -132
  54. package/templates/cli/instructions.yaml +31 -31
  55. package/templates/cli/mcp-servers.yaml +11 -11
  56. package/templates/cli/review.yaml +53 -53
  57. package/templates/cli/structure.yaml +16 -16
  58. package/templates/data-lineage/instructions.yaml +28 -28
  59. package/templates/data-lineage/mcp-servers.yaml +22 -22
  60. package/templates/data-pipeline/instructions.yaml +84 -84
  61. package/templates/data-pipeline/mcp-servers.yaml +13 -13
  62. package/templates/data-pipeline/nfr.yaml +39 -39
  63. package/templates/data-pipeline/structure.yaml +23 -23
  64. package/templates/fintech/hooks.yaml +55 -55
  65. package/templates/fintech/instructions.yaml +112 -112
  66. package/templates/fintech/mcp-servers.yaml +13 -13
  67. package/templates/fintech/nfr.yaml +46 -46
  68. package/templates/fintech/playbook.yaml +210 -210
  69. package/templates/fintech/verification.yaml +239 -239
  70. package/templates/game/instructions.yaml +289 -289
  71. package/templates/game/mcp-servers.yaml +38 -38
  72. package/templates/game/nfr.yaml +64 -64
  73. package/templates/game/playbook.yaml +214 -214
  74. package/templates/game/review.yaml +97 -97
  75. package/templates/game/structure.yaml +67 -67
  76. package/templates/game/verification.yaml +174 -174
  77. package/templates/healthcare/instructions.yaml +42 -42
  78. package/templates/healthcare/mcp-servers.yaml +13 -13
  79. package/templates/healthcare/nfr.yaml +47 -47
  80. package/templates/hipaa/instructions.yaml +41 -41
  81. package/templates/hipaa/mcp-servers.yaml +13 -13
  82. package/templates/infra/instructions.yaml +104 -104
  83. package/templates/infra/mcp-servers.yaml +20 -20
  84. package/templates/infra/nfr.yaml +46 -46
  85. package/templates/infra/review.yaml +65 -65
  86. package/templates/infra/structure.yaml +25 -25
  87. package/templates/library/instructions.yaml +36 -36
  88. package/templates/library/mcp-servers.yaml +20 -20
  89. package/templates/library/review.yaml +56 -56
  90. package/templates/library/structure.yaml +19 -19
  91. package/templates/medallion-architecture/instructions.yaml +41 -41
  92. package/templates/medallion-architecture/mcp-servers.yaml +22 -22
  93. package/templates/ml/instructions.yaml +85 -85
  94. package/templates/ml/mcp-servers.yaml +11 -11
  95. package/templates/ml/nfr.yaml +39 -39
  96. package/templates/ml/structure.yaml +25 -25
  97. package/templates/ml/verification.yaml +156 -156
  98. package/templates/mobile/instructions.yaml +44 -44
  99. package/templates/mobile/mcp-servers.yaml +11 -11
  100. package/templates/mobile/nfr.yaml +49 -49
  101. package/templates/mobile/structure.yaml +27 -27
  102. package/templates/mobile/verification.yaml +121 -121
  103. package/templates/observability-xray/instructions.yaml +40 -40
  104. package/templates/observability-xray/mcp-servers.yaml +15 -15
  105. package/templates/realtime/instructions.yaml +42 -42
  106. package/templates/realtime/mcp-servers.yaml +13 -13
  107. package/templates/soc2/instructions.yaml +41 -41
  108. package/templates/soc2/mcp-servers.yaml +24 -24
  109. package/templates/social/instructions.yaml +43 -43
  110. package/templates/social/mcp-servers.yaml +24 -24
  111. package/templates/state-machine/instructions.yaml +42 -42
  112. package/templates/state-machine/mcp-servers.yaml +11 -11
  113. package/templates/tools-registry.yaml +164 -164
  114. package/templates/universal/hooks.yaml +531 -531
  115. package/templates/universal/instructions.yaml +1692 -1692
  116. package/templates/universal/mcp-servers.yaml +50 -50
  117. package/templates/universal/nfr.yaml +197 -197
  118. package/templates/universal/reference.yaml +326 -326
  119. package/templates/universal/review.yaml +204 -204
  120. package/templates/universal/skills.yaml +262 -262
  121. package/templates/universal/structure.yaml +67 -67
  122. package/templates/universal/verification.yaml +416 -416
  123. package/templates/web-react/hooks.yaml +44 -44
  124. package/templates/web-react/instructions.yaml +207 -207
  125. package/templates/web-react/mcp-servers.yaml +20 -20
  126. package/templates/web-react/nfr.yaml +27 -27
  127. package/templates/web-react/review.yaml +94 -94
  128. package/templates/web-react/structure.yaml +46 -46
  129. package/templates/web-react/verification.yaml +126 -126
  130. package/templates/web-static/instructions.yaml +115 -115
  131. package/templates/web-static/mcp-servers.yaml +20 -20
  132. package/templates/web3/instructions.yaml +44 -44
  133. package/templates/web3/mcp-servers.yaml +11 -11
  134. package/templates/web3/verification.yaml +159 -159
  135. package/templates/zero-trust/instructions.yaml +41 -41
  136. 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;AAWH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AAItE;;;;;;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,CAkBT;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAcpE;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;AAgBD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,GAC1B,OAAO,CAMT;AAgBD,OAAO,EAAE,6BAA6B,EAAE,CAAC;AAEzC;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,EAAE,GAAG,IAAI,CAUzF"}
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, } from "node:fs";
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
- // ── Git initialization ────────────────────────────────────────────────
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 ? csv.split(",").map((s) => `- ${s.trim()}`).join("\n") : fill(placeholder);
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 ? aiFields.primaryUsers.split(",").map((s) => s.trim()) : [];
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 ? aiFields.problemStatement.slice(0, 150).replace(/\n/g, " ") : fill("problem context");
165
- const uc1 = [`## UC-001: Accomplish Primary Goal`, ``, `**Actor**: ${primaryActor}`, `**Precondition**: Actor is authenticated and the system is operational.`, `**Steps**:`, `1. Actor initiates the primary workflow.`, `2. System validates the request and processes the input.`, `3. System returns the result confirming the action was completed.`, `**Outcome**: The actor's goal is achieved. Context: ${problemContext}`].join("\n");
166
- const uc2 = [`## UC-002: Configure and Manage`, ``, `**Actor**: ${secondaryActor}`, `**Precondition**: Actor has appropriate permissions.`, `**Steps**:`, `1. Actor selects the configuration option.`, `2. System presents available options and current state.`, `3. Actor applies changes; system persists the configuration.`, `**Outcome**: Configuration is updated and takes effect immediately.`].join("\n");
167
- const uc3 = [`## UC-003: Review and Observe`, ``, `**Actor**: ${thirdActor}`, `**Precondition**: At least one operation has been completed.`, `**Steps**:`, `1. Actor navigates to the overview section.`, `2. System retrieves and displays the current state and history.`, `3. Actor reviews the information and takes appropriate action.`, `**Outcome**: Actor has a clear picture of the current system state.`].join("\n");
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
  */