forgecraft-mcp 1.1.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 (142) 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.d.ts +43 -0
  23. package/dist/tools/scaffold-spec-stubs.d.ts.map +1 -1
  24. package/dist/tools/scaffold-spec-stubs.js +166 -24
  25. package/dist/tools/scaffold-spec-stubs.js.map +1 -1
  26. package/dist/tools/scaffold-templates.js +62 -62
  27. package/dist/tools/scaffold-writer.d.ts.map +1 -1
  28. package/dist/tools/scaffold-writer.js +11 -3
  29. package/dist/tools/scaffold-writer.js.map +1 -1
  30. package/dist/tools/setup-artifact-writers.d.ts +30 -0
  31. package/dist/tools/setup-artifact-writers.d.ts.map +1 -1
  32. package/dist/tools/setup-artifact-writers.js +120 -8
  33. package/dist/tools/setup-artifact-writers.js.map +1 -1
  34. package/dist/tools/setup-phase1.d.ts +3 -0
  35. package/dist/tools/setup-phase1.d.ts.map +1 -1
  36. package/dist/tools/setup-phase1.js +79 -35
  37. package/dist/tools/setup-phase1.js.map +1 -1
  38. package/dist/tools/setup-phase2.d.ts +2 -0
  39. package/dist/tools/setup-phase2.d.ts.map +1 -1
  40. package/dist/tools/setup-phase2.js +10 -1
  41. package/dist/tools/setup-phase2.js.map +1 -1
  42. package/dist/tools/setup-project.d.ts +18 -0
  43. package/dist/tools/setup-project.d.ts.map +1 -1
  44. package/dist/tools/setup-project.js +77 -1
  45. package/dist/tools/setup-project.js.map +1 -1
  46. package/dist/tools/spec-parser-tags.d.ts +9 -0
  47. package/dist/tools/spec-parser-tags.d.ts.map +1 -1
  48. package/dist/tools/spec-parser-tags.js +92 -0
  49. package/dist/tools/spec-parser-tags.js.map +1 -1
  50. package/package.json +89 -86
  51. package/templates/analytics/instructions.yaml +37 -37
  52. package/templates/analytics/mcp-servers.yaml +11 -11
  53. package/templates/analytics/structure.yaml +25 -25
  54. package/templates/api/instructions.yaml +231 -231
  55. package/templates/api/mcp-servers.yaml +22 -13
  56. package/templates/api/nfr.yaml +23 -23
  57. package/templates/api/review.yaml +103 -103
  58. package/templates/api/structure.yaml +34 -34
  59. package/templates/api/verification.yaml +132 -132
  60. package/templates/cli/instructions.yaml +31 -31
  61. package/templates/cli/mcp-servers.yaml +11 -11
  62. package/templates/cli/review.yaml +53 -53
  63. package/templates/cli/structure.yaml +16 -16
  64. package/templates/data-lineage/instructions.yaml +28 -28
  65. package/templates/data-lineage/mcp-servers.yaml +22 -22
  66. package/templates/data-pipeline/instructions.yaml +84 -84
  67. package/templates/data-pipeline/mcp-servers.yaml +13 -13
  68. package/templates/data-pipeline/nfr.yaml +39 -39
  69. package/templates/data-pipeline/structure.yaml +23 -23
  70. package/templates/fintech/hooks.yaml +55 -55
  71. package/templates/fintech/instructions.yaml +112 -112
  72. package/templates/fintech/mcp-servers.yaml +13 -13
  73. package/templates/fintech/nfr.yaml +46 -46
  74. package/templates/fintech/playbook.yaml +210 -210
  75. package/templates/fintech/verification.yaml +239 -239
  76. package/templates/game/instructions.yaml +289 -289
  77. package/templates/game/mcp-servers.yaml +38 -38
  78. package/templates/game/nfr.yaml +64 -64
  79. package/templates/game/playbook.yaml +214 -214
  80. package/templates/game/review.yaml +97 -97
  81. package/templates/game/structure.yaml +67 -67
  82. package/templates/game/verification.yaml +174 -174
  83. package/templates/healthcare/instructions.yaml +42 -42
  84. package/templates/healthcare/mcp-servers.yaml +13 -13
  85. package/templates/healthcare/nfr.yaml +47 -47
  86. package/templates/hipaa/instructions.yaml +41 -41
  87. package/templates/hipaa/mcp-servers.yaml +13 -13
  88. package/templates/infra/instructions.yaml +104 -104
  89. package/templates/infra/mcp-servers.yaml +20 -20
  90. package/templates/infra/nfr.yaml +46 -46
  91. package/templates/infra/review.yaml +65 -65
  92. package/templates/infra/structure.yaml +25 -25
  93. package/templates/library/instructions.yaml +36 -36
  94. package/templates/library/mcp-servers.yaml +20 -20
  95. package/templates/library/review.yaml +56 -56
  96. package/templates/library/structure.yaml +19 -19
  97. package/templates/medallion-architecture/instructions.yaml +41 -41
  98. package/templates/medallion-architecture/mcp-servers.yaml +22 -22
  99. package/templates/ml/instructions.yaml +85 -85
  100. package/templates/ml/mcp-servers.yaml +11 -11
  101. package/templates/ml/nfr.yaml +39 -39
  102. package/templates/ml/structure.yaml +25 -25
  103. package/templates/ml/verification.yaml +156 -156
  104. package/templates/mobile/instructions.yaml +44 -44
  105. package/templates/mobile/mcp-servers.yaml +11 -11
  106. package/templates/mobile/nfr.yaml +49 -49
  107. package/templates/mobile/structure.yaml +27 -27
  108. package/templates/mobile/verification.yaml +121 -121
  109. package/templates/observability-xray/instructions.yaml +40 -40
  110. package/templates/observability-xray/mcp-servers.yaml +15 -15
  111. package/templates/realtime/instructions.yaml +42 -42
  112. package/templates/realtime/mcp-servers.yaml +13 -13
  113. package/templates/soc2/instructions.yaml +41 -41
  114. package/templates/soc2/mcp-servers.yaml +24 -24
  115. package/templates/social/instructions.yaml +43 -43
  116. package/templates/social/mcp-servers.yaml +24 -24
  117. package/templates/state-machine/instructions.yaml +42 -42
  118. package/templates/state-machine/mcp-servers.yaml +11 -11
  119. package/templates/tools-registry.yaml +164 -164
  120. package/templates/universal/hooks.yaml +531 -531
  121. package/templates/universal/instructions.yaml +1692 -1681
  122. package/templates/universal/mcp-servers.yaml +50 -50
  123. package/templates/universal/nfr.yaml +197 -197
  124. package/templates/universal/reference.yaml +326 -326
  125. package/templates/universal/review.yaml +204 -204
  126. package/templates/universal/skills.yaml +262 -262
  127. package/templates/universal/structure.yaml +67 -67
  128. package/templates/universal/verification.yaml +416 -416
  129. package/templates/web-react/hooks.yaml +44 -44
  130. package/templates/web-react/instructions.yaml +207 -207
  131. package/templates/web-react/mcp-servers.yaml +20 -20
  132. package/templates/web-react/nfr.yaml +27 -27
  133. package/templates/web-react/review.yaml +94 -94
  134. package/templates/web-react/structure.yaml +46 -46
  135. package/templates/web-react/verification.yaml +126 -126
  136. package/templates/web-static/instructions.yaml +115 -115
  137. package/templates/web-static/mcp-servers.yaml +20 -20
  138. package/templates/web3/instructions.yaml +44 -44
  139. package/templates/web3/mcp-servers.yaml +11 -11
  140. package/templates/web3/verification.yaml +159 -159
  141. package/templates/zero-trust/instructions.yaml +41 -41
  142. package/templates/zero-trust/mcp-servers.yaml +15 -15
