codex-genesis-harness 0.1.0 → 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.
- package/.codebase/API_CONTRACTS.md +12 -0
- package/.codebase/ARCHITECTURE.md +6 -0
- package/.codebase/ARCHITECTURE_REVIEW_COMPLETE.md +216 -0
- package/.codebase/CURRENT_STATE.md +8 -0
- package/.codebase/DEPENDENCY_GRAPH.md +14 -0
- package/.codebase/DOMAIN_MODELS.md +10 -0
- package/.codebase/EVOLUTION_PLAN.md +35 -0
- package/.codebase/FILE_NAMING_CLARIFICATION.md +161 -0
- package/.codebase/HARNESS_COMPLETENESS_AUDIT.md +613 -0
- package/.codebase/IMPLEMENTATION_COMPLETE.md +429 -0
- package/.codebase/IMPLEMENTATION_HANDOFF.md +351 -0
- package/.codebase/IMPROVEMENTS_SUMMARY.md +419 -0
- package/.codebase/KNOWN_PROBLEMS.md +6 -0
- package/.codebase/MODULE_INDEX.md +13 -0
- package/.codebase/PHASE3_SKILLS_NAMING_COMPLETE.md +292 -0
- package/.codebase/PHASE_DEPENDENCY_MAP.md +486 -0
- package/.codebase/PIPELINE_FLOW.md +14 -0
- package/.codebase/QUICK_START_SPEC_IMPACT.md +456 -0
- package/.codebase/README.md +139 -0
- package/.codebase/RECOVERY_POINTS.md +438 -0
- package/.codebase/TEST_MATRIX.md +11 -0
- package/.codebase/UI_ROUTES.md +4 -0
- package/.codebase/context/backend-summary.md +4 -0
- package/.codebase/context/frontend-summary.md +4 -0
- package/.codebase/context/pipeline-summary.md +4 -0
- package/.codebase/context/providers-summary.md +4 -0
- package/.codebase/context/render-summary.md +4 -0
- package/.codebase/context/tests-summary.md +4 -0
- package/.codex/skills/genesis-ai-provider/SKILL.md +46 -0
- package/.codex/skills/genesis-ai-provider/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-ai-provider/checklists/checklist.md +9 -0
- package/.codex/skills/genesis-ai-provider/examples/example.md +4 -0
- package/.codex/skills/genesis-ai-provider/templates/provider-contract-template.md +9 -0
- package/.codex/skills/genesis-api-contract/SKILL.md +46 -0
- package/.codex/skills/genesis-api-contract/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-api-contract/checklists/checklist.md +8 -0
- package/.codex/skills/genesis-api-contract/examples/example.md +4 -0
- package/.codex/skills/genesis-api-contract/templates/api-contract-template.md +4 -0
- package/.codex/skills/genesis-api-sync/SKILL.md +354 -0
- package/.codex/skills/genesis-api-sync/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-api-sync/checklists/api-sync-checklist.md +101 -0
- package/.codex/skills/genesis-api-sync/examples/example.md +68 -0
- package/.codex/skills/genesis-api-sync/templates/api-change-template.md +257 -0
- package/.codex/skills/genesis-architecture/SKILL.md +46 -0
- package/.codex/skills/genesis-architecture/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-architecture/checklists/checklist.md +8 -0
- package/.codex/skills/genesis-architecture/examples/example.md +4 -0
- package/.codex/skills/genesis-architecture/templates/architecture-decision-template.md +14 -0
- package/.codex/skills/genesis-codebase-map/SKILL.md +46 -0
- package/.codex/skills/genesis-codebase-map/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-codebase-map/checklists/checklist.md +7 -0
- package/.codex/skills/genesis-codebase-map/examples/example.md +4 -0
- package/.codex/skills/genesis-codebase-map/templates/map-update-template.md +8 -0
- package/.codex/skills/genesis-debug-guide/SKILL.md +479 -0
- package/.codex/skills/genesis-debug-guide/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-debug-guide/checklists/flaky-test-investigation.md +339 -0
- package/.codex/skills/genesis-debug-guide/checklists/production-bug-debug.md +210 -0
- package/.codex/skills/genesis-debug-guide/checklists/test-failure-debug.md +158 -0
- package/.codex/skills/genesis-debug-guide/examples/example.md +48 -0
- package/.codex/skills/genesis-debug-guide/observability/debug-commands.md +365 -0
- package/.codex/skills/genesis-debug-guide/playbooks/unit-test-failures.md +289 -0
- package/.codex/skills/genesis-debug-guide/templates/debug-investigation-log.md +288 -0
- package/.codex/skills/genesis-design-spec/SKILL.md +46 -0
- package/.codex/skills/genesis-design-spec/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-design-spec/checklists/checklist.md +7 -0
- package/.codex/skills/genesis-design-spec/examples/example.md +4 -0
- package/.codex/skills/genesis-design-spec/templates/design-spec-template.md +9 -0
- package/.codex/skills/genesis-docs/SKILL.md +46 -0
- package/.codex/skills/genesis-docs/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-docs/checklists/checklist.md +7 -0
- package/.codex/skills/genesis-docs/examples/example.md +4 -0
- package/.codex/skills/genesis-docs/templates/docs-update-template.md +8 -0
- package/.codex/skills/genesis-docs-automation/SKILL.md +1003 -0
- package/.codex/skills/genesis-docs-automation/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-docs-automation/checklists/docs-validation.md +359 -0
- package/.codex/skills/genesis-docs-automation/checklists/spec-alignment.md +312 -0
- package/.codex/skills/genesis-docs-automation/examples/example.md +59 -0
- package/.codex/skills/genesis-docs-automation/observability/docs-tracking.md +382 -0
- package/.codex/skills/genesis-docs-automation/playbooks/auto-update-flow.md +851 -0
- package/.codex/skills/genesis-docs-automation/playbooks/changelog-generation.md +491 -0
- package/.codex/skills/genesis-docs-automation/templates/changelog-entry-template.md +187 -0
- package/.codex/skills/genesis-docs-automation/templates/handoff-template.md +297 -0
- package/.codex/skills/genesis-harness/SKILL.md +1418 -0
- package/.codex/skills/genesis-harness/agents/openai.yaml +9 -0
- package/.codex/skills/genesis-harness/checklists/bug-fix-qa.md +169 -0
- package/.codex/skills/genesis-harness/checklists/checklist.md +10 -0
- package/.codex/skills/genesis-harness/checklists/new-feature-qa.md +157 -0
- package/.codex/skills/genesis-harness/checklists/refactor-qa.md +216 -0
- package/.codex/skills/genesis-harness/checklists/requirements-validation.md +211 -0
- package/.codex/skills/genesis-harness/examples/example.md +4 -0
- package/.codex/skills/genesis-harness/resources/change-impact-matrix-template.md +204 -0
- package/.codex/skills/genesis-harness/resources/foundation-phase-template.md +131 -0
- package/.codex/skills/genesis-harness/resources/phase-00-foundation-template.md +76 -0
- package/.codex/skills/genesis-harness/resources/post-implementation-guide.md +347 -0
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/check-architecture-boundaries.sh +23 -23
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/check-docs-sync.sh +24 -24
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/check-no-debug-logs.sh +21 -21
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/check-required-planning-files.sh +46 -46
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/check-spec-changelog.sh +24 -24
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/check-task-tracking.sh +25 -25
- package/.codex/skills/genesis-harness/scripts/compact-context.sh +54 -0
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/create-adr.sh +74 -74
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/create-bug.sh +160 -160
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/create-feature.sh +217 -217
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/detect-stack.sh +26 -26
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/init-planning.sh +750 -719
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/list-changed-files.sh +12 -12
- package/.codex/skills/genesis-harness/scripts/offload-log.sh +72 -0
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/run-verification.sh +47 -47
- package/.codex/skills/genesis-harness/scripts/run-verify-loop.sh +75 -0
- package/.codex/skills/{project-genesis-harness → genesis-harness}/scripts/update-state.sh +33 -33
- package/.codex/skills/genesis-harness/templates/harness-workflow-template.md +10 -0
- package/.codex/skills/genesis-harness-engineering/SKILL.md +159 -0
- package/.codex/skills/genesis-harness-engineering/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-harness-engineering/checklists/checklist.md +48 -0
- package/.codex/skills/genesis-harness-engineering/examples/example.md +57 -0
- package/.codex/skills/genesis-harness-engineering/playbooks/harness-evolution.md +99 -0
- package/.codex/skills/genesis-harness-engineering/templates/harness-change-template.md +37 -0
- package/.codex/skills/genesis-new-design/SKILL.md +95 -0
- package/.codex/skills/genesis-new-design/agents/openai.yaml +4 -0
- package/.codex/skills/genesis-new-design/checklists/checklist.md +8 -0
- package/.codex/skills/genesis-new-design/examples/example.md +4 -0
- package/.codex/skills/genesis-new-design/templates/new-design-template.md +9 -0
- package/.codex/skills/genesis-observability-automation/SKILL.md +382 -0
- package/.codex/skills/genesis-observability-automation/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-observability-automation/examples/example.md +86 -0
- package/.codex/skills/genesis-performance-profiling/SKILL.md +510 -0
- package/.codex/skills/genesis-performance-profiling/agents/openai.yaml +6 -0
- package/.codex/skills/genesis-performance-profiling/checklists/optimization-verification.md +199 -0
- package/.codex/skills/genesis-performance-profiling/checklists/performance-baseline.md +183 -0
- package/.codex/skills/genesis-performance-profiling/examples/example.md +234 -0
- package/.codex/skills/genesis-performance-profiling/observability/performance-tracking.md +202 -0
- package/.codex/skills/genesis-performance-profiling/playbooks/load-testing-orchestration.md +593 -0
- package/.codex/skills/genesis-performance-profiling/playbooks/profiling-playbook.md +601 -0
- package/.codex/skills/genesis-performance-profiling/templates/load-test-config-template.md +428 -0
- package/.codex/skills/genesis-performance-profiling/templates/performance-report-template.md +238 -0
- package/.codex/skills/genesis-pipeline-orchestration/SKILL.md +46 -0
- package/.codex/skills/genesis-pipeline-orchestration/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-pipeline-orchestration/checklists/checklist.md +12 -0
- package/.codex/skills/genesis-pipeline-orchestration/examples/example.md +4 -0
- package/.codex/skills/genesis-pipeline-orchestration/templates/orchestration-template.md +12 -0
- package/.codex/skills/genesis-planning/SKILL.md +46 -0
- package/.codex/skills/genesis-planning/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-planning/checklists/checklist.md +8 -0
- package/.codex/skills/genesis-planning/examples/example.md +4 -0
- package/.codex/skills/genesis-planning/templates/plan-template.md +11 -0
- package/.codex/skills/genesis-release/SKILL.md +46 -0
- package/.codex/skills/genesis-release/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-release/checklists/checklist.md +8 -0
- package/.codex/skills/genesis-release/examples/example.md +4 -0
- package/.codex/skills/genesis-release/templates/release-checklist-template.md +9 -0
- package/.codex/skills/genesis-release-orchestration/SKILL.md +653 -0
- package/.codex/skills/genesis-release-orchestration/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-release-orchestration/checklists/post-deployment-verification.md +274 -0
- package/.codex/skills/genesis-release-orchestration/checklists/pre-release-validation.md +220 -0
- package/.codex/skills/genesis-release-orchestration/examples/example.md +78 -0
- package/.codex/skills/genesis-release-orchestration/observability/release-tracking.md +253 -0
- package/.codex/skills/genesis-release-orchestration/playbooks/canary-deployment-orchestration.md +472 -0
- package/.codex/skills/genesis-release-orchestration/playbooks/semantic-versioning-automation.md +494 -0
- package/.codex/skills/genesis-release-orchestration/templates/deployment-strategy-template.md +303 -0
- package/.codex/skills/genesis-release-orchestration/templates/release-runbook-template.md +420 -0
- package/.codex/skills/genesis-research/SKILL.md +46 -0
- package/.codex/skills/genesis-research/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-research/checklists/checklist.md +7 -0
- package/.codex/skills/genesis-research/examples/example.md +4 -0
- package/.codex/skills/genesis-research/templates/research-note-template.md +9 -0
- package/.codex/skills/genesis-research-first/SKILL.md +237 -0
- package/.codex/skills/genesis-research-first/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-research-first/examples/example.md +85 -0
- package/.codex/skills/genesis-spec-propagation/SKILL.md +534 -0
- package/.codex/skills/genesis-spec-propagation/agents/openai.yaml +7 -0
- package/.codex/skills/genesis-spec-propagation/checklists/phase-update-verification.md +384 -0
- package/.codex/skills/genesis-spec-propagation/checklists/spec-change-detection.md +257 -0
- package/.codex/skills/genesis-spec-propagation/examples/example.md +63 -0
- package/.codex/skills/genesis-spec-propagation/observability/propagation-tracking.md +373 -0
- package/.codex/skills/genesis-spec-propagation/playbooks/breaking-change-propagation.md +692 -0
- package/.codex/skills/genesis-spec-propagation/playbooks/feature-change-propagation.md +434 -0
- package/.codex/skills/genesis-spec-propagation/templates/migration-guide-template.md +407 -0
- package/.codex/skills/genesis-upgrade-design/SKILL.md +97 -0
- package/.codex/skills/genesis-upgrade-design/agents/openai.yaml +4 -0
- package/.codex/skills/genesis-upgrade-design/checklists/checklist.md +8 -0
- package/.codex/skills/genesis-upgrade-design/examples/example.md +4 -0
- package/.codex/skills/genesis-upgrade-design/templates/upgrade-design-template.md +9 -0
- package/.codex/skills/spec-impact-engine/SKILL.md +504 -0
- package/.codex/skills/spec-impact-engine/agents/openai.yaml +7 -0
- package/.codex/skills/spec-impact-engine/detect-spec-changes.sh +262 -0
- package/.codex/skills/spec-impact-engine/examples/example.md +98 -0
- package/.codex/skills/spec-impact-engine/templates/impact-report.md +248 -0
- package/.codex/skills/spec-impact-engine/templates/migration-guide.md +223 -0
- package/.codex/skills/ui-ux-test-skill/SKILL.md +46 -0
- package/.codex/skills/ui-ux-test-skill/agents/openai.yaml +7 -0
- package/.codex/skills/ui-ux-test-skill/checklists/checklist.md +8 -0
- package/.codex/skills/ui-ux-test-skill/examples/example.md +4 -0
- package/.codex/skills/ui-ux-test-skill/templates/playwright-test-template.md +4 -0
- package/.codex-plugin/plugin.json +13 -11
- package/README.EN.md +719 -0
- package/README.VI.md +712 -0
- package/README.md +318 -181
- package/VERSION +1 -1
- package/bin/genesis-harness.js +133 -79
- package/contracts/agents/CharacterBibleAgent/error.json +1 -0
- package/contracts/agents/CharacterBibleAgent/example.json +1 -0
- package/contracts/agents/CharacterBibleAgent/request.json +1 -0
- package/contracts/agents/CharacterBibleAgent/response.json +1 -0
- package/contracts/agents/CharacterBibleAgent/schema.json +1 -0
- package/contracts/agents/ImageGenerationAgent/error.json +1 -0
- package/contracts/agents/ImageGenerationAgent/example.json +1 -0
- package/contracts/agents/ImageGenerationAgent/request.json +1 -0
- package/contracts/agents/ImageGenerationAgent/response.json +1 -0
- package/contracts/agents/ImageGenerationAgent/schema.json +1 -0
- package/contracts/agents/PipelineOrchestrator/error.json +1 -0
- package/contracts/agents/PipelineOrchestrator/example.json +1 -0
- package/contracts/agents/PipelineOrchestrator/request.json +1 -0
- package/contracts/agents/PipelineOrchestrator/response.json +1 -0
- package/contracts/agents/PipelineOrchestrator/schema.json +1 -0
- package/contracts/agents/PromptGenerationAgent/error.json +1 -0
- package/contracts/agents/PromptGenerationAgent/example.json +1 -0
- package/contracts/agents/PromptGenerationAgent/request.json +1 -0
- package/contracts/agents/PromptGenerationAgent/response.json +1 -0
- package/contracts/agents/PromptGenerationAgent/schema.json +1 -0
- package/contracts/agents/RenderAgent/error.json +1 -0
- package/contracts/agents/RenderAgent/example.json +1 -0
- package/contracts/agents/RenderAgent/request.json +1 -0
- package/contracts/agents/RenderAgent/response.json +1 -0
- package/contracts/agents/RenderAgent/schema.json +1 -0
- package/contracts/agents/ScenePlanningAgent/error.json +1 -0
- package/contracts/agents/ScenePlanningAgent/example.json +1 -0
- package/contracts/agents/ScenePlanningAgent/request.json +1 -0
- package/contracts/agents/ScenePlanningAgent/response.json +1 -0
- package/contracts/agents/ScenePlanningAgent/schema.json +1 -0
- package/contracts/agents/ScreenplayAgent/error.json +1 -0
- package/contracts/agents/ScreenplayAgent/example.json +1 -0
- package/contracts/agents/ScreenplayAgent/request.json +1 -0
- package/contracts/agents/ScreenplayAgent/response.json +1 -0
- package/contracts/agents/ScreenplayAgent/schema.json +1 -0
- package/contracts/agents/StoryAnalysisAgent/error.json +1 -0
- package/contracts/agents/StoryAnalysisAgent/example.json +1 -0
- package/contracts/agents/StoryAnalysisAgent/request.json +1 -0
- package/contracts/agents/StoryAnalysisAgent/response.json +1 -0
- package/contracts/agents/StoryAnalysisAgent/schema.json +1 -0
- package/contracts/agents/SubtitleGenerationAgent/error.json +1 -0
- package/contracts/agents/SubtitleGenerationAgent/example.json +1 -0
- package/contracts/agents/SubtitleGenerationAgent/request.json +1 -0
- package/contracts/agents/SubtitleGenerationAgent/response.json +1 -0
- package/contracts/agents/SubtitleGenerationAgent/schema.json +1 -0
- package/contracts/agents/VoiceGenerationAgent/error.json +1 -0
- package/contracts/agents/VoiceGenerationAgent/example.json +1 -0
- package/contracts/agents/VoiceGenerationAgent/request.json +1 -0
- package/contracts/agents/VoiceGenerationAgent/response.json +1 -0
- package/contracts/agents/VoiceGenerationAgent/schema.json +1 -0
- package/contracts/api/README.md +4 -0
- package/contracts/api/endpoint-template/error.json +7 -0
- package/contracts/api/endpoint-template/example.json +11 -0
- package/contracts/api/endpoint-template/request.json +7 -0
- package/contracts/api/endpoint-template/response.json +6 -0
- package/contracts/api/endpoint-template/schema.json +9 -0
- package/contracts/events/README.md +4 -0
- package/contracts/events/event-template/error.json +4 -0
- package/contracts/events/event-template/example.json +6 -0
- package/contracts/events/event-template/request.json +6 -0
- package/contracts/events/event-template/response.json +3 -0
- package/contracts/events/event-template/schema.json +8 -0
- package/contracts/ui/README.md +4 -0
- package/contracts/ui/screen-template/error.json +4 -0
- package/contracts/ui/screen-template/example.json +7 -0
- package/contracts/ui/screen-template/request.json +4 -0
- package/contracts/ui/screen-template/response.json +4 -0
- package/contracts/ui/screen-template/schema.json +8 -0
- package/fixtures/agents/agent-fixture-template.md +14 -0
- package/fixtures/api/api-fixture-template.md +14 -0
- package/fixtures/images/image-fixture-template.md +14 -0
- package/fixtures/pipeline/pipeline-fixture-template.md +14 -0
- package/fixtures/render/render-fixture-template.md +14 -0
- package/fixtures/tts/tts-fixture-template.md +14 -0
- package/fixtures/videos/video-fixture-template.md +14 -0
- package/observability/agent-runs/agent-run-template.md +22 -0
- package/observability/decision-logs/decision-log-template.md +18 -0
- package/observability/failures/failure-template.md +18 -0
- package/package.json +8 -2
- package/playwright/e2e/e2e-template.md +4 -0
- package/playwright/fixtures/ui-fixture-template.md +4 -0
- package/playwright/smoke/smoke-template.md +4 -0
- package/playwright/visual/visual-regression-template.md +4 -0
- package/scripts/README.md +342 -0
- package/scripts/compact-context.sh +54 -0
- package/scripts/detect-changes.sh +152 -0
- package/scripts/install.sh +103 -69
- package/scripts/offload-log.sh +72 -0
- package/scripts/run-evals.sh +118 -52
- package/scripts/run-verify-loop.sh +75 -0
- package/scripts/uninstall.sh +81 -52
- package/scripts/verify.sh +380 -109
- package/tests/contracts/contract-template.test.md +10 -0
- package/tests/fixtures/fixture-index.md +4 -0
- package/tests/integration/integration-template.test.md +4 -0
- package/tests/unit/unit-template.test.md +4 -0
- package/.codex/skills/project-genesis-harness/SKILL.md +0 -727
- package/.codex/skills/project-genesis-harness/agents/openai.yaml +0 -9
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/references/planning-schema.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/references/quality-rubric.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/references/research-rubric.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/references/workflows.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/agents-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/api-docs-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/architecture-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/audit-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/bug-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/check-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/conventions-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/decision-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/design-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/escalation-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/feature-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/integrations-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/journeys-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/lessons-learned-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/observability-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/phase-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/pitfalls-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/planning-tree-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/project-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/quality-score-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/requirements-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/research-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/review-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/spec-changelog-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/stack-template.md +0 -0
- /package/.codex/skills/{project-genesis-harness → genesis-harness}/resources/verification-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 |
|