forgecraft-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/README.md +251 -0
  2. package/dist/analyzers/anti-pattern.d.ts +21 -0
  3. package/dist/analyzers/anti-pattern.d.ts.map +1 -0
  4. package/dist/analyzers/anti-pattern.js +130 -0
  5. package/dist/analyzers/anti-pattern.js.map +1 -0
  6. package/dist/analyzers/completeness.d.ts +15 -0
  7. package/dist/analyzers/completeness.d.ts.map +1 -0
  8. package/dist/analyzers/completeness.js +207 -0
  9. package/dist/analyzers/completeness.js.map +1 -0
  10. package/dist/analyzers/folder-structure.d.ts +35 -0
  11. package/dist/analyzers/folder-structure.d.ts.map +1 -0
  12. package/dist/analyzers/folder-structure.js +151 -0
  13. package/dist/analyzers/folder-structure.js.map +1 -0
  14. package/dist/analyzers/package-json.d.ts +22 -0
  15. package/dist/analyzers/package-json.d.ts.map +1 -0
  16. package/dist/analyzers/package-json.js +229 -0
  17. package/dist/analyzers/package-json.js.map +1 -0
  18. package/dist/index.d.ts +9 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +59 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/registry/composer.d.ts +32 -0
  23. package/dist/registry/composer.d.ts.map +1 -0
  24. package/dist/registry/composer.js +169 -0
  25. package/dist/registry/composer.js.map +1 -0
  26. package/dist/registry/loader.d.ts +37 -0
  27. package/dist/registry/loader.d.ts.map +1 -0
  28. package/dist/registry/loader.js +278 -0
  29. package/dist/registry/loader.js.map +1 -0
  30. package/dist/registry/renderer.d.ts +53 -0
  31. package/dist/registry/renderer.d.ts.map +1 -0
  32. package/dist/registry/renderer.js +275 -0
  33. package/dist/registry/renderer.js.map +1 -0
  34. package/dist/shared/config/index.d.ts +15 -0
  35. package/dist/shared/config/index.d.ts.map +1 -0
  36. package/dist/shared/config/index.js +16 -0
  37. package/dist/shared/config/index.js.map +1 -0
  38. package/dist/shared/errors/index.d.ts +30 -0
  39. package/dist/shared/errors/index.d.ts.map +1 -0
  40. package/dist/shared/errors/index.js +44 -0
  41. package/dist/shared/errors/index.js.map +1 -0
  42. package/dist/shared/logger/index.d.ts +27 -0
  43. package/dist/shared/logger/index.d.ts.map +1 -0
  44. package/dist/shared/logger/index.js +59 -0
  45. package/dist/shared/logger/index.js.map +1 -0
  46. package/dist/shared/types.d.ts +212 -0
  47. package/dist/shared/types.d.ts.map +1 -0
  48. package/dist/shared/types.js +30 -0
  49. package/dist/shared/types.js.map +1 -0
  50. package/dist/tools/add-hook.d.ts +26 -0
  51. package/dist/tools/add-hook.d.ts.map +1 -0
  52. package/dist/tools/add-hook.js +82 -0
  53. package/dist/tools/add-hook.js.map +1 -0
  54. package/dist/tools/add-module.d.ts +29 -0
  55. package/dist/tools/add-module.d.ts.map +1 -0
  56. package/dist/tools/add-module.js +244 -0
  57. package/dist/tools/add-module.js.map +1 -0
  58. package/dist/tools/audit.d.ts +26 -0
  59. package/dist/tools/audit.d.ts.map +1 -0
  60. package/dist/tools/audit.js +111 -0
  61. package/dist/tools/audit.js.map +1 -0
  62. package/dist/tools/classify.d.ts +23 -0
  63. package/dist/tools/classify.d.ts.map +1 -0
  64. package/dist/tools/classify.js +73 -0
  65. package/dist/tools/classify.js.map +1 -0
  66. package/dist/tools/configure-mcp.d.ts +49 -0
  67. package/dist/tools/configure-mcp.d.ts.map +1 -0
  68. package/dist/tools/configure-mcp.js +127 -0
  69. package/dist/tools/configure-mcp.js.map +1 -0
  70. package/dist/tools/convert.d.ts +27 -0
  71. package/dist/tools/convert.d.ts.map +1 -0
  72. package/dist/tools/convert.js +154 -0
  73. package/dist/tools/convert.js.map +1 -0
  74. package/dist/tools/generate-claude-md.d.ts +29 -0
  75. package/dist/tools/generate-claude-md.d.ts.map +1 -0
  76. package/dist/tools/generate-claude-md.js +116 -0
  77. package/dist/tools/generate-claude-md.js.map +1 -0
  78. package/dist/tools/get-nfr.d.ts +20 -0
  79. package/dist/tools/get-nfr.d.ts.map +1 -0
  80. package/dist/tools/get-nfr.js +53 -0
  81. package/dist/tools/get-nfr.js.map +1 -0
  82. package/dist/tools/list.d.ts +33 -0
  83. package/dist/tools/list.d.ts.map +1 -0
  84. package/dist/tools/list.js +155 -0
  85. package/dist/tools/list.js.map +1 -0
  86. package/dist/tools/refresh-project.d.ts +34 -0
  87. package/dist/tools/refresh-project.d.ts.map +1 -0
  88. package/dist/tools/refresh-project.js +257 -0
  89. package/dist/tools/refresh-project.js.map +1 -0
  90. package/dist/tools/review.d.ts +31 -0
  91. package/dist/tools/review.d.ts.map +1 -0
  92. package/dist/tools/review.js +62 -0
  93. package/dist/tools/review.js.map +1 -0
  94. package/dist/tools/scaffold.d.ts +32 -0
  95. package/dist/tools/scaffold.d.ts.map +1 -0
  96. package/dist/tools/scaffold.js +160 -0
  97. package/dist/tools/scaffold.js.map +1 -0
  98. package/dist/tools/setup-project.d.ts +37 -0
  99. package/dist/tools/setup-project.d.ts.map +1 -0
  100. package/dist/tools/setup-project.js +270 -0
  101. package/dist/tools/setup-project.js.map +1 -0
  102. package/package.json +69 -0
  103. package/templates/analytics/claude-md.yaml +37 -0
  104. package/templates/analytics/structure.yaml +25 -0
  105. package/templates/api/claude-md.yaml +85 -0
  106. package/templates/api/nfr.yaml +23 -0
  107. package/templates/api/review.yaml +103 -0
  108. package/templates/api/structure.yaml +34 -0
  109. package/templates/cli/claude-md.yaml +31 -0
  110. package/templates/cli/review.yaml +53 -0
  111. package/templates/cli/structure.yaml +16 -0
  112. package/templates/data-pipeline/claude-md.yaml +42 -0
  113. package/templates/data-pipeline/nfr.yaml +39 -0
  114. package/templates/data-pipeline/structure.yaml +23 -0
  115. package/templates/fintech/claude-md.yaml +42 -0
  116. package/templates/fintech/nfr.yaml +46 -0
  117. package/templates/game/claude-md.yaml +42 -0
  118. package/templates/healthcare/claude-md.yaml +42 -0
  119. package/templates/healthcare/nfr.yaml +47 -0
  120. package/templates/infra/claude-md.yaml +104 -0
  121. package/templates/infra/nfr.yaml +46 -0
  122. package/templates/infra/review.yaml +65 -0
  123. package/templates/infra/structure.yaml +25 -0
  124. package/templates/library/claude-md.yaml +36 -0
  125. package/templates/library/review.yaml +56 -0
  126. package/templates/library/structure.yaml +19 -0
  127. package/templates/ml/claude-md.yaml +42 -0
  128. package/templates/ml/nfr.yaml +39 -0
  129. package/templates/ml/structure.yaml +25 -0
  130. package/templates/mobile/claude-md.yaml +44 -0
  131. package/templates/mobile/nfr.yaml +49 -0
  132. package/templates/mobile/structure.yaml +27 -0
  133. package/templates/realtime/claude-md.yaml +42 -0
  134. package/templates/social/claude-md.yaml +43 -0
  135. package/templates/state-machine/claude-md.yaml +42 -0
  136. package/templates/universal/claude-md.yaml +477 -0
  137. package/templates/universal/hooks.yaml +196 -0
  138. package/templates/universal/nfr.yaml +197 -0
  139. package/templates/universal/review.yaml +164 -0
  140. package/templates/universal/structure.yaml +52 -0
  141. package/templates/web-react/claude-md.yaml +110 -0
  142. package/templates/web-react/hooks.yaml +44 -0
  143. package/templates/web-react/nfr.yaml +27 -0
  144. package/templates/web-react/review.yaml +94 -0
  145. package/templates/web-react/structure.yaml +46 -0
  146. package/templates/web-static/claude-md.yaml +73 -0
  147. package/templates/web3/claude-md.yaml +44 -0
