codex-genesis-harness 0.1.1 → 0.1.4

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 (180) hide show
  1. package/.codebase/ARCHITECTURE_REVIEW_COMPLETE.md +216 -0
  2. package/.codebase/CURRENT_STATE.md +2 -0
  3. package/.codebase/DOMAIN_MODELS.md +5 -3
  4. package/.codebase/FILE_NAMING_CLARIFICATION.md +161 -0
  5. package/.codebase/HARNESS_COMPLETENESS_AUDIT.md +613 -0
  6. package/.codebase/IMPLEMENTATION_COMPLETE.md +429 -0
  7. package/.codebase/IMPLEMENTATION_HANDOFF.md +351 -0
  8. package/.codebase/IMPROVEMENTS_SUMMARY.md +419 -0
  9. package/.codebase/PHASE3_SKILLS_NAMING_COMPLETE.md +292 -0
  10. package/.codebase/PHASE_DEPENDENCY_MAP.md +486 -0
  11. package/.codebase/QUICK_START_SPEC_IMPACT.md +456 -0
  12. package/.codebase/README.md +139 -0
  13. package/.codebase/RECOVERY_POINTS.md +438 -0
  14. package/.codex/skills/genesis-api-sync/SKILL.md +354 -0
  15. package/.codex/skills/genesis-api-sync/agents/openai.yaml +7 -0
  16. package/.codex/skills/genesis-api-sync/checklists/api-sync-checklist.md +101 -0
  17. package/.codex/skills/genesis-api-sync/examples/example.md +68 -0
  18. package/.codex/skills/genesis-api-sync/templates/api-change-template.md +257 -0
  19. package/.codex/skills/genesis-debug-guide/SKILL.md +479 -0
  20. package/.codex/skills/genesis-debug-guide/agents/openai.yaml +7 -0
  21. package/.codex/skills/genesis-debug-guide/checklists/flaky-test-investigation.md +339 -0
  22. package/.codex/skills/genesis-debug-guide/checklists/production-bug-debug.md +210 -0
  23. package/.codex/skills/genesis-debug-guide/checklists/test-failure-debug.md +158 -0
  24. package/.codex/skills/genesis-debug-guide/examples/example.md +48 -0
  25. package/.codex/skills/genesis-debug-guide/observability/debug-commands.md +365 -0
  26. package/.codex/skills/genesis-debug-guide/playbooks/unit-test-failures.md +289 -0
  27. package/.codex/skills/genesis-debug-guide/templates/debug-investigation-log.md +288 -0
  28. package/.codex/skills/genesis-docs-automation/SKILL.md +1003 -0
  29. package/.codex/skills/genesis-docs-automation/agents/openai.yaml +7 -0
  30. package/.codex/skills/genesis-docs-automation/checklists/docs-validation.md +359 -0
  31. package/.codex/skills/genesis-docs-automation/checklists/spec-alignment.md +312 -0
  32. package/.codex/skills/genesis-docs-automation/examples/example.md +59 -0
  33. package/.codex/skills/genesis-docs-automation/observability/docs-tracking.md +382 -0
  34. package/.codex/skills/genesis-docs-automation/playbooks/auto-update-flow.md +851 -0
  35. package/.codex/skills/genesis-docs-automation/playbooks/changelog-generation.md +491 -0
  36. package/.codex/skills/genesis-docs-automation/templates/changelog-entry-template.md +187 -0
  37. package/.codex/skills/genesis-docs-automation/templates/handoff-template.md +297 -0
  38. package/.codex/skills/genesis-harness/SKILL.md +734 -82
  39. package/.codex/skills/genesis-harness/checklists/bug-fix-qa.md +169 -0
  40. package/.codex/skills/genesis-harness/checklists/new-feature-qa.md +157 -0
  41. package/.codex/skills/genesis-harness/checklists/refactor-qa.md +216 -0
  42. package/.codex/skills/genesis-harness/checklists/requirements-validation.md +211 -0
  43. package/.codex/skills/genesis-harness/resources/change-impact-matrix-template.md +204 -0
  44. package/.codex/skills/genesis-harness/resources/foundation-phase-template.md +131 -0
  45. package/.codex/skills/genesis-harness/resources/phase-00-foundation-template.md +76 -0
  46. package/.codex/skills/genesis-harness/resources/post-implementation-guide.md +347 -0
  47. package/.codex/skills/genesis-harness/scripts/check-architecture-boundaries.sh +23 -23
  48. package/.codex/skills/genesis-harness/scripts/check-docs-sync.sh +24 -24
  49. package/.codex/skills/genesis-harness/scripts/check-no-debug-logs.sh +21 -21
  50. package/.codex/skills/genesis-harness/scripts/check-required-planning-files.sh +46 -46
  51. package/.codex/skills/genesis-harness/scripts/check-spec-changelog.sh +24 -24
  52. package/.codex/skills/genesis-harness/scripts/check-task-tracking.sh +25 -25
  53. package/.codex/skills/genesis-harness/scripts/compact-context.sh +54 -0
  54. package/.codex/skills/genesis-harness/scripts/create-adr.sh +74 -74
  55. package/.codex/skills/genesis-harness/scripts/create-bug.sh +160 -160
  56. package/.codex/skills/genesis-harness/scripts/create-feature.sh +217 -217
  57. package/.codex/skills/genesis-harness/scripts/detect-stack.sh +26 -26
  58. package/.codex/skills/genesis-harness/scripts/init-planning.sh +750 -719
  59. package/.codex/skills/genesis-harness/scripts/list-changed-files.sh +12 -12
  60. package/.codex/skills/genesis-harness/scripts/offload-log.sh +72 -0
  61. package/.codex/skills/genesis-harness/scripts/run-verification.sh +47 -47
  62. package/.codex/skills/genesis-harness/scripts/run-verify-loop.sh +75 -0
  63. package/.codex/skills/genesis-harness/scripts/update-state.sh +33 -33
  64. package/.codex/skills/genesis-harness-engineering/SKILL.md +159 -0
  65. package/.codex/skills/genesis-harness-engineering/checklists/checklist.md +48 -0
  66. package/.codex/skills/genesis-harness-engineering/examples/example.md +57 -0
  67. package/.codex/skills/genesis-harness-engineering/playbooks/harness-evolution.md +99 -0
  68. package/.codex/skills/genesis-harness-engineering/templates/harness-change-template.md +37 -0
  69. package/.codex/skills/genesis-observability-automation/SKILL.md +382 -0
  70. package/.codex/skills/genesis-observability-automation/agents/openai.yaml +7 -0
  71. package/.codex/skills/genesis-observability-automation/examples/example.md +86 -0
  72. package/.codex/skills/genesis-performance-profiling/SKILL.md +510 -0
  73. package/.codex/skills/genesis-performance-profiling/agents/openai.yaml +6 -0
  74. package/.codex/skills/genesis-performance-profiling/checklists/optimization-verification.md +199 -0
  75. package/.codex/skills/genesis-performance-profiling/checklists/performance-baseline.md +183 -0
  76. package/.codex/skills/genesis-performance-profiling/examples/example.md +234 -0
  77. package/.codex/skills/genesis-performance-profiling/observability/performance-tracking.md +202 -0
  78. package/.codex/skills/genesis-performance-profiling/playbooks/load-testing-orchestration.md +593 -0
  79. package/.codex/skills/genesis-performance-profiling/playbooks/profiling-playbook.md +601 -0
  80. package/.codex/skills/genesis-performance-profiling/templates/load-test-config-template.md +428 -0
  81. package/.codex/skills/genesis-performance-profiling/templates/performance-report-template.md +238 -0
  82. package/.codex/skills/genesis-release-orchestration/SKILL.md +653 -0
  83. package/.codex/skills/genesis-release-orchestration/agents/openai.yaml +7 -0
  84. package/.codex/skills/genesis-release-orchestration/checklists/post-deployment-verification.md +274 -0
  85. package/.codex/skills/genesis-release-orchestration/checklists/pre-release-validation.md +220 -0
  86. package/.codex/skills/genesis-release-orchestration/examples/example.md +78 -0
  87. package/.codex/skills/genesis-release-orchestration/observability/release-tracking.md +253 -0
  88. package/.codex/skills/genesis-release-orchestration/playbooks/canary-deployment-orchestration.md +472 -0
  89. package/.codex/skills/genesis-release-orchestration/playbooks/semantic-versioning-automation.md +494 -0
  90. package/.codex/skills/genesis-release-orchestration/templates/deployment-strategy-template.md +303 -0
  91. package/.codex/skills/genesis-release-orchestration/templates/release-runbook-template.md +420 -0
  92. package/.codex/skills/genesis-research-first/SKILL.md +237 -0
  93. package/.codex/skills/genesis-research-first/agents/openai.yaml +7 -0
  94. package/.codex/skills/genesis-research-first/examples/example.md +85 -0
  95. package/.codex/skills/genesis-spec-propagation/SKILL.md +534 -0
  96. package/.codex/skills/genesis-spec-propagation/agents/openai.yaml +7 -0
  97. package/.codex/skills/genesis-spec-propagation/checklists/phase-update-verification.md +384 -0
  98. package/.codex/skills/genesis-spec-propagation/checklists/spec-change-detection.md +257 -0
  99. package/.codex/skills/genesis-spec-propagation/examples/example.md +63 -0
  100. package/.codex/skills/genesis-spec-propagation/observability/propagation-tracking.md +373 -0
  101. package/.codex/skills/genesis-spec-propagation/playbooks/breaking-change-propagation.md +692 -0
  102. package/.codex/skills/genesis-spec-propagation/playbooks/feature-change-propagation.md +434 -0
  103. package/.codex/skills/genesis-spec-propagation/templates/migration-guide-template.md +407 -0
  104. package/.codex/skills/spec-impact-engine/SKILL.md +504 -0
  105. package/.codex/skills/spec-impact-engine/agents/openai.yaml +7 -0
  106. package/.codex/skills/spec-impact-engine/detect-spec-changes.sh +262 -0
  107. package/.codex/skills/spec-impact-engine/examples/example.md +98 -0
  108. package/.codex/skills/spec-impact-engine/templates/impact-report.md +248 -0
  109. package/.codex/skills/spec-impact-engine/templates/migration-guide.md +223 -0
  110. package/.codex-plugin/plugin.json +1 -1
  111. package/README.EN.md +719 -0
  112. package/README.VI.md +712 -0
  113. package/README.md +261 -107
  114. package/VERSION +1 -1
  115. package/bin/genesis-harness.js +20 -11
  116. package/package.json +1 -1
  117. package/scripts/README.md +342 -0
  118. package/scripts/compact-context.sh +54 -0
  119. package/scripts/detect-changes.sh +152 -0
  120. package/scripts/install.sh +50 -41
  121. package/scripts/offload-log.sh +72 -0
  122. package/scripts/run-evals.sh +70 -43
  123. package/scripts/run-verify-loop.sh +75 -0
  124. package/scripts/uninstall.sh +52 -43
  125. package/scripts/verify.sh +165 -73
  126. package/.codex/skills/harness-engineering-skill/SKILL.md +0 -45
  127. package/.codex/skills/harness-engineering-skill/checklists/checklist.md +0 -8
  128. package/.codex/skills/harness-engineering-skill/examples/example.md +0 -4
  129. package/.codex/skills/harness-engineering-skill/templates/harness-change-template.md +0 -8
  130. /package/.codex/skills/{ai-provider-skill → genesis-ai-provider}/SKILL.md +0 -0
  131. /package/.codex/skills/{ai-provider-skill → genesis-ai-provider}/agents/openai.yaml +0 -0
  132. /package/.codex/skills/{ai-provider-skill → genesis-ai-provider}/checklists/checklist.md +0 -0
  133. /package/.codex/skills/{ai-provider-skill → genesis-ai-provider}/examples/example.md +0 -0
  134. /package/.codex/skills/{ai-provider-skill → genesis-ai-provider}/templates/provider-contract-template.md +0 -0
  135. /package/.codex/skills/{api-contract-skill → genesis-api-contract}/SKILL.md +0 -0
  136. /package/.codex/skills/{api-contract-skill → genesis-api-contract}/agents/openai.yaml +0 -0
  137. /package/.codex/skills/{api-contract-skill → genesis-api-contract}/checklists/checklist.md +0 -0
  138. /package/.codex/skills/{api-contract-skill → genesis-api-contract}/examples/example.md +0 -0
  139. /package/.codex/skills/{api-contract-skill → genesis-api-contract}/templates/api-contract-template.md +0 -0
  140. /package/.codex/skills/{architecture-skill → genesis-architecture}/SKILL.md +0 -0
  141. /package/.codex/skills/{architecture-skill → genesis-architecture}/agents/openai.yaml +0 -0
  142. /package/.codex/skills/{architecture-skill → genesis-architecture}/checklists/checklist.md +0 -0
  143. /package/.codex/skills/{architecture-skill → genesis-architecture}/examples/example.md +0 -0
  144. /package/.codex/skills/{architecture-skill → genesis-architecture}/templates/architecture-decision-template.md +0 -0
  145. /package/.codex/skills/{codebase-map-skill → genesis-codebase-map}/SKILL.md +0 -0
  146. /package/.codex/skills/{codebase-map-skill → genesis-codebase-map}/agents/openai.yaml +0 -0
  147. /package/.codex/skills/{codebase-map-skill → genesis-codebase-map}/checklists/checklist.md +0 -0
  148. /package/.codex/skills/{codebase-map-skill → genesis-codebase-map}/examples/example.md +0 -0
  149. /package/.codex/skills/{codebase-map-skill → genesis-codebase-map}/templates/map-update-template.md +0 -0
  150. /package/.codex/skills/{design-spec-skill → genesis-design-spec}/SKILL.md +0 -0
  151. /package/.codex/skills/{design-spec-skill → genesis-design-spec}/agents/openai.yaml +0 -0
  152. /package/.codex/skills/{design-spec-skill → genesis-design-spec}/checklists/checklist.md +0 -0
  153. /package/.codex/skills/{design-spec-skill → genesis-design-spec}/examples/example.md +0 -0
  154. /package/.codex/skills/{design-spec-skill → genesis-design-spec}/templates/design-spec-template.md +0 -0
  155. /package/.codex/skills/{docs-skill → genesis-docs}/SKILL.md +0 -0
  156. /package/.codex/skills/{docs-skill → genesis-docs}/agents/openai.yaml +0 -0
  157. /package/.codex/skills/{docs-skill → genesis-docs}/checklists/checklist.md +0 -0
  158. /package/.codex/skills/{docs-skill → genesis-docs}/examples/example.md +0 -0
  159. /package/.codex/skills/{docs-skill → genesis-docs}/templates/docs-update-template.md +0 -0
  160. /package/.codex/skills/{harness-engineering-skill → genesis-harness-engineering}/agents/openai.yaml +0 -0
  161. /package/.codex/skills/{pipeline-orchestration-skill → genesis-pipeline-orchestration}/SKILL.md +0 -0
  162. /package/.codex/skills/{pipeline-orchestration-skill → genesis-pipeline-orchestration}/agents/openai.yaml +0 -0
  163. /package/.codex/skills/{pipeline-orchestration-skill → genesis-pipeline-orchestration}/checklists/checklist.md +0 -0
  164. /package/.codex/skills/{pipeline-orchestration-skill → genesis-pipeline-orchestration}/examples/example.md +0 -0
  165. /package/.codex/skills/{pipeline-orchestration-skill → genesis-pipeline-orchestration}/templates/orchestration-template.md +0 -0
  166. /package/.codex/skills/{planning-skill → genesis-planning}/SKILL.md +0 -0
  167. /package/.codex/skills/{planning-skill → genesis-planning}/agents/openai.yaml +0 -0
  168. /package/.codex/skills/{planning-skill → genesis-planning}/checklists/checklist.md +0 -0
  169. /package/.codex/skills/{planning-skill → genesis-planning}/examples/example.md +0 -0
  170. /package/.codex/skills/{planning-skill → genesis-planning}/templates/plan-template.md +0 -0
  171. /package/.codex/skills/{release-skill → genesis-release}/SKILL.md +0 -0
  172. /package/.codex/skills/{release-skill → genesis-release}/agents/openai.yaml +0 -0
  173. /package/.codex/skills/{release-skill → genesis-release}/checklists/checklist.md +0 -0
  174. /package/.codex/skills/{release-skill → genesis-release}/examples/example.md +0 -0
  175. /package/.codex/skills/{release-skill → genesis-release}/templates/release-checklist-template.md +0 -0
  176. /package/.codex/skills/{research-skill → genesis-research}/SKILL.md +0 -0
  177. /package/.codex/skills/{research-skill → genesis-research}/agents/openai.yaml +0 -0
  178. /package/.codex/skills/{research-skill → genesis-research}/checklists/checklist.md +0 -0
  179. /package/.codex/skills/{research-skill → genesis-research}/examples/example.md +0 -0
  180. /package/.codex/skills/{research-skill → genesis-research}/templates/research-note-template.md +0 -0
