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.
- package/README.md +251 -0
- package/dist/analyzers/anti-pattern.d.ts +21 -0
- package/dist/analyzers/anti-pattern.d.ts.map +1 -0
- package/dist/analyzers/anti-pattern.js +130 -0
- package/dist/analyzers/anti-pattern.js.map +1 -0
- package/dist/analyzers/completeness.d.ts +15 -0
- package/dist/analyzers/completeness.d.ts.map +1 -0
- package/dist/analyzers/completeness.js +207 -0
- package/dist/analyzers/completeness.js.map +1 -0
- package/dist/analyzers/folder-structure.d.ts +35 -0
- package/dist/analyzers/folder-structure.d.ts.map +1 -0
- package/dist/analyzers/folder-structure.js +151 -0
- package/dist/analyzers/folder-structure.js.map +1 -0
- package/dist/analyzers/package-json.d.ts +22 -0
- package/dist/analyzers/package-json.d.ts.map +1 -0
- package/dist/analyzers/package-json.js +229 -0
- package/dist/analyzers/package-json.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/registry/composer.d.ts +32 -0
- package/dist/registry/composer.d.ts.map +1 -0
- package/dist/registry/composer.js +169 -0
- package/dist/registry/composer.js.map +1 -0
- package/dist/registry/loader.d.ts +37 -0
- package/dist/registry/loader.d.ts.map +1 -0
- package/dist/registry/loader.js +278 -0
- package/dist/registry/loader.js.map +1 -0
- package/dist/registry/renderer.d.ts +53 -0
- package/dist/registry/renderer.d.ts.map +1 -0
- package/dist/registry/renderer.js +275 -0
- package/dist/registry/renderer.js.map +1 -0
- package/dist/shared/config/index.d.ts +15 -0
- package/dist/shared/config/index.d.ts.map +1 -0
- package/dist/shared/config/index.js +16 -0
- package/dist/shared/config/index.js.map +1 -0
- package/dist/shared/errors/index.d.ts +30 -0
- package/dist/shared/errors/index.d.ts.map +1 -0
- package/dist/shared/errors/index.js +44 -0
- package/dist/shared/errors/index.js.map +1 -0
- package/dist/shared/logger/index.d.ts +27 -0
- package/dist/shared/logger/index.d.ts.map +1 -0
- package/dist/shared/logger/index.js +59 -0
- package/dist/shared/logger/index.js.map +1 -0
- package/dist/shared/types.d.ts +212 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +30 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/tools/add-hook.d.ts +26 -0
- package/dist/tools/add-hook.d.ts.map +1 -0
- package/dist/tools/add-hook.js +82 -0
- package/dist/tools/add-hook.js.map +1 -0
- package/dist/tools/add-module.d.ts +29 -0
- package/dist/tools/add-module.d.ts.map +1 -0
- package/dist/tools/add-module.js +244 -0
- package/dist/tools/add-module.js.map +1 -0
- package/dist/tools/audit.d.ts +26 -0
- package/dist/tools/audit.d.ts.map +1 -0
- package/dist/tools/audit.js +111 -0
- package/dist/tools/audit.js.map +1 -0
- package/dist/tools/classify.d.ts +23 -0
- package/dist/tools/classify.d.ts.map +1 -0
- package/dist/tools/classify.js +73 -0
- package/dist/tools/classify.js.map +1 -0
- package/dist/tools/configure-mcp.d.ts +49 -0
- package/dist/tools/configure-mcp.d.ts.map +1 -0
- package/dist/tools/configure-mcp.js +127 -0
- package/dist/tools/configure-mcp.js.map +1 -0
- package/dist/tools/convert.d.ts +27 -0
- package/dist/tools/convert.d.ts.map +1 -0
- package/dist/tools/convert.js +154 -0
- package/dist/tools/convert.js.map +1 -0
- package/dist/tools/generate-claude-md.d.ts +29 -0
- package/dist/tools/generate-claude-md.d.ts.map +1 -0
- package/dist/tools/generate-claude-md.js +116 -0
- package/dist/tools/generate-claude-md.js.map +1 -0
- package/dist/tools/get-nfr.d.ts +20 -0
- package/dist/tools/get-nfr.d.ts.map +1 -0
- package/dist/tools/get-nfr.js +53 -0
- package/dist/tools/get-nfr.js.map +1 -0
- package/dist/tools/list.d.ts +33 -0
- package/dist/tools/list.d.ts.map +1 -0
- package/dist/tools/list.js +155 -0
- package/dist/tools/list.js.map +1 -0
- package/dist/tools/refresh-project.d.ts +34 -0
- package/dist/tools/refresh-project.d.ts.map +1 -0
- package/dist/tools/refresh-project.js +257 -0
- package/dist/tools/refresh-project.js.map +1 -0
- package/dist/tools/review.d.ts +31 -0
- package/dist/tools/review.d.ts.map +1 -0
- package/dist/tools/review.js +62 -0
- package/dist/tools/review.js.map +1 -0
- package/dist/tools/scaffold.d.ts +32 -0
- package/dist/tools/scaffold.d.ts.map +1 -0
- package/dist/tools/scaffold.js +160 -0
- package/dist/tools/scaffold.js.map +1 -0
- package/dist/tools/setup-project.d.ts +37 -0
- package/dist/tools/setup-project.d.ts.map +1 -0
- package/dist/tools/setup-project.js +270 -0
- package/dist/tools/setup-project.js.map +1 -0
- package/package.json +69 -0
- package/templates/analytics/claude-md.yaml +37 -0
- package/templates/analytics/structure.yaml +25 -0
- package/templates/api/claude-md.yaml +85 -0
- package/templates/api/nfr.yaml +23 -0
- package/templates/api/review.yaml +103 -0
- package/templates/api/structure.yaml +34 -0
- package/templates/cli/claude-md.yaml +31 -0
- package/templates/cli/review.yaml +53 -0
- package/templates/cli/structure.yaml +16 -0
- package/templates/data-pipeline/claude-md.yaml +42 -0
- package/templates/data-pipeline/nfr.yaml +39 -0
- package/templates/data-pipeline/structure.yaml +23 -0
- package/templates/fintech/claude-md.yaml +42 -0
- package/templates/fintech/nfr.yaml +46 -0
- package/templates/game/claude-md.yaml +42 -0
- package/templates/healthcare/claude-md.yaml +42 -0
- package/templates/healthcare/nfr.yaml +47 -0
- package/templates/infra/claude-md.yaml +104 -0
- package/templates/infra/nfr.yaml +46 -0
- package/templates/infra/review.yaml +65 -0
- package/templates/infra/structure.yaml +25 -0
- package/templates/library/claude-md.yaml +36 -0
- package/templates/library/review.yaml +56 -0
- package/templates/library/structure.yaml +19 -0
- package/templates/ml/claude-md.yaml +42 -0
- package/templates/ml/nfr.yaml +39 -0
- package/templates/ml/structure.yaml +25 -0
- package/templates/mobile/claude-md.yaml +44 -0
- package/templates/mobile/nfr.yaml +49 -0
- package/templates/mobile/structure.yaml +27 -0
- package/templates/realtime/claude-md.yaml +42 -0
- package/templates/social/claude-md.yaml +43 -0
- package/templates/state-machine/claude-md.yaml +42 -0
- package/templates/universal/claude-md.yaml +477 -0
- package/templates/universal/hooks.yaml +196 -0
- package/templates/universal/nfr.yaml +197 -0
- package/templates/universal/review.yaml +164 -0
- package/templates/universal/structure.yaml +52 -0
- package/templates/web-react/claude-md.yaml +110 -0
- package/templates/web-react/hooks.yaml +44 -0
- package/templates/web-react/nfr.yaml +27 -0
- package/templates/web-react/review.yaml +94 -0
- package/templates/web-react/structure.yaml +46 -0
- package/templates/web-static/claude-md.yaml +73 -0
- package/templates/web3/claude-md.yaml +44 -0
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
tag: UNIVERSAL
|
|
2
|
+
section: claude-md
|
|
3
|
+
blocks:
|
|
4
|
+
- id: project-identity
|
|
5
|
+
tier: core
|
|
6
|
+
title: "Project Identity"
|
|
7
|
+
content: |
|
|
8
|
+
## Project Identity
|
|
9
|
+
- **Repo**: {{repo_url}}
|
|
10
|
+
- **Primary Language**: {{language}}
|
|
11
|
+
- **Framework**: {{framework}}
|
|
12
|
+
- **Domain**: {{domain}}
|
|
13
|
+
- **Sensitive Data**: {{sensitive_data}}
|
|
14
|
+
- **Project Tags**: {{tags}}
|
|
15
|
+
|
|
16
|
+
- id: code-standards
|
|
17
|
+
tier: core
|
|
18
|
+
title: "Code Standards"
|
|
19
|
+
content: |
|
|
20
|
+
## Code Standards
|
|
21
|
+
- Maximum function/method length: {{max_function_length | default: 50}} lines. If longer, decompose.
|
|
22
|
+
- Maximum file length: {{max_file_length | default: 300}} lines. If longer, split by responsibility.
|
|
23
|
+
- Maximum function parameters: {{max_function_params | default: 5}}. If more, use a parameter object.
|
|
24
|
+
- Every public function/method must have a docstring/JSDoc with typed params and returns.
|
|
25
|
+
- Delete orphaned code. Do not comment it out. Git has history.
|
|
26
|
+
- Before creating a new utility, search the entire codebase for existing ones.
|
|
27
|
+
- Reuse existing patterns โ check shared modules before writing new.
|
|
28
|
+
- No abbreviations in names except universally understood ones (id, url, http, db, api).
|
|
29
|
+
- All names must be intention-revealing. If you need a comment to explain what a variable
|
|
30
|
+
holds, the name is wrong.
|
|
31
|
+
|
|
32
|
+
- id: production-code-standards
|
|
33
|
+
tier: core
|
|
34
|
+
title: "Production Code Standards"
|
|
35
|
+
content: |
|
|
36
|
+
## Production Code Standards โ NON-NEGOTIABLE
|
|
37
|
+
|
|
38
|
+
These apply to ALL code including prototypes. "It's just a prototype" is never a valid
|
|
39
|
+
exception. Prototypes become production code within days at CC development speed.
|
|
40
|
+
|
|
41
|
+
### SOLID Principles
|
|
42
|
+
- **Single Responsibility**: One module = one reason to change. Use "and" to describe it? Split it.
|
|
43
|
+
- **Open/Closed**: Extend via interfaces and composition. Never modify working code for new behavior.
|
|
44
|
+
- **Liskov Substitution**: Any interface implementation must be fully swappable. No isinstance checks.
|
|
45
|
+
- **Interface Segregation**: Small focused interfaces. No god-interfaces.
|
|
46
|
+
- **Dependency Inversion**: Depend on abstractions. Concrete classes are injected, never instantiated
|
|
47
|
+
inside business logic.
|
|
48
|
+
|
|
49
|
+
### Zero Hardcoded Values
|
|
50
|
+
- ALL configuration through environment variables or config files. No exceptions.
|
|
51
|
+
- ALL external URLs, ports, credentials, thresholds, feature flags must be configurable.
|
|
52
|
+
- ALL magic numbers must be named constants with documentation.
|
|
53
|
+
- Config is validated at startup โ fail fast if required values are missing.
|
|
54
|
+
|
|
55
|
+
### Zero Mocks in Application Code
|
|
56
|
+
- No mock objects, fake data, or stub responses in source code. Ever.
|
|
57
|
+
- Mocks belong ONLY in test files.
|
|
58
|
+
- For local dev: create proper interface implementations selected via config.
|
|
59
|
+
- No `if DEBUG: return fake_data` patterns. Use dependency injection to swap implementations.
|
|
60
|
+
- No TODO/FIXME stubs returning hardcoded values. Use NotImplementedError with a description.
|
|
61
|
+
|
|
62
|
+
### Interfaces First
|
|
63
|
+
Before writing any implementation:
|
|
64
|
+
1. Define the interface/protocol/abstract class
|
|
65
|
+
2. Define the data contracts (input/output DTOs)
|
|
66
|
+
3. Write the consuming code against the interface
|
|
67
|
+
4. Write tests against the interface
|
|
68
|
+
5. THEN implement the concrete class
|
|
69
|
+
|
|
70
|
+
### Dependency Injection
|
|
71
|
+
- Every service receives dependencies through its constructor.
|
|
72
|
+
- A composition root (main.py / app.ts / container) wires everything.
|
|
73
|
+
- No service locator pattern. No global singletons. No module-level instances.
|
|
74
|
+
|
|
75
|
+
### Error Handling
|
|
76
|
+
- Custom exception hierarchy per module. No bare Exception raises.
|
|
77
|
+
- Errors carry context: IDs, timestamps, operation names.
|
|
78
|
+
- Fail fast, fail loud. No silent swallowing of exceptions.
|
|
79
|
+
- Domain code never returns HTTP status codes โ that's the API layer's job.
|
|
80
|
+
|
|
81
|
+
### Modular from Day One
|
|
82
|
+
- Feature-based modules over layer-based. Each feature owns its models, service, repository, routes.
|
|
83
|
+
- Module dependency graph must be acyclic.
|
|
84
|
+
- Every module has a clear public API via __init__.py / index.ts exports.
|
|
85
|
+
|
|
86
|
+
- id: layered-architecture
|
|
87
|
+
tier: recommended
|
|
88
|
+
title: "Layered Architecture"
|
|
89
|
+
content: |
|
|
90
|
+
## Layered Architecture (Ports & Adapters / Hexagonal)
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
94
|
+
โ API / CLI / Event Handlers โ โ Thin. Validation + delegation only. No logic.
|
|
95
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค These are DRIVING ADAPTERS (primary).
|
|
96
|
+
โ Services (Business Logic) โ โ Orchestration. Depends on PORT INTERFACES only.
|
|
97
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
|
|
98
|
+
โ Domain Models โ โ Pure data + behavior. No I/O. No framework imports.
|
|
99
|
+
โ (Entities, Value Objects) โ The inner hexagon. Zero external dependencies.
|
|
100
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
|
|
101
|
+
โ Port Interfaces โ โ Abstract contracts (Repository, Gateway, Notifier).
|
|
102
|
+
โ โ Defined by the domain, implemented by adapters.
|
|
103
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
|
|
104
|
+
โ Repositories / Adapters โ โ DRIVEN ADAPTERS (secondary). All external I/O
|
|
105
|
+
โ โ (DB, APIs, files, queues, email, caches).
|
|
106
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
|
|
107
|
+
โ Infrastructure / Config โ โ DI container, env config, connection factories
|
|
108
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Ports (Interfaces owned by the domain)
|
|
112
|
+
- **Repository ports**: `UserRepository`, `OrderRepository` โ data persistence contracts.
|
|
113
|
+
- **Gateway ports**: `PaymentGateway`, `EmailSender` โ external service contracts.
|
|
114
|
+
- Ports are defined in the domain/service layer, never in the adapter layer.
|
|
115
|
+
- Port interfaces specify WHAT, never HOW.
|
|
116
|
+
|
|
117
|
+
### Adapters (Implementations of ports)
|
|
118
|
+
- **Driving adapters** (primary): HTTP controllers, CLI handlers, message consumers
|
|
119
|
+
โ they CALL the application through port interfaces.
|
|
120
|
+
- **Driven adapters** (secondary): PostgresUserRepository, StripePaymentGateway,
|
|
121
|
+
SESEmailSender โ they ARE CALLED BY the application through port interfaces.
|
|
122
|
+
- Adapters are interchangeable. Swap `PostgresUserRepository` for `InMemoryUserRepository`
|
|
123
|
+
in tests without changing a single line of business logic.
|
|
124
|
+
|
|
125
|
+
### Data Transfer Objects (DTOs)
|
|
126
|
+
- Use DTOs at layer boundaries โ never pass domain entities to/from the API layer.
|
|
127
|
+
- **Request DTOs**: validated at the API boundary (Zod schema โ typed object).
|
|
128
|
+
- **Response DTOs**: shaped for the consumer, not mirroring the domain model.
|
|
129
|
+
- **Domain โ Persistence mapping**: repositories map between domain entities and DB rows/documents.
|
|
130
|
+
- DTOs are plain data objects โ no methods, no behavior, no framework decorators.
|
|
131
|
+
|
|
132
|
+
### Layer Rules
|
|
133
|
+
- Never skip layers. API handlers do not call repositories directly.
|
|
134
|
+
- Dependencies point INWARD only. Inner layers never import from outer layers.
|
|
135
|
+
- Domain models have ZERO external dependencies.
|
|
136
|
+
- The domain layer does not know HTTP, SQL, or any framework exists.
|
|
137
|
+
|
|
138
|
+
- id: clean-code-principles
|
|
139
|
+
tier: recommended
|
|
140
|
+
title: "Clean Code Principles"
|
|
141
|
+
content: |
|
|
142
|
+
## Clean Code Principles
|
|
143
|
+
|
|
144
|
+
### Command-Query Separation (CQS)
|
|
145
|
+
- **Commands** change state but return nothing (void).
|
|
146
|
+
- **Queries** return data but change nothing (no side effects).
|
|
147
|
+
- A function should do one or the other, never both.
|
|
148
|
+
- Exception: stack.pop() style operations where separation is impractical โ document why.
|
|
149
|
+
|
|
150
|
+
### Guard Clauses & Early Return
|
|
151
|
+
- Eliminate deep nesting. Handle invalid cases first, return early.
|
|
152
|
+
- The happy path runs at the shallowest indentation level.
|
|
153
|
+
- Before:
|
|
154
|
+
```
|
|
155
|
+
if (user) {
|
|
156
|
+
if (user.isActive) {
|
|
157
|
+
if (user.hasPermission) {
|
|
158
|
+
// actual logic buried 3 levels deep
|
|
159
|
+
```
|
|
160
|
+
- After:
|
|
161
|
+
```
|
|
162
|
+
if (!user) throw new NotFoundError(...);
|
|
163
|
+
if (!user.isActive) throw new InactiveError(...);
|
|
164
|
+
if (!user.hasPermission) throw new ForbiddenError(...);
|
|
165
|
+
// actual logic at top level
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Composition over Inheritance
|
|
169
|
+
- Prefer composing objects via interfaces and delegation over class inheritance.
|
|
170
|
+
- Inheritance creates tight coupling and fragile hierarchies.
|
|
171
|
+
- Use inheritance ONLY for genuine "is-a" relationships (rare).
|
|
172
|
+
- When in doubt, compose: inject a collaborator, don't extend a base class.
|
|
173
|
+
|
|
174
|
+
### Law of Demeter (Principle of Least Knowledge)
|
|
175
|
+
- A method should only call methods on: its own object, its parameters, objects it creates,
|
|
176
|
+
its direct dependencies.
|
|
177
|
+
- Do NOT chain through objects: `order.getCustomer().getAddress().getCity()` โ BAD.
|
|
178
|
+
- Instead: `order.getShippingCity()` or pass the needed data directly.
|
|
179
|
+
|
|
180
|
+
### Immutability by Default
|
|
181
|
+
- Use `const` over `let`. Use `readonly` on properties and parameters.
|
|
182
|
+
- Prefer `ReadonlyArray<T>`, `Readonly<T>`, `ReadonlyMap`, `ReadonlySet`.
|
|
183
|
+
- When you need to "modify" data, create a new copy with the change.
|
|
184
|
+
- Mutable state is the #1 source of bugs. Restrict it to the smallest possible scope.
|
|
185
|
+
|
|
186
|
+
### Pure Functions
|
|
187
|
+
- A pure function: same inputs โ same outputs, no side effects.
|
|
188
|
+
- Domain logic, validation, transformation, and calculation should be pure.
|
|
189
|
+
- Side effects (I/O, logging, database) are pushed to the edges (adapters).
|
|
190
|
+
- Pure functions are trivially testable โ no mocks needed.
|
|
191
|
+
|
|
192
|
+
### Factory Pattern
|
|
193
|
+
- Use factories to encapsulate complex object construction.
|
|
194
|
+
- Factory methods on the class itself for simple cases: `User.create(dto)`.
|
|
195
|
+
- Factory classes/functions when construction involves dependencies or conditional logic.
|
|
196
|
+
- Factories are the natural companion to dependency injection โ the DI container
|
|
197
|
+
IS the top-level factory.
|
|
198
|
+
|
|
199
|
+
- id: domain-driven-design
|
|
200
|
+
tier: optional
|
|
201
|
+
title: "Domain-Driven Design Essentials"
|
|
202
|
+
content: |
|
|
203
|
+
## Domain-Driven Design (DDD) Essentials
|
|
204
|
+
|
|
205
|
+
### Entities vs. Value Objects
|
|
206
|
+
- **Entity**: has identity (ID) that persists across state changes. Two users with the
|
|
207
|
+
same name are NOT the same user. Compared by ID.
|
|
208
|
+
- **Value Object**: defined by its attributes, not identity. Two `Money(100, "USD")` are
|
|
209
|
+
the same. Immutable. Compared by value.
|
|
210
|
+
- When in doubt, make it a Value Object โ they're simpler and safer.
|
|
211
|
+
|
|
212
|
+
### Eliminate Primitive Obsession
|
|
213
|
+
- Don't use raw `string` for email, `number` for currency, `string` for phone.
|
|
214
|
+
- Wrap domain concepts in typed Value Objects: `EmailAddress`, `Money`, `PhoneNumber`.
|
|
215
|
+
- Value Objects enforce validation at construction โ an invalid email can never exist.
|
|
216
|
+
- This moves validation FROM every call site TO the constructor โ DRY + safe.
|
|
217
|
+
|
|
218
|
+
### Aggregates
|
|
219
|
+
- An aggregate is a cluster of domain objects treated as a single unit for data changes.
|
|
220
|
+
- One entity is the **aggregate root** โ all external access goes through it.
|
|
221
|
+
- Aggregates enforce invariants: `Order` ensures its `OrderLines` don't exceed the limit.
|
|
222
|
+
- Reference other aggregates by ID, not by direct object reference.
|
|
223
|
+
|
|
224
|
+
### Bounded Contexts
|
|
225
|
+
- A bounded context is a boundary within which a domain model has a specific meaning.
|
|
226
|
+
- The word "Account" means different things in Billing vs. Auth vs. Social.
|
|
227
|
+
- Each context owns its models, language, and persistence โ no shared database tables.
|
|
228
|
+
- Contexts communicate via well-defined interfaces, events, or an **Anti-Corruption Layer**
|
|
229
|
+
that translates between contexts.
|
|
230
|
+
|
|
231
|
+
### Domain Events
|
|
232
|
+
- When something important happens in the domain, publish an event: `OrderPlaced`,
|
|
233
|
+
`MemberDeactivated`, `PaymentFailed`.
|
|
234
|
+
- Events decouple modules: the Order module publishes `OrderPlaced`, the Notification
|
|
235
|
+
module subscribes โ neither imports the other.
|
|
236
|
+
- Events are past-tense named facts. They carry the data needed by subscribers.
|
|
237
|
+
- In-process event bus for monoliths; message broker (SQS, Kafka, NATS) for distributed.
|
|
238
|
+
|
|
239
|
+
- id: cqrs-event-patterns
|
|
240
|
+
tier: optional
|
|
241
|
+
title: "CQRS & Event Patterns"
|
|
242
|
+
content: |
|
|
243
|
+
## CQRS & Event-Driven Patterns
|
|
244
|
+
|
|
245
|
+
### CQRS (Command Query Responsibility Segregation)
|
|
246
|
+
When read and write patterns diverge significantly:
|
|
247
|
+
- **Command side**: validates, enforces business rules, writes to the canonical store.
|
|
248
|
+
- **Query side**: reads from optimized read models (denormalized views, search indices).
|
|
249
|
+
- Start simple: same database, separate service methods. Optimize to separate stores
|
|
250
|
+
only when read/write scaling demands it.
|
|
251
|
+
- CQRS is not mandatory everywhere โ use it where read/write asymmetry is real.
|
|
252
|
+
|
|
253
|
+
### Event Sourcing (when appropriate)
|
|
254
|
+
- Store the sequence of events, not just current state.
|
|
255
|
+
- Useful for: audit trails, temporal queries, debugging, undo/redo.
|
|
256
|
+
- NOT appropriate for: simple CRUD, low-value data, early-stage features.
|
|
257
|
+
- If you use event sourcing, you MUST also maintain a read-projection.
|
|
258
|
+
|
|
259
|
+
### Pub/Sub & Message Patterns
|
|
260
|
+
- **Fire and forget**: publish event, don't wait for subscribers.
|
|
261
|
+
- **Request/Reply**: send command, wait for response.
|
|
262
|
+
- In-process: use an event emitter or mediator.
|
|
263
|
+
- Distributed: use durable message queues with at-least-once delivery.
|
|
264
|
+
|
|
265
|
+
- id: design-patterns-reference
|
|
266
|
+
tier: optional
|
|
267
|
+
title: "Design Patterns Quick Reference"
|
|
268
|
+
content: |
|
|
269
|
+
## Design Patterns โ When to Reach for What
|
|
270
|
+
|
|
271
|
+
### Creational
|
|
272
|
+
- **Factory Method / Abstract Factory**: Use when instantiation logic is complex or varies by context.
|
|
273
|
+
Prefer over `new` in business logic โ keep constructors for DI only.
|
|
274
|
+
- **Builder**: Use when constructing objects with many optional parameters. Fluent API preferred.
|
|
275
|
+
- **Singleton**: Almost never in application code. Use DI to manage lifecycle instead.
|
|
276
|
+
Acceptable only for: loggers, config singletons in composition root.
|
|
277
|
+
|
|
278
|
+
### Structural
|
|
279
|
+
- **Adapter**: Wrap third-party APIs to match your port interfaces. Isolates vendor lock-in.
|
|
280
|
+
- **Facade**: Simplify complex subsystem interactions behind a unified interface.
|
|
281
|
+
Every module's `index.ts` exports are a facade.
|
|
282
|
+
- **Decorator**: Add behavior (logging, caching, retry, auth) without modifying the original.
|
|
283
|
+
Middleware pipelines are decorator chains.
|
|
284
|
+
- **Proxy**: Lazy loading, access control, or caching in front of expensive resources.
|
|
285
|
+
|
|
286
|
+
### Behavioral
|
|
287
|
+
- **Strategy**: Extract interchangeable algorithms behind an interface. Inject the right one.
|
|
288
|
+
Examples: pricing calculators, render strategies, sort algorithms.
|
|
289
|
+
- **Observer / Pub-Sub**: Decouple event producers from consumers. Use for: domain events,
|
|
290
|
+
UI state changes, webhook fan-out. See CQRS & Event Patterns section.
|
|
291
|
+
- **Chain of Responsibility**: Middleware pipelines (Express, Koa). Each handler decides
|
|
292
|
+
to process or pass to the next. Order matters.
|
|
293
|
+
- **Command**: Encapsulate actions as objects. Enables: undo/redo, queuing, audit trail.
|
|
294
|
+
|
|
295
|
+
### Enterprise
|
|
296
|
+
- **Repository**: Encapsulate data access behind a collection-like interface. Defined in the
|
|
297
|
+
domain layer, implemented in the infrastructure layer as adapters.
|
|
298
|
+
- **Unit of Work**: Track changes within a transaction boundary. Commit or roll back atomically.
|
|
299
|
+
Pair with Repository for database operations.
|
|
300
|
+
- **Saga**: Coordinate multi-step distributed operations. Each step has a compensating action
|
|
301
|
+
for rollback. Use for: order processing, payment flows, multi-service workflows.
|
|
302
|
+
- **Outbox**: Write events to a local outbox table in the same transaction as the state change.
|
|
303
|
+
A separate process reliably publishes them. Guarantees at-least-once event delivery.
|
|
304
|
+
|
|
305
|
+
### Anti-Patterns to Avoid
|
|
306
|
+
- **God Object**: One class that knows/does everything. Split by responsibility.
|
|
307
|
+
- **Service Locator**: Global registry looked up at runtime. Use constructor injection instead.
|
|
308
|
+
- **Anemic Domain Model**: Entities with only getters/setters, logic in services.
|
|
309
|
+
Push behavior into domain objects.
|
|
310
|
+
|
|
311
|
+
- id: twelve-factor-ops
|
|
312
|
+
tier: optional
|
|
313
|
+
title: "12-Factor & Operational Readiness"
|
|
314
|
+
content: |
|
|
315
|
+
## 12-Factor App & Operational Readiness
|
|
316
|
+
|
|
317
|
+
### Configuration
|
|
318
|
+
- ALL config comes from environment variables or external config services. Zero config in code.
|
|
319
|
+
- Config is validated at startup โ fail fast with a clear error if required values are missing.
|
|
320
|
+
- `.env.example` committed with every variable documented. `.env` is gitignored.
|
|
321
|
+
|
|
322
|
+
### Stateless Processes
|
|
323
|
+
- Application processes are stateless. Session data lives in external stores (Redis, DB).
|
|
324
|
+
- Any process can be killed and restarted without data loss.
|
|
325
|
+
- File uploads go to object storage (S3, GCS), not local disk.
|
|
326
|
+
|
|
327
|
+
### Port Binding
|
|
328
|
+
- The application is self-contained and exports services via port binding.
|
|
329
|
+
- No runtime injection of a web server โ the app embeds its own (Express, Uvicorn, etc.).
|
|
330
|
+
|
|
331
|
+
### Disposability
|
|
332
|
+
- Processes start fast (< 5 seconds) and shut down gracefully.
|
|
333
|
+
- SIGTERM triggers: stop accepting new work โ finish in-flight requests โ close connections โ exit.
|
|
334
|
+
- Workers use robust job queues so interrupted work is retried, not lost.
|
|
335
|
+
|
|
336
|
+
### Dev/Prod Parity
|
|
337
|
+
- Minimize gaps between development and production environments.
|
|
338
|
+
- Use the same backing services in dev as prod (same DB engine, same cache).
|
|
339
|
+
- Docker / containers recommended for environment parity.
|
|
340
|
+
|
|
341
|
+
### Logs as Event Streams
|
|
342
|
+
- The app writes logs to stdout/stderr โ never to local files.
|
|
343
|
+
- Log aggregation is an ops concern (ELK, Datadog, CloudWatch), not an application concern.
|
|
344
|
+
- Structured JSON logs with correlation IDs for tracing across services.
|
|
345
|
+
|
|
346
|
+
### Build, Release, Run
|
|
347
|
+
- Strict separation: build (compile + assets), release (build + config), run (execute).
|
|
348
|
+
- Every release is immutable and tagged. Rollback = deploy a previous release.
|
|
349
|
+
- CI/CD pipeline automates: lint โ test โ build โ deploy with gates at each stage.
|
|
350
|
+
|
|
351
|
+
- id: cicd-deployment
|
|
352
|
+
tier: recommended
|
|
353
|
+
title: "CI/CD & Deployment"
|
|
354
|
+
content: |
|
|
355
|
+
## CI/CD & Deployment
|
|
356
|
+
|
|
357
|
+
### Pipeline
|
|
358
|
+
- Every push triggers: lint โ type-check โ unit tests โ build โ integration tests.
|
|
359
|
+
- Merges to main additionally run: security scan โ deploy to staging โ smoke tests โ promote.
|
|
360
|
+
- Pipeline must complete in under 10 minutes. Parallelize test suites, cache dependencies.
|
|
361
|
+
- Failed pipelines block merge. No exceptions.
|
|
362
|
+
|
|
363
|
+
### Environments
|
|
364
|
+
- Minimum three environments: **development** (local), **staging** (mirrors prod), **production**.
|
|
365
|
+
- Environment config is injected โ same artifact runs everywhere with different env vars.
|
|
366
|
+
- Staging is a faithful replica of production (same provider, same DB engine, same services).
|
|
367
|
+
|
|
368
|
+
### Deployment Strategy
|
|
369
|
+
- Default: **rolling deployment** with health checks (zero downtime).
|
|
370
|
+
- For critical services: **blue-green** or **canary** with automated rollback on error rate spike.
|
|
371
|
+
- Every deploy is tagged with git SHA. Rollback = redeploy a previous SHA.
|
|
372
|
+
- Deployment must be one command or one button. No multi-step manual runbooks.
|
|
373
|
+
|
|
374
|
+
### Preview Environments
|
|
375
|
+
- Pull requests get ephemeral preview deployments where feasible (Vercel, Netlify, Railway).
|
|
376
|
+
- Preview URLs in PR comments for stakeholder review before merge.
|
|
377
|
+
|
|
378
|
+
- id: testing-pyramid
|
|
379
|
+
tier: core
|
|
380
|
+
title: "Testing Pyramid"
|
|
381
|
+
content: |
|
|
382
|
+
## Testing Pyramid
|
|
383
|
+
|
|
384
|
+
```
|
|
385
|
+
/ E2E \ โ 5-10% of tests. Core journeys only.
|
|
386
|
+
/ Integration \ โ 20-30%. Real dependencies at boundaries.
|
|
387
|
+
/ Unit Tests \ โ 60-75%. Fast, isolated, every public function.
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Coverage Targets
|
|
391
|
+
- Overall minimum: {{coverage_minimum | default: 80}}% line coverage (blocks commit)
|
|
392
|
+
- New/changed code: {{coverage_new_code_min | default: 90}}% minimum (measured on diff)
|
|
393
|
+
- Critical paths: 95%+ (data pipelines, auth, PHI handling, financial calculations)
|
|
394
|
+
|
|
395
|
+
### Test Rules
|
|
396
|
+
- Every test name is a specification: `test_rejects_duplicate_member_ids` not `test_validation`
|
|
397
|
+
- No empty catch blocks. No `assert True`. No tests that can't fail.
|
|
398
|
+
- Test files colocated: `[module].test.[ext]` or in `tests/` mirroring src structure.
|
|
399
|
+
- Flaky tests are bugs โ fix or quarantine, never ignore.
|
|
400
|
+
|
|
401
|
+
### Test Doubles Taxonomy
|
|
402
|
+
Use the correct double for the job:
|
|
403
|
+
- **Stub**: Returns canned data. No assertions on calls. Use when you need to control input.
|
|
404
|
+
- **Spy**: Records calls. Assert after the fact. Use to verify side effects.
|
|
405
|
+
- **Fake**: Working implementation with shortcuts (in-memory DB). Use for integration-speed tests.
|
|
406
|
+
- **Mock**: Pre-programmed expectations. Assert call patterns. Use sparingly โ they couple to implementation.
|
|
407
|
+
Prefer stubs and fakes over mocks. Tests that mock everything test nothing.
|
|
408
|
+
|
|
409
|
+
### Test Data Builders
|
|
410
|
+
- Use Builder or Factory pattern for test data: `UserBuilder.anAdmin().withName('Alice').build()`.
|
|
411
|
+
- One builder per domain entity. Builders provide sensible defaults so tests only specify what matters.
|
|
412
|
+
- No raw object literals scattered across tests. Centralize in `tests/fixtures/` or `tests/builders/`.
|
|
413
|
+
|
|
414
|
+
### Property-Based Testing
|
|
415
|
+
- For pure functions with wide input ranges, add property tests (fast-check, Hypothesis, QuickCheck).
|
|
416
|
+
- Define invariants, not examples: "sorting is idempotent", "encode then decode = identity".
|
|
417
|
+
- Property tests complement, not replace, example-based tests.
|
|
418
|
+
|
|
419
|
+
- id: data-guardrails
|
|
420
|
+
tier: core
|
|
421
|
+
title: "Data Guardrails"
|
|
422
|
+
content: |
|
|
423
|
+
## Data Guardrails โ ๏ธ
|
|
424
|
+
- NEVER sample, truncate, or subset data unless explicitly instructed.
|
|
425
|
+
- NEVER make simplifying assumptions about distributions, scales, or schemas.
|
|
426
|
+
- State exact row counts, column sets, and filters for every data operation.
|
|
427
|
+
- If data is too large for in-memory, say so โ don't silently downsample.
|
|
428
|
+
|
|
429
|
+
- id: commit-protocol
|
|
430
|
+
tier: core
|
|
431
|
+
title: "Commit Protocol"
|
|
432
|
+
content: |
|
|
433
|
+
## Commit Protocol
|
|
434
|
+
- Conventional commits: feat|fix|refactor|docs|test|chore(scope): description
|
|
435
|
+
- Commits must pass: compilation, lint, tests, coverage gate, anti-pattern scan.
|
|
436
|
+
- Keep commits atomic โ one logical change per commit.
|
|
437
|
+
- Commit BEFORE any risky refactor. Tag stable states.
|
|
438
|
+
- Update Status.md at the end of every session.
|
|
439
|
+
|
|
440
|
+
- id: mcp-tooling
|
|
441
|
+
tier: recommended
|
|
442
|
+
title: "MCP-Powered Tooling"
|
|
443
|
+
content: |
|
|
444
|
+
## MCP-Powered Tooling
|
|
445
|
+
### CodeSeeker โ Graph-Powered Code Intelligence
|
|
446
|
+
CodeSeeker builds a knowledge graph of the codebase with hybrid search
|
|
447
|
+
(vector + text + path, fused with RRF). Use it for:
|
|
448
|
+
- **Semantic search**: "find code that handles errors like this" โ not just grep.
|
|
449
|
+
- **Graph traversal**: imports, calls, extends โ follow dependency chains.
|
|
450
|
+
- **Coding standards**: auto-detected validation, error handling, and state patterns.
|
|
451
|
+
- **Contextual reads**: `get_file_context` returns a file with its related code.
|
|
452
|
+
Indexing is automatic on first search (~30sโ5min depending on codebase size).
|
|
453
|
+
Most valuable on mid-to-large projects (10K+ files) with established patterns.
|
|
454
|
+
Install: `npx codeseeker install --vscode` or see https://github.com/jghiringhelli/codeseeker
|
|
455
|
+
|
|
456
|
+
- id: engineering-preferences
|
|
457
|
+
tier: recommended
|
|
458
|
+
title: "Engineering Preferences"
|
|
459
|
+
content: |
|
|
460
|
+
## Engineering Preferences
|
|
461
|
+
These calibrate Claude Code's judgment on subjective trade-offs.
|
|
462
|
+
- **DRY is important** โ flag repetition aggressively.
|
|
463
|
+
- **Well-tested code is non-negotiable**; I'd rather have too many tests than too few.
|
|
464
|
+
- **"Engineered enough"** โ not under-engineered (fragile, hacky) and not over-engineered
|
|
465
|
+
(premature abstraction, unnecessary complexity).
|
|
466
|
+
- **Handle more edge cases**, not fewer; thoughtfulness > speed.
|
|
467
|
+
- **Bias toward explicit over clever** โ readability wins over brevity.
|
|
468
|
+
- When in doubt, ask rather than assume.
|
|
469
|
+
|
|
470
|
+
- id: corrections-log
|
|
471
|
+
tier: core
|
|
472
|
+
title: "Corrections Log"
|
|
473
|
+
content: |
|
|
474
|
+
## Corrections Log
|
|
475
|
+
When I correct your output, record the correction pattern here so you don't repeat it.
|
|
476
|
+
### Learned Corrections
|
|
477
|
+
- [CC appends corrections here with date and description]
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
tag: UNIVERSAL
|
|
2
|
+
section: hooks
|
|
3
|
+
hooks:
|
|
4
|
+
- name: branch-protection
|
|
5
|
+
trigger: pre-commit
|
|
6
|
+
description: "Block direct commits to main/master branches"
|
|
7
|
+
filename: pre-commit-branch-check.sh
|
|
8
|
+
script: |
|
|
9
|
+
#!/bin/bash
|
|
10
|
+
BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
|
11
|
+
if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "master" ]; then
|
|
12
|
+
echo "โ Direct commits to $BRANCH are blocked. Create a feature branch."
|
|
13
|
+
exit 1
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
- name: dangerous-commands
|
|
17
|
+
trigger: pre-exec
|
|
18
|
+
description: "Block destructive commands (rm -rf /, DROP DATABASE, force push)"
|
|
19
|
+
filename: pre-exec-safety.sh
|
|
20
|
+
script: |
|
|
21
|
+
#!/bin/bash
|
|
22
|
+
DANGEROUS_PATTERNS=(
|
|
23
|
+
"rm -rf /"
|
|
24
|
+
"DROP DATABASE"
|
|
25
|
+
"DROP TABLE"
|
|
26
|
+
"TRUNCATE"
|
|
27
|
+
"force push"
|
|
28
|
+
"git push.*--force"
|
|
29
|
+
"kubectl delete namespace"
|
|
30
|
+
)
|
|
31
|
+
for pattern in "${DANGEROUS_PATTERNS[@]}"; do
|
|
32
|
+
if echo "$1" | grep -iqE "$pattern"; then
|
|
33
|
+
echo "โ Blocked dangerous command matching: $pattern"
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
done
|
|
37
|
+
|
|
38
|
+
- name: auto-format
|
|
39
|
+
trigger: pre-commit
|
|
40
|
+
description: "Run language-appropriate formatter on staged files"
|
|
41
|
+
filename: pre-commit-format.sh
|
|
42
|
+
script: |
|
|
43
|
+
#!/bin/bash
|
|
44
|
+
STAGED=$(git diff --cached --name-only --diff-filter=ACM)
|
|
45
|
+
# Python
|
|
46
|
+
echo "$STAGED" | grep '\.py$' | xargs -r black --quiet 2>/dev/null
|
|
47
|
+
echo "$STAGED" | grep '\.py$' | xargs -r isort --quiet 2>/dev/null
|
|
48
|
+
# TypeScript/JavaScript
|
|
49
|
+
echo "$STAGED" | grep '\.\(ts\|tsx\|js\|jsx\)$' | xargs -r npx prettier --write 2>/dev/null
|
|
50
|
+
# Re-stage formatted files
|
|
51
|
+
echo "$STAGED" | xargs -r git add
|
|
52
|
+
|
|
53
|
+
- name: secrets-scanner
|
|
54
|
+
trigger: pre-commit
|
|
55
|
+
description: "Scan for accidentally committed secrets (AWS keys, API keys, passwords)"
|
|
56
|
+
filename: pre-commit-secrets.sh
|
|
57
|
+
script: |
|
|
58
|
+
#!/bin/bash
|
|
59
|
+
PATTERNS=(
|
|
60
|
+
'AKIA[0-9A-Z]{16}'
|
|
61
|
+
'password\s*=\s*["\x27][^"\x27]+'
|
|
62
|
+
'BEGIN RSA PRIVATE KEY'
|
|
63
|
+
'sk-[a-zA-Z0-9]{48}'
|
|
64
|
+
'ghp_[a-zA-Z0-9]{36}'
|
|
65
|
+
)
|
|
66
|
+
STAGED=$(git diff --cached --name-only)
|
|
67
|
+
for file in $STAGED; do
|
|
68
|
+
for pattern in "${PATTERNS[@]}"; do
|
|
69
|
+
if grep -qE "$pattern" "$file" 2>/dev/null; then
|
|
70
|
+
echo "โ Potential secret found in $file matching pattern"
|
|
71
|
+
exit 1
|
|
72
|
+
fi
|
|
73
|
+
done
|
|
74
|
+
done
|
|
75
|
+
|
|
76
|
+
- name: compile-check
|
|
77
|
+
trigger: pre-commit
|
|
78
|
+
description: "Detect project type and run appropriate compile/build check"
|
|
79
|
+
filename: pre-commit-compile.sh
|
|
80
|
+
script: |
|
|
81
|
+
#!/bin/bash
|
|
82
|
+
echo "๐จ Running build check..."
|
|
83
|
+
if [ -f "pyproject.toml" ] || [ -f "setup.py" ] || [ -f "requirements.txt" ]; then
|
|
84
|
+
STAGED_PY=$(git diff --cached --name-only --diff-filter=ACM | grep '\.py$')
|
|
85
|
+
if [ -n "$STAGED_PY" ]; then
|
|
86
|
+
for file in $STAGED_PY; do
|
|
87
|
+
python -m py_compile "$file" 2>&1
|
|
88
|
+
if [ $? -ne 0 ]; then
|
|
89
|
+
echo "โ Syntax error in $file"
|
|
90
|
+
exit 1
|
|
91
|
+
fi
|
|
92
|
+
done
|
|
93
|
+
echo " โ
Python syntax OK"
|
|
94
|
+
fi
|
|
95
|
+
fi
|
|
96
|
+
if [ -f "tsconfig.json" ]; then
|
|
97
|
+
npx tsc --noEmit 2>&1
|
|
98
|
+
if [ $? -ne 0 ]; then
|
|
99
|
+
echo "โ TypeScript compilation failed."
|
|
100
|
+
exit 1
|
|
101
|
+
fi
|
|
102
|
+
echo " โ
TypeScript compilation OK"
|
|
103
|
+
fi
|
|
104
|
+
echo "๐จ Build check passed"
|
|
105
|
+
|
|
106
|
+
- name: test-coverage
|
|
107
|
+
trigger: pre-commit
|
|
108
|
+
description: "Run tests with coverage and enforce minimum thresholds"
|
|
109
|
+
filename: pre-commit-test.sh
|
|
110
|
+
script: |
|
|
111
|
+
#!/bin/bash
|
|
112
|
+
COVERAGE_MIN={{coverage_minimum | default: 80}}
|
|
113
|
+
echo "๐งช Running tests with coverage..."
|
|
114
|
+
if [ -f "package.json" ]; then
|
|
115
|
+
if grep -q '"vitest"' package.json 2>/dev/null; then
|
|
116
|
+
npx vitest run --reporter=verbose 2>&1
|
|
117
|
+
if [ $? -ne 0 ]; then
|
|
118
|
+
echo "โ Tests failed."
|
|
119
|
+
exit 1
|
|
120
|
+
fi
|
|
121
|
+
echo " โ
Tests passed"
|
|
122
|
+
elif grep -q '"jest"' package.json 2>/dev/null; then
|
|
123
|
+
npx jest --passWithNoTests --coverage \
|
|
124
|
+
--coverageThreshold="{\"global\":{\"lines\":$COVERAGE_MIN}}" \
|
|
125
|
+
--silent 2>&1
|
|
126
|
+
if [ $? -ne 0 ]; then
|
|
127
|
+
echo "โ Jest tests failed or coverage below ${COVERAGE_MIN}%."
|
|
128
|
+
exit 1
|
|
129
|
+
fi
|
|
130
|
+
echo " โ
Jest tests passed"
|
|
131
|
+
fi
|
|
132
|
+
fi
|
|
133
|
+
if [ -f "pyproject.toml" ] || [ -f "setup.py" ]; then
|
|
134
|
+
if command -v pytest &> /dev/null; then
|
|
135
|
+
pytest --tb=short --quiet --cov=src --cov-fail-under=$COVERAGE_MIN 2>&1
|
|
136
|
+
if [ $? -ne 0 ]; then
|
|
137
|
+
echo "โ Tests failed or coverage below ${COVERAGE_MIN}%."
|
|
138
|
+
exit 1
|
|
139
|
+
fi
|
|
140
|
+
echo " โ
Python tests passed"
|
|
141
|
+
fi
|
|
142
|
+
fi
|
|
143
|
+
echo "๐งช All tests passed"
|
|
144
|
+
|
|
145
|
+
- name: anti-pattern-detector
|
|
146
|
+
trigger: pre-commit
|
|
147
|
+
description: "Scan source files for production code anti-patterns"
|
|
148
|
+
filename: pre-commit-prod-quality.sh
|
|
149
|
+
script: |
|
|
150
|
+
#!/bin/bash
|
|
151
|
+
STAGED=$(git diff --cached --name-only --diff-filter=ACM)
|
|
152
|
+
SOURCE_FILES=$(echo "$STAGED" | grep -E '\.(py|ts|tsx|js|jsx)$' | grep -vE '(test_|\.test\.|\.spec\.|__tests__|tests/|fixtures/|mock|conftest)')
|
|
153
|
+
if [ -z "$SOURCE_FILES" ]; then exit 0; fi
|
|
154
|
+
VIOLATIONS=0
|
|
155
|
+
WARNINGS=0
|
|
156
|
+
echo "๐ Scanning for production code anti-patterns..."
|
|
157
|
+
for file in $SOURCE_FILES; do
|
|
158
|
+
if echo "$file" | grep -vqE '(config|settings|\.env)'; then
|
|
159
|
+
if grep -nE '(localhost|127\.0\.0\.1|0\.0\.0\.0)' "$file" | grep -vE '(#|//|""")' > /tmp/violations 2>/dev/null; then
|
|
160
|
+
if [ -s /tmp/violations ]; then
|
|
161
|
+
echo " โ $file โ hardcoded URL/host"
|
|
162
|
+
VIOLATIONS=$((VIOLATIONS + 1))
|
|
163
|
+
fi
|
|
164
|
+
fi
|
|
165
|
+
fi
|
|
166
|
+
if grep -nEi '\b(mock_data|fake_data|dummy_data|stub_response)' "$file" > /tmp/violations 2>/dev/null; then
|
|
167
|
+
if [ -s /tmp/violations ]; then
|
|
168
|
+
echo " โ $file โ mock/stub data in production code"
|
|
169
|
+
VIOLATIONS=$((VIOLATIONS + 1))
|
|
170
|
+
fi
|
|
171
|
+
fi
|
|
172
|
+
LINE_COUNT=$(wc -l < "$file")
|
|
173
|
+
if [ "$LINE_COUNT" -gt {{max_file_length | default: 300}} ]; then
|
|
174
|
+
echo " โ ๏ธ $file โ $LINE_COUNT lines (max {{max_file_length | default: 300}})"
|
|
175
|
+
WARNINGS=$((WARNINGS + 1))
|
|
176
|
+
fi
|
|
177
|
+
done
|
|
178
|
+
rm -f /tmp/violations
|
|
179
|
+
if [ $VIOLATIONS -gt 0 ]; then
|
|
180
|
+
echo "โ $VIOLATIONS violation(s) found โ commit blocked."
|
|
181
|
+
exit 1
|
|
182
|
+
fi
|
|
183
|
+
echo "๐ Production quality scan passed"
|
|
184
|
+
|
|
185
|
+
- name: code-review
|
|
186
|
+
trigger: pre-commit
|
|
187
|
+
description: "Claude Code reviews diff against project standards"
|
|
188
|
+
filename: pre-commit-review.sh
|
|
189
|
+
script: |
|
|
190
|
+
#!/bin/bash
|
|
191
|
+
DIFF=$(git diff --cached)
|
|
192
|
+
if [ -z "$DIFF" ]; then exit 0; fi
|
|
193
|
+
echo "๐ Staged changes ready for review"
|
|
194
|
+
# Full auto-review requires claude CLI integration
|
|
195
|
+
# This hook validates the diff is non-empty and staged
|
|
196
|
+
exit 0
|