@juho0719/cckit 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/assets/agents/architect.md +211 -0
  2. package/assets/agents/build-error-resolver.md +114 -0
  3. package/assets/agents/ccwin-code-reviewer.md +224 -0
  4. package/assets/agents/database-reviewer.md +91 -0
  5. package/assets/agents/doc-updater.md +107 -0
  6. package/assets/agents/e2e-runner.md +107 -0
  7. package/assets/agents/planner.md +212 -0
  8. package/assets/agents/python-reviewer.md +98 -0
  9. package/assets/agents/refactor-cleaner.md +85 -0
  10. package/assets/agents/security-reviewer.md +108 -0
  11. package/assets/agents/superpower-code-reviewer.md +48 -0
  12. package/assets/agents/tdd-guide.md +80 -0
  13. package/assets/commands/build-fix.md +62 -0
  14. package/assets/commands/checkpoint.md +74 -0
  15. package/assets/commands/code-review.md +40 -0
  16. package/assets/commands/e2e.md +362 -0
  17. package/assets/commands/eval.md +120 -0
  18. package/assets/commands/orchestrate.md +172 -0
  19. package/assets/commands/plan.md +113 -0
  20. package/assets/commands/python-review.md +297 -0
  21. package/assets/commands/refactor-clean.md +80 -0
  22. package/assets/commands/sessions.md +305 -0
  23. package/assets/commands/tdd.md +326 -0
  24. package/assets/commands/test-coverage.md +69 -0
  25. package/assets/commands/update-codemaps.md +72 -0
  26. package/assets/commands/update-docs.md +84 -0
  27. package/assets/commands/verify.md +59 -0
  28. package/assets/hooks/post-edit-format.js +49 -0
  29. package/assets/hooks/post-edit-typecheck.js +96 -0
  30. package/assets/mcps/mcp-servers.json +92 -0
  31. package/assets/rules/common/agents.md +49 -0
  32. package/assets/rules/common/coding-style.md +48 -0
  33. package/assets/rules/common/git-workflow.md +45 -0
  34. package/assets/rules/common/hooks.md +30 -0
  35. package/assets/rules/common/patterns.md +31 -0
  36. package/assets/rules/common/performance.md +55 -0
  37. package/assets/rules/common/security.md +29 -0
  38. package/assets/rules/common/testing.md +29 -0
  39. package/assets/rules/python/coding-style.md +42 -0
  40. package/assets/rules/python/hooks.md +19 -0
  41. package/assets/rules/python/patterns.md +39 -0
  42. package/assets/rules/python/security.md +30 -0
  43. package/assets/rules/python/testing.md +38 -0
  44. package/assets/rules/typescript/coding-style.md +18 -0
  45. package/assets/rules/typescript/hooks.md +19 -0
  46. package/assets/rules/typescript/patterns.md +39 -0
  47. package/assets/rules/typescript/security.md +30 -0
  48. package/assets/rules/typescript/testing.md +38 -0
  49. package/assets/skills/api-design/SKILL.md +522 -0
  50. package/assets/skills/backend-patterns/SKILL.md +597 -0
  51. package/assets/skills/brainstorming/SKILL.md +96 -0
  52. package/assets/skills/coding-standards/SKILL.md +529 -0
  53. package/assets/skills/database-migrations/SKILL.md +334 -0
  54. package/assets/skills/deployment-patterns/SKILL.md +426 -0
  55. package/assets/skills/dispatching-parallel-agents/SKILL.md +180 -0
  56. package/assets/skills/docker-patterns/SKILL.md +363 -0
  57. package/assets/skills/e2e-testing/SKILL.md +325 -0
  58. package/assets/skills/eval-harness/SKILL.md +235 -0
  59. package/assets/skills/executing-plans/SKILL.md +84 -0
  60. package/assets/skills/finishing-a-development-branch/SKILL.md +200 -0
  61. package/assets/skills/frontend-patterns/SKILL.md +641 -0
  62. package/assets/skills/iterative-retrieval/SKILL.md +210 -0
  63. package/assets/skills/postgres-patterns/SKILL.md +145 -0
  64. package/assets/skills/python-patterns/SKILL.md +749 -0
  65. package/assets/skills/python-testing/SKILL.md +815 -0
  66. package/assets/skills/receiving-code-review/SKILL.md +213 -0
  67. package/assets/skills/requesting-code-review/SKILL.md +105 -0
  68. package/assets/skills/requesting-code-review/code-reviewer-template.md +146 -0
  69. package/assets/skills/subagent-driven-development/SKILL.md +242 -0
  70. package/assets/skills/subagent-driven-development/code-quality-reviewer-prompt.md +20 -0
  71. package/assets/skills/subagent-driven-development/implementer-prompt.md +78 -0
  72. package/assets/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
  73. package/assets/skills/systematic-debugging/CREATION-LOG.md +114 -0
  74. package/assets/skills/systematic-debugging/SKILL.md +296 -0
  75. package/assets/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  76. package/assets/skills/systematic-debugging/condition-based-waiting.md +115 -0
  77. package/assets/skills/systematic-debugging/defense-in-depth.md +122 -0
  78. package/assets/skills/systematic-debugging/root-cause-tracing.md +169 -0
  79. package/assets/skills/systematic-debugging/scripts/find-polluter.sh +63 -0
  80. package/assets/skills/systematic-debugging/test-academic.md +14 -0
  81. package/assets/skills/systematic-debugging/test-pressure-1.md +58 -0
  82. package/assets/skills/systematic-debugging/test-pressure-2.md +68 -0
  83. package/assets/skills/systematic-debugging/test-pressure-3.md +69 -0
  84. package/assets/skills/tdd-workflow/SKILL.md +409 -0
  85. package/assets/skills/test-driven-development/SKILL.md +371 -0
  86. package/assets/skills/test-driven-development/testing-anti-patterns.md +299 -0
  87. package/assets/skills/using-git-worktrees/SKILL.md +218 -0
  88. package/assets/skills/verification-before-completion/SKILL.md +139 -0
  89. package/assets/skills/verification-loop/SKILL.md +125 -0
  90. package/assets/skills/writing-plans/SKILL.md +116 -0
  91. package/dist/agents-AEKT67A6.js +9 -0
  92. package/dist/chunk-3GUKEMND.js +28 -0
  93. package/dist/chunk-3UNN3IBE.js +54 -0
  94. package/dist/chunk-3Y26YU4R.js +27 -0
  95. package/dist/chunk-5XOKKPAA.js +21 -0
  96. package/dist/chunk-6B46AIFM.js +136 -0
  97. package/dist/chunk-EYY2IZ7N.js +27 -0
  98. package/dist/chunk-K25UZZVG.js +17 -0
  99. package/dist/chunk-KEENFBLL.js +24 -0
  100. package/dist/chunk-RMUKD7CW.js +44 -0
  101. package/dist/chunk-W63UKEIT.js +50 -0
  102. package/dist/cli-VZRGF733.js +238 -0
  103. package/dist/commands-P5LILVZ5.js +9 -0
  104. package/dist/hooks-IIG2XK4I.js +9 -0
  105. package/dist/index.js +131 -0
  106. package/dist/mcps-67Q7TBGW.js +6 -0
  107. package/dist/paths-FT6KBIRD.js +10 -0
  108. package/dist/registry-EGXWYWWK.js +17 -0
  109. package/dist/rules-2CPBVNNJ.js +7 -0
  110. package/dist/skills-ULMW3UCM.js +8 -0
  111. package/package.json +36 -0