@@ -0,0 +1,593 @@
1
+ # Load Testing Orchestration Playbook
2
+
3
+ Complete guide to designing, configuring, and running load tests with k6, Artillery, and Locust. Includes ramp-up strategies, threshold configuration, and result interpretation.
4
+
5
+ ---
6
+
7
+ ## Part 1: Load Test Types and When to Use Each
8
+
9
+ | Test Type | Goal | Duration | Concurrency | Frequency |
10
+ |-----------|------|----------|-------------|-----------|
11
+ | **Smoke** | Verify endpoint responds at all under minimal load | 1 min | 1 VU | Every deploy |
12
+ | **Load** | Verify steady-state performance at expected traffic | 10-30 min | Target VUs | Daily / per PR |
13
+ | **Stress** | Find breaking point; observe degradation behavior | 5-10 min | 2-5× target | Weekly |
14
+ | **Soak** | Detect memory leaks, connection exhaustion, drift | 30-120 min | 50-75% target | Weekly |
15
+ | **Spike** | Simulate sudden traffic burst (flash sale, breaking news) | 2 min | 10× target (instant) | Monthly |
16
+ | **Breakpoint** | Find the exact RPS at which the system fails | 30 min | Linear ramp to failure | Pre-launch |
17
+
18
+ ---
19
+
20
+ ## Part 2: k6 Load Test Templates
21
+
22
+ ### 2.1 Complete k6 Script Template
23
+
24
+ ```javascript
25
+ import http from 'k6/http';
26
+ import { sleep, check } from 'k6';
27
+ import { Counter, Rate, Trend } from 'k6/metrics';
28
+
29
+ // ─── Custom Metrics ──────────────────────────────────────────────────────────
30
+ const errorRate = new Rate('custom_error_rate');
31
+ const apiResponseTime = new Trend('api_response_time', true); // true = milliseconds
32
+
33
+ // ─── Test Configuration ──────────────────────────────────────────────────────
34
+ export const options = {
35
+ // Stages define the VU (virtual user) ramp pattern
36
+ stages: [
37
+ { duration: '30s', target: 5 }, // Smoke: minimal load
38
+ { duration: '2m', target: 100 }, // Ramp-up: 0 → 100 VUs over 2 minutes
39
+ { duration: '5m', target: 100 }, // Peak: sustain 100 VUs for 5 minutes
40
+ { duration: '2m', target: 150 }, // Stress: push to 150% of target
41
+ { duration: '1m', target: 0 }, // Ramp-down: drain connections
42
+ ],
43
+
44
+ // Thresholds: test FAILS if any threshold is breached
45
+ thresholds: {
46
+ // P95 response time must stay under 200ms
47
+ 'http_req_duration': ['p(95)<200', 'p(99)<500'],
48
+ // Error rate must stay under 1%
49
+ 'http_req_failed': ['rate<0.01'],
50
+ // Custom error rate under 0.5%
51
+ 'custom_error_rate': ['rate<0.005'],
52
+ // Specific endpoint threshold
53
+ 'http_req_duration{name:users-list}': ['p(95)<150'],
54
+ },
55
+
56
+ // Tags applied to all metrics in this run
57
+ tags: {
58
+ environment: __ENV.ENVIRONMENT || 'staging',
59
+ version: __ENV.APP_VERSION || 'unknown',
60
+ test_type: 'load',
61
+ },
62
+
63
+ // Scenarios (advanced: allows mixing multiple test types)
64
+ // Uncomment to use scenario-based config instead of stages:
65
+ // scenarios: { ... }
66
+ };
67
+
68
+ // ─── Test Data ───────────────────────────────────────────────────────────────
69
+ const BASE_URL = __ENV.BASE_URL || 'https://api.staging.example.com';
70
+ const AUTH_TOKEN = __ENV.AUTH_TOKEN || 'test-token-here';
71
+
72
+ const HEADERS = {
73
+ 'Authorization': `Bearer ${AUTH_TOKEN}`,
74
+ 'Content-Type': 'application/json',
75
+ 'Accept': 'application/json',
76
+ };
77
+
78
+ // Realistic user payloads (sample from production logs)
79
+ const TEST_PAYLOADS = [
80
+ { query: 'active', page: 1, limit: 20 },
81
+ { query: 'inactive', page: 2, limit: 20 },
82
+ { query: 'active', page: 1, limit: 50 },
83
+ ];
84
+
85
+ // ─── Setup (runs once before test) ───────────────────────────────────────────
86
+ export function setup() {
87
+ // Verify the target is reachable before starting the real test
88
+ const healthRes = http.get(`${BASE_URL}/health`);
89
+ if (healthRes.status !== 200) {
90
+ throw new Error(`Target not healthy: ${healthRes.status}`);
91
+ }
92
+ console.log('Target is healthy. Starting load test.');
93
+ return { baseUrl: BASE_URL };
94
+ }
95
+
96
+ // ─── Main VU Function (runs for each VU on each iteration) ───────────────────
97
+ export default function(data) {
98
+ const baseUrl = data.baseUrl;
99
+
100
+ // ── Scenario: Browse users (most common user journey) ─────────────────────
101
+ // 1. List users
102
+ const payload = TEST_PAYLOADS[Math.floor(Math.random() * TEST_PAYLOADS.length)];
103
+ const listRes = http.get(
104
+ `${baseUrl}/api/users?status=${payload.query}&page=${payload.page}&limit=${payload.limit}`,
105
+ { headers: HEADERS, tags: { name: 'users-list' } }
106
+ );
107
+
108
+ apiResponseTime.add(listRes.timings.duration);
109
+
110
+ const listOk = check(listRes, {
111
+ 'list status 200': (r) => r.status === 200,
112
+ 'list body has items': (r) => {
113
+ try {
114
+ const body = JSON.parse(r.body);
115
+ return Array.isArray(body.data) && body.data.length >= 0;
116
+ } catch(e) { return false; }
117
+ },
118
+ 'list response time < 200ms': (r) => r.timings.duration < 200,
119
+ });
120
+ errorRate.add(!listOk);
121
+
122
+ sleep(1); // Think time: 1 second between actions
123
+
124
+ // 2. Get a specific user (simulate user click)
125
+ if (listRes.status === 200) {
126
+ try {
127
+ const users = JSON.parse(listRes.body).data;
128
+ if (users && users.length > 0) {
129
+ const userId = users[0].id;
130
+ const detailRes = http.get(
131
+ `${baseUrl}/api/users/${userId}`,
132
+ { headers: HEADERS, tags: { name: 'user-detail' } }
133
+ );
134
+
135
+ check(detailRes, {
136
+ 'detail status 200': (r) => r.status === 200,
137
+ 'detail has id': (r) => {
138
+ try { return JSON.parse(r.body).id === userId; } catch(e) { return false; }
139
+ },
140
+ });
141
+ }
142
+ } catch(e) {
143
+ console.error('Failed to parse user list:', e.message);
144
+ }
145
+ }
146
+
147
+ sleep(2); // Think time before next iteration
148
+ }
149
+
150
+ // ─── Teardown (runs once after test) ─────────────────────────────────────────
151
+ export function teardown(data) {
152
+ console.log('Load test complete. Cleaning up.');
153
+ }
154
+ ```
155
+
156
+ ### 2.2 Environment-Specific Config Override
157
+
158
+ ```javascript
159
+ // config/staging.js
160
+ export const stagingConfig = {
161
+ BASE_URL: 'https://api.staging.example.com',
162
+ stages: [
163
+ { duration: '1m', target: 50 },
164
+ { duration: '5m', target: 50 },
165
+ { duration: '30s', target: 0 },
166
+ ],
167
+ thresholds: {
168
+ 'http_req_duration': ['p(95)<300'], // relaxed for staging
169
+ 'http_req_failed': ['rate<0.02'],
170
+ },
171
+ };
172
+
173
+ // config/production-canary.js
174
+ export const productionCanaryConfig = {
175
+ BASE_URL: 'https://api.example.com',
176
+ stages: [
177
+ { duration: '2m', target: 10 }, // Very conservative for prod canary
178
+ { duration: '5m', target: 10 },
179
+ { duration: '1m', target: 0 },
180
+ ],
181
+ thresholds: {
182
+ 'http_req_duration': ['p(95)<200'],
183
+ 'http_req_failed': ['rate<0.001'], // stricter for production
184
+ },
185
+ };
186
+ ```
187
+
188
+ ### 2.3 k6 Scenario-Based Config (Advanced)
189
+
190
+ ```javascript
191
+ export const options = {
192
+ scenarios: {
193
+ // Scenario 1: Constant arrival rate (simulates real traffic)
194
+ constant_arrival: {
195
+ executor: 'constant-arrival-rate',
196
+ rate: 100, // 100 requests per second
197
+ timeUnit: '1s',
198
+ duration: '5m',
199
+ preAllocatedVUs: 50,
200
+ maxVUs: 150,
201
+ },
202
+
203
+ // Scenario 2: Ramping VUs (simulates growing user base)
204
+ ramp_up: {
205
+ executor: 'ramping-vus',
206
+ startVUs: 0,
207
+ stages: [
208
+ { duration: '2m', target: 100 },
209
+ { duration: '5m', target: 100 },
210
+ { duration: '1m', target: 0 },
211
+ ],
212
+ startTime: '5m', // Start after constant_arrival ends
213
+ },
214
+
215
+ // Scenario 3: Spike test (run separately)
216
+ spike: {
217
+ executor: 'ramping-vus',
218
+ stages: [
219
+ { duration: '10s', target: 500 }, // Instant spike to 500 VUs
220
+ { duration: '1m', target: 500 },
221
+ { duration: '10s', target: 0 },
222
+ ],
223
+ startTime: '12m', // Start after ramp_up ends
224
+ },
225
+ },
226
+ };
227
+ ```
228
+
229
+ ### 2.4 Running k6
230
+
231
+ ```bash
232
+ # Basic run
233
+ k6 run load-test.js
234
+
235
+ # With environment variables
236
+ k6 run \
237
+ --env BASE_URL=https://api.staging.example.com \
238
+ --env AUTH_TOKEN=eyJhbGc... \
239
+ --env ENVIRONMENT=staging \
240
+ load-test.js
241
+
242
+ # Output to JSON for programmatic analysis
243
+ k6 run --out json=results/load-test-$(date +%Y%m%d-%H%M%S).json load-test.js
244
+
245
+ # Output to InfluxDB (for Grafana real-time dashboard)
246
+ k6 run --out influxdb=http://localhost:8086/k6 load-test.js
247
+
248
+ # Dry run (validate script without sending traffic)
249
+ k6 run --dry-run load-test.js
250
+
251
+ # Soak test (override stages)
252
+ k6 run --stage 2m:50,30m:50,1m:0 load-test.js
253
+ ```
254
+
255
+ ---
256
+
257
+ ## Part 3: Artillery YAML Config Template
258
+
259
+ ```yaml
260
+ # artillery-config.yml
261
+
262
+ config:
263
+ target: "https://api.staging.example.com"
264
+
265
+ # Phases define load pattern
266
+ phases:
267
+ - name: "Warm-up"
268
+ duration: 60 # seconds
269
+ arrivalRate: 5 # new users per second
270
+
271
+ - name: "Ramp-up"
272
+ duration: 120
273
+ arrivalRate: 5
274
+ rampTo: 50 # ramp from 5 to 50 new users/sec over 2 min
275
+
276
+ - name: "Peak load"
277
+ duration: 300
278
+ arrivalRate: 50
279
+
280
+ - name: "Stress test"
281
+ duration: 120
282
+ arrivalRate: 50
283
+ rampTo: 100 # push to 2× target
284
+
285
+ - name: "Ramp-down"
286
+ duration: 60
287
+ arrivalRate: 100
288
+ rampTo: 0
289
+
290
+ # Default HTTP settings
291
+ http:
292
+ timeout: 10 # request timeout in seconds
293
+ pool: 50 # connection pool size
294
+
295
+ # Default headers for all requests
296
+ defaults:
297
+ headers:
298
+ Content-Type: "application/json"
299
+ Authorization: "Bearer {{ $env.AUTH_TOKEN }}"
300
+ Accept: "application/json"
301
+
302
+ # Plugins
303
+ plugins:
304
+ expect: {} # Enable response assertion plugin
305
+
306
+ # Threshold configuration
307
+ ensure:
308
+ p95: 200 # p95 must be < 200ms
309
+ p99: 500 # p99 must be < 500ms
310
+ maxErrorRate: 1 # error rate must be < 1%
311
+
312
+ # Scenarios define the request flows
313
+ scenarios:
314
+ - name: "Browse users"
315
+ weight: 40 # 40% of virtual users run this scenario
316
+ flow:
317
+ - get:
318
+ url: "/api/users?status=active&page=1&limit=20"
319
+ expect:
320
+ - statusCode: 200
321
+ - contentType: json
322
+ - hasProperty: "data"
323
+ capture:
324
+ - json: "$.data[0].id"
325
+ as: "firstUserId"
326
+
327
+ - think: 1 # 1 second pause
328
+
329
+ - get:
330
+ url: "/api/users/{{ firstUserId }}"
331
+ ifTrue: "firstUserId"
332
+ expect:
333
+ - statusCode: 200
334
+
335
+ - name: "Create order"
336
+ weight: 20 # 20% of virtual users
337
+ flow:
338
+ - post:
339
+ url: "/api/orders"
340
+ json:
341
+ product_id: "{{ $randomString() }}"
342
+ quantity: "{{ $randomInt(1, 5) }}"
343
+ user_id: "user-test-001"
344
+ expect:
345
+ - statusCode: 201
346
+ capture:
347
+ - json: "$.id"
348
+ as: "orderId"
349
+
350
+ - think: 2
351
+
352
+ - get:
353
+ url: "/api/orders/{{ orderId }}"
354
+ expect:
355
+ - statusCode: 200
356
+
357
+ - name: "Health check only"
358
+ weight: 40 # 40% just check health (background traffic)
359
+ flow:
360
+ - get:
361
+ url: "/health"
362
+ expect:
363
+ - statusCode: 200
364
+ ```
365
+
366
+ **Running Artillery:**
367
+ ```bash
368
+ # Install
369
+ npm install -g artillery
370
+
371
+ # Validate config
372
+ artillery validate artillery-config.yml
373
+
374
+ # Quick test (10-second smoke)
375
+ artillery quick --count 10 --num 5 https://api.staging.example.com/api/users
376
+
377
+ # Full test run
378
+ artillery run artillery-config.yml
379
+
380
+ # With environment variables
381
+ AUTH_TOKEN=eyJhbGc... artillery run artillery-config.yml
382
+
383
+ # Generate HTML report
384
+ artillery run --output results/report.json artillery-config.yml
385
+ artillery report results/report.json # Opens HTML report in browser
386
+ ```
387
+
388
+ ---
389
+
390
+ ## Part 4: Locust Scenario Design Pattern
391
+
392
+ ```python
393
+ # locustfile.py
394
+ import random
395
+ import json
396
+ from locust import HttpUser, TaskSet, task, between, events
397
+ from locust.contrib.fasthttp import FastHttpUser
398
+
399
+ class UserBrowsingTasks(TaskSet):
400
+ """Simulates a user browsing the platform."""
401
+
402
+ def on_start(self):
403
+ """Login before starting tasks."""
404
+ response = self.client.post("/auth/login", json={
405
+ "email": "test@example.com",
406
+ "password": "test-password"
407
+ })
408
+ if response.status_code == 200:
409
+ self.token = response.json().get("token")
410
+ else:
411
+ self.token = None
412
+
413
+ @task(5) # weight: 5x more likely to be chosen than tasks with weight 1
414
+ def list_users(self):
415
+ """Most common action: listing users."""
416
+ page = random.randint(1, 5)
417
+ with self.client.get(
418
+ f"/api/users?status=active&page={page}&limit=20",
419
+ headers={"Authorization": f"Bearer {self.token}"},
420
+ name="/api/users (list)", # Group in reports under this name
421
+ catch_response=True
422
+ ) as response:
423
+ if response.status_code == 200:
424
+ data = response.json()
425
+ if not isinstance(data.get("data"), list):
426
+ response.failure("Response missing 'data' array")
427
+ else:
428
+ response.success()
429
+ else:
430
+ response.failure(f"Status {response.status_code}")
431
+
432
+ @task(3)
433
+ def view_user_detail(self):
434
+ """View a specific user profile."""
435
+ user_id = f"user-{random.randint(1, 1000):04d}"
436
+ with self.client.get(
437
+ f"/api/users/{user_id}",
438
+ headers={"Authorization": f"Bearer {self.token}"},
439
+ name="/api/users/:id (detail)",
440
+ catch_response=True
441
+ ) as response:
442
+ if response.status_code in (200, 404):
443
+ response.success()
444
+ else:
445
+ response.failure(f"Unexpected status {response.status_code}")
446
+
447
+ @task(1)
448
+ def create_order(self):
449
+ """Create an order (less frequent, higher impact)."""
450
+ with self.client.post(
451
+ "/api/orders",
452
+ json={
453
+ "product_id": f"product-{random.randint(1, 100)}",
454
+ "quantity": random.randint(1, 5),
455
+ },
456
+ headers={"Authorization": f"Bearer {self.token}"},
457
+ name="/api/orders (create)",
458
+ catch_response=True
459
+ ) as response:
460
+ if response.status_code == 201:
461
+ response.success()
462
+ else:
463
+ response.failure(f"Create order failed: {response.status_code}")
464
+
465
+ @task(1)
466
+ def check_health(self):
467
+ """Simulate health check traffic."""
468
+ self.client.get("/health", name="/health")
469
+
470
+
471
+ class ApiUser(FastHttpUser):
472
+ """Virtual user class. Uses FastHttpUser for high concurrency."""
473
+ tasks = [UserBrowsingTasks]
474
+ wait_time = between(1, 3) # Random wait 1-3 seconds between tasks
475
+ host = "https://api.staging.example.com"
476
+
477
+
478
+ # ─── Event hooks for custom reporting ─────────────────────────────────────────
479
+ @events.request.add_listener
480
+ def on_request(request_type, name, response_time, response_length, response, context, exception, **kwargs):
481
+ if exception:
482
+ print(f"Request failed: {name} - {exception}")
483
+ elif response_time > 500:
484
+ print(f"Slow request: {name} took {response_time:.0f}ms")
485
+ ```
486
+
487
+ **Running Locust:**
488
+ ```bash
489
+ # Install
490
+ pip install locust
491
+
492
+ # Web UI mode (recommended for interactive testing)
493
+ locust -f locustfile.py
494
+ # Open http://localhost:8089
495
+ # Set: Number of users = 100, Spawn rate = 10/sec, Host = https://api.staging.example.com
496
+
497
+ # Headless mode (for CI)
498
+ locust -f locustfile.py \
499
+ --headless \
500
+ --users 100 \
501
+ --spawn-rate 10 \
502
+ --run-time 10m \
503
+ --host https://api.staging.example.com \
504
+ --csv results/locust \
505
+ --only-summary
506
+
507
+ # Results: locust_stats.csv, locust_failures.csv, locust_stats_history.csv
508
+ ```
509
+
510
+ ---
511
+
512
+ ## Part 5: Ramp-Up Strategy by Test Type
513
+
514
+ | Test Type | Ramp-up | Peak | Ramp-down | Notes |
515
+ |-----------|---------|------|-----------|-------|
516
+ | Smoke | None | 1 VU, 1 min | None | No ramp needed at 1 VU |
517
+ | Load | 2 min | 5-30 min | 1 min | Standard for daily regression |
518
+ | Stress | 3 min | 10 min | 2 min | Observe degradation behavior |
519
+ | Soak | 2 min | 30-120 min | 2 min | Memory/connection leak detection |
520
+ | Spike | 0 (instant) | 2 min | 0 (instant) | Test resilience to sudden burst |
521
+ | Breakpoint | Linear over 30 min | Until failure | N/A | Step-increase until system breaks |
522
+
523
+ ---
524
+
525
+ ## Part 6: Go/No-Go Criteria by Percentile
526
+
527
+ ### Pass criteria (all must be met)
528
+
529
+ | Percentile | Web API | Internal Service | Real-Time | Batch Job |
530
+ |-----------|---------|-----------------|-----------|-----------|
531
+ | p50 | ≤ 50 ms | ≤ 20 ms | ≤ 10 ms | ≤ 1 s |
532
+ | p95 | ≤ 200 ms | ≤ 100 ms | ≤ 50 ms | ≤ 10 s |
533
+ | p99 | ≤ 500 ms | ≤ 300 ms | ≤ 100 ms | ≤ 30 s |
534
+ | Error rate | < 0.1% | < 0.5% | < 0.01% | < 1% |
535
+ | Throughput | ≥ SLO target | ≥ SLO target | ≥ SLO target | ≥ SLO target |
536
+
537
+ **Decision**: If ANY criterion fails → FAIL. Fix before proceeding to production.
538
+
539
+ ---
540
+
541
+ ## Part 7: Result Interpretation Guide
542
+
543
+ ### Reading k6 Output
544
+
545
+ ```
546
+ scenarios: (100.00%) 1 scenario, 100 max VUs, 10m30s max duration
547
+ default: 100 looping VUs for 10m0s (gracefulStop: 30s)
548
+
549
+ ✗ http_req_duration.............: avg=145ms min=12ms med=89ms max=2.3s p(90)=312ms p(95)=456ms ← FAIL (> 200ms)
550
+ ✓ http_req_failed...............: 0.23% ✓ 4567 ✗ 11
551
+ http_reqs......................: 4578 7.63/s
552
+
553
+ Interpretation:
554
+ - p95=456ms → SLA breach. This FAILS the p(95)<200 threshold.
555
+ - Error rate=0.23% → PASSES the rate<0.01 (1%) threshold.
556
+ - Throughput=7.63 RPS → May be too low. Compare to required RPS.
557
+ - max=2.3s → Some requests are very slow. Check outliers.
558
+ ```
559
+
560
+ ### Reading Artillery Output
561
+
562
+ ```
563
+ Summary report @ 14:35:23(+0000)
564
+ Scenarios launched: 5000
565
+ Scenarios completed: 4998
566
+ Requests completed: 14994
567
+ Mean response/sec: 49.98
568
+ Response time (msec):
569
+ min: 12
570
+ max: 3421
571
+ median: 95 ← p50 = 95ms ✅
572
+ p95: 287 ← p95 = 287ms ❌ (> 200ms SLA)
573
+ p99: 645 ← p99 = 645ms ❌ (> 500ms SLA)
574
+ Scenario counts:
575
+ Browse users: 2002 (40%)
576
+ Create order: 1001 (20%)
577
+ Health check only: 1997 (40%)
578
+ Codes:
579
+ 200: 9997
580
+ 201: 998
581
+ 500: 12 ← 12 server errors (0.08% error rate) ✅
582
+ ```
583
+
584
+ ### Common Result Patterns and Their Meanings
585
+
586
+ | Pattern | Meaning | Action |
587
+ |---------|---------|--------|
588
+ | p95 >> p50 (large gap) | Outlier requests (occasional slow requests) | Profile the slow-path code branch |
589
+ | High p99, low p95 | Long tail (extreme outliers only) | Investigate timeouts, GC pauses |
590
+ | Error rate spikes at peak | Concurrency limit hit | Check connection pool, thread pool, rate limiter |
591
+ | Latency increases over test duration | Memory leak or connection accumulation | Run soak test; take memory snapshots |
592
+ | Throughput plateaus before concurrency does | Bottleneck upstream (DB, external API) | Profile dependencies |
593
+ | Max latency >> p99 | Extreme outliers (network timeout?) | Check for TCP retransmits, DNS issues |