claude-code-kit 0.7.0__py3-none-any.whl
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.
- claude_code_kit-0.7.0.dist-info/METADATA +384 -0
- claude_code_kit-0.7.0.dist-info/RECORD +209 -0
- claude_code_kit-0.7.0.dist-info/WHEEL +4 -0
- claude_code_kit-0.7.0.dist-info/entry_points.txt +4 -0
- claude_code_kit-0.7.0.dist-info/licenses/LICENSE +21 -0
- claude_kit/__init__.py +10 -0
- claude_kit/__main__.py +8 -0
- claude_kit/_payload/agents/acceptance-reviewer.md +60 -0
- claude_kit/_payload/agents/auditor.md +76 -0
- claude_kit/_payload/agents/dependency-scanner.md +84 -0
- claude_kit/_payload/agents/developer.md +187 -0
- claude_kit/_payload/agents/devils-advocate.md +62 -0
- claude_kit/_payload/agents/devops-engineer.md +134 -0
- claude_kit/_payload/agents/e2e-tester.md +152 -0
- claude_kit/_payload/agents/em-reviewer.md +105 -0
- claude_kit/_payload/agents/incident-responder.md +64 -0
- claude_kit/_payload/agents/merge-reviewer.md +194 -0
- claude_kit/_payload/agents/observability-engineer.md +94 -0
- claude_kit/_payload/agents/orchestrator.md +551 -0
- claude_kit/_payload/agents/owasp-reviewer.md +76 -0
- claude_kit/_payload/agents/policy-validator.md +63 -0
- claude_kit/_payload/agents/pr-raiser.md +138 -0
- claude_kit/_payload/agents/risk-classifier.md +50 -0
- claude_kit/_payload/agents/sdlc-code-reviewer.md +196 -0
- claude_kit/_payload/agents/secret-scanner.md +70 -0
- claude_kit/_payload/agents/security-reviewer.md +80 -0
- claude_kit/_payload/agents/senior-backend-dev.md +199 -0
- claude_kit/_payload/agents/senior-frontend-dev.md +181 -0
- claude_kit/_payload/agents/senior-tester.md +206 -0
- claude_kit/_payload/agents/spec-doc-writer.md +331 -0
- claude_kit/_payload/agents/story-planner.md +56 -0
- claude_kit/_payload/agents/technical-architect.md +139 -0
- claude_kit/_payload/agents/tester.md +193 -0
- claude_kit/_payload/agents/ui-designer.md +73 -0
- claude_kit/_payload/agents/unit-tester.md +119 -0
- claude_kit/_payload/catalog/mcp.yaml +54 -0
- claude_kit/_payload/catalog/org.yaml +145 -0
- claude_kit/_payload/catalog/profiles.yaml +96 -0
- claude_kit/_payload/catalog/stacks.yaml +96 -0
- claude_kit/_payload/commands/init.md +36 -0
- claude_kit/_payload/commands/sdlc.md +18 -0
- claude_kit/_payload/commands/status.md +20 -0
- claude_kit/_payload/hooks/hooks.json +58 -0
- claude_kit/_payload/hooks/scripts/audit-log.sh +18 -0
- claude_kit/_payload/hooks/scripts/guard-secrets.sh +26 -0
- claude_kit/_payload/hooks/scripts/lint-fix.sh +38 -0
- claude_kit/_payload/hooks/scripts/load-continuity.sh +32 -0
- claude_kit/_payload/hooks/scripts/load-learnings.sh +40 -0
- claude_kit/_payload/hooks/scripts/type-check.sh +23 -0
- claude_kit/_payload/hooks/scripts/validate-frontmatter.sh +34 -0
- claude_kit/_payload/hooks/scripts/validate-settings.sh +21 -0
- claude_kit/_payload/hooks/scripts/warn-large-edits.sh +24 -0
- claude_kit/_payload/hooks/scripts/warn-missing-tests.sh +24 -0
- claude_kit/_payload/hooks/scripts/warn-sensitive-files.sh +30 -0
- claude_kit/_payload/hooks/scripts/warn-shared-modules.sh +33 -0
- claude_kit/_payload/rules/agent-guardrails.md +83 -0
- claude_kit/_payload/rules/agent-memory.md +106 -0
- claude_kit/_payload/rules/agent-resilience.md +61 -0
- claude_kit/_payload/rules/autonomy-levels.md +30 -0
- claude_kit/_payload/rules/code-organization.md +312 -0
- claude_kit/_payload/rules/continuity.md +84 -0
- claude_kit/_payload/rules/design-patterns.md +422 -0
- claude_kit/_payload/rules/devops-observability.md +57 -0
- claude_kit/_payload/rules/documentation.md +326 -0
- claude_kit/_payload/rules/evals.md +62 -0
- claude_kit/_payload/rules/frontend-best-practices.md +157 -0
- claude_kit/_payload/rules/goal-setting-and-monitoring.md +72 -0
- claude_kit/_payload/rules/human-in-the-loop.md +64 -0
- claude_kit/_payload/rules/linting-and-formatting.md +220 -0
- claude_kit/_payload/rules/mandatory-workflow.md +309 -0
- claude_kit/_payload/rules/model-tiers.md +34 -0
- claude_kit/_payload/rules/quality-gates.md +107 -0
- claude_kit/_payload/rules/rarv-cycle.md +31 -0
- claude_kit/_payload/rules/reasoning-techniques.md +62 -0
- claude_kit/_payload/rules/responsive-and-accessibility.md +353 -0
- claude_kit/_payload/rules/risk-classification.md +36 -0
- claude_kit/_payload/rules/testing.md +417 -0
- claude_kit/_payload/rules/tool-design.md +66 -0
- claude_kit/_payload/skills/_references/accessibility-checklist.md +160 -0
- claude_kit/_payload/skills/_references/orchestration-patterns.md +405 -0
- claude_kit/_payload/skills/_references/performance-checklist.md +153 -0
- claude_kit/_payload/skills/_references/security-checklist.md +134 -0
- claude_kit/_payload/skills/_references/testing-patterns.md +236 -0
- claude_kit/_payload/skills/accessibility-review/SKILL.md +56 -0
- claude_kit/_payload/skills/api-and-interface-design/SKILL.md +294 -0
- claude_kit/_payload/skills/api-integration/SKILL.md +348 -0
- claude_kit/_payload/skills/archive-sprint/SKILL.md +31 -0
- claude_kit/_payload/skills/backlog/SKILL.md +41 -0
- claude_kit/_payload/skills/backlog/item-template.md +20 -0
- claude_kit/_payload/skills/browser-testing-with-devtools/SKILL.md +302 -0
- claude_kit/_payload/skills/ci-cd-and-automation/SKILL.md +402 -0
- claude_kit/_payload/skills/code-review-and-quality/SKILL.md +347 -0
- claude_kit/_payload/skills/code-simplification/SKILL.md +331 -0
- claude_kit/_payload/skills/component-design/SKILL.md +171 -0
- claude_kit/_payload/skills/consolidate-learnings/SKILL.md +55 -0
- claude_kit/_payload/skills/context-engineering/SKILL.md +321 -0
- claude_kit/_payload/skills/debugging-and-error-recovery/SKILL.md +300 -0
- claude_kit/_payload/skills/decision/SKILL.md +46 -0
- claude_kit/_payload/skills/decision/adr-template.md +36 -0
- claude_kit/_payload/skills/deprecation-and-migration/SKILL.md +207 -0
- claude_kit/_payload/skills/documentation-and-adrs/SKILL.md +299 -0
- claude_kit/_payload/skills/doubt-driven-development/SKILL.md +243 -0
- claude_kit/_payload/skills/execute/SKILL.md +27 -0
- claude_kit/_payload/skills/frontend-ui-engineering/SKILL.md +328 -0
- claude_kit/_payload/skills/git-workflow-and-versioning/SKILL.md +300 -0
- claude_kit/_payload/skills/idea-refine/SKILL.md +178 -0
- claude_kit/_payload/skills/idea-refine/examples.md +238 -0
- claude_kit/_payload/skills/idea-refine/frameworks.md +99 -0
- claude_kit/_payload/skills/idea-refine/refinement-criteria.md +113 -0
- claude_kit/_payload/skills/idea-refine/scripts/idea-refine.sh +15 -0
- claude_kit/_payload/skills/incident-postmortem/SKILL.md +74 -0
- claude_kit/_payload/skills/incremental-implementation/SKILL.md +245 -0
- claude_kit/_payload/skills/interview-me/SKILL.md +221 -0
- claude_kit/_payload/skills/load-testing/SKILL.md +83 -0
- claude_kit/_payload/skills/manual-test/SKILL.md +516 -0
- claude_kit/_payload/skills/performance-optimization/SKILL.md +277 -0
- claude_kit/_payload/skills/planning-and-task-breakdown/SKILL.md +223 -0
- claude_kit/_payload/skills/playwright-verification/SKILL.md +205 -0
- claude_kit/_payload/skills/refresh-docs/SKILL.md +63 -0
- claude_kit/_payload/skills/remember/SKILL.md +96 -0
- claude_kit/_payload/skills/scope/SKILL.md +52 -0
- claude_kit/_payload/skills/scope/scope-template.md +82 -0
- claude_kit/_payload/skills/sdlc/SKILL.md +83 -0
- claude_kit/_payload/skills/security-and-hardening/SKILL.md +368 -0
- claude_kit/_payload/skills/security-verification/SKILL.md +209 -0
- claude_kit/_payload/skills/shipping-and-launch/SKILL.md +309 -0
- claude_kit/_payload/skills/smoke-test/SKILL.md +78 -0
- claude_kit/_payload/skills/source-driven-development/SKILL.md +195 -0
- claude_kit/_payload/skills/spec-driven-development/SKILL.md +200 -0
- claude_kit/_payload/skills/sprint/SKILL.md +67 -0
- claude_kit/_payload/skills/sprint/sprint-template.md +90 -0
- claude_kit/_payload/skills/test-driven-development/SKILL.md +383 -0
- claude_kit/_payload/skills/threat-model/SKILL.md +60 -0
- claude_kit/_payload/skills/triage/SKILL.md +87 -0
- claude_kit/_payload/skills/ui-ux-design/SKILL.md +71 -0
- claude_kit/_payload/skills/unit-test/SKILL.md +237 -0
- claude_kit/_payload/skills/using-agent-skills/SKILL.md +180 -0
- claude_kit/_payload/templates/CLAUDE.md +238 -0
- claude_kit/_payload/templates/CLAUDE.stack.md.tmpl +53 -0
- claude_kit/_payload/templates/CONTINUITY.template.md +35 -0
- claude_kit/_payload/templates/README.claude-sdlc.md.tmpl +219 -0
- claude_kit/_payload/templates/agent-memory/MEMORY.md +30 -0
- claude_kit/_payload/templates/agent-memory/api/.gitkeep +0 -0
- claude_kit/_payload/templates/agent-memory/architecture/.gitkeep +0 -0
- claude_kit/_payload/templates/agent-memory/debugging/.gitkeep +0 -0
- claude_kit/_payload/templates/agent-memory/gotchas/.gitkeep +0 -0
- claude_kit/_payload/templates/agent-memory/patterns/.gitkeep +0 -0
- claude_kit/_payload/templates/agent-memory/performance/.gitkeep +0 -0
- claude_kit/_payload/templates/artifacts/adr.md +18 -0
- claude_kit/_payload/templates/artifacts/feature-spec.md +29 -0
- claude_kit/_payload/templates/artifacts/release-plan.md +23 -0
- claude_kit/_payload/templates/artifacts/runbook.md +24 -0
- claude_kit/_payload/templates/artifacts/security-review.md +23 -0
- claude_kit/_payload/templates/artifacts/test-plan.md +22 -0
- claude_kit/_payload/templates/org/README.md +53 -0
- claude_kit/_payload/templates/org/agents/data-workflow-agent.md +59 -0
- claude_kit/_payload/templates/org/agents/founder-prototype-agent.md +61 -0
- claude_kit/_payload/templates/org/agents/internal-tools-builder.md +63 -0
- claude_kit/_payload/templates/org/agents/pm-copilot.md +60 -0
- claude_kit/_payload/templates/org/agents/support-ticket-engineer.md +63 -0
- claude_kit/_payload/templates/org/packs/devops-and-release/README.md +46 -0
- claude_kit/_payload/templates/org/packs/devops-and-release/pack.yaml +32 -0
- claude_kit/_payload/templates/org/packs/engineering-core/README.md +46 -0
- claude_kit/_payload/templates/org/packs/engineering-core/pack.yaml +44 -0
- claude_kit/_payload/templates/org/packs/non-engineer-builder/README.md +53 -0
- claude_kit/_payload/templates/org/packs/non-engineer-builder/pack.yaml +39 -0
- claude_kit/_payload/templates/org/packs/onboarding-and-docs/README.md +49 -0
- claude_kit/_payload/templates/org/packs/onboarding-and-docs/pack.yaml +26 -0
- claude_kit/_payload/templates/org/packs/product-to-code/README.md +50 -0
- claude_kit/_payload/templates/org/packs/product-to-code/pack.yaml +34 -0
- claude_kit/_payload/templates/org/packs/quality-and-review/README.md +53 -0
- claude_kit/_payload/templates/org/packs/quality-and-review/pack.yaml +40 -0
- claude_kit/_payload/templates/org/packs/security-and-compliance/README.md +50 -0
- claude_kit/_payload/templates/org/packs/security-and-compliance/pack.yaml +36 -0
- claude_kit/_payload/templates/org/rules/ai-working-agreement.md +45 -0
- claude_kit/_payload/templates/org/rules/ambiguity-resolution.md +36 -0
- claude_kit/_payload/templates/org/rules/branch-and-pr-policy.md +41 -0
- claude_kit/_payload/templates/org/rules/compliance-policy.md +50 -0
- claude_kit/_payload/templates/org/rules/non-engineer-safe-coding.md +37 -0
- claude_kit/_payload/templates/org/rules/pii-policy.md +46 -0
- claude_kit/_payload/templates/org/rules/production-data-policy.md +35 -0
- claude_kit/_payload/templates/org/rules/prompt-to-task-conversion.md +30 -0
- claude_kit/_payload/templates/org/rules/prototype-boundaries.md +40 -0
- claude_kit/_payload/templates/org/rules/secrets-policy.md +34 -0
- claude_kit/_payload/templates/org/skills/customer-issue-to-fix/SKILL.md +61 -0
- claude_kit/_payload/templates/org/skills/feature-from-idea/SKILL.md +56 -0
- claude_kit/_payload/templates/org/skills/prompt-to-safe-task/SKILL.md +59 -0
- claude_kit/_payload/templates/org/skills/prototype-to-production/SKILL.md +61 -0
- claude_kit/_payload/templates/org/skills/repo-onboarding/SKILL.md +60 -0
- claude_kit/_payload/templates/settings.json +53 -0
- claude_kit/_payload/templates/stacks/backend/python/fastapi/rules/fastapi-patterns.md +64 -0
- claude_kit/_payload/templates/stacks/db/mongodb/agents/migration-specialist.md +61 -0
- claude_kit/_payload/templates/stacks/db/mongodb/agents/mongodb-specialist.md +59 -0
- claude_kit/_payload/templates/stacks/db/mongodb/rules/mongodb-patterns.md +39 -0
- claude_kit/_payload/templates/stacks/db/postgres/agents/db-performance-reviewer.md +66 -0
- claude_kit/_payload/templates/stacks/db/postgres/agents/migration-specialist.md +56 -0
- claude_kit/_payload/templates/stacks/db/postgres/agents/postgres-specialist.md +58 -0
- claude_kit/_payload/templates/stacks/db/postgres/rules/database-performance.md +64 -0
- claude_kit/_payload/templates/stacks/db/postgres/rules/postgres-patterns.md +43 -0
- claude_kit/_payload/templates/stacks/frontend/react/rules/react-patterns.md +63 -0
- claude_kit/catalog.py +476 -0
- claude_kit/cli.py +327 -0
- claude_kit/hooks.py +246 -0
- claude_kit/models.py +205 -0
- claude_kit/prompts.py +209 -0
- claude_kit/render.py +146 -0
- claude_kit/scaffold.py +492 -0
- claude_kit/upgrader.py +294 -0
- claude_kit/validator.py +197 -0
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
# Design Patterns
|
|
2
|
+
|
|
3
|
+
Mandatory design patterns for backend and frontend code. Apply the appropriate pattern whenever the described situation arises.
|
|
4
|
+
|
|
5
|
+
**Async-first consideration:** When your project uses async I/O (async/await, promises, event loops), all patterns below should be implemented with async primitives. No blocking I/O should exist in the request path. See `.claude/rules/code-organization.md` for async architecture guidance.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Backend Patterns
|
|
10
|
+
|
|
11
|
+
### 1. Repository Pattern
|
|
12
|
+
**When:** Any database access.
|
|
13
|
+
**Why:** Isolate data access logic from business rules. Makes services testable without DB.
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
<domain>/<resource>/
|
|
17
|
+
├── repository.{ext} ← Repository (DB I/O only)
|
|
18
|
+
├── service.{ext} ← Service (business rules)
|
|
19
|
+
├── handler.{ext} ← Router/handler (HTTP interface)
|
|
20
|
+
└── schemas.{ext} ← Typed request/response schemas
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Rules:**
|
|
24
|
+
- Repository functions accept a database connection/session as first param
|
|
25
|
+
- Repositories return domain objects or `None`/`null` — never raise HTTP-level exceptions
|
|
26
|
+
- Repositories never commit — they call `flush()` or equivalent at most
|
|
27
|
+
- One repository per domain aggregate (User, Organization, Tenant)
|
|
28
|
+
|
|
29
|
+
**Example (Python with async ORM):**
|
|
30
|
+
```python
|
|
31
|
+
# repository.py
|
|
32
|
+
async def get_by_email(db: AsyncSession, email: str) -> User | None:
|
|
33
|
+
stmt = select(User).where(User.email == email.lower())
|
|
34
|
+
result = await db.execute(stmt)
|
|
35
|
+
return result.scalar_one_or_none()
|
|
36
|
+
|
|
37
|
+
async def create(db: AsyncSession, **fields: Any) -> User:
|
|
38
|
+
user = User(**fields)
|
|
39
|
+
db.add(user)
|
|
40
|
+
await db.flush()
|
|
41
|
+
return user
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Example (TypeScript/Node with Prisma):**
|
|
45
|
+
```typescript
|
|
46
|
+
// repository.ts
|
|
47
|
+
async function getByEmail(db: PrismaClient, email: string): Promise<User | null> {
|
|
48
|
+
return db.user.findUnique({ where: { email: email.toLowerCase() } });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function create(db: PrismaClient, fields: CreateUserData): Promise<User> {
|
|
52
|
+
return db.user.create({ data: fields });
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 2. Service Layer Pattern
|
|
57
|
+
**When:** Any business logic that involves validation, orchestration, or side effects.
|
|
58
|
+
**Why:** Keeps handlers thin. Business rules live in one testable place.
|
|
59
|
+
|
|
60
|
+
**Rules:**
|
|
61
|
+
- Services call repositories for DB access
|
|
62
|
+
- Services raise HTTP-level exceptions (or return error types) for user-facing errors
|
|
63
|
+
- Services own the transaction commit — not repositories, not handlers
|
|
64
|
+
- Services accept typed schemas or primitives as input — never raw dictionaries/objects
|
|
65
|
+
- Services can call multiple repositories in a single operation
|
|
66
|
+
|
|
67
|
+
**Example (Python):**
|
|
68
|
+
```python
|
|
69
|
+
# service.py
|
|
70
|
+
async def create_user(
|
|
71
|
+
db: AsyncSession,
|
|
72
|
+
payload: UserCreate,
|
|
73
|
+
*,
|
|
74
|
+
actor: User,
|
|
75
|
+
) -> User:
|
|
76
|
+
if await repository.get_by_email(db, payload.email):
|
|
77
|
+
raise HTTPException(status_code=409, detail="email already registered")
|
|
78
|
+
|
|
79
|
+
user = await repository.create(
|
|
80
|
+
db,
|
|
81
|
+
email=payload.email,
|
|
82
|
+
password_hash=hash_password(payload.password),
|
|
83
|
+
organization_id=actor.organization_id,
|
|
84
|
+
)
|
|
85
|
+
await db.commit()
|
|
86
|
+
return user
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Example (TypeScript/Node):**
|
|
90
|
+
```typescript
|
|
91
|
+
// service.ts
|
|
92
|
+
async function createUser(
|
|
93
|
+
db: PrismaClient,
|
|
94
|
+
payload: UserCreate,
|
|
95
|
+
actor: User
|
|
96
|
+
): Promise<User> {
|
|
97
|
+
const existing = await repository.getByEmail(db, payload.email);
|
|
98
|
+
if (existing) {
|
|
99
|
+
throw new ConflictError("email already registered");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const user = await repository.create(db, {
|
|
103
|
+
email: payload.email,
|
|
104
|
+
passwordHash: hashPassword(payload.password),
|
|
105
|
+
organizationId: actor.organizationId,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
return user;
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 3. Dependency Injection
|
|
113
|
+
**When:** Any cross-cutting concern — auth, DB session, permissions, rate limiting.
|
|
114
|
+
**Why:** Composable, testable, declarative dependencies.
|
|
115
|
+
|
|
116
|
+
**Rules:**
|
|
117
|
+
- Reusable deps in a common dependencies module or per-domain deps file
|
|
118
|
+
- Named clearly: `getCurrentUser`, `getDbSession`, `requireRole("admin")`
|
|
119
|
+
- Order in handler signature: request artifacts → auth → authorization → DB/cache clients
|
|
120
|
+
- Never instantiate services or sessions manually inside handlers — always via dependency injection
|
|
121
|
+
|
|
122
|
+
**Example (FastAPI with Depends):**
|
|
123
|
+
```python
|
|
124
|
+
@router.post("", response_model=UserRead, status_code=201)
|
|
125
|
+
async def create_user(
|
|
126
|
+
payload: UserCreate,
|
|
127
|
+
current_user: User = Depends(get_current_user),
|
|
128
|
+
_: None = Depends(require_role("org_admin")),
|
|
129
|
+
db: AsyncSession = Depends(get_db_session),
|
|
130
|
+
) -> UserRead:
|
|
131
|
+
user = await service.create_user(db, payload, actor=current_user)
|
|
132
|
+
return UserRead.model_validate(user)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Example (NestJS with decorators):**
|
|
136
|
+
```typescript
|
|
137
|
+
@Post()
|
|
138
|
+
@UseGuards(AuthGuard, RoleGuard)
|
|
139
|
+
@Roles('org_admin')
|
|
140
|
+
async createUser(
|
|
141
|
+
@Body() payload: UserCreateDto,
|
|
142
|
+
@CurrentUser() currentUser: User,
|
|
143
|
+
@InjectDb() db: PrismaClient,
|
|
144
|
+
): Promise<UserRead> {
|
|
145
|
+
const user = await this.service.createUser(db, payload, currentUser);
|
|
146
|
+
return new UserRead(user);
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 4. Unit of Work
|
|
151
|
+
**When:** Multiple DB operations that must succeed or fail together.
|
|
152
|
+
**Why:** Transactional consistency without explicit transaction management.
|
|
153
|
+
|
|
154
|
+
**Rules:**
|
|
155
|
+
- The DB session dependency wraps operations in a transaction — rollback on exception
|
|
156
|
+
- Service layer calls `commit()` at the end of a successful operation
|
|
157
|
+
- Use `flush()` or equivalent when you need a generated ID before commit
|
|
158
|
+
- Never call `commit()` in repository functions
|
|
159
|
+
- For multi-step workflows, keep all operations in the same session/transaction
|
|
160
|
+
|
|
161
|
+
### 5. Mixin Pattern (for ORM models)
|
|
162
|
+
**When:** Cross-cutting model fields (timestamps, soft-delete).
|
|
163
|
+
**Why:** DRY — mixins applied once, inherited everywhere.
|
|
164
|
+
|
|
165
|
+
**Example (Python with SQLAlchemy):**
|
|
166
|
+
```python
|
|
167
|
+
class User(Base, CreatedAtMixin, UpdatedAtMixin, SoftDeleteMixin):
|
|
168
|
+
...
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**Example (TypeScript with TypeORM):**
|
|
172
|
+
```typescript
|
|
173
|
+
@Entity()
|
|
174
|
+
class User extends CreatedAtEntity {
|
|
175
|
+
// ...
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**Rules:**
|
|
180
|
+
- New cross-cutting fields → add a mixin, don't copy-paste columns
|
|
181
|
+
- Mixins provide column definitions via framework-specific mechanisms
|
|
182
|
+
- Mixins never define relationships — keep them pure column providers
|
|
183
|
+
|
|
184
|
+
### 6. Factory Pattern (App Factory)
|
|
185
|
+
**When:** Application setup.
|
|
186
|
+
**Why:** Testability (fresh app per test), configurable middleware/routers.
|
|
187
|
+
|
|
188
|
+
**Rules:**
|
|
189
|
+
- Never import a module-level app object — always call a factory function
|
|
190
|
+
- Tests use the factory to create isolated app instances
|
|
191
|
+
|
|
192
|
+
**Example (Python):**
|
|
193
|
+
```python
|
|
194
|
+
def get_app() -> Application:
|
|
195
|
+
app = Application()
|
|
196
|
+
# configure middleware, routes, etc.
|
|
197
|
+
return app
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**Example (Node/Express):**
|
|
201
|
+
```typescript
|
|
202
|
+
function createApp(): Express {
|
|
203
|
+
const app = express();
|
|
204
|
+
// configure middleware, routes, etc.
|
|
205
|
+
return app;
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### 7. Strategy Pattern
|
|
210
|
+
**When:** Multiple algorithms for the same operation (e.g., hashing, notification channels, export formats).
|
|
211
|
+
**Why:** Swap behavior without modifying callers.
|
|
212
|
+
|
|
213
|
+
**Example (Python with Protocol):**
|
|
214
|
+
```python
|
|
215
|
+
from typing import Protocol
|
|
216
|
+
|
|
217
|
+
class PasswordHasher(Protocol):
|
|
218
|
+
def hash(self, password: str) -> str: ...
|
|
219
|
+
def verify(self, password: str, hash: str) -> bool: ...
|
|
220
|
+
|
|
221
|
+
class StrongHasher:
|
|
222
|
+
def hash(self, password: str) -> str: ...
|
|
223
|
+
def verify(self, password: str, hash: str) -> bool: ...
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**Example (TypeScript with interface):**
|
|
227
|
+
```typescript
|
|
228
|
+
interface PasswordHasher {
|
|
229
|
+
hash(password: string): string;
|
|
230
|
+
verify(password: string, hash: string): boolean;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
class StrongHasher implements PasswordHasher {
|
|
234
|
+
hash(password: string): string { /* ... */ }
|
|
235
|
+
verify(password: string, hash: string): boolean { /* ... */ }
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
**Rules:**
|
|
240
|
+
- Use interface/protocol for strategy contracts
|
|
241
|
+
- Inject via dependency — not hardcoded `if/else` chains
|
|
242
|
+
- Use when there are 2+ interchangeable implementations
|
|
243
|
+
|
|
244
|
+
### 8. Enum Pattern
|
|
245
|
+
**When:** Constrained string fields with a known set of values (roles, statuses, types).
|
|
246
|
+
**Why:** Type safety, autocomplete, no magic strings.
|
|
247
|
+
|
|
248
|
+
**Example (Python):**
|
|
249
|
+
```python
|
|
250
|
+
class UserRole(str, Enum):
|
|
251
|
+
SYS_ADMIN = "sys_admin"
|
|
252
|
+
ORG_ADMIN = "org_admin"
|
|
253
|
+
MEMBER = "member"
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Example (TypeScript):**
|
|
257
|
+
```typescript
|
|
258
|
+
enum UserRole {
|
|
259
|
+
SYS_ADMIN = "sys_admin",
|
|
260
|
+
ORG_ADMIN = "org_admin",
|
|
261
|
+
MEMBER = "member",
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**Rules:**
|
|
266
|
+
- Always use string-based enums for JSON-serializable values
|
|
267
|
+
- Use enums in typed schemas and data models
|
|
268
|
+
- Never compare with raw strings: `if role == "admin"` → `if role == UserRole.SYS_ADMIN`
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## Frontend Patterns
|
|
273
|
+
|
|
274
|
+
### 9. Container / Presentational Split
|
|
275
|
+
**When:** A component both fetches data and renders UI.
|
|
276
|
+
**Why:** Separation of concerns — data logic vs display logic.
|
|
277
|
+
|
|
278
|
+
```
|
|
279
|
+
src/pages/UsersPage.{ext} ← Container (data fetching, state)
|
|
280
|
+
src/components/UserList.{ext} ← Presentational (props → UI)
|
|
281
|
+
src/components/UserCard.{ext} ← Presentational (props → UI)
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**Rules:**
|
|
285
|
+
- Pages/containers own data fetching and state
|
|
286
|
+
- Components are presentational — they receive props and render
|
|
287
|
+
- Presentational components are pure functions where possible
|
|
288
|
+
|
|
289
|
+
### 10. Custom Hook Pattern (React/Vue composables)
|
|
290
|
+
**When:** Shared stateful logic across components.
|
|
291
|
+
**Why:** Reusable, testable state logic extracted from components.
|
|
292
|
+
|
|
293
|
+
**Example (React):**
|
|
294
|
+
```typescript
|
|
295
|
+
// hooks/useAuth.ts
|
|
296
|
+
export function useAuth() {
|
|
297
|
+
const user = useAuthStore((s) => s.user);
|
|
298
|
+
const logout = useAuthStore((s) => s.logout);
|
|
299
|
+
return { user, isAuthenticated: !!user, logout };
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**Example (Vue):**
|
|
304
|
+
```typescript
|
|
305
|
+
// composables/useAuth.ts
|
|
306
|
+
export function useAuth() {
|
|
307
|
+
const store = useAuthStore();
|
|
308
|
+
return {
|
|
309
|
+
user: computed(() => store.user),
|
|
310
|
+
isAuthenticated: computed(() => !!store.user),
|
|
311
|
+
logout: () => store.logout(),
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
**Rules:**
|
|
317
|
+
- One concern per hook/composable
|
|
318
|
+
- Return stable references (memoize functions where needed)
|
|
319
|
+
- Name as `use<Purpose>` — `useAuth`, `usePagination`, `useDebounce`
|
|
320
|
+
|
|
321
|
+
### 11. Store Pattern
|
|
322
|
+
**When:** Shared state across components that isn't server-state.
|
|
323
|
+
**Why:** Simple, minimal boilerplate, good type support.
|
|
324
|
+
|
|
325
|
+
**Example (with client state library):**
|
|
326
|
+
```typescript
|
|
327
|
+
interface AuthState {
|
|
328
|
+
user: User | null;
|
|
329
|
+
setUser: (user: User | null) => void;
|
|
330
|
+
logout: () => void;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
export const useAuthStore = createStore<AuthState>({
|
|
334
|
+
user: null,
|
|
335
|
+
setUser: (user) => ({ user }),
|
|
336
|
+
logout: () => ({ user: null }),
|
|
337
|
+
});
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
**Rules:**
|
|
341
|
+
- Always use selectors: `useStore((s) => s.value)` — never `useStore()` (full state)
|
|
342
|
+
- Never create new objects/arrays inside selectors
|
|
343
|
+
- Actions are stable references — exclude from dependency arrays
|
|
344
|
+
- One store per concern — don't dump everything in one god-store
|
|
345
|
+
|
|
346
|
+
### 12. API Client Pattern
|
|
347
|
+
**When:** Any HTTP call from the frontend.
|
|
348
|
+
**Why:** Centralized error handling, auth, base URL.
|
|
349
|
+
|
|
350
|
+
**Example:**
|
|
351
|
+
```typescript
|
|
352
|
+
// lib/api.ts
|
|
353
|
+
import axios from "axios";
|
|
354
|
+
|
|
355
|
+
const api = axios.create({
|
|
356
|
+
baseURL: import.meta.env.VITE_API_BASE_URL || "http://localhost:8000",
|
|
357
|
+
withCredentials: true, // session cookies
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
api.interceptors.response.use(
|
|
361
|
+
(response) => response,
|
|
362
|
+
(error) => {
|
|
363
|
+
if (error.response?.status === 401) {
|
|
364
|
+
// redirect to login
|
|
365
|
+
}
|
|
366
|
+
return Promise.reject(error);
|
|
367
|
+
},
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
export default api;
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
**Rules:**
|
|
374
|
+
- One shared HTTP client instance — don't create clients per request
|
|
375
|
+
- Configure global interceptors for auth expiry
|
|
376
|
+
- Per-domain API modules for organized endpoints: `lib/users.ts`, `lib/orgs.ts`
|
|
377
|
+
|
|
378
|
+
### 13. Error Boundary Pattern
|
|
379
|
+
**When:** Any page or major section that could throw during render.
|
|
380
|
+
**Why:** Graceful degradation — don't crash the entire app.
|
|
381
|
+
|
|
382
|
+
**Rules:**
|
|
383
|
+
- Wrap each route-level page in an error boundary
|
|
384
|
+
- Show a user-friendly error message — not a blank screen
|
|
385
|
+
- Log the error for observability
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
## Anti-Patterns (DO NOT)
|
|
390
|
+
|
|
391
|
+
### Backend
|
|
392
|
+
- ❌ **God service** — one service that does everything. Split by domain.
|
|
393
|
+
- ❌ **Anemic domain** — models are just data bags with all logic in utilities. Put behavior near data.
|
|
394
|
+
- ❌ **Business logic in handlers** — handlers are thin wrappers. Logic goes in services.
|
|
395
|
+
- ❌ **Repository that raises HTTP exceptions** — repositories return data or None/null.
|
|
396
|
+
- ❌ **Raw dict/object passing** — use typed schemas or data classes for structured data.
|
|
397
|
+
- ❌ **Hardcoded magic strings** — use Enums or constants.
|
|
398
|
+
- ❌ **Circular imports** — respect the dependency direction: handler → service → repository → models.
|
|
399
|
+
|
|
400
|
+
### Frontend
|
|
401
|
+
- ❌ **Prop drilling 3+ levels deep** — use a state store or context instead.
|
|
402
|
+
- ❌ **Ad-hoc data fetching in effects** — use a data-fetching library or at minimum a dedicated hook.
|
|
403
|
+
- ❌ **God component** — components over 200 lines should be split.
|
|
404
|
+
- ❌ **Inline styles** — use a styling system (CSS modules, utility classes, styled components).
|
|
405
|
+
- ❌ **Direct localStorage for auth** — use secure cookie-based sessions where possible.
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## When to Apply Which Pattern
|
|
410
|
+
|
|
411
|
+
| Situation | Pattern |
|
|
412
|
+
|-----------|---------|
|
|
413
|
+
| New API endpoint | Repository + Service + DI + Typed schemas |
|
|
414
|
+
| New DB model | Mixin (if applicable) + Factory (app) + Enum (for constrained fields) |
|
|
415
|
+
| Shared model fields | Mixin (ORM-specific) |
|
|
416
|
+
| Auth/permissions | DI + Strategy (if multiple auth methods) |
|
|
417
|
+
| Multi-step DB operation | Unit of Work |
|
|
418
|
+
| New frontend page | Container/Presentational + Store + API Client |
|
|
419
|
+
| Shared frontend state | Store + Custom Hook |
|
|
420
|
+
| Constrained string values | Enum (backend) or union type (frontend) |
|
|
421
|
+
| Multiple implementations | Strategy (interface/protocol) |
|
|
422
|
+
| Cross-cutting render concern | Error Boundary |
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# DevOps & Observability Phases
|
|
2
|
+
|
|
3
|
+
Two delivery-side phases that run **after** the test-coverage merge gate (MR3 VERIFIED) and **before** the PR Raiser, so that pipeline and observability artifacts ship *inside* the same PR as the code. They are owned by dedicated agents and each has its own quality gate.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
... MR3 (test coverage VERIFIED)
|
|
7
|
+
-> [DevOps] devops-engineer -> Gate: Pipeline Green
|
|
8
|
+
-> [Observability] observability-engineer -> Gate: Observability Ready
|
|
9
|
+
-> PR Raiser
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## When these phases run (conditional)
|
|
13
|
+
|
|
14
|
+
Run them when the change touches a **deployable or observable surface**:
|
|
15
|
+
- a new/changed endpoint, service, container, dependency, env var, port, or migration;
|
|
16
|
+
- anything that adds a user-facing critical path worth an SLO or an alert.
|
|
17
|
+
|
|
18
|
+
**Skip (note in CONTINUITY.md why)** for pure-internal changes with no deployment or observability surface — a refactor behind an unchanged interface, a copy tweak, a test-only change. Fast-track (Mode D) skips both unless infra/observability is the actual subject of the fix.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Phase: DevOps · Agent: `devops-engineer` · Gate: **Pipeline Green**
|
|
23
|
+
|
|
24
|
+
Owns the infra seam (containerization, orchestration, migrations-at-boot, ports, CORS, env). For a feature, it ensures the change is **buildable and deployable**, not just runnable on the author's machine.
|
|
25
|
+
|
|
26
|
+
**Pipeline Green passes when:**
|
|
27
|
+
- [ ] CI config is valid and includes lint + type-check + unit tests for the changed stack(s) (CI pipeline config files — editing those requires user approval per CLAUDE.md).
|
|
28
|
+
- [ ] Container orchestration config resolves; a clean rebuild and restart brings all services up **healthy**.
|
|
29
|
+
- [ ] New env vars are in the project's settings/config, orchestration config, `.env.example`, and the README table.
|
|
30
|
+
- [ ] Migrations (if applicable) apply cleanly at boot and have a working rollback/downgrade.
|
|
31
|
+
- [ ] A short **runbook** entry exists for anything operationally new (how to deploy it, how to roll it back).
|
|
32
|
+
- [ ] No secrets committed; ports/CORS changes reflected in README.
|
|
33
|
+
|
|
34
|
+
Findings classified by `.claude/rules/quality-gates.md` severity; Critical/High/Medium block.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Phase: Observability · Agent: `observability-engineer` · Gate: **Observability Ready**
|
|
39
|
+
|
|
40
|
+
Ensures the feature is **operable in production**: you can tell when it breaks and why. Builds on the project's existing health endpoints and structured logging.
|
|
41
|
+
|
|
42
|
+
**Observability Ready passes when:**
|
|
43
|
+
- [ ] **SLOs/SLIs** defined for each critical user journey the feature adds (e.g., "p95 endpoint latency < 200ms", "login success rate ≥ 99.5%").
|
|
44
|
+
- [ ] **Health/readiness** — any new external dependency (database, cache, third-party service) is reflected in the readiness check; liveness stays dependency-free.
|
|
45
|
+
- [ ] **Structured logging** — new state changes log via the project's structured logger as JSON key-values, semantic event names, **no secrets/PII**; error paths log at `error`/`exception` level.
|
|
46
|
+
- [ ] **Alerts** — alert rules defined for the feature's failure modes (error-rate spike, latency breach, dependency down) with a severity and an owner.
|
|
47
|
+
- [ ] **Traceability** — correlation/request id flows through new code paths where the stack supports it.
|
|
48
|
+
|
|
49
|
+
Findings classified by `.claude/rules/quality-gates.md` severity; Critical/High/Medium block.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Notes
|
|
54
|
+
|
|
55
|
+
- Both agents follow the **RARV cycle** (`.claude/rules/rarv-cycle.md`) and update `CONTINUITY.md` at handoff.
|
|
56
|
+
- Neither agent writes application business logic — they own infra and operability only. Logic gaps go back to the relevant dev lane.
|
|
57
|
+
- Editing CI pipeline config, package manifests, or other project-wide files still requires explicit user approval (CLAUDE.md §"Files that require user approval").
|