package/README.md ADDED
@@ -0,0 +1,251 @@
1
+ <p align="center">
2
+ <h1 align="center">ForgeCraft</h1>
3
+ <p align="center">
4
+ <strong>Give Claude Code real engineering standards. Automatically.</strong>
5
+ </p>
6
+ <p align="center">
7
+ <a href="https://www.npmjs.com/package/forgecraft-mcp"><img src="https://img.shields.io/npm/v/forgecraft-mcp.svg" alt="npm version"></a>
8
+ <a href="https://github.com/jghiringhelli/forgecraft-mcp/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/forgecraft-mcp.svg" alt="license"></a>
9
+ <a href="https://www.npmjs.com/package/forgecraft-mcp"><img src="https://img.shields.io/npm/dm/forgecraft-mcp.svg" alt="downloads"></a>
10
+ </p>
11
+ </p>
12
+
13
+ ---
14
+
15
+ `claude init` gets you started — it scans your project and generates a basic CLAUDE.md. That's a great first step.
16
+
17
+ **ForgeCraft is the next step.**
18
+
19
+ `claude init` gives you a generic starting point. ForgeCraft gives you production engineering standards: SOLID principles, testing pyramids with coverage targets, architecture patterns, CI/CD pipelines, domain-specific rules, and quality-gate hooks — all composed from 112 curated template blocks matched to your actual stack.
20
+
21
+ ```bash
22
+ claude mcp add forgecraft -- npx -y forgecraft-mcp
23
+ ```
24
+
25
+ Then tell Claude:
26
+
27
+ > "Set up this project for production"
28
+
29
+ Done. Claude now has a tailored CLAUDE.md with SOLID principles, testing standards, architecture patterns, CI/CD guidance, and quality-gate hooks — all matched to your stack.
30
+
31
+ ## `claude init` vs ForgeCraft
32
+
33
+ | | `claude init` | ForgeCraft |
34
+ |---|---|---|
35
+ | **CLAUDE.md** | Generic, one-size-fits-all | 112 curated blocks matched to your stack |
36
+ | **Architecture** | None | SOLID, hexagonal, clean code, DDD |
37
+ | **Testing** | Basic mention | Testing pyramid with coverage targets (80%+) |
38
+ | **Domain rules** | None | 18 domains (fintech, healthcare, gaming…) |
39
+ | **Commit standards** | None | Conventional commits, atomic changes |
40
+ | **Quality gates** | None | Pre-commit hooks that enforce standards |
41
+ | **CI/CD** | None | Pipeline stages, environments, deploy guidance |
42
+ | **Session continuity** | None | `Status.md` + `forgecraft.yaml` persist context |
43
+ | **Drift detection** | None | `refresh_project` detects scope changes |
44
+ | **Compliance scoring** | None | `audit_project` scores 0-100 |
45
+
46
+ ## How It Works
47
+
48
+ ```
49
+ You: "Set up this project for production"
50
+
51
+ Claude calls setup_project → scans your code → detects [API] + [WEB-REACT]
52
+ → creates forgecraft.yaml
53
+ → generates CLAUDE.md from 112 curated template blocks
54
+ → adds quality-gate hooks
55
+ → done
56
+ ```
57
+
58
+ ForgeCraft is an [MCP server](https://modelcontextprotocol.io/) — it gives Claude 14 specialized tools. Claude picks the right ones automatically. You just describe what you want in plain English.
59
+
60
+ > **Already ran `claude init`?** ForgeCraft's `generate_claude_md` can merge with your existing CLAUDE.md (`merge_with_existing: true`), keeping your custom sections while adding production standards.
61
+
62
+ ## Install
63
+
64
+ **One line. Takes 10 seconds.**
65
+
66
+ ```bash
67
+ claude mcp add forgecraft -- npx -y forgecraft-mcp
68
+ ```
69
+
70
+ Restart Claude Code. That's it.
71
+
72
+ <details>
73
+ <summary>Alternative: manual config</summary>
74
+
75
+ Add to `.claude/settings.json`:
76
+ ```json
77
+ {
78
+ "mcpServers": {
79
+ "forgecraft": {
80
+ "command": "npx",
81
+ "args": ["-y", "forgecraft-mcp"]
82
+ }
83
+ }
84
+ }
85
+ ```
86
+ </details>
87
+
88
+ ## What You Get
89
+
90
+ After `setup_project`, your project has:
91
+
92
+ ```
93
+ your-project/
94
+ ├── forgecraft.yaml ← Your config (tags, tier, customizations)
95
+ ├── CLAUDE.md ← Engineering standards tailored to your stack
96
+ ├── Status.md ← Session continuity tracker
97
+ ├── .claude/hooks/ ← Pre-commit quality gates
98
+ ├── docs/
99
+ │ ├── PRD.md ← Requirements skeleton
100
+ │ └── TechSpec.md ← Architecture + NFR sections
101
+ └── src/shared/ ← Config, errors, logger starters
102
+ ```
103
+
104
+ ### The CLAUDE.md
105
+
106
+ This is the core value. Assembled from curated blocks covering:
107
+
108
+ - **SOLID principles** — concrete rules, not platitudes
109
+ - **Hexagonal architecture** — ports, adapters, DTOs, layer boundaries
110
+ - **Testing pyramid** — unit/integration/E2E targets, test doubles taxonomy
111
+ - **Clean code** — CQS, guard clauses, immutability, pure functions
112
+ - **CI/CD & deployment** — pipeline stages, environments, preview deploys
113
+ - **Domain patterns** — DDD, CQRS, event sourcing (when your project needs it)
114
+ - **12-Factor ops** — config, statelessness, disposability, logging
115
+
116
+ Every block is sourced from established engineering literature (Martin, Evans, Wiggins) and adapted for AI-assisted development.
117
+
118
+ ## 18 Tags — Pick What Fits
119
+
120
+ Tags are domain classifiers. ForgeCraft auto-detects them from your code, or you choose manually. Combine freely — blocks merge without conflicts.
121
+
122
+ | Tag | What it adds |
123
+ |-----|-------------|
124
+ | `UNIVERSAL` | SOLID, testing, commits, error handling *(always on)* |
125
+ | `API` | REST/GraphQL contracts, auth, rate limiting, versioning |
126
+ | `WEB-REACT` | Component arch, state management, a11y, perf budgets |
127
+ | `WEB-STATIC` | Build optimization, SEO, CDN, static deploy |
128
+ | `CLI` | Arg parsing, output formatting, exit codes |
129
+ | `LIBRARY` | API design, semver, backwards compatibility |
130
+ | `INFRA` | Terraform/CDK, Kubernetes, secrets management |
131
+ | `DATA-PIPELINE` | ETL, idempotency, checkpointing, schema evolution |
132
+ | `ML` | Experiment tracking, model versioning, reproducibility |
133
+ | `FINTECH` | Double-entry accounting, decimal precision, compliance |
134
+ | `HEALTHCARE` | HIPAA, PHI handling, audit logs, encryption |
135
+ | `MOBILE` | React Native/Flutter, offline-first, native APIs |
136
+ | `REALTIME` | WebSockets, presence, conflict resolution |
137
+ | `GAME` | Game loop, ECS, physics, rendering pipeline |
138
+ | `SOCIAL` | Feeds, connections, messaging, moderation |
139
+ | `ANALYTICS` | Event tracking, dashboards, data warehousing |
140
+ | `STATE-MACHINE` | Transitions, guards, event-driven workflows |
141
+ | `WEB3` | Smart contracts, gas optimization, wallet security |
142
+
143
+ ## Content Tiers
144
+
145
+ Not every project needs DDD on day one.
146
+
147
+ | Tier | Includes | Best for |
148
+ |------|----------|----------|
149
+ | **core** | Code standards, testing, commit protocol | New/small projects |
150
+ | **recommended** | + architecture, CI/CD, clean code, deploy | Most projects *(default)* |
151
+ | **optional** | + DDD, CQRS, event sourcing, design patterns | Mature teams, complex domains |
152
+
153
+ Set in `forgecraft.yaml`:
154
+ ```yaml
155
+ projectName: my-api
156
+ tags: [UNIVERSAL, API]
157
+ tier: recommended
158
+ ```
159
+
160
+ ## All 14 Tools
161
+
162
+ | Tool | Purpose |
163
+ |------|---------|
164
+ | `setup_project` | **Start here.** Analyze → classify → configure → generate. |
165
+ | `refresh_project` | Re-scan after changes. Detects new tags, updates config. |
166
+ | `classify_project` | Analyze code to suggest tags |
167
+ | `scaffold_project` | Generate full project structure |
168
+ | `generate_claude_md` | Create/regenerate CLAUDE.md |
169
+ | `audit_project` | Score compliance (0-100). Run in CI. |
170
+ | `review_project` | Structured review checklist |
171
+ | `convert_existing` | Phased migration plan for legacy code |
172
+ | `add_hook` | Add quality-gate hooks |
173
+ | `add_module` | Scaffold a feature module |
174
+ | `configure_mcp` | Generate `.claude/settings.json` |
175
+ | `get_nfr_template` | NFR sections for tech specs |
176
+ | `list_tags` | Show all available tags |
177
+ | `list_hooks` | Show hooks, filterable by tag |
178
+
179
+ ## Configuration
180
+
181
+ ### Fine-tune what Claude sees
182
+
183
+ ```yaml
184
+ # forgecraft.yaml
185
+ projectName: my-api
186
+ tags: [UNIVERSAL, API, FINTECH]
187
+ tier: recommended
188
+
189
+ exclude:
190
+ - cqrs-event-patterns # Don't need this yet
191
+
192
+ variables:
193
+ coverage_minimum: 90 # Override defaults
194
+ max_file_length: 400
195
+ ```
196
+
197
+ ### Community template packs
198
+
199
+ ```yaml
200
+ templateDirs:
201
+ - ./my-company-standards
202
+ - node_modules/@my-org/forgecraft-flutter/templates
203
+ ```
204
+
205
+ ## Keeping Standards Fresh
206
+
207
+ ### Audit (run anytime, or in CI)
208
+
209
+ ```
210
+ Score: 72/100 Grade: C
211
+
212
+ ✅ CLAUDE.md exists
213
+ ✅ Hooks installed (3/3)
214
+ ✅ Test script configured
215
+ 🔴 hardcoded_url: src/auth/service.ts
216
+ 🔴 status_md_current: not updated in 12 days
217
+ 🟡 lock_file: not committed
218
+ ```
219
+
220
+ ### Refresh (project scope changed?)
221
+
222
+ Tell Claude *"refresh this project"* — it re-scans, suggests new tags, shows before/after impact, and updates everything on approval.
223
+
224
+ ## Contributing
225
+
226
+ Templates are YAML, not code. You can add patterns without writing TypeScript.
227
+
228
+ ```
229
+ templates/your-tag/
230
+ ├── claude-md.yaml # CLAUDE.md blocks (with tier metadata)
231
+ ├── structure.yaml # Folder structure
232
+ ├── nfr.yaml # Non-functional requirements
233
+ ├── hooks.yaml # Quality gate scripts
234
+ └── review.yaml # Code review checklists
235
+ ```
236
+
237
+ PRs welcome. See [`templates/universal/`](templates/universal/) for the format.
238
+
239
+ ## Development
240
+
241
+ ```bash
242
+ git clone https://github.com/jghiringhelli/forgecraft-mcp.git
243
+ cd forgecraft-mcp
244
+ npm install
245
+ npm run build
246
+ npm test # 111 tests, 9 suites
247
+ ```
248
+
249
+ ## License
250
+
251
+ MIT
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Anti-pattern detector.
3
+ *
4
+ * Scans source files for production code anti-patterns:
5
+ * hardcoded values, mock data in source, monolith files, etc.
6
+ */
7
+ import type { AuditCheck } from "../shared/types.js";
8
+ /** Anti-pattern scan configuration. */
9
+ interface ScanConfig {
10
+ readonly maxFileLength: number;
11
+ readonly maxFunctionParams: number;
12
+ }
13
+ /**
14
+ * Scan project source files for anti-patterns.
15
+ */
16
+ export declare function scanAntiPatterns(projectDir: string, config?: Partial<ScanConfig>): {
17
+ violations: AuditCheck[];
18
+ warnings: AuditCheck[];
19
+ };
20
+ export {};
21
+ //# sourceMappingURL=anti-pattern.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anti-pattern.d.ts","sourceRoot":"","sources":["../../src/analyzers/anti-pattern.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAIrD,uCAAuC;AACvC,UAAU,UAAU;IAClB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACpC;AAOD;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,EAClB,MAAM,GAAE,OAAO,CAAC,UAAU,CAAM,GAC/B;IAAE,UAAU,EAAE,UAAU,EAAE,CAAC;IAAC,QAAQ,EAAE,UAAU,EAAE,CAAA;CAAE,CA+FtD"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Anti-pattern detector.
3
+ *
4
+ * Scans source files for production code anti-patterns:
5
+ * hardcoded values, mock data in source, monolith files, etc.
6
+ */
7
+ import { readFileSync, existsSync } from "node:fs";
8
+ import { join, extname } from "node:path";
9
+ import { createLogger } from "../shared/logger/index.js";
10
+ import { listAllFiles } from "./folder-structure.js";
11
+ const logger = createLogger("analyzers/anti-pattern");
12
+ const DEFAULT_CONFIG = {
13
+ maxFileLength: 300,
14
+ maxFunctionParams: 5,
15
+ };
16
+ /**
17
+ * Scan project source files for anti-patterns.
18
+ */
19
+ export function scanAntiPatterns(projectDir, config = {}) {
20
+ const cfg = { ...DEFAULT_CONFIG, ...config };
21
+ const violations = [];
22
+ const warnings = [];
23
+ const allFiles = listAllFiles(projectDir);
24
+ const sourceFiles = allFiles.filter((f) => isSourceFile(f) && !isTestFile(f));
25
+ logger.info("Scanning for anti-patterns", {
26
+ totalFiles: allFiles.length,
27
+ sourceFiles: sourceFiles.length,
28
+ });
29
+ for (const relPath of sourceFiles) {
30
+ const fullPath = join(projectDir, relPath);
31
+ if (!existsSync(fullPath))
32
+ continue;
33
+ try {
34
+ const content = readFileSync(fullPath, "utf-8");
35
+ const lines = content.split("\n");
36
+ // Check file length
37
+ if (lines.length > cfg.maxFileLength) {
38
+ warnings.push({
39
+ check: "file_length",
40
+ message: `${relPath}: ${lines.length} lines (max ${cfg.maxFileLength}). Consider splitting.`,
41
+ severity: "warning",
42
+ });
43
+ }
44
+ // Check for hardcoded URLs (skip config files)
45
+ if (!isConfigFile(relPath)) {
46
+ const urlMatches = findPattern(lines, /(localhost|127\.0\.0\.1|0\.0\.0\.0)/, /\/\/|\/\*|\*|#|test|spec|mock/i);
47
+ if (urlMatches.length > 0) {
48
+ violations.push({
49
+ check: "hardcoded_url",
50
+ message: `${relPath}: hardcoded URL/host at line(s) ${urlMatches.join(", ")}. Use config/env vars.`,
51
+ severity: "error",
52
+ });
53
+ }
54
+ }
55
+ // Check for mock/stub data in production code
56
+ const mockMatches = findPattern(lines, /\b(mock_data|fake_data|dummy_data|stub_response|FIXME.*return|TODO.*hardcod)/i);
57
+ if (mockMatches.length > 0) {
58
+ violations.push({
59
+ check: "mock_in_source",
60
+ message: `${relPath}: mock/stub/fake data at line(s) ${mockMatches.join(", ")}. Remove from production code.`,
61
+ severity: "error",
62
+ });
63
+ }
64
+ // Check for bare exception catches (TypeScript)
65
+ if (relPath.endsWith(".ts") || relPath.endsWith(".js")) {
66
+ const bareCatches = findPattern(lines, /catch\s*\(\s*\)\s*\{/);
67
+ if (bareCatches.length > 0) {
68
+ warnings.push({
69
+ check: "bare_exception",
70
+ message: `${relPath}: bare catch() at line(s) ${bareCatches.join(", ")}. Use typed error handling.`,
71
+ severity: "warning",
72
+ });
73
+ }
74
+ }
75
+ // Check for hardcoded credentials
76
+ const credMatches = findPattern(lines, /(password|secret|api_key|token)\s*[:=]\s*['"][^'"]{3,}/i, /env|config|example|template|schema|type|interface|\/\//i);
77
+ if (credMatches.length > 0) {
78
+ violations.push({
79
+ check: "hardcoded_credential",
80
+ message: `${relPath}: possible hardcoded credential at line(s) ${credMatches.join(", ")}.`,
81
+ severity: "error",
82
+ });
83
+ }
84
+ }
85
+ catch {
86
+ // Skip unreadable files
87
+ }
88
+ }
89
+ logger.info("Anti-pattern scan complete", {
90
+ violations: violations.length,
91
+ warnings: warnings.length,
92
+ });
93
+ return { violations, warnings };
94
+ }
95
+ /**
96
+ * Check if a file is a source code file.
97
+ */
98
+ function isSourceFile(filePath) {
99
+ const ext = extname(filePath);
100
+ return [".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".kt", ".rs"].includes(ext);
101
+ }
102
+ /**
103
+ * Check if a file is a test file.
104
+ */
105
+ function isTestFile(filePath) {
106
+ return /(\btest[_.]|\.test\.|\.spec\.|__tests__|tests\/|test\/|fixtures\/|mock|conftest|\.d\.ts)/.test(filePath);
107
+ }
108
+ /**
109
+ * Check if a file is a config file.
110
+ */
111
+ function isConfigFile(filePath) {
112
+ return /(config|settings|\.env|\.yaml|\.yml|\.json|\.toml)/.test(filePath);
113
+ }
114
+ /**
115
+ * Find lines matching a pattern, optionally excluding lines matching an exclude pattern.
116
+ * Returns array of 1-based line numbers.
117
+ */
118
+ function findPattern(lines, pattern, excludePattern) {
119
+ const matches = [];
120
+ for (let i = 0; i < lines.length; i++) {
121
+ const line = lines[i];
122
+ if (pattern.test(line)) {
123
+ if (!excludePattern || !excludePattern.test(line)) {
124
+ matches.push(i + 1);
125
+ }
126
+ }
127
+ }
128
+ return matches;
129
+ }
130
+ //# sourceMappingURL=anti-pattern.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anti-pattern.js","sourceRoot":"","sources":["../../src/analyzers/anti-pattern.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Completeness checker.
3
+ *
4
+ * Checks a project against the expected infrastructure for its tags.
5
+ * Reports what's present, missing, and suggestions.
6
+ */
7
+ import type { AuditCheck, Tag } from "../shared/types.js";
8
+ /**
9
+ * Run all completeness checks for a project.
10
+ */
11
+ export declare function checkCompleteness(projectDir: string, activeTags: Tag[]): {
12
+ passing: AuditCheck[];
13
+ failing: AuditCheck[];
14
+ };
15
+ //# sourceMappingURL=completeness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completeness.d.ts","sourceRoot":"","sources":["../../src/analyzers/completeness.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAI1D;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,GAAG,EAAE,GAChB;IAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IAAC,OAAO,EAAE,UAAU,EAAE,CAAA;CAAE,CAqClD"}
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Completeness checker.
3
+ *
4
+ * Checks a project against the expected infrastructure for its tags.
5
+ * Reports what's present, missing, and suggestions.
6
+ */
7
+ import { existsSync, readFileSync, statSync } from "node:fs";
8
+ import { join } from "node:path";
9
+ import { createLogger } from "../shared/logger/index.js";
10
+ const logger = createLogger("analyzers/completeness");
11
+ /**
12
+ * Run all completeness checks for a project.
13
+ */
14
+ export function checkCompleteness(projectDir, activeTags) {
15
+ const passing = [];
16
+ const failing = [];
17
+ // UNIVERSAL checks — always run
18
+ checkFileExists(projectDir, "CLAUDE.md", "claude_md_exists", "CLAUDE.md is the CC instruction set", passing, failing);
19
+ checkFileExists(projectDir, "Status.md", "status_md_exists", "Status.md enables session continuity", passing, failing);
20
+ checkFileExists(projectDir, ".env.example", "env_example_exists", ".env.example documents required env vars", passing, failing);
21
+ // Check Status.md freshness
22
+ checkStatusMdFreshness(projectDir, passing, failing);
23
+ // Check hooks
24
+ checkHooksInstalled(projectDir, passing, failing);
25
+ // Check docs
26
+ checkFileExists(projectDir, "docs/PRD.md", "prd_exists", "PRD documents requirements", passing, failing);
27
+ checkFileExists(projectDir, "docs/TechSpec.md", "tech_spec_exists", "Tech Spec documents architecture", passing, failing);
28
+ // Check shared modules
29
+ checkSharedModules(projectDir, passing, failing);
30
+ // Tag-specific checks
31
+ if (activeTags.includes("API") || activeTags.includes("LIBRARY")) {
32
+ checkPackageJson(projectDir, passing, failing);
33
+ }
34
+ if (activeTags.includes("WEB-REACT")) {
35
+ checkFileExists(projectDir, "src/locales", "i18n_setup", "i18n locale files configured", passing, failing);
36
+ }
37
+ logger.info("Completeness check done", {
38
+ passing: passing.length,
39
+ failing: failing.length,
40
+ });
41
+ return { passing, failing };
42
+ }
43
+ /**
44
+ * Check if a file or directory exists.
45
+ */
46
+ function checkFileExists(projectDir, relativePath, checkId, description, passing, failing) {
47
+ const fullPath = join(projectDir, relativePath);
48
+ if (existsSync(fullPath)) {
49
+ passing.push({ check: checkId, message: `✅ ${relativePath} exists` });
50
+ }
51
+ else {
52
+ failing.push({
53
+ check: checkId,
54
+ message: `${relativePath} is missing — ${description}`,
55
+ severity: "error",
56
+ });
57
+ }
58
+ }
59
+ /**
60
+ * Check if Status.md was updated recently (within 7 days).
61
+ */
62
+ function checkStatusMdFreshness(projectDir, passing, failing) {
63
+ const statusPath = join(projectDir, "Status.md");
64
+ if (!existsSync(statusPath))
65
+ return;
66
+ try {
67
+ const stat = statSync(statusPath);
68
+ const daysSinceModified = (Date.now() - stat.mtimeMs) / (1000 * 60 * 60 * 24);
69
+ if (daysSinceModified <= 7) {
70
+ passing.push({
71
+ check: "status_md_current",
72
+ message: `✅ Status.md updated ${Math.round(daysSinceModified)} day(s) ago`,
73
+ });
74
+ }
75
+ else {
76
+ failing.push({
77
+ check: "status_md_current",
78
+ message: `Status.md not updated in ${Math.round(daysSinceModified)} days — update at end of each session`,
79
+ severity: "warning",
80
+ });
81
+ }
82
+ }
83
+ catch {
84
+ // Can't stat the file, skip this check
85
+ }
86
+ }
87
+ /**
88
+ * Check if hook scripts are installed.
89
+ */
90
+ function checkHooksInstalled(projectDir, passing, failing) {
91
+ const hooksDir = join(projectDir, ".claude", "hooks");
92
+ if (!existsSync(hooksDir)) {
93
+ failing.push({
94
+ check: "hooks_installed",
95
+ message: ".claude/hooks/ directory missing — quality gate hooks not installed",
96
+ severity: "error",
97
+ });
98
+ return;
99
+ }
100
+ // Check for key hooks
101
+ const expectedHooks = [
102
+ "pre-commit-branch-check.sh",
103
+ "pre-commit-secrets.sh",
104
+ "pre-commit-compile.sh",
105
+ ];
106
+ let hookCount = 0;
107
+ for (const hookFile of expectedHooks) {
108
+ if (existsSync(join(hooksDir, hookFile))) {
109
+ hookCount++;
110
+ }
111
+ }
112
+ if (hookCount === expectedHooks.length) {
113
+ passing.push({
114
+ check: "hooks_installed",
115
+ message: `✅ ${hookCount}/${expectedHooks.length} essential hooks installed`,
116
+ });
117
+ }
118
+ else {
119
+ failing.push({
120
+ check: "hooks_installed",
121
+ message: `Only ${hookCount}/${expectedHooks.length} essential hooks installed`,
122
+ severity: "warning",
123
+ });
124
+ }
125
+ }
126
+ /**
127
+ * Check for shared modules (config, errors, logging).
128
+ */
129
+ function checkSharedModules(projectDir, passing, failing) {
130
+ const sharedPatterns = [
131
+ { path: "src/shared/config", name: "config module" },
132
+ { path: "src/shared/errors", name: "error hierarchy" },
133
+ { path: "src/shared/exceptions", name: "exception hierarchy" },
134
+ ];
135
+ let foundShared = false;
136
+ for (const pattern of sharedPatterns) {
137
+ if (existsSync(join(projectDir, pattern.path))) {
138
+ foundShared = true;
139
+ break;
140
+ }
141
+ }
142
+ if (foundShared) {
143
+ passing.push({
144
+ check: "shared_modules",
145
+ message: "✅ Shared modules (config/errors) present",
146
+ });
147
+ }
148
+ else {
149
+ failing.push({
150
+ check: "shared_modules",
151
+ message: "No shared modules found — create config, errors, logging modules in src/shared/",
152
+ severity: "warning",
153
+ });
154
+ }
155
+ }
156
+ /**
157
+ * Check package.json for required fields.
158
+ */
159
+ function checkPackageJson(projectDir, passing, failing) {
160
+ const pkgPath = join(projectDir, "package.json");
161
+ if (!existsSync(pkgPath)) {
162
+ failing.push({
163
+ check: "package_json",
164
+ message: "package.json missing",
165
+ severity: "error",
166
+ });
167
+ return;
168
+ }
169
+ try {
170
+ const content = readFileSync(pkgPath, "utf-8");
171
+ const pkg = JSON.parse(content);
172
+ // Check for lock file
173
+ const hasLockFile = existsSync(join(projectDir, "package-lock.json")) ||
174
+ existsSync(join(projectDir, "pnpm-lock.yaml")) ||
175
+ existsSync(join(projectDir, "yarn.lock"));
176
+ if (hasLockFile) {
177
+ passing.push({ check: "lock_file", message: "✅ Lock file committed" });
178
+ }
179
+ else {
180
+ failing.push({
181
+ check: "lock_file",
182
+ message: "No lock file found — commit package-lock.json",
183
+ severity: "warning",
184
+ });
185
+ }
186
+ // Check for scripts
187
+ const scripts = pkg["scripts"];
188
+ if (scripts?.["test"]) {
189
+ passing.push({ check: "test_script", message: "✅ Test script configured" });
190
+ }
191
+ else {
192
+ failing.push({
193
+ check: "test_script",
194
+ message: "No test script in package.json",
195
+ severity: "warning",
196
+ });
197
+ }
198
+ }
199
+ catch {
200
+ failing.push({
201
+ check: "package_json",
202
+ message: "package.json could not be parsed",
203
+ severity: "error",
204
+ });
205
+ }
206
+ }
207
+ //# sourceMappingURL=completeness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completeness.js","sourceRoot":"","sources":["../../src/analyzers/completeness.ts"],"names":[],"mappings":"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"}