100xprism 2.3.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 (207) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +196 -0
  3. package/VERSION +1 -0
  4. package/adapters/antigravity.sh +14 -0
  5. package/adapters/claude-code.sh +160 -0
  6. package/adapters/codex.sh +13 -0
  7. package/adapters/copilot.sh +13 -0
  8. package/adapters/cursor.sh +13 -0
  9. package/adapters/gemini.sh +13 -0
  10. package/adapters/lib/__pycache__/modules.cpython-312.pyc +0 -0
  11. package/adapters/lib/modules.py +592 -0
  12. package/adapters/lib/shared.sh +83 -0
  13. package/adapters/lib/sync_plugins.py +113 -0
  14. package/adapters/windsurf.sh +15 -0
  15. package/bin/100xprism.js +29 -0
  16. package/get.sh +24 -0
  17. package/install-project.sh +82 -0
  18. package/install.sh +281 -0
  19. package/lib/adapters/windows.js +429 -0
  20. package/lib/bootstrap.js +33 -0
  21. package/lib/init.js +19 -0
  22. package/lib/install.js +18 -0
  23. package/lib/migrate.js +52 -0
  24. package/lib/platform.js +22 -0
  25. package/lib/update.js +29 -0
  26. package/modules/_lib/reference.md +77 -0
  27. package/modules/a11y-auditor/SKILL.md +151 -0
  28. package/modules/ab-test-setup/SKILL.md +266 -0
  29. package/modules/ab-test-setup/evals/evals.json +105 -0
  30. package/modules/ab-test-setup/references/sample-size-guide.md +263 -0
  31. package/modules/ab-test-setup/references/test-templates.md +277 -0
  32. package/modules/ad-creative/SKILL.md +362 -0
  33. package/modules/ad-creative/evals/evals.json +90 -0
  34. package/modules/ad-creative/references/generative-tools.md +637 -0
  35. package/modules/ad-creative/references/platform-specs.md +213 -0
  36. package/modules/ai-seo/SKILL.md +398 -0
  37. package/modules/ai-seo/evals/evals.json +90 -0
  38. package/modules/ai-seo/references/content-patterns.md +285 -0
  39. package/modules/ai-seo/references/platform-ranking-factors.md +152 -0
  40. package/modules/analytics-tracking/SKILL.md +309 -0
  41. package/modules/analytics-tracking/evals/evals.json +90 -0
  42. package/modules/analytics-tracking/references/event-library.md +260 -0
  43. package/modules/analytics-tracking/references/ga4-implementation.md +300 -0
  44. package/modules/analytics-tracking/references/gtm-implementation.md +390 -0
  45. package/modules/architect/SKILL.md +282 -0
  46. package/modules/branch/SKILL.md +105 -0
  47. package/modules/churn-prevention/SKILL.md +424 -0
  48. package/modules/churn-prevention/evals/evals.json +93 -0
  49. package/modules/churn-prevention/references/cancel-flow-patterns.md +316 -0
  50. package/modules/churn-prevention/references/dunning-playbook.md +408 -0
  51. package/modules/cloud-security/SKILL.md +240 -0
  52. package/modules/cold-email/SKILL.md +178 -0
  53. package/modules/cold-email/evals/evals.json +94 -0
  54. package/modules/cold-email/references/benchmarks.md +83 -0
  55. package/modules/cold-email/references/follow-up-sequences.md +81 -0
  56. package/modules/cold-email/references/frameworks.md +90 -0
  57. package/modules/cold-email/references/personalization.md +79 -0
  58. package/modules/cold-email/references/subject-lines.md +53 -0
  59. package/modules/commit/SKILL.md +195 -0
  60. package/modules/competitor-alternatives/SKILL.md +256 -0
  61. package/modules/competitor-alternatives/evals/evals.json +93 -0
  62. package/modules/competitor-alternatives/references/content-architecture.md +271 -0
  63. package/modules/competitor-alternatives/references/templates.md +223 -0
  64. package/modules/connect/SKILL.md +894 -0
  65. package/modules/content-strategy/SKILL.md +359 -0
  66. package/modules/content-strategy/evals/evals.json +90 -0
  67. package/modules/context-dump/SKILL.md +67 -0
  68. package/modules/copy-editing/SKILL.md +447 -0
  69. package/modules/copy-editing/evals/evals.json +89 -0
  70. package/modules/copy-editing/references/plain-english-alternatives.md +394 -0
  71. package/modules/copywriting/SKILL.md +271 -0
  72. package/modules/copywriting/evals/evals.json +111 -0
  73. package/modules/copywriting/references/cold-email-benchmarks.md +83 -0
  74. package/modules/copywriting/references/cold-email-follow-ups.md +81 -0
  75. package/modules/copywriting/references/cold-email-frameworks.md +90 -0
  76. package/modules/copywriting/references/cold-email-personalization.md +79 -0
  77. package/modules/copywriting/references/cold-email-subject-lines.md +53 -0
  78. package/modules/copywriting/references/copy-frameworks.md +344 -0
  79. package/modules/copywriting/references/email-copy-guidelines.md +113 -0
  80. package/modules/copywriting/references/email-types.md +515 -0
  81. package/modules/copywriting/references/natural-transitions.md +272 -0
  82. package/modules/copywriting/references/sequence-templates.md +168 -0
  83. package/modules/data-query/SKILL.md +58 -0
  84. package/modules/data-viz/SKILL.md +225 -0
  85. package/modules/db/SKILL.md +205 -0
  86. package/modules/db/db-engines/_router.md +24 -0
  87. package/modules/db/db-engines/athena.md +16 -0
  88. package/modules/db/db-engines/cloud-sql.md +16 -0
  89. package/modules/db/db-engines/databricks.md +14 -0
  90. package/modules/db/db-engines/oracle.md +14 -0
  91. package/modules/db/db-engines/postgres.md +15 -0
  92. package/modules/db/db-engines/presto.md +14 -0
  93. package/modules/db/db-engines/snowflake.md +14 -0
  94. package/modules/docs/SKILL.md +100 -0
  95. package/modules/email-sequence/SKILL.md +309 -0
  96. package/modules/email-sequence/evals/evals.json +93 -0
  97. package/modules/email-sequence/references/copy-guidelines.md +113 -0
  98. package/modules/email-sequence/references/email-types.md +515 -0
  99. package/modules/email-sequence/references/sequence-templates.md +168 -0
  100. package/modules/enterprise-design/SKILL.md +75 -0
  101. package/modules/eval/SKILL.md +105 -0
  102. package/modules/figma-translator/SKILL.md +49 -0
  103. package/modules/fix-bugs/SKILL.md +104 -0
  104. package/modules/form-cro/SKILL.md +429 -0
  105. package/modules/form-cro/evals/evals.json +90 -0
  106. package/modules/free-tool-strategy/SKILL.md +178 -0
  107. package/modules/free-tool-strategy/evals/evals.json +90 -0
  108. package/modules/free-tool-strategy/references/tool-types.md +217 -0
  109. package/modules/gate/SKILL.md +232 -0
  110. package/modules/grill-me/SKILL.md +59 -0
  111. package/modules/interaction-engineer/SKILL.md +49 -0
  112. package/modules/issue/SKILL.md +272 -0
  113. package/modules/launch/SKILL.md +345 -0
  114. package/modules/launch-strategy/SKILL.md +353 -0
  115. package/modules/launch-strategy/evals/evals.json +91 -0
  116. package/modules/lint/SKILL.md +126 -0
  117. package/modules/marketing-ideas/SKILL.md +167 -0
  118. package/modules/marketing-ideas/evals/evals.json +90 -0
  119. package/modules/marketing-ideas/references/ideas-by-category.md +366 -0
  120. package/modules/marketing-psychology/SKILL.md +455 -0
  121. package/modules/marketing-psychology/evals/evals.json +88 -0
  122. package/modules/motion-designer/SKILL.md +214 -0
  123. package/modules/onboarding-cro/SKILL.md +220 -0
  124. package/modules/onboarding-cro/evals/evals.json +92 -0
  125. package/modules/onboarding-cro/references/experiments.md +258 -0
  126. package/modules/orchestrate/SKILL.md +77 -0
  127. package/modules/page-cro/SKILL.md +182 -0
  128. package/modules/page-cro/evals/evals.json +111 -0
  129. package/modules/page-cro/references/experiments.md +248 -0
  130. package/modules/page-cro/references/paywall-experiments.md +164 -0
  131. package/modules/paid-ads/SKILL.md +315 -0
  132. package/modules/paid-ads/evals/evals.json +90 -0
  133. package/modules/paid-ads/references/ad-copy-templates.md +207 -0
  134. package/modules/paid-ads/references/audience-targeting.md +243 -0
  135. package/modules/paid-ads/references/platform-setup-checklists.md +277 -0
  136. package/modules/paywall-upgrade-cro/SKILL.md +227 -0
  137. package/modules/paywall-upgrade-cro/evals/evals.json +93 -0
  138. package/modules/paywall-upgrade-cro/references/experiments.md +164 -0
  139. package/modules/popup-cro/SKILL.md +453 -0
  140. package/modules/popup-cro/evals/evals.json +94 -0
  141. package/modules/pr/SKILL.md +203 -0
  142. package/modules/pricing-strategy/SKILL.md +231 -0
  143. package/modules/pricing-strategy/evals/evals.json +90 -0
  144. package/modules/pricing-strategy/references/research-methods.md +152 -0
  145. package/modules/pricing-strategy/references/tier-structure.md +232 -0
  146. package/modules/product-marketing-context/SKILL.md +241 -0
  147. package/modules/product-marketing-context/evals/evals.json +85 -0
  148. package/modules/programmatic-seo/SKILL.md +238 -0
  149. package/modules/programmatic-seo/evals/evals.json +94 -0
  150. package/modules/programmatic-seo/references/playbooks.md +308 -0
  151. package/modules/push/SKILL.md +202 -0
  152. package/modules/referral-program/SKILL.md +255 -0
  153. package/modules/referral-program/evals/evals.json +89 -0
  154. package/modules/referral-program/references/affiliate-programs.md +164 -0
  155. package/modules/referral-program/references/program-examples.md +143 -0
  156. package/modules/release/SKILL.md +293 -0
  157. package/modules/revops/SKILL.md +343 -0
  158. package/modules/revops/evals/evals.json +91 -0
  159. package/modules/revops/references/automation-playbooks.md +290 -0
  160. package/modules/revops/references/lifecycle-definitions.md +278 -0
  161. package/modules/revops/references/routing-rules.md +203 -0
  162. package/modules/revops/references/scoring-models.md +247 -0
  163. package/modules/sales-enablement/SKILL.md +349 -0
  164. package/modules/sales-enablement/evals/evals.json +91 -0
  165. package/modules/sales-enablement/references/deck-frameworks.md +263 -0
  166. package/modules/sales-enablement/references/demo-scripts.md +355 -0
  167. package/modules/sales-enablement/references/objection-library.md +270 -0
  168. package/modules/sales-enablement/references/one-pager-templates.md +208 -0
  169. package/modules/schema-markup/SKILL.md +179 -0
  170. package/modules/schema-markup/evals/evals.json +87 -0
  171. package/modules/schema-markup/references/schema-examples.md +398 -0
  172. package/modules/security/SKILL.md +138 -0
  173. package/modules/seo-audit/SKILL.md +412 -0
  174. package/modules/seo-audit/evals/evals.json +136 -0
  175. package/modules/seo-audit/references/ai-writing-detection.md +200 -0
  176. package/modules/seo-audit/references/content-patterns.md +285 -0
  177. package/modules/seo-audit/references/platform-ranking-factors.md +152 -0
  178. package/modules/signup-flow-cro/SKILL.md +359 -0
  179. package/modules/signup-flow-cro/evals/evals.json +88 -0
  180. package/modules/site-architecture/SKILL.md +357 -0
  181. package/modules/site-architecture/evals/evals.json +88 -0
  182. package/modules/site-architecture/references/mermaid-templates.md +216 -0
  183. package/modules/site-architecture/references/navigation-patterns.md +305 -0
  184. package/modules/site-architecture/references/site-type-templates.md +293 -0
  185. package/modules/social-content/SKILL.md +278 -0
  186. package/modules/social-content/evals/evals.json +92 -0
  187. package/modules/social-content/references/platforms.md +170 -0
  188. package/modules/social-content/references/post-templates.md +177 -0
  189. package/modules/social-content/references/reverse-engineering.md +195 -0
  190. package/modules/spec/SKILL.md +81 -0
  191. package/modules/subagents/SKILL.md +123 -0
  192. package/modules/techdebt/SKILL.md +71 -0
  193. package/modules/terminal-setup/SKILL.md +49 -0
  194. package/modules/test/SKILL.md +493 -0
  195. package/modules/test/references/e2e-patterns.md +294 -0
  196. package/modules/update-claude-md/SKILL.md +52 -0
  197. package/modules/visual-system-architect/SKILL.md +53 -0
  198. package/package.json +44 -0
  199. package/plugins/plugins.json +43 -0
  200. package/shell/aliases.sh +24 -0
  201. package/shell/check-update.sh +212 -0
  202. package/templates/.env.example +199 -0
  203. package/templates/docker-compose.md +46 -0
  204. package/templates/node-frontend.md +56 -0
  205. package/templates/node-fullstack.md +59 -0
  206. package/templates/python-api.md +57 -0
  207. package/update.sh +231 -0