@@ -0,0 +1,363 @@
1
+ ---
2
+ name: docker-patterns
3
+ description: Docker and Docker Compose patterns for local development, container security, networking, volume strategies, and multi-service orchestration.
4
+ ---
5
+
6
+ # Docker Patterns
7
+
8
+ Docker and Docker Compose best practices for containerized development.
9
+
10
+ ## When to Activate
11
+
12
+ - Setting up Docker Compose for local development
13
+ - Designing multi-container architectures
14
+ - Troubleshooting container networking or volume issues
15
+ - Reviewing Dockerfiles for security and size
16
+ - Migrating from local dev to containerized workflow
17
+
18
+ ## Docker Compose for Local Development
19
+
20
+ ### Standard Web App Stack
21
+
22
+ ```yaml
23
+ # docker-compose.yml
24
+ services:
25
+ app:
26
+ build:
27
+ context: .
28
+ target: dev # Use dev stage of multi-stage Dockerfile
29
+ ports:
30
+ - "3000:3000"
31
+ volumes:
32
+ - .:/app # Bind mount for hot reload
33
+ - /app/node_modules # Anonymous volume -- preserves container deps
34
+ environment:
35
+ - DATABASE_URL=postgres://postgres:postgres@db:5432/app_dev
36
+ - REDIS_URL=redis://redis:6379/0
37
+ - NODE_ENV=development
38
+ depends_on:
39
+ db:
40
+ condition: service_healthy
41
+ redis:
42
+ condition: service_started
43
+ command: npm run dev
44
+
45
+ db:
46
+ image: postgres:16-alpine
47
+ ports:
48
+ - "5432:5432"
49
+ environment:
50
+ POSTGRES_USER: postgres
51
+ POSTGRES_PASSWORD: postgres
52
+ POSTGRES_DB: app_dev
53
+ volumes:
54
+ - pgdata:/var/lib/postgresql/data
55
+ - ./scripts/init-db.sql:/docker-entrypoint-initdb.d/init.sql
56
+ healthcheck:
57
+ test: ["CMD-SHELL", "pg_isready -U postgres"]
58
+ interval: 5s
59
+ timeout: 3s
60
+ retries: 5
61
+
62
+ redis:
63
+ image: redis:7-alpine
64
+ ports:
65
+ - "6379:6379"
66
+ volumes:
67
+ - redisdata:/data
68
+
69
+ mailpit: # Local email testing
70
+ image: axllent/mailpit
71
+ ports:
72
+ - "8025:8025" # Web UI
73
+ - "1025:1025" # SMTP
74
+
75
+ volumes:
76
+ pgdata:
77
+ redisdata:
78
+ ```
79
+
80
+ ### Development vs Production Dockerfile
81
+
82
+ ```dockerfile
83
+ # Stage: dependencies
84
+ FROM node:22-alpine AS deps
85
+ WORKDIR /app
86
+ COPY package.json package-lock.json ./
87
+ RUN npm ci
88
+
89
+ # Stage: dev (hot reload, debug tools)
90
+ FROM node:22-alpine AS dev
91
+ WORKDIR /app
92
+ COPY --from=deps /app/node_modules ./node_modules
93
+ COPY . .
94
+ EXPOSE 3000
95
+ CMD ["npm", "run", "dev"]
96
+
97
+ # Stage: build
98
+ FROM node:22-alpine AS build
99
+ WORKDIR /app
100
+ COPY --from=deps /app/node_modules ./node_modules
101
+ COPY . .
102
+ RUN npm run build && npm prune --production
103
+
104
+ # Stage: production (minimal image)
105
+ FROM node:22-alpine AS production
106
+ WORKDIR /app
107
+ RUN addgroup -g 1001 -S appgroup && adduser -S appuser -u 1001
108
+ USER appuser
109
+ COPY --from=build --chown=appuser:appgroup /app/dist ./dist
110
+ COPY --from=build --chown=appuser:appgroup /app/node_modules ./node_modules
111
+ COPY --from=build --chown=appuser:appgroup /app/package.json ./
112
+ ENV NODE_ENV=production
113
+ EXPOSE 3000
114
+ HEALTHCHECK --interval=30s --timeout=3s CMD wget -qO- http://localhost:3000/health || exit 1
115
+ CMD ["node", "dist/server.js"]
116
+ ```
117
+
118
+ ### Override Files
119
+
120
+ ```yaml
121
+ # docker-compose.override.yml (auto-loaded, dev-only settings)
122
+ services:
123
+ app:
124
+ environment:
125
+ - DEBUG=app:*
126
+ - LOG_LEVEL=debug
127
+ ports:
128
+ - "9229:9229" # Node.js debugger
129
+
130
+ # docker-compose.prod.yml (explicit for production)
131
+ services:
132
+ app:
133
+ build:
134
+ target: production
135
+ restart: always
136
+ deploy:
137
+ resources:
138
+ limits:
139
+ cpus: "1.0"
140
+ memory: 512M
141
+ ```
142
+
143
+ ```bash
144
+ # Development (auto-loads override)
145
+ docker compose up
146
+
147
+ # Production
148
+ docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
149
+ ```
150
+
151
+ ## Networking
152
+
153
+ ### Service Discovery
154
+
155
+ Services in the same Compose network resolve by service name:
156
+ ```
157
+ # From "app" container:
158
+ postgres://postgres:postgres@db:5432/app_dev # "db" resolves to the db container
159
+ redis://redis:6379/0 # "redis" resolves to the redis container
160
+ ```
161
+
162
+ ### Custom Networks
163
+
164
+ ```yaml
165
+ services:
166
+ frontend:
167
+ networks:
168
+ - frontend-net
169
+
170
+ api:
171
+ networks:
172
+ - frontend-net
173
+ - backend-net
174
+
175
+ db:
176
+ networks:
177
+ - backend-net # Only reachable from api, not frontend
178
+
179
+ networks:
180
+ frontend-net:
181
+ backend-net:
182
+ ```
183
+
184
+ ### Exposing Only What's Needed
185
+
186
+ ```yaml
187
+ services:
188
+ db:
189
+ ports:
190
+ - "127.0.0.1:5432:5432" # Only accessible from host, not network
191
+ # Omit ports entirely in production -- accessible only within Docker network
192
+ ```
193
+
194
+ ## Volume Strategies
195
+
196
+ ```yaml
197
+ volumes:
198
+ # Named volume: persists across container restarts, managed by Docker
199
+ pgdata:
200
+
201
+ # Bind mount: maps host directory into container (for development)
202
+ # - ./src:/app/src
203
+
204
+ # Anonymous volume: preserves container-generated content from bind mount override
205
+ # - /app/node_modules
206
+ ```
207
+
208
+ ### Common Patterns
209
+
210
+ ```yaml
211
+ services:
212
+ app:
213
+ volumes:
214
+ - .:/app # Source code (bind mount for hot reload)
215
+ - /app/node_modules # Protect container's node_modules from host
216
+ - /app/.next # Protect build cache
217
+
218
+ db:
219
+ volumes:
220
+ - pgdata:/var/lib/postgresql/data # Persistent data
221
+ - ./scripts/init.sql:/docker-entrypoint-initdb.d/init.sql # Init scripts
222
+ ```
223
+
224
+ ## Container Security
225
+
226
+ ### Dockerfile Hardening
227
+
228
+ ```dockerfile
229
+ # 1. Use specific tags (never :latest)
230
+ FROM node:22.12-alpine3.20
231
+
232
+ # 2. Run as non-root
233
+ RUN addgroup -g 1001 -S app && adduser -S app -u 1001
234
+ USER app
235
+
236
+ # 3. Drop capabilities (in compose)
237
+ # 4. Read-only root filesystem where possible
238
+ # 5. No secrets in image layers
239
+ ```
240
+
241
+ ### Compose Security
242
+
243
+ ```yaml
244
+ services:
245
+ app:
246
+ security_opt:
247
+ - no-new-privileges:true
248
+ read_only: true
249
+ tmpfs:
250
+ - /tmp
251
+ - /app/.cache
252
+ cap_drop:
253
+ - ALL
254
+ cap_add:
255
+ - NET_BIND_SERVICE # Only if binding to ports < 1024
256
+ ```
257
+
258
+ ### Secret Management
259
+
260
+ ```yaml
261
+ # GOOD: Use environment variables (injected at runtime)
262
+ services:
263
+ app:
264
+ env_file:
265
+ - .env # Never commit .env to git
266
+ environment:
267
+ - API_KEY # Inherits from host environment
268
+
269
+ # GOOD: Docker secrets (Swarm mode)
270
+ secrets:
271
+ db_password:
272
+ file: ./secrets/db_password.txt
273
+
274
+ services:
275
+ db:
276
+ secrets:
277
+ - db_password
278
+
279
+ # BAD: Hardcoded in image
280
+ # ENV API_KEY=sk-proj-xxxxx # NEVER DO THIS
281
+ ```
282
+
283
+ ## .dockerignore
284
+
285
+ ```
286
+ node_modules
287
+ .git
288
+ .env
289
+ .env.*
290
+ dist
291
+ coverage
292
+ *.log
293
+ .next
294
+ .cache
295
+ docker-compose*.yml
296
+ Dockerfile*
297
+ README.md
298
+ tests/
299
+ ```
300
+
301
+ ## Debugging
302
+
303
+ ### Common Commands
304
+
305
+ ```bash
306
+ # View logs
307
+ docker compose logs -f app # Follow app logs
308
+ docker compose logs --tail=50 db # Last 50 lines from db
309
+
310
+ # Execute commands in running container
311
+ docker compose exec app sh # Shell into app
312
+ docker compose exec db psql -U postgres # Connect to postgres
313
+
314
+ # Inspect
315
+ docker compose ps # Running services
316
+ docker compose top # Processes in each container
317
+ docker stats # Resource usage
318
+
319
+ # Rebuild
320
+ docker compose up --build # Rebuild images
321
+ docker compose build --no-cache app # Force full rebuild
322
+
323
+ # Clean up
324
+ docker compose down # Stop and remove containers
325
+ docker compose down -v # Also remove volumes (DESTRUCTIVE)
326
+ docker system prune # Remove unused images/containers
327
+ ```
328
+
329
+ ### Debugging Network Issues
330
+
331
+ ```bash
332
+ # Check DNS resolution inside container
333
+ docker compose exec app nslookup db
334
+
335
+ # Check connectivity
336
+ docker compose exec app wget -qO- http://api:3000/health
337
+
338
+ # Inspect network
339
+ docker network ls
340
+ docker network inspect <project>_default
341
+ ```
342
+
343
+ ## Anti-Patterns
344
+
345
+ ```
346
+ # BAD: Using docker compose in production without orchestration
347
+ # Use Kubernetes, ECS, or Docker Swarm for production multi-container workloads
348
+
349
+ # BAD: Storing data in containers without volumes
350
+ # Containers are ephemeral -- all data lost on restart without volumes
351
+
352
+ # BAD: Running as root
353
+ # Always create and use a non-root user
354
+
355
+ # BAD: Using :latest tag
356
+ # Pin to specific versions for reproducible builds
357
+
358
+ # BAD: One giant container with all services
359
+ # Separate concerns: one process per container
360
+
361
+ # BAD: Putting secrets in docker-compose.yml
362
+ # Use .env files (gitignored) or Docker secrets
363
+ ```
@@ -0,0 +1,325 @@
1
+ ---
2
+ name: e2e-testing
3
+ description: Playwright E2E testing patterns, Page Object Model, configuration, CI/CD integration, artifact management, and flaky test strategies.
4
+ ---
5
+
6
+ # E2E Testing Patterns
7
+
8
+ Comprehensive Playwright patterns for building stable, fast, and maintainable E2E test suites.
9
+
10
+ ## Test File Organization
11
+
12
+ ```
13
+ tests/
14
+ ├── e2e/
15
+ │ ├── auth/
16
+ │ │ ├── login.spec.ts
17
+ │ │ ├── logout.spec.ts
18
+ │ │ └── register.spec.ts
19
+ │ ├── features/
20
+ │ │ ├── browse.spec.ts
21
+ │ │ ├── search.spec.ts
22
+ │ │ └── create.spec.ts
23
+ │ └── api/
24
+ │ └── endpoints.spec.ts
25
+ ├── fixtures/
26
+ │ ├── auth.ts
27
+ │ └── data.ts
28
+ └── playwright.config.ts
29
+ ```
30
+
31
+ ## Page Object Model (POM)
32
+
33
+ ```typescript
34
+ import { Page, Locator } from '@playwright/test'
35
+
36
+ export class ItemsPage {
37
+ readonly page: Page
38
+ readonly searchInput: Locator
39
+ readonly itemCards: Locator
40
+ readonly createButton: Locator
41
+
42
+ constructor(page: Page) {
43
+ this.page = page
44
+ this.searchInput = page.locator('[data-testid="search-input"]')
45
+ this.itemCards = page.locator('[data-testid="item-card"]')
46
+ this.createButton = page.locator('[data-testid="create-btn"]')
47
+ }
48
+
49
+ async goto() {
50
+ await this.page.goto('/items')
51
+ await this.page.waitForLoadState('networkidle')
52
+ }
53
+
54
+ async search(query: string) {
55
+ await this.searchInput.fill(query)
56
+ await this.page.waitForResponse(resp => resp.url().includes('/api/search'))
57
+ await this.page.waitForLoadState('networkidle')
58
+ }
59
+
60
+ async getItemCount() {
61
+ return await this.itemCards.count()
62
+ }
63
+ }
64
+ ```
65
+
66
+ ## Test Structure
67
+
68
+ ```typescript
69
+ import { test, expect } from '@playwright/test'
70
+ import { ItemsPage } from '../../pages/ItemsPage'
71
+
72
+ test.describe('Item Search', () => {
73
+ let itemsPage: ItemsPage
74
+
75
+ test.beforeEach(async ({ page }) => {
76
+ itemsPage = new ItemsPage(page)
77
+ await itemsPage.goto()
78
+ })
79
+
80
+ test('should search by keyword', async ({ page }) => {
81
+ await itemsPage.search('test')
82
+
83
+ const count = await itemsPage.getItemCount()
84
+ expect(count).toBeGreaterThan(0)
85
+
86
+ await expect(itemsPage.itemCards.first()).toContainText(/test/i)
87
+ await page.screenshot({ path: 'artifacts/search-results.png' })
88
+ })
89
+
90
+ test('should handle no results', async ({ page }) => {
91
+ await itemsPage.search('xyznonexistent123')
92
+
93
+ await expect(page.locator('[data-testid="no-results"]')).toBeVisible()
94
+ expect(await itemsPage.getItemCount()).toBe(0)
95
+ })
96
+ })
97
+ ```
98
+
99
+ ## Playwright Configuration
100
+
101
+ ```typescript
102
+ import { defineConfig, devices } from '@playwright/test'
103
+
104
+ export default defineConfig({
105
+ testDir: './tests/e2e',
106
+ fullyParallel: true,
107
+ forbidOnly: !!process.env.CI,
108
+ retries: process.env.CI ? 2 : 0,
109
+ workers: process.env.CI ? 1 : undefined,
110
+ reporter: [
111
+ ['html', { outputFolder: 'playwright-report' }],
112
+ ['junit', { outputFile: 'playwright-results.xml' }],
113
+ ['json', { outputFile: 'playwright-results.json' }]
114
+ ],
115
+ use: {
116
+ baseURL: process.env.BASE_URL || 'http://localhost:3000',
117
+ trace: 'on-first-retry',
118
+ screenshot: 'only-on-failure',
119
+ video: 'retain-on-failure',
120
+ actionTimeout: 10000,
121
+ navigationTimeout: 30000,
122
+ },
123
+ projects: [
124
+ { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
125
+ { name: 'firefox', use: { ...devices['Desktop Firefox'] } },
126
+ { name: 'webkit', use: { ...devices['Desktop Safari'] } },
127
+ { name: 'mobile-chrome', use: { ...devices['Pixel 5'] } },
128
+ ],
129
+ webServer: {
130
+ command: 'npm run dev',
131
+ url: 'http://localhost:3000',
132
+ reuseExistingServer: !process.env.CI,
133
+ timeout: 120000,
134
+ },
135
+ })
136
+ ```
137
+
138
+ ## Flaky Test Patterns
139
+
140
+ ### Quarantine
141
+
142
+ ```typescript
143
+ test('flaky: complex search', async ({ page }) => {
144
+ test.fixme(true, 'Flaky - Issue #123')
145
+ // test code...
146
+ })
147
+
148
+ test('conditional skip', async ({ page }) => {
149
+ test.skip(process.env.CI, 'Flaky in CI - Issue #123')
150
+ // test code...
151
+ })
152
+ ```
153
+
154
+ ### Identify Flakiness
155
+
156
+ ```bash
157
+ npx playwright test tests/search.spec.ts --repeat-each=10
158
+ npx playwright test tests/search.spec.ts --retries=3
159
+ ```
160
+
161
+ ### Common Causes & Fixes
162
+
163
+ **Race conditions:**
164
+ ```typescript
165
+ // Bad: assumes element is ready
166
+ await page.click('[data-testid="button"]')
167
+
168
+ // Good: auto-wait locator
169
+ await page.locator('[data-testid="button"]').click()
170
+ ```
171
+
172
+ **Network timing:**
173
+ ```typescript
174
+ // Bad: arbitrary timeout
175
+ await page.waitForTimeout(5000)
176
+
177
+ // Good: wait for specific condition
178
+ await page.waitForResponse(resp => resp.url().includes('/api/data'))
179
+ ```
180
+
181
+ **Animation timing:**
182
+ ```typescript
183
+ // Bad: click during animation
184
+ await page.click('[data-testid="menu-item"]')
185
+
186
+ // Good: wait for stability
187
+ await page.locator('[data-testid="menu-item"]').waitFor({ state: 'visible' })
188
+ await page.waitForLoadState('networkidle')
189
+ await page.locator('[data-testid="menu-item"]').click()
190
+ ```
191
+
192
+ ## Artifact Management
193
+
194
+ ### Screenshots
195
+
196
+ ```typescript
197
+ await page.screenshot({ path: 'artifacts/after-login.png' })
198
+ await page.screenshot({ path: 'artifacts/full-page.png', fullPage: true })
199
+ await page.locator('[data-testid="chart"]').screenshot({ path: 'artifacts/chart.png' })
200
+ ```
201
+
202
+ ### Traces
203
+
204
+ ```typescript
205
+ await browser.startTracing(page, {
206
+ path: 'artifacts/trace.json',
207
+ screenshots: true,
208
+ snapshots: true,
209
+ })
210
+ // ... test actions ...
211
+ await browser.stopTracing()
212
+ ```
213
+
214
+ ### Video
215
+
216
+ ```typescript
217
+ // In playwright.config.ts
218
+ use: {
219
+ video: 'retain-on-failure',
220
+ videosPath: 'artifacts/videos/'
221
+ }
222
+ ```
223
+
224
+ ## CI/CD Integration
225
+
226
+ ```yaml
227
+ # .github/workflows/e2e.yml
228
+ name: E2E Tests
229
+ on: [push, pull_request]
230
+
231
+ jobs:
232
+ test:
233
+ runs-on: ubuntu-latest
234
+ steps:
235
+ - uses: actions/checkout@v4
236
+ - uses: actions/setup-node@v4
237
+ with:
238
+ node-version: 20
239
+ - run: npm ci
240
+ - run: npx playwright install --with-deps
241
+ - run: npx playwright test
242
+ env:
243
+ BASE_URL: ${{ vars.STAGING_URL }}
244
+ - uses: actions/upload-artifact@v4
245
+ if: always()
246
+ with:
247
+ name: playwright-report
248
+ path: playwright-report/
249
+ retention-days: 30
250
+ ```
251
+
252
+ ## Test Report Template
253
+
254
+ ```markdown
255
+ # E2E Test Report
256
+
257
+ **Date:** YYYY-MM-DD HH:MM
258
+ **Duration:** Xm Ys
259
+ **Status:** PASSING / FAILING
260
+
261
+ ## Summary
262
+ - Total: X | Passed: Y (Z%) | Failed: A | Flaky: B | Skipped: C
263
+
264
+ ## Failed Tests
265
+
266
+ ### test-name
267
+ **File:** `tests/e2e/feature.spec.ts:45`
268
+ **Error:** Expected element to be visible
269
+ **Screenshot:** artifacts/failed.png
270
+ **Recommended Fix:** [description]
271
+
272
+ ## Artifacts
273
+ - HTML Report: playwright-report/index.html
274
+ - Screenshots: artifacts/*.png
275
+ - Videos: artifacts/videos/*.webm
276
+ - Traces: artifacts/*.zip
277
+ ```
278
+
279
+ ## Wallet / Web3 Testing
280
+
281
+ ```typescript
282
+ test('wallet connection', async ({ page, context }) => {
283
+ // Mock wallet provider
284
+ await context.addInitScript(() => {
285
+ window.ethereum = {
286
+ isMetaMask: true,
287
+ request: async ({ method }) => {
288
+ if (method === 'eth_requestAccounts')
289
+ return ['0x1234567890123456789012345678901234567890']
290
+ if (method === 'eth_chainId') return '0x1'
291
+ }
292
+ }
293
+ })
294
+
295
+ await page.goto('/')
296
+ await page.locator('[data-testid="connect-wallet"]').click()
297
+ await expect(page.locator('[data-testid="wallet-address"]')).toContainText('0x1234')
298
+ })
299
+ ```
300
+
301
+ ## Financial / Critical Flow Testing
302
+
303
+ ```typescript
304
+ test('trade execution', async ({ page }) => {
305
+ // Skip on production — real money
306
+ test.skip(process.env.NODE_ENV === 'production', 'Skip on production')
307
+
308
+ await page.goto('/markets/test-market')
309
+ await page.locator('[data-testid="position-yes"]').click()
310
+ await page.locator('[data-testid="trade-amount"]').fill('1.0')
311
+
312
+ // Verify preview
313
+ const preview = page.locator('[data-testid="trade-preview"]')
314
+ await expect(preview).toContainText('1.0')
315
+
316
+ // Confirm and wait for blockchain
317
+ await page.locator('[data-testid="confirm-trade"]').click()
318
+ await page.waitForResponse(
319
+ resp => resp.url().includes('/api/trade') && resp.status() === 200,
320
+ { timeout: 30000 }
321
+ )
322
+
323
+ await expect(page.locator('[data-testid="trade-success"]')).toBeVisible()
324
+ })
325
+ ```