package/dist/cli/help.js CHANGED
@@ -5,50 +5,50 @@
5
5
  * Print usage help to stdout.
6
6
  */
7
7
  export function showHelp() {
8
- console.log(`
9
- ForgeCraft MCP — engineering standards for AI coding assistants
10
-
11
- USAGE
12
- npx forgecraft-mcp <command> [arguments] [flags]
13
- npx forgecraft-mcp serve (default — starts MCP server)
14
-
15
- COMMANDS
16
- setup <dir> First-time project setup (auto-detects stack)
17
- refresh <dir> Re-sync instruction files after project changes
18
- audit <dir> Check project against configured standards
19
- scaffold <dir> Generate project structure and instruction files
20
- review [dir] Generate code review checklist
21
- list [tags|hooks|skills] Discover available resources
22
- classify [dir] Suggest tags for a project
23
- generate <dir> Generate instruction files only
24
- convert <dir> Generate migration plan
25
- add-hook <name> <dir> Install a quality-gate hook
26
- add-module <name> <dir> Scaffold a feature module
27
- verify [dir] Run tests + score §4.3 GS properties + report layer violations
28
- advice [dir] Quality cycle checklist + tool stack + example configs for your tags
29
- metrics [dir] External quality report: LOC, coverage, layer violations, dead code, complexity
30
- FLAGS (vary by command)
31
- --tags <tags...> Project classification tags (or read from forgecraft.yaml)
32
- --tier <tier> Content depth: core | recommended | optional
33
- --targets <targets...> AI assistant targets: claude cursor copilot windsurf cline aider
34
- --name <name> Project name
35
- --description <text> Project description for tag detection
36
- --dry-run Preview without writing files
37
- --apply Apply changes (for refresh, default is preview)
38
- --add-tags <tags...> Add tags during refresh
39
- --remove-tags <tags...> Remove tags during refresh
40
- --no-anti-patterns Skip anti-pattern scanning (for audit)
41
- --language <lang> typescript | python (default: typescript)
42
- --scope <scope> comprehensive | focused (for review)
43
- --test-cmd <cmd> Test command override for verify (default: npm test)
44
- --timeout <ms> Test suite timeout in milliseconds (default: 120000)
45
- --threshold <n> Minimum GS score out of 12 for pass (default: 10)
46
- --mutation Run Stryker mutation testing (slow, opt-in; used by metrics)
47
- --coverage-dir <path> Path to existing coverage report directory (used by metrics)
48
- --force Overwrite existing files
49
- --compact Strip explanatory bullet tails and deduplicate lines (~20-40% smaller output)
50
- --tag <tag> Single tag filter (for add-hook)
51
- --check Drift-check mode for refresh: exit 1 if tag/tier drift detected (CI gate)
8
+ console.log(`
9
+ ForgeCraft MCP — engineering standards for AI coding assistants
10
+
11
+ USAGE
12
+ npx forgecraft-mcp <command> [arguments] [flags]
13
+ npx forgecraft-mcp serve (default — starts MCP server)
14
+
15
+ COMMANDS
16
+ setup <dir> First-time project setup (auto-detects stack)
17
+ refresh <dir> Re-sync instruction files after project changes
18
+ audit <dir> Check project against configured standards
19
+ scaffold <dir> Generate project structure and instruction files
20
+ review [dir] Generate code review checklist
21
+ list [tags|hooks|skills] Discover available resources
22
+ classify [dir] Suggest tags for a project
23
+ generate <dir> Generate instruction files only
24
+ convert <dir> Generate migration plan
25
+ add-hook <name> <dir> Install a quality-gate hook
26
+ add-module <name> <dir> Scaffold a feature module
27
+ verify [dir] Run tests + score §4.3 GS properties + report layer violations
28
+ advice [dir] Quality cycle checklist + tool stack + example configs for your tags
29
+ metrics [dir] External quality report: LOC, coverage, layer violations, dead code, complexity
30
+ FLAGS (vary by command)
31
+ --tags <tags...> Project classification tags (or read from forgecraft.yaml)
32
+ --tier <tier> Content depth: core | recommended | optional
33
+ --targets <targets...> AI assistant targets: claude cursor copilot windsurf cline aider
34
+ --name <name> Project name
35
+ --description <text> Project description for tag detection
36
+ --dry-run Preview without writing files
37
+ --apply Apply changes (for refresh, default is preview)
38
+ --add-tags <tags...> Add tags during refresh
39
+ --remove-tags <tags...> Remove tags during refresh
40
+ --no-anti-patterns Skip anti-pattern scanning (for audit)
41
+ --language <lang> typescript | python (default: typescript)
42
+ --scope <scope> comprehensive | focused (for review)
43
+ --test-cmd <cmd> Test command override for verify (default: npm test)
44
+ --timeout <ms> Test suite timeout in milliseconds (default: 120000)
45
+ --threshold <n> Minimum GS score out of 12 for pass (default: 10)
46
+ --mutation Run Stryker mutation testing (slow, opt-in; used by metrics)
47
+ --coverage-dir <path> Path to existing coverage report directory (used by metrics)
48
+ --force Overwrite existing files
49
+ --compact Strip explanatory bullet tails and deduplicate lines (~20-40% smaller output)
50
+ --tag <tag> Single tag filter (for add-hook)
51
+ --check Drift-check mode for refresh: exit 1 if tag/tier drift detected (CI gate)
52
52
  `);
53
53
  }
54
54
  //# sourceMappingURL=help.js.map
@@ -11,42 +11,42 @@
11
11
  * @returns Status.md content ready to write
12
12
  */
13
13
  export function renderStatusMd(context) {
14
- return `# Status.md
15
-
16
- ## Last Updated: ${new Date().toISOString().split("T")[0]}
17
- ## Session Summary
18
- Project initialized with ForgeCraft. Tags: ${context.tags.join(", ")}.
19
-
20
- ## Project Structure
21
- \`\`\`
22
- [Run 'tree -L 3 --dirsfirst' to populate]
23
- \`\`\`
24
-
25
- ## Feature Tracker
26
- | Feature | Status | Branch | Notes |
27
- |---------|--------|--------|-------|
28
- | | ⬚ Not Started | | |
29
-
30
- ## Known Bugs
31
- | ID | Description | Severity | Status |
32
- |----|-------------|----------|--------|
33
- | | | | |
34
-
35
- ## Technical Debt
36
- | Item | Impact | Effort | Priority |
37
- |------|--------|--------|----------|
38
- | | | | |
39
-
40
- ## Current Context
41
- - Working on:
42
- - Blocked by:
43
- - Decisions pending:
44
- - Next steps:
45
-
46
- ## Architecture Decision Log
47
- | Date | Decision | Rationale | Status |
48
- |------|----------|-----------|--------|
49
- | | | | |
14
+ return `# Status.md
15
+
16
+ ## Last Updated: ${new Date().toISOString().split("T")[0]}
17
+ ## Session Summary
18
+ Project initialized with ForgeCraft. Tags: ${context.tags.join(", ")}.
19
+
20
+ ## Project Structure
21
+ \`\`\`
22
+ [Run 'tree -L 3 --dirsfirst' to populate]
23
+ \`\`\`
24
+
25
+ ## Feature Tracker
26
+ | Feature | Status | Branch | Notes |
27
+ |---------|--------|--------|-------|
28
+ | | ⬚ Not Started | | |
29
+
30
+ ## Known Bugs
31
+ | ID | Description | Severity | Status |
32
+ |----|-------------|----------|--------|
33
+ | | | | |
34
+
35
+ ## Technical Debt
36
+ | Item | Impact | Effort | Priority |
37
+ |------|--------|--------|----------|
38
+ | | | | |
39
+
40
+ ## Current Context
41
+ - Working on:
42
+ - Blocked by:
43
+ - Decisions pending:
44
+ - Next steps:
45
+
46
+ ## Architecture Decision Log
47
+ | Date | Decision | Rationale | Status |
48
+ |------|----------|-----------|--------|
49
+ | | | | |
50
50
  `;
51
51
  }
52
52
  /**
@@ -56,33 +56,33 @@ Project initialized with ForgeCraft. Tags: ${context.tags.join(", ")}.
56
56
  * @returns PRD.md content ready to write
57
57
  */
58
58
  export function renderPrdSkeleton(context) {
59
- return `# PRD: ${context.projectName}
60
-
61
- ## Background & Context
62
- [Why this project exists, what problem it solves]
63
-
64
- ## Stakeholders
65
- [Who owns it, who uses it, who's affected]
66
-
67
- ## User Stories
68
- [Organized by feature area]
69
- - US-001: As a [type], I want [action] so that [benefit]
70
-
71
- ## Requirements
72
- ### Functional Requirements
73
- - FR-001: [requirement]
74
-
75
- ### Non-Functional Requirements
76
- [Generated from active tags: ${context.tags.join(", ")}]
77
-
78
- ## Out of Scope
79
- [Explicitly list what this project does NOT do]
80
-
81
- ## Success Metrics
82
- [How do we know this project succeeded?]
83
-
84
- ## Open Questions
85
- [Unresolved decisions]
59
+ return `# PRD: ${context.projectName}
60
+
61
+ ## Background & Context
62
+ [Why this project exists, what problem it solves]
63
+
64
+ ## Stakeholders
65
+ [Who owns it, who uses it, who's affected]
66
+
67
+ ## User Stories
68
+ [Organized by feature area]
69
+ - US-001: As a [type], I want [action] so that [benefit]
70
+
71
+ ## Requirements
72
+ ### Functional Requirements
73
+ - FR-001: [requirement]
74
+
75
+ ### Non-Functional Requirements
76
+ [Generated from active tags: ${context.tags.join(", ")}]
77
+
78
+ ## Out of Scope
79
+ [Explicitly list what this project does NOT do]
80
+
81
+ ## Success Metrics
82
+ [How do we know this project succeeded?]
83
+
84
+ ## Open Questions
85
+ [Unresolved decisions]
86
86
  `;
87
87
  }
88
88
  /**
@@ -92,35 +92,35 @@ export function renderPrdSkeleton(context) {
92
92
  * @returns TechSpec.md content ready to write
93
93
  */
94
94
  export function renderTechSpecSkeleton(context) {
95
- return `# Tech Spec: ${context.projectName}
96
-
97
- ## Overview
98
- [One paragraph translating PRD to technical approach]
99
-
100
- ## Architecture
101
- ### System Diagram
102
- [Mermaid diagram or description of components]
103
-
104
- ### Tech Stack
105
- - Runtime: ${context.language}
106
- - Framework: ${context.framework ?? "[TBD]"}
107
-
108
- ### Data Flow
109
- [How data moves through the system]
110
-
111
- ## API Contracts
112
- [Key endpoints, request/response shapes]
113
-
114
- ## Security & Compliance
115
- [Auth approach, encryption, audit logging]
116
-
117
- ## Dependencies
118
- [External services, APIs, libraries with version pins]
119
-
120
- ## Risks & Mitigations
121
- | Risk | Likelihood | Impact | Mitigation |
122
- |------|-----------|--------|------------|
123
- | | H/M/L | H/M/L | |
95
+ return `# Tech Spec: ${context.projectName}
96
+
97
+ ## Overview
98
+ [One paragraph translating PRD to technical approach]
99
+
100
+ ## Architecture
101
+ ### System Diagram
102
+ [Mermaid diagram or description of components]
103
+
104
+ ### Tech Stack
105
+ - Runtime: ${context.language}
106
+ - Framework: ${context.framework ?? "[TBD]"}
107
+
108
+ ### Data Flow
109
+ [How data moves through the system]
110
+
111
+ ## API Contracts
112
+ [Key endpoints, request/response shapes]
113
+
114
+ ## Security & Compliance
115
+ [Auth approach, encryption, audit logging]
116
+
117
+ ## Dependencies
118
+ [External services, APIs, libraries with version pins]
119
+
120
+ ## Risks & Mitigations
121
+ | Risk | Likelihood | Impact | Mitigation |
122
+ |------|-----------|--------|------------|
123
+ | | H/M/L | H/M/L | |
124
124
  `;
125
125
  }
126
126
  //# sourceMappingURL=renderer-skeletons.js.map
@@ -11,12 +11,12 @@ import { appendFileSync, existsSync, mkdirSync, writeFileSync } from "fs";
11
11
  import { join } from "path";
12
12
  // ── Constants ────────────────────────────────────────────────────────
13
13
  const GS_SCORE_FILE = "docs/gs-score.md";
14
- const GS_SCORE_HEADER = `# GS Score Log
15
-
16
- Tracks S_realized and GS property scores per loop.
17
-
18
- | date | loop | roadmap_item | s_realized | self-describing | bounded | verifiable | defended | auditable | composable | executable |
19
- |------|------|--------------|------------|-----------------|---------|-----------|----------|-----------|-----------|-----------|
14
+ const GS_SCORE_HEADER = `# GS Score Log
15
+
16
+ Tracks S_realized and GS property scores per loop.
17
+
18
+ | date | loop | roadmap_item | s_realized | self-describing | bounded | verifiable | defended | auditable | composable | executable |
19
+ |------|------|--------------|------------|-----------------|---------|-----------|----------|-----------|-----------|-----------|
20
20
  `;
21
21
  const GS_PROPERTY_ORDER = [
22
22
  "self-describing",
@@ -60,97 +60,97 @@ function generateTypeScriptModule(moduleDir, moduleName, className, tags) {
60
60
  const files = [];
61
61
  const relBase = `src/modules/${moduleName}`;
62
62
  // Types
63
- const typesContent = `/**
64
- * ${className} module types.
65
- */
66
-
67
- export interface ${className} {
68
- readonly id: string;
69
- // TODO: Define ${className} properties
70
- }
71
-
72
- export interface Create${className}Input {
73
- // TODO: Define creation input
74
- }
75
-
76
- export interface Update${className}Input {
77
- readonly id: string;
78
- // TODO: Define update input
79
- }
63
+ const typesContent = `/**
64
+ * ${className} module types.
65
+ */
66
+
67
+ export interface ${className} {
68
+ readonly id: string;
69
+ // TODO: Define ${className} properties
70
+ }
71
+
72
+ export interface Create${className}Input {
73
+ // TODO: Define creation input
74
+ }
75
+
76
+ export interface Update${className}Input {
77
+ readonly id: string;
78
+ // TODO: Define update input
79
+ }
80
80
  `;
81
81
  writeFileSync(join(moduleDir, "types.ts"), typesContent);
82
82
  files.push(`${relBase}/types.ts`);
83
83
  // Interface
84
- const interfaceContent = `/**
85
- * ${className} service interface.
86
- *
87
- * Defines the contract — implementations are swappable.
88
- */
89
-
90
- import type { ${className}, Create${className}Input, Update${className}Input } from "./types.js";
91
-
92
- export interface I${className}Service {
93
- create(input: Create${className}Input): Promise<${className}>;
94
- findById(id: string): Promise<${className} | null>;
95
- update(input: Update${className}Input): Promise<${className}>;
96
- delete(id: string): Promise<void>;
97
- }
84
+ const interfaceContent = `/**
85
+ * ${className} service interface.
86
+ *
87
+ * Defines the contract — implementations are swappable.
88
+ */
89
+
90
+ import type { ${className}, Create${className}Input, Update${className}Input } from "./types.js";
91
+
92
+ export interface I${className}Service {
93
+ create(input: Create${className}Input): Promise<${className}>;
94
+ findById(id: string): Promise<${className} | null>;
95
+ update(input: Update${className}Input): Promise<${className}>;
96
+ delete(id: string): Promise<void>;
97
+ }
98
98
  `;
99
99
  writeFileSync(join(moduleDir, "interface.ts"), interfaceContent);
100
100
  files.push(`${relBase}/interface.ts`);
101
101
  // Service implementation
102
- const serviceContent = `/**
103
- * ${className} service implementation.
104
- */
105
-
106
- import type { ${className}, Create${className}Input, Update${className}Input } from "./types.js";
107
- import type { I${className}Service } from "./interface.js";
108
-
109
- export class ${className}Service implements I${className}Service {
110
- async create(input: Create${className}Input): Promise<${className}> {
111
- // TODO: Implement creation logic
112
- throw new Error("Not implemented");
113
- }
114
-
115
- async findById(id: string): Promise<${className} | null> {
116
- // TODO: Implement find logic
117
- throw new Error("Not implemented");
118
- }
119
-
120
- async update(input: Update${className}Input): Promise<${className}> {
121
- // TODO: Implement update logic
122
- throw new Error("Not implemented");
123
- }
124
-
125
- async delete(id: string): Promise<void> {
126
- // TODO: Implement delete logic
127
- throw new Error("Not implemented");
128
- }
129
- }
102
+ const serviceContent = `/**
103
+ * ${className} service implementation.
104
+ */
105
+
106
+ import type { ${className}, Create${className}Input, Update${className}Input } from "./types.js";
107
+ import type { I${className}Service } from "./interface.js";
108
+
109
+ export class ${className}Service implements I${className}Service {
110
+ async create(input: Create${className}Input): Promise<${className}> {
111
+ // TODO: Implement creation logic
112
+ throw new Error("Not implemented");
113
+ }
114
+
115
+ async findById(id: string): Promise<${className} | null> {
116
+ // TODO: Implement find logic
117
+ throw new Error("Not implemented");
118
+ }
119
+
120
+ async update(input: Update${className}Input): Promise<${className}> {
121
+ // TODO: Implement update logic
122
+ throw new Error("Not implemented");
123
+ }
124
+
125
+ async delete(id: string): Promise<void> {
126
+ // TODO: Implement delete logic
127
+ throw new Error("Not implemented");
128
+ }
129
+ }
130
130
  `;
131
131
  writeFileSync(join(moduleDir, "service.ts"), serviceContent);
132
132
  files.push(`${relBase}/service.ts`);
133
133
  // Index barrel
134
- const indexContent = `export type { ${className}, Create${className}Input, Update${className}Input } from "./types.js";
135
- export type { I${className}Service } from "./interface.js";
136
- export { ${className}Service } from "./service.js";
134
+ const indexContent = `export type { ${className}, Create${className}Input, Update${className}Input } from "./types.js";
135
+ export type { I${className}Service } from "./interface.js";
136
+ export { ${className}Service } from "./service.js";
137
137
  `;
138
138
  writeFileSync(join(moduleDir, "index.ts"), indexContent);
139
139
  files.push(`${relBase}/index.ts`);
140
140
  // API routes if API tag present
141
141
  if (tags.includes("API")) {
142
- const routesContent = `/**
143
- * ${className} API routes.
144
- */
145
-
146
- // TODO: Register routes with your HTTP framework
147
- // Example:
148
- // router.post("/${moduleName}", create${className}Handler);
149
- // router.get("/${moduleName}/:id", get${className}Handler);
150
- // router.put("/${moduleName}/:id", update${className}Handler);
151
- // router.delete("/${moduleName}/:id", delete${className}Handler);
152
-
153
- export {};
142
+ const routesContent = `/**
143
+ * ${className} API routes.
144
+ */
145
+
146
+ // TODO: Register routes with your HTTP framework
147
+ // Example:
148
+ // router.post("/${moduleName}", create${className}Handler);
149
+ // router.get("/${moduleName}/:id", get${className}Handler);
150
+ // router.put("/${moduleName}/:id", update${className}Handler);
151
+ // router.delete("/${moduleName}/:id", delete${className}Handler);
152
+
153
+ export {};
154
154
  `;
155
155
  writeFileSync(join(moduleDir, "routes.ts"), routesContent);
156
156
  files.push(`${relBase}/routes.ts`);
@@ -158,17 +158,17 @@ export {};
158
158
  // Test file
159
159
  const testDir = join(moduleDir, "__tests__");
160
160
  mkdirSync(testDir, { recursive: true });
161
- const testContent = `import { describe, it, expect } from "vitest";
162
- import { ${className}Service } from "../service.js";
163
-
164
- describe("${className}Service", () => {
165
- it("should be defined", () => {
166
- const service = new ${className}Service();
167
- expect(service).toBeDefined();
168
- });
169
-
170
- // TODO: Add comprehensive tests
171
- });
161
+ const testContent = `import { describe, it, expect } from "vitest";
162
+ import { ${className}Service } from "../service.js";
163
+
164
+ describe("${className}Service", () => {
165
+ it("should be defined", () => {
166
+ const service = new ${className}Service();
167
+ expect(service).toBeDefined();
168
+ });
169
+
170
+ // TODO: Add comprehensive tests
171
+ });
172
172
  `;
173
173
  writeFileSync(join(testDir, `${moduleName}.test.ts`), testContent);
174
174
  files.push(`${relBase}/__tests__/${moduleName}.test.ts`);
@@ -185,48 +185,48 @@ function generatePythonModule(moduleDir, moduleName, className, _tags) {
185
185
  writeFileSync(join(moduleDir, "__init__.py"), `"""${className} module."""\n`);
186
186
  files.push(`${relBase}/__init__.py`);
187
187
  // models.py
188
- const modelsContent = `"""${className} data models."""
189
-
190
- from dataclasses import dataclass
191
-
192
-
193
- @dataclass
194
- class ${className}:
195
- id: str
196
- # TODO: Define ${className} fields
197
-
198
-
199
- @dataclass
200
- class Create${className}Input:
201
- # TODO: Define creation input
202
- pass
203
-
204
-
205
- @dataclass
206
- class Update${className}Input:
207
- id: str
208
- # TODO: Define update input
188
+ const modelsContent = `"""${className} data models."""
189
+
190
+ from dataclasses import dataclass
191
+
192
+
193
+ @dataclass
194
+ class ${className}:
195
+ id: str
196
+ # TODO: Define ${className} fields
197
+
198
+
199
+ @dataclass
200
+ class Create${className}Input:
201
+ # TODO: Define creation input
202
+ pass
203
+
204
+
205
+ @dataclass
206
+ class Update${className}Input:
207
+ id: str
208
+ # TODO: Define update input
209
209
  `;
210
210
  writeFileSync(join(moduleDir, "models.py"), modelsContent);
211
211
  files.push(`${relBase}/models.py`);
212
212
  // service.py
213
- const serviceContent = `"""${className} service."""
214
-
215
- from .models import ${className}, Create${className}Input, Update${className}Input
216
-
217
-
218
- class ${className}Service:
219
- async def create(self, input: Create${className}Input) -> ${className}:
220
- raise NotImplementedError
221
-
222
- async def find_by_id(self, id: str) -> ${className} | None:
223
- raise NotImplementedError
224
-
225
- async def update(self, input: Update${className}Input) -> ${className}:
226
- raise NotImplementedError
227
-
228
- async def delete(self, id: str) -> None:
229
- raise NotImplementedError
213
+ const serviceContent = `"""${className} service."""
214
+
215
+ from .models import ${className}, Create${className}Input, Update${className}Input
216
+
217
+
218
+ class ${className}Service:
219
+ async def create(self, input: Create${className}Input) -> ${className}:
220
+ raise NotImplementedError
221
+
222
+ async def find_by_id(self, id: str) -> ${className} | None:
223
+ raise NotImplementedError
224
+
225
+ async def update(self, input: Update${className}Input) -> ${className}:
226
+ raise NotImplementedError
227
+
228
+ async def delete(self, id: str) -> None:
229
+ raise NotImplementedError
230
230
  `;
231
231
  writeFileSync(join(moduleDir, "service.py"), serviceContent);
232
232
  files.push(`${relBase}/service.py`);
@@ -189,24 +189,24 @@ export function smokeConfigExample(tags) {
189
189
  if (hasApi) {
190
190
  projects.push(" // API smoke uses APIRequestContext — no browser project needed");
191
191
  }
192
- return `
193
- ## Example: playwright.smoke.config.ts
194
-
195
- \`\`\`typescript
196
- import { defineConfig${hasBrowser ? ", devices" : ""} } from '@playwright/test';
197
-
198
- export default defineConfig({
199
- testMatch: '**/*.smoke.ts',
200
- retries: 1, // one retry — smoke fail = broken deploy
201
- timeout: 15_000,
202
- use: {
203
- baseURL: process.env['PLAYWRIGHT_BASE_URL'] ?? 'http://localhost:3000',
204
- // Never run smoke against localhost in CI — use staging URL
205
- },${hasBrowser ? `\n projects: [\n${projects.join(",\n")}\n ],` : ""}
206
- });
207
- \`\`\`
208
-
209
- Run with: \`npx playwright test --config playwright.smoke.config.ts\`
192
+ return `
193
+ ## Example: playwright.smoke.config.ts
194
+
195
+ \`\`\`typescript
196
+ import { defineConfig${hasBrowser ? ", devices" : ""} } from '@playwright/test';
197
+
198
+ export default defineConfig({
199
+ testMatch: '**/*.smoke.ts',
200
+ retries: 1, // one retry — smoke fail = broken deploy
201
+ timeout: 15_000,
202
+ use: {
203
+ baseURL: process.env['PLAYWRIGHT_BASE_URL'] ?? 'http://localhost:3000',
204
+ // Never run smoke against localhost in CI — use staging URL
205
+ },${hasBrowser ? `\n projects: [\n${projects.join(",\n")}\n ],` : ""}
206
+ });
207
+ \`\`\`
208
+
209
+ Run with: \`npx playwright test --config playwright.smoke.config.ts\`
210
210
  `;
211
211
  }
212
212
  //# sourceMappingURL=advice-registry.js.map