@@ -0,0 +1,493 @@
1
+ ---
2
+ name: test
3
+ description: You are a senior test engineer. Auto-detect all test layers (unit, integration, frontend, backend, E2E/system), run them all, write more if coverage is below threshold, and loop until everything passes.
4
+ category: quality
5
+ tier: on-demand
6
+ slash_command: /test
7
+ ---
8
+
9
+ # Test — Run All Tests: Unit → Integration → E2E
10
+
11
+ You are a senior test engineer. Auto-detect all test layers (unit, integration, frontend, backend, E2E/system), run them all, write more if coverage is below threshold, and loop until everything passes.
12
+
13
+ ## Do NOT ask for permission. Do NOT stop until coverage is met.
14
+
15
+ ---
16
+
17
+ ## Testing philosophy
18
+
19
+ **Prefer real implementations over mocks.**
20
+
21
+ | Layer | Environment | What to mock |
22
+ |---|---|---|
23
+ | Unit | In-process only | External APIs that cannot run locally (Stripe, Firebase Auth, Resend, Twilio, cloud SDKs) |
24
+ | Integration | Real DB + real app via Docker | Only payment gateways and third-party external APIs |
25
+ | E2E / System | Full stack via `docker compose up` | Nothing — zero mocks |
26
+
27
+ **Never mock:** the database, internal services, business logic, utilities, or pure functions.
28
+ **Only mock:** services that are genuinely unreachable locally (payment processors, auth providers, email senders, external SaaS APIs).
29
+
30
+ ---
31
+
32
+ ## How to use
33
+
34
+ - `/test` — all layers for files changed since last commit
35
+ - `/test --all` — full pass across the entire codebase
36
+ - `/test <file>` — target a specific source file
37
+ - `/test --unit` — unit tests only
38
+ - `/test --integration` — integration tests only (spins up Docker services)
39
+ - `/test --e2e` — E2E/system tests only (full docker compose stack)
40
+ - `/test --e2e staging` — E2E against staging environment
41
+ - `/test --e2e prod` — E2E against production
42
+
43
+ ---
44
+
45
+ ## Coverage thresholds (unit + integration — not E2E)
46
+
47
+ These are **defaults, used only when the project does not declare its own.** Check first
48
+ and honor a project-declared threshold:
49
+
50
+ ```bash
51
+ # Project-declared thresholds win over the defaults below. Look, in order, at:
52
+ # - the instruction file (CLAUDE.md/AGENTS.md/…): a line like "coverage: lines 80, branches 70"
53
+ # - jest/vitest config: coverageThreshold.global.{lines,functions,statements,branches}
54
+ # - pyproject.toml / .coveragerc: [tool.coverage.report] fail_under
55
+ grep -hiE "coverage(Threshold)?|fail_under" CLAUDE.md AGENTS.md GEMINI.md jest.config.* vitest.config.* vite.config.* pyproject.toml .coveragerc 2>/dev/null | head
56
+ ```
57
+
58
+ | Metric | Default threshold (override if the project declares one) |
59
+ |---|---|
60
+ | Lines | ≥ 95% |
61
+ | Functions | ≥ 95% |
62
+ | Statements | ≥ 95% |
63
+ | Branches | ≥ 90% |
64
+
65
+ **The coverage loop does not exit until ALL thresholds (project-declared or the defaults
66
+ above) are met AND zero unit/integration tests fail — or the iteration cap is reached
67
+ (see Phase 3).**
68
+
69
+ ---
70
+
71
+ ## Phase 0 — Docker test environment setup
72
+
73
+ Before running integration or E2E tests, check if Docker services are required and start them.
74
+
75
+ ```bash
76
+ PROJECT_ROOT=$(git rev-parse --show-toplevel)
77
+ cd "$PROJECT_ROOT"
78
+ ```
79
+
80
+ ### Detect test service requirements
81
+
82
+ ```bash
83
+ # Check for docker-compose test config
84
+ TEST_COMPOSE=""
85
+ for f in docker-compose.test.yml docker-compose.testing.yml docker-compose.yml compose.yml; do
86
+ [ -f "$PROJECT_ROOT/$f" ] && TEST_COMPOSE="$f" && break
87
+ done
88
+
89
+ # Check for service dependencies in pyproject.toml or package.json
90
+ grep -qE "postgres|redis|mysql|mongodb|elasticsearch" \
91
+ "$PROJECT_ROOT/pyproject.toml" \
92
+ "$PROJECT_ROOT/requirements*.txt" \
93
+ "$PROJECT_ROOT/package.json" \
94
+ "$PROJECT_ROOT/api/package.json" 2>/dev/null && NEEDS_SERVICES=true || NEEDS_SERVICES=false
95
+
96
+ echo "Test compose file: ${TEST_COMPOSE:-none}"
97
+ echo "Needs services: $NEEDS_SERVICES"
98
+ ```
99
+
100
+ ### Start test services (if needed)
101
+
102
+ ```bash
103
+ # Auto-detect and start required services
104
+ TEST_COMPOSE=$(ls docker-compose.test.yml docker-compose.testing.yml docker-compose.yml compose.yml 2>/dev/null | head -1 || true)
105
+ NEEDS_SERVICES=$(grep -qE "postgres|redis|mysql|mongodb|elasticsearch" \
106
+ "$PROJECT_ROOT/pyproject.toml" "$PROJECT_ROOT/requirements"*.txt "$PROJECT_ROOT/package.json" 2>/dev/null && echo true || echo false)
107
+
108
+ if [ -n "$TEST_COMPOSE" ]; then
109
+ docker compose -f "$TEST_COMPOSE" up -d --wait 2>/dev/null || true
110
+ elif $NEEDS_SERVICES; then
111
+ # Match the version the project already declares — don't pin a version it doesn't use.
112
+ # Look in any compose file for the image tag; fall back to a current LTS only if absent.
113
+ PG_IMAGE=$(grep -hoE "postgres:[0-9.]+(-[a-z0-9]+)?" "$PROJECT_ROOT"/docker-compose*.y*ml "$PROJECT_ROOT"/compose*.y*ml 2>/dev/null | head -1)
114
+ REDIS_IMAGE=$(grep -hoE "redis:[0-9.]+(-[a-z0-9]+)?" "$PROJECT_ROOT"/docker-compose*.y*ml "$PROJECT_ROOT"/compose*.y*ml 2>/dev/null | head -1)
115
+ : "${PG_IMAGE:=postgres:16}"; : "${REDIS_IMAGE:=redis:7}" # defaults only when undeclared
116
+ docker run -d --name test-postgres \
117
+ -e POSTGRES_USER=test -e POSTGRES_PASSWORD=test -e POSTGRES_DB=test \
118
+ -p 5432:5432 "$PG_IMAGE" 2>/dev/null || true
119
+ grep -qE "redis" "$PROJECT_ROOT/package.json" "$PROJECT_ROOT/pyproject.toml" 2>/dev/null && \
120
+ docker run -d --name test-redis -p 6379:6379 "$REDIS_IMAGE" 2>/dev/null || true
121
+ sleep 3 && docker exec test-postgres pg_isready -U test 2>/dev/null || sleep 3
122
+ fi
123
+ ```
124
+
125
+ **Run migrations against test DB:**
126
+ ```bash
127
+ # Django
128
+ [ -f manage.py ] && ./venv/bin/python manage.py migrate --settings=config.settings.test 2>/dev/null || true
129
+ # Alembic
130
+ [ -f alembic.ini ] && ./venv/bin/alembic upgrade head 2>/dev/null || true
131
+ # Prisma
132
+ [ -f prisma/schema.prisma ] && npx prisma migrate deploy 2>/dev/null || true
133
+ # Custom
134
+ [ -f scripts/migrate.sh ] && bash scripts/migrate.sh 2>/dev/null || true
135
+ ```
136
+
137
+ **Verify services are healthy before proceeding:**
138
+ ```bash
139
+ docker compose ps 2>/dev/null || docker ps --filter "name=test-" 2>/dev/null
140
+ ```
141
+
142
+ **GATE: Required services must be running before integration or E2E tests.**
143
+
144
+ ### Cleanup (run after all tests complete)
145
+
146
+ ```bash
147
+ # Stop test compose
148
+ [ -n "$TEST_COMPOSE" ] && docker compose -f "$TEST_COMPOSE" down -v 2>/dev/null || true
149
+ # Stop standalone containers
150
+ docker rm -f test-postgres test-redis 2>/dev/null || true
151
+ ```
152
+
153
+ ---
154
+
155
+ ## Step 1 — Detect test stack
156
+
157
+ ```bash
158
+ ls package.json api/package.json requirements.txt pyproject.toml 2>/dev/null
159
+ cat package.json 2>/dev/null | grep -E '"vitest"|"jest"' || true
160
+ cat api/package.json 2>/dev/null | grep '"jest"' || true
161
+ ls e2e/ tests/e2e/ playwright.config.* e2e/playwright.config.* 2>/dev/null || true
162
+ ```
163
+
164
+ Determine which layers apply:
165
+ - **Frontend unit/integration (Vitest)**: root `package.json` has `vitest`
166
+ - **Backend unit/integration (Jest)**: `api/package.json` has `jest`
167
+ - **Python unit/integration (pytest)**: `pyproject.toml` or `requirements.txt` present
168
+ - **E2E/System (Playwright)**: `playwright.config.*` found anywhere
169
+ - **E2E/System (pytest)**: `tests/e2e/` directory found in Python project
170
+
171
+ ---
172
+
173
+ ## Phase 1 — Unit Tests
174
+
175
+ Run smallest-scope tests first to get fast feedback.
176
+
177
+ The detected unit layers (**Frontend Vitest / Backend Jest / Python pytest**) are
178
+ independent — they run in separate processes and share no state — so **fan them out** per
179
+ the `subagents` skill ladder (Workflow tool → parallel subagents → serial fallback)
180
+ instead of running them one after another. Each layer returns
181
+ `{ layer, status, passed, failed, coverage }`; the parent collects them. This is safe
182
+ *before* Phase 2 only — the integration phase shares one Docker DB and stays serial.
183
+
184
+ ### Frontend unit (Vitest):
185
+ ```bash
186
+ cd "$PROJECT_ROOT"
187
+ npm run test:unit 2>&1
188
+ ```
189
+
190
+ ### Backend unit (Jest):
191
+ ```bash
192
+ cd "$PROJECT_ROOT/api"
193
+ npm run test:unit 2>&1
194
+ ```
195
+
196
+ ### Python unit (pytest):
197
+ ```bash
198
+ cd "$PROJECT_ROOT"
199
+ ./venv/bin/python -m pytest tests/unit/ -v --tb=short -q
200
+ ```
201
+
202
+ **Test patterns:**
203
+ - Pure functions, hooks, utilities, lib modules
204
+ - Every code path: success, error, edge cases, empty input, boundary values
205
+ - Mock ONLY genuinely unreachable external services: Stripe, Firebase Auth, Resend, Twilio, AWS SES
206
+ - Do NOT mock the database — unit tests that need DB state should use the real test DB started in Phase 0
207
+ - Do NOT mock internal services, business logic, or utilities
208
+
209
+ ---
210
+
211
+ ## Phase 2 — Integration Tests
212
+
213
+ Run against real services started in Phase 0. No mocking of internal infrastructure.
214
+
215
+ ### Frontend integration (Vitest):
216
+ ```bash
217
+ cd "$PROJECT_ROOT"
218
+ npm run test:integration 2>&1
219
+ ```
220
+
221
+ ### Backend integration (Jest + supertest):
222
+ ```bash
223
+ cd "$PROJECT_ROOT/api"
224
+ # Set test DB URL — real Docker DB from Phase 0
225
+ DATABASE_URL="${TEST_DATABASE_URL:-postgresql://test:test@localhost:5432/test}" \
226
+ REDIS_URL="${TEST_REDIS_URL:-redis://localhost:6379}" \
227
+ npm run test:integration 2>&1
228
+ ```
229
+
230
+ ### Python integration (pytest):
231
+ ```bash
232
+ cd "$PROJECT_ROOT"
233
+ DATABASE_URL="${TEST_DATABASE_URL:-postgresql+asyncpg://test:test@localhost:5432/test}" \
234
+ REDIS_URL="${TEST_REDIS_URL:-redis://localhost:6379}" \
235
+ ./venv/bin/python -m pytest tests/integration/ -v --tb=short -q
236
+ ```
237
+
238
+ **Test patterns:**
239
+ - Full HTTP request → response through the real app against a real DB
240
+ - Multi-component flows, context providers, routing, auth state
241
+ - Real DB reads and writes — assert actual persisted state, not mock return values
242
+ - Mock ONLY payment gateways (Stripe) and third-party external APIs (email providers, SMS)
243
+ - Do NOT mock: your own DB, Redis, internal queues, internal services
244
+
245
+ ---
246
+
247
+ ## Phase 3 — Coverage loop (unit + integration)
248
+
249
+ Run coverage for all detected stacks and loop until thresholds are met:
250
+
251
+ ### Vitest (frontend):
252
+ ```bash
253
+ cd "$PROJECT_ROOT"
254
+ npm run test:coverage 2>&1
255
+ ```
256
+
257
+ ### Jest (backend):
258
+ ```bash
259
+ cd "$PROJECT_ROOT/api"
260
+ DATABASE_URL="${TEST_DATABASE_URL:-postgresql://test:test@localhost:5432/test}" \
261
+ npm run test:coverage 2>&1
262
+ ```
263
+
264
+ ### pytest (Python):
265
+ ```bash
266
+ cd "$PROJECT_ROOT"
267
+ DATABASE_URL="${TEST_DATABASE_URL:-postgresql+asyncpg://test:test@localhost:5432/test}" \
268
+ ./venv/bin/python -m pytest tests/unit/ tests/integration/ --cov=. --cov-report=term-missing -q
269
+ ```
270
+
271
+ **Loop logic (bounded — never spin forever):**
272
+ 1. Parse coverage output — find files below threshold, find failing tests
273
+ 2. If all thresholds met AND zero failures → **exit loop ✅**
274
+ 3. Otherwise, if fewer than **MAX_ITERATIONS (default 6)** iterations have run:
275
+ - For each uncovered file: read it, write tests targeting uncovered lines/branches
276
+ - For each failing test: fix the test or the underlying code
277
+ - Re-run from top of loop
278
+ 4. **If the cap is reached without converging → STOP and escalate.** Report the remaining
279
+ gap (which files/metrics are short, which tests still fail) and ask the user whether to
280
+ keep going, lower a threshold, or investigate a stuck test. Do not loop indefinitely on
281
+ an unreachable target (e.g. coverage blocked by an untestable external dependency).
282
+
283
+ **Rules inside the loop:**
284
+ - Read the source file before writing tests — understand all code paths
285
+ - Test ALL paths: success, error, edge cases, auth failures, DB errors, empty state
286
+ - Write integration tests that assert real DB state — not mock return values
287
+ - Never skip, xfail, or comment-out failing tests — fix the code or the test
288
+ - Each iteration targets the files with lowest coverage first
289
+
290
+ ---
291
+
292
+ ## Phase 4 — E2E / System Tests (Docker full-stack)
293
+
294
+ Run after unit + integration pass. Spins up the complete application stack via Docker and runs real browser or API tests against it. **Zero mocks.**
295
+
296
+ ### 4a. Split Playwright configs
297
+
298
+ Use **two separate Playwright config files** — one for component/browser-unit tests that don't need the full stack, and one for true E2E against docker compose:
299
+
300
+ ```
301
+ playwright.config.ts ← component tests (no server required)
302
+ playwright.e2e.config.ts ← full-stack E2E (requires docker compose)
303
+ e2e/
304
+ fixtures/
305
+ auth.ts ← real auth fixture (creates user, gets JWT)
306
+ api.ts ← API helper (authenticated HTTP client)
307
+ smoke/
308
+ health.spec.ts ← health + smoke tests
309
+ auth/
310
+ login.spec.ts ← real browser login flow
311
+ agents/
312
+ crud.spec.ts ← real CRUD tests via browser
313
+ ```
314
+
315
+ **`playwright.config.ts`** (component tests — no docker required):
316
+ ```typescript
317
+ import { defineConfig } from '@playwright/test'
318
+
319
+ export default defineConfig({
320
+ testDir: './src',
321
+ testMatch: '**/*.spec.ts',
322
+ use: { baseURL: 'http://localhost:5173' },
323
+ webServer: {
324
+ command: 'npm run dev',
325
+ port: 5173,
326
+ reuseExistingServer: !process.env.CI,
327
+ },
328
+ })
329
+ ```
330
+
331
+ **`playwright.e2e.config.ts`** (full-stack E2E — requires `docker compose up`):
332
+ ```typescript
333
+ import { defineConfig } from '@playwright/test'
334
+
335
+ export default defineConfig({
336
+ testDir: './e2e',
337
+ testMatch: '**/*.spec.ts',
338
+ timeout: 60_000,
339
+ retries: process.env.CI ? 2 : 0,
340
+ reporter: [['html', { open: 'never' }], ['list']],
341
+ use: {
342
+ baseURL: process.env.BASE_URL ?? 'http://localhost:3000',
343
+ trace: 'retain-on-failure',
344
+ screenshot: 'only-on-failure',
345
+ video: 'retain-on-failure',
346
+ },
347
+ })
348
+ ```
349
+
350
+ ### 4b. Docker Compose E2E override file
351
+
352
+ Create `docker-compose.e2e.yml` to override production compose settings for E2E testing (seed data, test credentials, exposed ports):
353
+
354
+ ```yaml
355
+ # docker-compose.e2e.yml
356
+ # Extend your base docker-compose.yml for E2E tests
357
+ # Usage: docker compose -f docker-compose.yml -f docker-compose.e2e.yml up -d
358
+
359
+ services:
360
+ api:
361
+ environment:
362
+ - NODE_ENV=test
363
+ - DATABASE_URL=postgresql://test:test@db:5432/testdb
364
+ - REDIS_URL=redis://redis:6379
365
+ - JWT_SECRET=e2e-test-secret-not-for-production
366
+ - SEED_TEST_DATA=true # trigger seed on startup
367
+ ports:
368
+ - "8000:8000"
369
+
370
+ web:
371
+ environment:
372
+ - VITE_API_URL=http://localhost:8000
373
+ ports:
374
+ - "3000:3000"
375
+
376
+ db:
377
+ image: postgres:16 # match your base docker-compose.yml version — don't drift the test DB
378
+ environment:
379
+ POSTGRES_USER: test
380
+ POSTGRES_PASSWORD: test
381
+ POSTGRES_DB: testdb
382
+ ports:
383
+ - "5432:5432"
384
+ tmpfs:
385
+ - /var/lib/postgresql/data # ephemeral — fast, discarded after tests
386
+
387
+ redis:
388
+ image: redis:7 # match your base docker-compose.yml version
389
+ ports:
390
+ - "6379:6379"
391
+ ```
392
+
393
+ **Detection and start:**
394
+ ```bash
395
+ cd "$PROJECT_ROOT"
396
+
397
+ # Prefer e2e override, fall back to test compose, fall back to main
398
+ if [ -f docker-compose.e2e.yml ] && [ -f docker-compose.yml ]; then
399
+ COMPOSE_CMD="docker compose -f docker-compose.yml -f docker-compose.e2e.yml"
400
+ echo "Starting E2E stack with override: docker-compose.e2e.yml"
401
+ elif [ -f docker-compose.test.yml ]; then
402
+ COMPOSE_CMD="docker compose -f docker-compose.test.yml"
403
+ else
404
+ COMPOSE_CMD="docker compose"
405
+ fi
406
+
407
+ $COMPOSE_CMD up -d --build --wait
408
+ $COMPOSE_CMD ps
409
+ ```
410
+
411
+ ### 4c–4g. Fixtures, smoke tests, auth E2E, CRUD E2E, running
412
+
413
+ See **[references/e2e-patterns.md](references/e2e-patterns.md)** for complete templates:
414
+ - API helper + real auth fixture
415
+ - Docker Compose E2E override file
416
+ - Smoke / health tests
417
+ - Real auth browser flows
418
+ - Real CRUD tests (browser → API → DB assertion)
419
+ - How to start the full stack and run in order
420
+
421
+ ---
422
+
423
+ ## When writing new tests
424
+
425
+ ### Integration test — Python example (real DB, no mocks):
426
+ ```python
427
+ import pytest
428
+ import httpx
429
+
430
+ @pytest.mark.asyncio
431
+ async def test_create_agent_persists(async_client: httpx.AsyncClient, db_session):
432
+ # Act — call real API against real test DB
433
+ response = await async_client.post("/api/agents", json={"name": "test-agent"})
434
+ assert response.status_code == 201
435
+ agent_id = response.json()["id"]
436
+
437
+ # Assert — verify it actually persisted in the real DB
438
+ row = await db_session.execute("SELECT name FROM agents WHERE id = $1", agent_id)
439
+ assert row["name"] == "test-agent"
440
+ ```
441
+
442
+ ### Integration test — JS/TS example (real DB via supertest):
443
+ ```typescript
444
+ it("POST /agents persists to database", async () => {
445
+ const res = await request(app).post("/agents").send({ name: "test-agent" })
446
+ expect(res.status).toBe(201)
447
+
448
+ // Assert real DB state — not a mock return value
449
+ const row = await db.query("SELECT name FROM agents WHERE id = $1", [res.body.id])
450
+ expect(row.rows[0].name).toBe("test-agent")
451
+ })
452
+ ```
453
+
454
+ ### Unit test — mock only external APIs:
455
+ ```python
456
+ # ✅ Correct: mock only the external payment API
457
+ async def test_create_subscription(monkeypatch):
458
+ monkeypatch.setattr("stripe.Subscription.create", AsyncMock(return_value={"id": "sub_test"}))
459
+ result = await billing_service.create_subscription(user_id=1, plan="pro")
460
+ assert result.stripe_subscription_id == "sub_test"
461
+
462
+ # ❌ Wrong: don't mock the DB
463
+ async def test_create_subscription(monkeypatch):
464
+ monkeypatch.setattr("db.session.add", MagicMock()) # Never do this
465
+ ```
466
+
467
+ ---
468
+
469
+ ## Output at each coverage iteration
470
+
471
+ ```
472
+ === Test Iteration N ===
473
+ Frontend: lines X% | functions X% | branches X%
474
+ Backend: lines X% | functions X% | branches X%
475
+ Python: lines X% | functions X% | branches X%
476
+ Failing: N tests
477
+ Action: [what's being written / fixed]
478
+ ```
479
+
480
+ ## Final output
481
+
482
+ ```
483
+ === /test Complete ===
484
+ Docker env: ✅ services running | skipped (not needed)
485
+ Unit: ✅ X passed
486
+ Integration: ✅ X passed (real DB)
487
+ Frontend: lines ✅ X% | functions ✅ X% | branches ✅ X%
488
+ Backend: lines ✅ X% | functions ✅ X% | branches ✅ X%
489
+ E2E: ✅ X passed (full-stack Docker) | ⚠️ X failed (non-blocking) | skipped
490
+ Failures: 0 ✅
491
+ New files: [list]
492
+ Status: COVERAGE MET ✅
493
+ ```