@ryuenn3123/agentic-senior-core 1.8.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/.agent-context/blueprints/api-nextjs.md +184 -0
- package/.agent-context/blueprints/aspnet-api.md +247 -0
- package/.agent-context/blueprints/ci-github-actions.md +226 -0
- package/.agent-context/blueprints/ci-gitlab.md +200 -0
- package/.agent-context/blueprints/fastapi-service.md +210 -0
- package/.agent-context/blueprints/go-service.md +217 -0
- package/.agent-context/blueprints/graphql-grpc-api.md +51 -0
- package/.agent-context/blueprints/infrastructure-as-code.md +62 -0
- package/.agent-context/blueprints/kubernetes-manifests.md +76 -0
- package/.agent-context/blueprints/laravel-api.md +223 -0
- package/.agent-context/blueprints/nestjs-logic.md +247 -0
- package/.agent-context/blueprints/observability.md +227 -0
- package/.agent-context/blueprints/spring-boot-api.md +218 -0
- package/.agent-context/policies/llm-judge-threshold.json +20 -0
- package/.agent-context/profiles/platform.md +13 -0
- package/.agent-context/profiles/regulated.md +13 -0
- package/.agent-context/profiles/startup.md +13 -0
- package/.agent-context/prompts/init-project.md +86 -0
- package/.agent-context/prompts/refactor.md +45 -0
- package/.agent-context/prompts/review-code.md +47 -0
- package/.agent-context/review-checklists/architecture-review.md +70 -0
- package/.agent-context/review-checklists/frontend-usability.md +33 -0
- package/.agent-context/review-checklists/performance-audit.md +65 -0
- package/.agent-context/review-checklists/pr-checklist.md +97 -0
- package/.agent-context/review-checklists/release-operations.md +29 -0
- package/.agent-context/review-checklists/security-audit.md +113 -0
- package/.agent-context/rules/api-docs.md +186 -0
- package/.agent-context/rules/architecture.md +198 -0
- package/.agent-context/rules/database-design.md +202 -0
- package/.agent-context/rules/efficiency-vs-hype.md +143 -0
- package/.agent-context/rules/error-handling.md +234 -0
- package/.agent-context/rules/event-driven.md +226 -0
- package/.agent-context/rules/frontend-architecture.md +66 -0
- package/.agent-context/rules/git-workflow.md +200 -0
- package/.agent-context/rules/microservices.md +174 -0
- package/.agent-context/rules/naming-conv.md +141 -0
- package/.agent-context/rules/performance.md +168 -0
- package/.agent-context/rules/realtime.md +47 -0
- package/.agent-context/rules/security.md +195 -0
- package/.agent-context/rules/testing.md +178 -0
- package/.agent-context/stacks/csharp.md +149 -0
- package/.agent-context/stacks/go.md +181 -0
- package/.agent-context/stacks/java.md +135 -0
- package/.agent-context/stacks/php.md +178 -0
- package/.agent-context/stacks/python.md +153 -0
- package/.agent-context/stacks/ruby.md +80 -0
- package/.agent-context/stacks/rust.md +86 -0
- package/.agent-context/stacks/typescript.md +317 -0
- package/.agent-context/state/architecture-map.md +25 -0
- package/.agent-context/state/dependency-map.md +32 -0
- package/.agent-override.md +36 -0
- package/.agents/workflows/init-project.md +29 -0
- package/.agents/workflows/refactor.md +29 -0
- package/.agents/workflows/review-code.md +29 -0
- package/.cursorrules +140 -0
- package/.gemini/instructions.md +97 -0
- package/.github/ISSUE_TEMPLATE/v1.7-frontend-work-item.yml +54 -0
- package/.github/copilot-instructions.md +104 -0
- package/.github/workflows/benchmark-detection.yml +38 -0
- package/.github/workflows/frontend-usability-gate.yml +36 -0
- package/.github/workflows/release-gate.yml +32 -0
- package/.github/workflows/sbom-compliance.yml +32 -0
- package/.windsurfrules +106 -0
- package/AGENTS.md +131 -0
- package/CONTRIBUTING.md +136 -0
- package/LICENSE +21 -0
- package/README.md +239 -0
- package/bin/agentic-senior-core.js +1147 -0
- package/mcp.json +29 -0
- package/package.json +50 -0
- package/scripts/detection-benchmark.mjs +138 -0
- package/scripts/frontend-usability-audit.mjs +87 -0
- package/scripts/generate-sbom.mjs +61 -0
- package/scripts/init-project.ps1 +105 -0
- package/scripts/init-project.sh +131 -0
- package/scripts/llm-judge.mjs +664 -0
- package/scripts/release-gate.mjs +116 -0
- package/scripts/validate.mjs +554 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# Git Workflow — Clean History, Atomic Commits
|
|
2
|
+
|
|
3
|
+
> Your git log is a changelog. If it reads like gibberish, your team is lost.
|
|
4
|
+
|
|
5
|
+
## Commit Message Format: Conventional Commits (Enforced)
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
<type>(<scope>): <description>
|
|
9
|
+
|
|
10
|
+
[optional body — explain WHY, not WHAT]
|
|
11
|
+
[optional footer — Breaking changes, issue references]
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### Types (Strict Set)
|
|
15
|
+
| Type | When | Example |
|
|
16
|
+
|------|------|---------|
|
|
17
|
+
| `feat` | New feature | `feat(auth): add JWT refresh token rotation` |
|
|
18
|
+
| `fix` | Bug fix | `fix(payment): handle race condition in checkout` |
|
|
19
|
+
| `refactor` | Code restructuring (no behavior change) | `refactor(user): extract validation to separate service` |
|
|
20
|
+
| `docs` | Documentation only | `docs(api): add OpenAPI schema for /orders endpoint` |
|
|
21
|
+
| `test` | Adding/fixing tests | `test(cart): add edge case for empty cart discount` |
|
|
22
|
+
| `chore` | Build, CI, config, dependencies | `chore(deps): upgrade prisma to 5.x` |
|
|
23
|
+
| `perf` | Performance improvement | `perf(search): add index on users.email column` |
|
|
24
|
+
| `style` | Formatting, semicolons (no logic change) | `style: apply prettier formatting` |
|
|
25
|
+
| `ci` | CI/CD changes | `ci: add Node 20 to test matrix` |
|
|
26
|
+
|
|
27
|
+
### Rules
|
|
28
|
+
1. **Type is mandatory.** No commits without a type prefix.
|
|
29
|
+
2. **Scope is recommended.** Use the module/feature name.
|
|
30
|
+
3. **Description is imperative mood.** "add", not "added" or "adds".
|
|
31
|
+
4. **Max 72 characters** for the subject line.
|
|
32
|
+
5. **Body explains WHY,** not what. The diff shows what.
|
|
33
|
+
|
|
34
|
+
### ❌ BANNED Commit Messages
|
|
35
|
+
```
|
|
36
|
+
fix bug
|
|
37
|
+
updates
|
|
38
|
+
WIP
|
|
39
|
+
asdf
|
|
40
|
+
misc changes
|
|
41
|
+
working now
|
|
42
|
+
final fix
|
|
43
|
+
fix fix fix
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Branching Model
|
|
49
|
+
|
|
50
|
+
### Main Branches
|
|
51
|
+
| Branch | Purpose | Merge Strategy |
|
|
52
|
+
|--------|---------|---------------|
|
|
53
|
+
| `main` | Production-ready code | Merge commit or squash |
|
|
54
|
+
| `develop` | Integration branch (if using GitFlow) | Merge commit |
|
|
55
|
+
|
|
56
|
+
### Feature Branches
|
|
57
|
+
```
|
|
58
|
+
Pattern: <type>/<ticket-id>-<short-description>
|
|
59
|
+
|
|
60
|
+
Examples:
|
|
61
|
+
feat/AUTH-123-jwt-refresh
|
|
62
|
+
fix/PAY-456-checkout-race-condition
|
|
63
|
+
refactor/USER-789-extract-validation
|
|
64
|
+
chore/INFRA-101-upgrade-node-20
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Rules
|
|
68
|
+
1. Branch from `main` (or `develop` if using GitFlow)
|
|
69
|
+
2. Keep branches short-lived (max 2-3 days)
|
|
70
|
+
3. Rebase on `main` before creating PR — don't merge main into your branch
|
|
71
|
+
4. Delete branch after merge
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Pull Request Standards
|
|
76
|
+
|
|
77
|
+
### PR Size
|
|
78
|
+
| Size | Lines Changed | Verdict |
|
|
79
|
+
|------|--------------|---------|
|
|
80
|
+
| Small | 1-100 | ✅ Ideal — easy to review |
|
|
81
|
+
| Medium | 100-300 | ⚠️ Acceptable — split if possible |
|
|
82
|
+
| Large | 300-500 | 🔶 Needs justification |
|
|
83
|
+
| Massive | 500+ | ❌ MUST be split into smaller PRs |
|
|
84
|
+
|
|
85
|
+
**Rule:** If a PR touches more than 5 files across different modules, it's doing too much. Split it.
|
|
86
|
+
|
|
87
|
+
### PR Description Template
|
|
88
|
+
```markdown
|
|
89
|
+
## What
|
|
90
|
+
Brief description of what this PR does.
|
|
91
|
+
|
|
92
|
+
## Why
|
|
93
|
+
Why this change is needed. Link to issue/ticket.
|
|
94
|
+
|
|
95
|
+
## How
|
|
96
|
+
High-level approach. Mention any non-obvious design decisions.
|
|
97
|
+
|
|
98
|
+
## Testing
|
|
99
|
+
- [ ] Unit tests added/updated
|
|
100
|
+
- [ ] Integration tests (if applicable)
|
|
101
|
+
- [ ] Manual testing steps
|
|
102
|
+
|
|
103
|
+
## Screenshots (if UI change)
|
|
104
|
+
Before | After
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### PR Review Rules
|
|
108
|
+
1. Every PR needs at least 1 approval
|
|
109
|
+
2. Author resolves all comments before merge
|
|
110
|
+
3. CI must pass (lint, test, build)
|
|
111
|
+
4. No `// TODO` without a linked issue
|
|
112
|
+
5. No `console.log` debugging statements in production code
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Commit Atomicity
|
|
117
|
+
|
|
118
|
+
### Rule: Each Commit Must Be a Complete, Working Unit
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
❌ BANNED sequence:
|
|
122
|
+
1. feat(user): add user model ← compiles? maybe
|
|
123
|
+
2. fix: fix import ← fixing previous commit
|
|
124
|
+
3. feat(user): add user service ← compiles? probably
|
|
125
|
+
4. fix: fix typo ← fixing previous commit
|
|
126
|
+
5. feat(user): add user controller ← finally works together
|
|
127
|
+
|
|
128
|
+
✅ REQUIRED:
|
|
129
|
+
1. feat(user): add user registration module
|
|
130
|
+
→ Model, Service, Controller, Tests — all in one complete, working commit
|
|
131
|
+
→ Or split into logical chunks that each compile and pass tests independently
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Rule:** Every commit on `main` should compile, pass lint, and pass tests. Use interactive rebase (`git rebase -i`) to squash fix-up commits before merging.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## .gitignore Standards
|
|
139
|
+
|
|
140
|
+
### MUST Ignore
|
|
141
|
+
```
|
|
142
|
+
# Dependencies
|
|
143
|
+
node_modules/
|
|
144
|
+
vendor/
|
|
145
|
+
venv/
|
|
146
|
+
__pycache__/
|
|
147
|
+
.gradle/
|
|
148
|
+
target/
|
|
149
|
+
|
|
150
|
+
# Environment
|
|
151
|
+
.env
|
|
152
|
+
.env.local
|
|
153
|
+
.env.*.local
|
|
154
|
+
|
|
155
|
+
# IDE
|
|
156
|
+
.idea/
|
|
157
|
+
.vscode/settings.json
|
|
158
|
+
*.swp
|
|
159
|
+
*.swo
|
|
160
|
+
.DS_Store
|
|
161
|
+
Thumbs.db
|
|
162
|
+
|
|
163
|
+
# Build output
|
|
164
|
+
dist/
|
|
165
|
+
build/
|
|
166
|
+
out/
|
|
167
|
+
*.min.js
|
|
168
|
+
*.min.css
|
|
169
|
+
|
|
170
|
+
# Logs
|
|
171
|
+
*.log
|
|
172
|
+
npm-debug.log*
|
|
173
|
+
|
|
174
|
+
# OS
|
|
175
|
+
.DS_Store
|
|
176
|
+
Thumbs.db
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### MUST Commit
|
|
180
|
+
```
|
|
181
|
+
.env.example # Template with placeholder values
|
|
182
|
+
.editorconfig # Consistent formatting across IDEs
|
|
183
|
+
.prettierrc # Formatter config
|
|
184
|
+
.eslintrc.* # Linter config
|
|
185
|
+
tsconfig.json # TypeScript config
|
|
186
|
+
docker-compose.yml # Dev environment
|
|
187
|
+
Makefile / Taskfile # Standard commands
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## The Git Health Check
|
|
193
|
+
|
|
194
|
+
Before pushing:
|
|
195
|
+
- [ ] All commits follow Conventional Commits format
|
|
196
|
+
- [ ] No fixup commits (squash them)
|
|
197
|
+
- [ ] Branch is rebased on latest main
|
|
198
|
+
- [ ] CI passes locally (lint, test, build)
|
|
199
|
+
- [ ] No secrets in any commit (check with `git log -p | grep -i "password\|secret\|key"`)
|
|
200
|
+
- [ ] No merge commits in feature branch (rebase instead)
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Microservices — When to Split, How to Split
|
|
2
|
+
|
|
3
|
+
> Don't start with microservices. Earn them through pain.
|
|
4
|
+
> A bad monolith becomes a distributed bad monolith faster than you think.
|
|
5
|
+
|
|
6
|
+
## The Default: Modular Monolith
|
|
7
|
+
|
|
8
|
+
**Start with a modular monolith. Always.** Microservices are a scaling strategy, not a design philosophy.
|
|
9
|
+
|
|
10
|
+
A well-structured modular monolith can handle most applications indefinitely. Splitting prematurely creates distributed complexity without distributed benefits.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## The Split Decision Framework
|
|
15
|
+
|
|
16
|
+
### Prerequisites (ALL Must Be True)
|
|
17
|
+
|
|
18
|
+
Before even considering microservices, these must exist:
|
|
19
|
+
|
|
20
|
+
1. **Mature CI/CD pipeline** — automated testing, deployment, rollback
|
|
21
|
+
2. **Observability in place** — distributed tracing, centralized logging, metrics
|
|
22
|
+
3. **Team maturity** — team understands distributed systems failure modes
|
|
23
|
+
4. **Clear module boundaries** — modules already communicate through interfaces, not internals
|
|
24
|
+
|
|
25
|
+
If any prerequisite is missing, **stop.** Fix the monolith first.
|
|
26
|
+
|
|
27
|
+
### Trigger Conditions (2+ Required)
|
|
28
|
+
|
|
29
|
+
Split a module into a service ONLY when **2 or more** of these triggers exist:
|
|
30
|
+
|
|
31
|
+
| # | Trigger | Evidence |
|
|
32
|
+
|---|---------|----------|
|
|
33
|
+
| 1 | **Deploy conflicts** | Teams block each other on releases; merge queues exceed 24h |
|
|
34
|
+
| 2 | **Scale mismatch** | One module needs 50-100x resources of another |
|
|
35
|
+
| 3 | **Team ownership collision** | Multiple teams edit the same module weekly |
|
|
36
|
+
| 4 | **Fault isolation** | One module crashing must not kill the entire system |
|
|
37
|
+
| 5 | **Technology divergence** | Module genuinely requires a different runtime/language |
|
|
38
|
+
| 6 | **Compliance boundary** | Regulatory requirement to isolate data processing (PCI, HIPAA) |
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
BANNED: "Let's use microservices because Netflix does"
|
|
42
|
+
BANNED: "We might need to scale later"
|
|
43
|
+
BANNED: "It's more modern"
|
|
44
|
+
BANNED: "Each developer gets their own service"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## How to Split (The Extraction Protocol)
|
|
50
|
+
|
|
51
|
+
### Step 1: Identify the Seam
|
|
52
|
+
|
|
53
|
+
Find the natural boundary in your modular monolith:
|
|
54
|
+
```
|
|
55
|
+
GOOD seams:
|
|
56
|
+
- Module communicates with others through a defined interface/API
|
|
57
|
+
- Module has its own database tables with no foreign keys to other modules
|
|
58
|
+
- Module can be deployed independently without breaking others
|
|
59
|
+
|
|
60
|
+
BAD seams:
|
|
61
|
+
- Two modules share a database table
|
|
62
|
+
- Extracting requires duplicating business logic
|
|
63
|
+
- Module makes 10+ synchronous calls to other modules per request
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Step 2: Strangle, Don't Rewrite
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
❌ BANNED: "Let's rewrite everything as microservices"
|
|
70
|
+
|
|
71
|
+
✅ REQUIRED: The Strangler Fig Pattern
|
|
72
|
+
1. Build the new service alongside the monolith
|
|
73
|
+
2. Route traffic to the new service gradually (feature flags, proxy rules)
|
|
74
|
+
3. Verify the new service handles all cases correctly
|
|
75
|
+
4. Remove the old code from the monolith
|
|
76
|
+
5. Repeat for the next service, ONE AT A TIME
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Step 3: Define the Contract
|
|
80
|
+
|
|
81
|
+
Before extracting, define the communication contract:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
REQUIRED for every service boundary:
|
|
85
|
+
- API contract (OpenAPI 3.1, Protobuf, or AsyncAPI for events)
|
|
86
|
+
- Versioning strategy (URL versioning, header versioning)
|
|
87
|
+
- Error contract (standardized error response format)
|
|
88
|
+
- SLA definition (latency, availability, throughput)
|
|
89
|
+
- Ownership (which team owns this service)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Communication Patterns
|
|
95
|
+
|
|
96
|
+
### Synchronous (Request-Response)
|
|
97
|
+
|
|
98
|
+
| Pattern | When | Watch Out |
|
|
99
|
+
|---------|------|-----------|
|
|
100
|
+
| REST/HTTP | Standard CRUD operations | Cascading failures, tight coupling |
|
|
101
|
+
| gRPC | High-performance, internal services | Schema evolution, debugging complexity |
|
|
102
|
+
|
|
103
|
+
**Rules:**
|
|
104
|
+
- Always set timeouts (connection: 1s, request: 5s default)
|
|
105
|
+
- Implement circuit breakers (fail-fast after N failures)
|
|
106
|
+
- Never chain more than 3 synchronous calls
|
|
107
|
+
- Implement retries with exponential backoff (transient errors only)
|
|
108
|
+
|
|
109
|
+
### Asynchronous (Events)
|
|
110
|
+
|
|
111
|
+
| Pattern | When | Watch Out |
|
|
112
|
+
|---------|------|-----------|
|
|
113
|
+
| Pub/Sub | One event, multiple consumers | Message ordering, at-least-once delivery |
|
|
114
|
+
| Command Queue | Exactly-once processing needed | Dead letter queues, poison messages |
|
|
115
|
+
| Event Sourcing | Full audit trail required | Complexity, event schema evolution |
|
|
116
|
+
|
|
117
|
+
**Rules:**
|
|
118
|
+
- Prefer async communication over sync between services
|
|
119
|
+
- Events are facts (past tense): `OrderPlaced`, `PaymentProcessed`
|
|
120
|
+
- Commands are requests (imperative): `ProcessPayment`, `ShipOrder`
|
|
121
|
+
- Always handle duplicate messages (idempotency)
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Data Ownership
|
|
126
|
+
|
|
127
|
+
### The Database-Per-Service Rule
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
❌ DEATH PENALTY: Shared databases between services
|
|
131
|
+
Service A → Database ← Service B
|
|
132
|
+
// One schema change breaks both services
|
|
133
|
+
|
|
134
|
+
✅ REQUIRED: Each service owns its data
|
|
135
|
+
Service A → Database A
|
|
136
|
+
Service B → Database B
|
|
137
|
+
// Services communicate through APIs or events
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Data Consistency
|
|
141
|
+
|
|
142
|
+
- **Accept eventual consistency** — strong consistency across services is extremely expensive
|
|
143
|
+
- **Use the Saga pattern** for distributed transactions (choreography or orchestration)
|
|
144
|
+
- **Never use distributed 2PC (two-phase commit)** in production — it doesn't scale
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Anti-Patterns (Instant Rejection)
|
|
149
|
+
|
|
150
|
+
| Anti-Pattern | Why It's Dangerous |
|
|
151
|
+
|-------------|-------------------|
|
|
152
|
+
| **Distributed Monolith** | Services that must be deployed together defeat the purpose |
|
|
153
|
+
| **Nano-services** | One function per service creates operational nightmare |
|
|
154
|
+
| **Shared libraries with logic** | Tight coupling through shared code |
|
|
155
|
+
| **Synchronous chains** | A→B→C→D means one failure kills everything |
|
|
156
|
+
| **Shared database** | Schema changes break multiple services |
|
|
157
|
+
| **"We'll figure out observability later"** | You won't find bugs without tracing. Ever. |
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## The Microservices Readiness Checklist
|
|
162
|
+
|
|
163
|
+
Before splitting ANY module:
|
|
164
|
+
|
|
165
|
+
- [ ] 2+ trigger conditions met (documented with evidence)
|
|
166
|
+
- [ ] All prerequisites in place (CI/CD, observability, team maturity)
|
|
167
|
+
- [ ] Service boundary defined with clear ownership
|
|
168
|
+
- [ ] API contract defined (OpenAPI, Protobuf, AsyncAPI)
|
|
169
|
+
- [ ] Data ownership clear — no shared tables
|
|
170
|
+
- [ ] Communication pattern chosen (sync vs async)
|
|
171
|
+
- [ ] Failure handling designed (timeouts, circuit breakers, retries)
|
|
172
|
+
- [ ] Monitoring and alerting planned
|
|
173
|
+
- [ ] Rollback strategy defined
|
|
174
|
+
- [ ] Team agrees this is the right decision (not just the architect)
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Naming Conventions — The "No Lazy Names" Standard
|
|
2
|
+
|
|
3
|
+
> If your variable name needs a comment to explain it, the name is wrong.
|
|
4
|
+
|
|
5
|
+
## Universal Rules (All Languages)
|
|
6
|
+
|
|
7
|
+
### Variables: Nouns That Tell a Story
|
|
8
|
+
```
|
|
9
|
+
❌ BANNED ✅ REQUIRED
|
|
10
|
+
─────────────────────────────────────────────
|
|
11
|
+
d durationInSeconds
|
|
12
|
+
data userProfilePayload
|
|
13
|
+
res httpResponse
|
|
14
|
+
temp unsortedItems
|
|
15
|
+
val discountPercentage
|
|
16
|
+
info orderSummary
|
|
17
|
+
item cartLineItem
|
|
18
|
+
list activeSubscriptions
|
|
19
|
+
obj paymentConfiguration
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Rule:** A variable name must answer "WHAT is this?" without reading surrounding code.
|
|
23
|
+
|
|
24
|
+
### Functions: Verbs That Declare Intent
|
|
25
|
+
```
|
|
26
|
+
❌ BANNED ✅ REQUIRED
|
|
27
|
+
─────────────────────────────────────────────
|
|
28
|
+
process() validatePaymentDetails()
|
|
29
|
+
handle() routeIncomingWebhook()
|
|
30
|
+
doStuff() calculateShippingCost()
|
|
31
|
+
run() executeScheduledCleanup()
|
|
32
|
+
getData() fetchActiveUsersByRegion()
|
|
33
|
+
check() isEligibleForDiscount()
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Rule:** A function name must answer "WHAT does this do?" as a verb phrase. Generic verbs like `process`, `handle`, `manage` are BANNED unless suffixed with a specific noun (e.g., `handlePaymentFailure`).
|
|
37
|
+
|
|
38
|
+
### Booleans: is/has/can/should Prefix
|
|
39
|
+
```
|
|
40
|
+
❌ BANNED ✅ REQUIRED
|
|
41
|
+
─────────────────────────────────────────────
|
|
42
|
+
active isActive
|
|
43
|
+
logged isLoggedIn
|
|
44
|
+
admin hasAdminRole
|
|
45
|
+
edit canEditDocument
|
|
46
|
+
visible shouldRenderSidebar
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Rule:** Boolean variables MUST use `is`, `has`, `can`, or `should` prefix. No exceptions.
|
|
50
|
+
|
|
51
|
+
### Constants: SCREAMING_SNAKE for True Constants
|
|
52
|
+
```
|
|
53
|
+
❌ BANNED ✅ REQUIRED
|
|
54
|
+
─────────────────────────────────────────────
|
|
55
|
+
maxRetries = 3 MAX_RETRY_COUNT = 3
|
|
56
|
+
timeout = 5000 REQUEST_TIMEOUT_MS = 5000
|
|
57
|
+
apiUrl = "..." API_BASE_URL = "..."
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Rule:** Use SCREAMING_SNAKE_CASE for compile-time constants and config values. Include the unit in the name when applicable (`_MS`, `_BYTES`, `_COUNT`).
|
|
61
|
+
|
|
62
|
+
### Single-Letter Variables
|
|
63
|
+
**BANNED.** With exactly ONE exception:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
// ALLOWED: Classic loop counter in simple iterations
|
|
67
|
+
for (let i = 0; i < items.length; i++) { ... }
|
|
68
|
+
|
|
69
|
+
// BANNED: Everything else
|
|
70
|
+
const x = getPrice(); // ❌ What is x?
|
|
71
|
+
const n = users.length; // ❌ Use userCount
|
|
72
|
+
arr.map(v => v.id); // ❌ Use user => user.id
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## File & Directory Naming
|
|
78
|
+
|
|
79
|
+
### Files
|
|
80
|
+
| Type | Convention | Example |
|
|
81
|
+
|------|-----------|---------|
|
|
82
|
+
| Component (React/Vue) | PascalCase | `PaymentForm.tsx` |
|
|
83
|
+
| Module/Service | camelCase or kebab-case | `paymentService.ts` or `payment-service.ts` |
|
|
84
|
+
| Utility | camelCase or kebab-case | `formatCurrency.ts` or `format-currency.ts` |
|
|
85
|
+
| Test | Same as source + `.test`/`.spec` | `paymentService.test.ts` |
|
|
86
|
+
| Type/Interface | PascalCase | `PaymentTypes.ts` |
|
|
87
|
+
| Constant file | SCREAMING_SNAKE or kebab-case | `constants.ts` or `api-endpoints.ts` |
|
|
88
|
+
| Config | kebab-case | `database-config.ts` |
|
|
89
|
+
|
|
90
|
+
**Rule:** Pick ONE convention per project and enforce it everywhere. Mixing `camelCase` and `kebab-case` in the same project is a code smell.
|
|
91
|
+
|
|
92
|
+
### Directories
|
|
93
|
+
- Always `kebab-case`: `user-management/`, `payment-processing/`
|
|
94
|
+
- Never PascalCase for directories (except component folders in React convention)
|
|
95
|
+
- No abbreviations: `auth/` → `authentication/` (unless universally understood like `api/`, `db/`)
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Abbreviation Policy
|
|
100
|
+
|
|
101
|
+
### Allowed (Universal)
|
|
102
|
+
`id`, `url`, `api`, `db`, `http`, `io`, `ui`, `dto`, `config`, `env`, `auth`, `admin`, `src`, `lib`, `pkg`, `cmd`, `ctx`, `err`, `req`, `res` (in HTTP handler context only)
|
|
103
|
+
|
|
104
|
+
### Banned
|
|
105
|
+
Everything else. Spell it out:
|
|
106
|
+
```
|
|
107
|
+
❌ usr → ✅ user
|
|
108
|
+
❌ cnt → ✅ count
|
|
109
|
+
❌ mgr → ✅ manager
|
|
110
|
+
❌ btn → ✅ button
|
|
111
|
+
❌ msg → ✅ message
|
|
112
|
+
❌ impl → ✅ implementation
|
|
113
|
+
❌ calc → ✅ calculate
|
|
114
|
+
❌ proc → ✅ process
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## The Naming Decision Tree
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
Is it a boolean?
|
|
123
|
+
→ Yes → Add is/has/can/should prefix
|
|
124
|
+
→ No ↓
|
|
125
|
+
|
|
126
|
+
Is it a function?
|
|
127
|
+
→ Yes → Start with a verb (fetch, create, validate, calculate, is, has)
|
|
128
|
+
→ No ↓
|
|
129
|
+
|
|
130
|
+
Is it a constant?
|
|
131
|
+
→ Yes → SCREAMING_SNAKE_CASE with unit suffix
|
|
132
|
+
→ No ↓
|
|
133
|
+
|
|
134
|
+
Is it a class/type/interface?
|
|
135
|
+
→ Yes → PascalCase, noun, no prefix (not IUser, not UserInterface)
|
|
136
|
+
→ No ↓
|
|
137
|
+
|
|
138
|
+
It's a variable
|
|
139
|
+
→ Descriptive noun, camelCase
|
|
140
|
+
→ Must be understandable without context
|
|
141
|
+
```
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# Performance — Measure Before You Optimize
|
|
2
|
+
|
|
3
|
+
> Premature optimization is the root of all evil.
|
|
4
|
+
> But ignoring obvious performance traps is just incompetence.
|
|
5
|
+
|
|
6
|
+
## The Performance Prime Directive
|
|
7
|
+
|
|
8
|
+
**Do NOT optimize without evidence.** CPU time is cheap. Developer time is expensive.
|
|
9
|
+
|
|
10
|
+
BUT — there are patterns so obviously bad that they don't need benchmarks to reject.
|
|
11
|
+
Those are listed below as **Death Penalties**.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Death Penalties (Always Reject)
|
|
16
|
+
|
|
17
|
+
### 1. N+1 Queries
|
|
18
|
+
```
|
|
19
|
+
❌ INSTANT REJECTION:
|
|
20
|
+
const users = await db.query('SELECT * FROM users');
|
|
21
|
+
for (const user of users) {
|
|
22
|
+
user.orders = await db.query('SELECT * FROM orders WHERE user_id = ?', [user.id]);
|
|
23
|
+
// This runs 1 + N queries. For 1000 users = 1001 database round trips.
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
✅ REQUIRED:
|
|
27
|
+
const users = await db.query('SELECT * FROM users');
|
|
28
|
+
const userIds = users.map(u => u.id);
|
|
29
|
+
const orders = await db.query('SELECT * FROM orders WHERE user_id = ANY($1)', [userIds]);
|
|
30
|
+
// 2 queries total, regardless of user count
|
|
31
|
+
// Or use ORM eager loading / DataLoader pattern
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Rule:** If you see a query inside a loop, it is almost certainly an N+1 bug. Fix it with JOINs, batch queries, or DataLoader.
|
|
35
|
+
|
|
36
|
+
### 2. Unbounded Queries
|
|
37
|
+
```
|
|
38
|
+
❌ INSTANT REJECTION:
|
|
39
|
+
const allUsers = await db.query('SELECT * FROM users');
|
|
40
|
+
// In production, "users" table has 2 million rows. Enjoy your OOM.
|
|
41
|
+
|
|
42
|
+
✅ REQUIRED:
|
|
43
|
+
const users = await db.query('SELECT * FROM users LIMIT $1 OFFSET $2', [pageSize, offset]);
|
|
44
|
+
// Or use cursor-based pagination for large datasets
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Rule:** EVERY query that returns a list MUST have a LIMIT. APIs MUST support pagination. Default page size: 20-50.
|
|
48
|
+
|
|
49
|
+
### 3. SELECT * in Production
|
|
50
|
+
```
|
|
51
|
+
❌ BANNED:
|
|
52
|
+
SELECT * FROM users; -- Fetches 30 columns when you need 3
|
|
53
|
+
|
|
54
|
+
✅ REQUIRED:
|
|
55
|
+
SELECT id, email, display_name FROM users;
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Rule:** Select only the columns you need. `SELECT *` wastes bandwidth, memory, and makes schema changes dangerous.
|
|
59
|
+
|
|
60
|
+
### 4. Synchronous I/O in Async Context
|
|
61
|
+
```
|
|
62
|
+
❌ BANNED:
|
|
63
|
+
// In an async Node.js server
|
|
64
|
+
const data = fs.readFileSync('/path/to/file');
|
|
65
|
+
const result = execSync('some-command');
|
|
66
|
+
|
|
67
|
+
✅ REQUIRED:
|
|
68
|
+
const data = await fs.promises.readFile('/path/to/file');
|
|
69
|
+
const result = await exec('some-command');
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Rule:** In async environments (Node.js, Python asyncio), NEVER block the event loop with synchronous I/O.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Optimize Only With Evidence
|
|
77
|
+
|
|
78
|
+
For everything else, follow this protocol:
|
|
79
|
+
|
|
80
|
+
### Step 1: Measure
|
|
81
|
+
```
|
|
82
|
+
// Use profiling tools, not guesses
|
|
83
|
+
console.time('operation');
|
|
84
|
+
await heavyOperation();
|
|
85
|
+
console.timeEnd('operation');
|
|
86
|
+
|
|
87
|
+
// Use proper APM: Datadog, New Relic, OpenTelemetry
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Step 2: Identify the Bottleneck
|
|
91
|
+
- Is it CPU? Memory? I/O? Network?
|
|
92
|
+
- Don't optimize CPU when the bottleneck is a slow database query
|
|
93
|
+
|
|
94
|
+
### Step 3: Optimize the Bottleneck (Not Everything Else)
|
|
95
|
+
- Fix the slowest thing first
|
|
96
|
+
- Re-measure after each change
|
|
97
|
+
- Stop when performance meets requirements
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Caching Rules
|
|
102
|
+
|
|
103
|
+
### When to Cache
|
|
104
|
+
- Data that is read frequently, written rarely
|
|
105
|
+
- Expensive computations that produce the same result for same inputs
|
|
106
|
+
- External API responses (respect their cache headers)
|
|
107
|
+
|
|
108
|
+
### When NOT to Cache
|
|
109
|
+
- Data that changes every request
|
|
110
|
+
- Small, fast queries (cache overhead > query time)
|
|
111
|
+
- When you can't define a clear invalidation strategy
|
|
112
|
+
|
|
113
|
+
### The Caching Devil's Triangle
|
|
114
|
+
You can have 2 of 3:
|
|
115
|
+
1. **Fresh data** (always up-to-date)
|
|
116
|
+
2. **Fast reads** (sub-millisecond)
|
|
117
|
+
3. **Simple code** (no cache layer)
|
|
118
|
+
|
|
119
|
+
Pick your 2 and document the trade-off.
|
|
120
|
+
|
|
121
|
+
### Invalidation Strategy (MANDATORY)
|
|
122
|
+
```
|
|
123
|
+
❌ BANNED:
|
|
124
|
+
cache.set('users', data); // When does this expire? Who invalidates it? Nobody knows.
|
|
125
|
+
|
|
126
|
+
✅ REQUIRED:
|
|
127
|
+
cache.set('users:active', data, { ttl: 300 }); // 5 min TTL, explicit key
|
|
128
|
+
// AND document: "Invalidated on user.created, user.deleted, user.deactivated events"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Rule:** NEVER add a cache without documenting the invalidation strategy. "We'll figure it out later" means "we'll have stale data in production."
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Connection Management
|
|
136
|
+
|
|
137
|
+
1. **Use connection pools** — never open/close connections per request
|
|
138
|
+
2. **Set pool limits** — max connections based on infrastructure, not infinity
|
|
139
|
+
3. **Implement timeouts** — connection timeout, query timeout, request timeout
|
|
140
|
+
4. **Handle pool exhaustion** — fail fast with clear error, don't queue forever
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Frontend Performance (When Applicable)
|
|
145
|
+
|
|
146
|
+
1. **Lazy load** routes and heavy components
|
|
147
|
+
2. **Debounce** search inputs and scroll handlers (300ms minimum)
|
|
148
|
+
3. **Virtualize** long lists (don't render 10,000 DOM nodes)
|
|
149
|
+
4. **Optimize images** — WebP/AVIF, responsive sizes, lazy loading
|
|
150
|
+
5. **Bundle analysis** — if your JS bundle exceeds 200KB gzipped, investigate
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## The Performance Decision Framework
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
Is it a known Death Penalty pattern (N+1, unbounded, SELECT *, sync I/O)?
|
|
158
|
+
→ Yes → Fix it now, no measurement needed
|
|
159
|
+
→ No ↓
|
|
160
|
+
|
|
161
|
+
Is there a measurable performance problem?
|
|
162
|
+
→ No → Don't optimize. Ship it.
|
|
163
|
+
→ Yes ↓
|
|
164
|
+
|
|
165
|
+
Have you identified the specific bottleneck?
|
|
166
|
+
→ No → Profile first
|
|
167
|
+
→ Yes → Optimize ONLY that bottleneck, re-measure, stop when sufficient
|
|
168
|
+
```
|