claude-flow-novice 2.6.0 → 2.8.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.
- package/.claude/adaptive-context/cfn-v3-reflection.json +21 -0
- package/.claude/agents/AGENT_LIFECYCLE.md +495 -0
- package/.claude/agents/CLAUDE.md +1002 -995
- package/.claude/agents/accessibility-advocate.md +457 -0
- package/.claude/agents/agent-principles/README.md +226 -226
- package/.claude/agents/agent-principles/agent-type-guidelines.md +10 -0
- package/.claude/agents/agent-principles/format-selection.md +10 -0
- package/.claude/agents/agent-principles/phase4-template-optimization.md +502 -494
- package/.claude/agents/agent-principles/prompt-engineering.md +8 -0
- package/.claude/agents/agent-principles/quality-metrics.md +8 -0
- package/.claude/agents/analysis/code-analyzer.md +7 -17
- package/.claude/agents/analysis/code-review/analyze-code-quality.md +2 -104
- package/.claude/agents/analysis/perf-analyzer.md +2 -196
- package/.claude/agents/context/context-curator.md +78 -84
- package/.claude/agents/context/context-reflector.md +27 -81
- package/.claude/agents/coordinators/README.md +42 -0
- package/.claude/agents/coordinators/cfn-v3-coordinator.md +440 -0
- package/.claude/agents/{product-owner-team → coordinators}/cto-agent.md +154 -187
- package/.claude/agents/coordinators/multi-sprint-coordinator.md +50 -0
- package/.claude/agents/{product-owner-team → coordinators}/product-owner-agent.md +6 -39
- package/.claude/agents/{cfn-loop → coordinators}/product-owner.md +72 -17
- package/.claude/agents/core-agents/reviewer.md +114 -135
- package/.claude/agents/custom/agent-builder.md +637 -637
- package/.claude/agents/developers/README.md +69 -0
- package/.claude/agents/developers/backend-dev.md +77 -0
- package/.claude/agents/{core-agents → developers}/coder.md +131 -26
- package/.claude/agents/developers/react-frontend-engineer.md +121 -0
- package/.claude/agents/{frontend → developers}/state-architect.md +1 -0
- package/.claude/agents/{frontend → developers}/ui-designer.md +1 -0
- package/.claude/agents/development/backend/dev-backend-api.md +0 -29
- package/.claude/agents/development/npm-package-specialist.md +355 -347
- package/.claude/agents/documentation/api-docs/docs-api-openapi.md +8 -0
- package/.claude/agents/documentation/api-docs.md +8 -0
- package/.claude/agents/github/github-commit-agent.md +125 -117
- package/.claude/agents/goal/goal-planner.md +8 -0
- package/.claude/agents/infrastructure/README.md +100 -0
- package/.claude/agents/{specialized → infrastructure}/devops-engineer.md +131 -150
- package/.claude/agents/planners/README.md +94 -0
- package/.claude/agents/{core-agents → planners}/analyst.md +1 -22
- package/.claude/agents/{planning-team → planners}/api-designer-persona.md +8 -0
- package/.claude/agents/{core-agents → planners}/architect.md +7 -20
- package/.claude/agents/{core-agents → planners}/planner.md +0 -21
- package/.claude/agents/{planning-team → planners}/security-architect-persona.md +8 -28
- package/.claude/agents/{planning-team → planners}/system-architect-persona.md +6 -38
- package/.claude/agents/{architecture → planners}/system-architect.md +12 -17
- package/.claude/agents/product-owner-team/accessibility-advocate-persona.md +132 -161
- package/.claude/agents/product-owner-team/power-user-persona.md +149 -182
- package/.claude/agents/retrospective-analyst.md +84 -0
- package/.claude/agents/reviewers/README.md +58 -0
- package/.claude/agents/{analysis → reviewers}/code-quality-validator.md +8 -17
- package/.claude/agents/reviewers/reviewer.md +181 -0
- package/.claude/agents/sparc/architecture.md +6 -25
- package/.claude/agents/sparc/pseudocode.md +6 -0
- package/.claude/agents/sparc/refinement.md +6 -0
- package/.claude/agents/sparc/specification.md +1 -0
- package/.claude/agents/specialists/README.md +60 -0
- package/.claude/agents/{core-agents → specialists}/base-template-generator.md +8 -21
- package/.claude/agents/{specialized → specialists}/cli-agent-optimizer.md +1 -1
- package/.claude/agents/{specialized → specialists}/code-booster.md +1 -0
- package/.claude/agents/{consensus → specialists}/consensus-builder.md +1 -17
- package/.claude/agents/{specialized/mobile → specialists}/mobile-dev.md +0 -20
- package/.claude/agents/{core-agents → specialists}/performance-benchmarker.md +134 -148
- package/.claude/agents/{specialized → specialists}/rust-developer.md +1 -20
- package/.claude/agents/{specialized → specialists}/rust-enterprise-developer.md +1 -20
- package/.claude/agents/{specialized → specialists}/rust-mvp-developer.md +1 -20
- package/.claude/agents/{core-agents → specialists}/security-manager.md +68 -88
- package/.claude/agents/{security → specialists}/security-specialist-existing.md +6 -57
- package/.claude/agents/{security → specialists}/security-specialist.md +6 -30
- package/.claude/agents/{specialized/mobile → specialists}/spec-mobile-react-native.md +2 -21
- package/.claude/agents/testers/README.md +94 -0
- package/.claude/agents/{testing → testers}/e2e/playwright-agent.md +1 -20
- package/.claude/agents/{testing → testers}/interaction-tester.md +1 -20
- package/.claude/agents/{testing → testers}/playwright-tester.md +1 -1
- package/.claude/agents/testers/tester.md +139 -0
- package/.claude/agents/testers/unit/tdd-london-swarm.md +49 -0
- package/.claude/agents/testers/validation/production-validator.md +33 -0
- package/.claude/agents-ignore/cfn-loop-coordinator.md +157 -0
- package/.claude/agents-ignore/cfn-loop-coordinator.md.backup +156 -0
- package/.claude/agents-ignore/coordinator.md.backup +182 -0
- package/.claude/agents-ignore/cost-savings-cfn-loop-coordinator.md +760 -0
- package/.claude/agents-ignore/cost-savings-coordinator.md +173 -0
- package/.claude/artifacts/ace-reflections/REFLECT-001-summary.json +39 -0
- package/.claude/artifacts/ace-reflections/sprint-7_$(date -u +/"%Y%m%d_%H%M%S/").json" +47 -0
- package/.claude/commands/CFN_COORDINATOR_PARAMETERS.md +10 -10
- package/.claude/commands/cfn-loop-epic.md +3 -3
- package/.claude/commands/cfn-loop-single.md +3 -3
- package/.claude/commands/cfn-loop-sprints.md +1 -1
- package/.claude/commands/cfn-loop.md +3 -3
- package/.claude/commands/cfn-mode.md +20 -0
- package/.claude/commands/write-plan.md +104 -0
- package/.claude/data/cfn-loop.db +0 -0
- package/.claude/data/cfn_loop_logs.db +0 -0
- package/.claude/hooks/BACKUP_USAGE.md +243 -0
- package/.claude/hooks/post-edit-cfn-retrospective.sh +79 -0
- package/.claude/hooks/post-edit.sh +21 -0
- package/.claude/hooks/pre-edit-backup.sh +71 -0
- package/.claude/hooks/restore-from-backup.sh +37 -0
- package/.claude/prompts/cfn-loop-context.md +115 -0
- package/.claude/prompts/loop-specific/loop2.md +50 -0
- package/.claude/prompts/loop-specific/loop3.md +43 -0
- package/.claude/prompts/loop-specific/loop4.md +54 -0
- package/.claude/root-claude-distribute/CLAUDE.md +76 -2
- package/.claude/skills/ace-system/sprint-7-lessons.json +46 -0
- package/.claude/skills/ace-system/store-reflection.sh +33 -136
- package/.claude/skills/agent-discovery/SKILL.md +40 -0
- package/.claude/skills/agent-discovery/agents-registry-clean.json +0 -0
- package/.claude/skills/agent-discovery/agents-registry-fixed.json +19 -0
- package/.claude/skills/agent-discovery/agents-registry.json +718 -0
- package/.claude/skills/agent-discovery/discover-agents.py +175 -0
- package/.claude/skills/agent-discovery/discover-agents.sh +87 -0
- package/.claude/skills/agent-discovery/invoke-registry.sh +11 -0
- package/.claude/skills/agent-discovery/temp_script.py +0 -0
- package/.claude/skills/agent-output-processing/SKILL.md +359 -0
- package/.claude/skills/agent-selector/SKILL.md +90 -0
- package/.claude/skills/agent-selector/select-agents.sh +96 -0
- package/.claude/skills/agent-spawning/agent-selection-guide.md +1 -1
- package/.claude/skills/agent-swap/SKILL.md +36 -0
- package/.claude/skills/agent-swap/recommend-swap.sh +60 -0
- package/.claude/skills/api-validation/test-endpoints.sh +54 -0
- package/.claude/skills/automatic-memory-persistence/SKILL.md +73 -0
- package/.claude/skills/automatic-memory-persistence/persist-agent-output.sh +49 -0
- package/.claude/skills/automatic-memory-persistence/query-agent-history.sh +35 -0
- package/.claude/skills/automatic-memory-persistence/test-memory-persistence.sh +235 -0
- package/.claude/skills/cfn-loop-orchestration/README.md +41 -0
- package/.claude/skills/cfn-loop-orchestration/SKILL.md +299 -0
- package/.claude/skills/cfn-loop-orchestration/helpers/auto-tune-timeouts.sh +228 -0
- package/.claude/skills/cfn-loop-orchestration/helpers/consensus.sh +84 -0
- package/.claude/skills/cfn-loop-orchestration/helpers/deliverable-verifier.sh +71 -0
- package/.claude/skills/cfn-loop-orchestration/helpers/gate-check.sh +90 -0
- package/.claude/skills/cfn-loop-orchestration/helpers/iteration-manager.sh +87 -0
- package/.claude/skills/cfn-loop-orchestration/helpers/timeout-calculator.sh +51 -0
- package/.claude/skills/cfn-loop-orchestration/inject-loop-context.sh +41 -0
- package/.claude/skills/cfn-loop-orchestration/monitor-execution.sh +156 -0
- package/.claude/skills/cfn-loop-orchestration/orchestrate.sh +840 -0
- package/.claude/skills/cfn-loop-orchestration/security_utils.sh +99 -0
- package/.claude/skills/cfn-loop-orchestration/test-cfn-orchestration.sh +281 -0
- package/.claude/skills/cfn-loop-orchestration/test-edge-cases.sh +188 -0
- package/.claude/skills/cfn-loop-validation/SKILL.md +307 -217
- package/.claude/skills/complexity-estimator/SKILL.md +96 -0
- package/.claude/skills/complexity-estimator/estimate-complexity.sh +144 -0
- package/.claude/skills/context-pruner/SKILL.md +75 -0
- package/.claude/skills/context-pruner/prune-context.sh +73 -0
- package/.claude/skills/defense-in-depth/SKILL.md +133 -0
- package/.claude/skills/dependency-extractor/SKILL.md +35 -0
- package/.claude/skills/dependency-extractor/extract-dependencies.sh +66 -0
- package/.claude/skills/epic-decomposer/SKILL.md +44 -0
- package/.claude/skills/epic-decomposer/decompose-epic.sh +104 -0
- package/.claude/skills/improvement-recommender/SKILL.md +33 -0
- package/.claude/skills/improvement-recommender/recommend-improvements.sh +92 -0
- package/.claude/skills/intervention-detector/SKILL.md +39 -0
- package/.claude/skills/intervention-detector/detect-intervention.sh +111 -0
- package/.claude/skills/intervention-orchestrator/SKILL.md +43 -0
- package/.claude/skills/intervention-orchestrator/execute-intervention.sh +59 -0
- package/.claude/skills/loop2-output-processing/SKILL.md +163 -0
- package/.claude/skills/loop2-output-processing/execute-and-extract.sh +77 -0
- package/.claude/skills/loop2-output-processing/execute-and-extract.sh.backup +36 -0
- package/.claude/skills/loop2-output-processing/parse-feedback.sh +147 -0
- package/.claude/skills/loop2-output-processing/process-validator-output.sh +275 -0
- package/.claude/skills/loop2-output-processing/test-bug27-fix.sh +200 -0
- package/.claude/skills/loop2-output-processing/test-loop2-processing.sh +113 -0
- package/.claude/skills/loop3-output-processing/AGENT_COMPLETION_PROTOCOL.md +206 -0
- package/.claude/skills/loop3-output-processing/SKILL.md +421 -0
- package/.claude/skills/loop3-output-processing/calculate-confidence.sh +28 -0
- package/.claude/skills/loop3-output-processing/execute-and-extract.sh +85 -0
- package/.claude/skills/loop3-output-processing/parse-confidence.sh +31 -0
- package/.claude/skills/loop3-output-processing/test-agent-timeout.sh +327 -0
- package/.claude/skills/loop3-output-processing/test-loop3-processing.sh +155 -0
- package/.claude/skills/loop3-output-processing/verify-deliverables.sh +42 -0
- package/.claude/skills/pattern-extraction/SKILL.md +30 -0
- package/.claude/skills/pattern-extraction/extract-patterns.sh +80 -0
- package/.claude/skills/playbook/SKILL.md +113 -0
- package/.claude/skills/playbook/init-playbook.sh +54 -0
- package/.claude/skills/playbook/playbook.db +0 -0
- package/.claude/skills/playbook/query-playbook.sh +79 -0
- package/.claude/skills/playbook/update-playbook.sh +69 -0
- package/.claude/skills/playbook-auto-update/SKILL.md +29 -0
- package/.claude/skills/playbook-auto-update/auto-update-playbook.sh +86 -0
- package/.claude/skills/product-owner-decision/SKILL.md +332 -0
- package/.claude/skills/product-owner-decision/execute-decision.sh +176 -0
- package/.claude/skills/product-owner-decision/parse-decision.sh +66 -0
- package/.claude/skills/product-owner-decision/validate-deliverables.sh +82 -0
- package/.claude/skills/redis-coordination/LOGGING.md +260 -0
- package/.claude/skills/redis-coordination/README.md +30 -29
- package/.claude/skills/redis-coordination/SKILL.md +685 -83
- package/.claude/skills/redis-coordination/analyze-task-complexity.sh +277 -0
- package/.claude/skills/redis-coordination/cfn-loop-exec.sh +468 -0
- package/.claude/skills/redis-coordination/collect-confidence-scores.sh +179 -0
- package/.claude/skills/redis-coordination/collect-results.sh +75 -0
- package/.claude/skills/redis-coordination/data/cfn-loop.db +0 -0
- package/.claude/skills/redis-coordination/{test-orchestrator.sh → demos/test-orchestrator.sh} +25 -0
- package/.claude/skills/redis-coordination/execute-product-owner-decision.sh +258 -0
- package/.claude/skills/redis-coordination/get-agent-timeout.sh +176 -176
- package/.claude/skills/redis-coordination/invoke-waiting-mode.sh +93 -227
- package/.claude/skills/redis-coordination/invoke-waiting-mode.sh.backup-p7 +423 -0
- package/.claude/skills/redis-coordination/log-event.sh +109 -0
- package/.claude/skills/redis-coordination/monitor-cfn-violations.sh +391 -0
- package/.claude/skills/redis-coordination/orchestrate-cfn-loop-v3.sh +141 -0
- package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh +31 -993
- package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh.backup +38 -0
- package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh.backup-1761167675 +1672 -0
- package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh.backup-p5 +1604 -0
- package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh.backup-phase1 +1550 -0
- package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh.backup-phase2 +1621 -0
- package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh.backup-phase3 +1621 -0
- package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh.bak +0 -0
- package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh.broken +1627 -0
- package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh.corrupted +80 -0
- package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh.deprecated +1864 -0
- package/.claude/skills/redis-coordination/query-logs.sh +103 -0
- package/.claude/skills/redis-coordination/retrieve-context.sh +58 -0
- package/.claude/skills/redis-coordination/select-specialist-agent.sh +371 -0
- package/.claude/skills/redis-coordination/semantic-match-tfidf.py +252 -0
- package/.claude/skills/redis-coordination/send-heartbeat.sh +164 -72
- package/.claude/skills/redis-coordination/signal.sh +38 -0
- package/.claude/skills/redis-coordination/store-context.sh +86 -0
- package/.claude/skills/redis-coordination/test-context-injection.sh +354 -0
- package/.claude/skills/redis-coordination/test-timeout-enforcement.sh +513 -0
- package/.claude/skills/redis-coordination/tests/convert-line-endings.sh +15 -0
- package/.claude/skills/redis-coordination/tests/dlq-functionality-test.sh +101 -101
- package/.claude/skills/redis-coordination/tests/edge-cases-test.sh +98 -98
- package/.claude/skills/redis-coordination/tests/integration-test.sh +169 -169
- package/.claude/skills/redis-coordination/tests/retry-mechanism-test.sh +81 -81
- package/.claude/skills/redis-coordination/tests/run-test-suite.sh +91 -91
- package/.claude/skills/redis-coordination/tests/run-tests.sh +4 -0
- package/.claude/skills/redis-coordination/tests/test-primitives.sh +166 -0
- package/.claude/skills/redis-coordination/tests/test-utils.sh +53 -121
- package/.claude/skills/redis-coordination/tests/test_coordination_primitives.sh.deprecated +20 -0
- package/.claude/skills/redis-coordination/tests/test_utils.sh +49 -0
- package/.claude/skills/redis-coordination/v2_modularization/core_orchestration.sh +76 -0
- package/.claude/skills/redis-coordination/validate-parameters.sh +492 -0
- package/.claude/skills/retrospective-report/SKILL.md +31 -0
- package/.claude/skills/retrospective-report/generate-report.sh +101 -0
- package/.claude/skills/run-all-skill-tests.sh +124 -0
- package/.claude/skills/scope-simplifier/SKILL.md +37 -0
- package/.claude/skills/scope-simplifier/simplify-scope.sh +68 -0
- package/.claude/skills/simplified-agent-lifecycle/COST_ANALYSIS.md +49 -0
- package/.claude/skills/simplified-agent-lifecycle/DESIGN.md +98 -0
- package/.claude/skills/simplified-agent-lifecycle/MIGRATION_PLAN.md +74 -0
- package/.claude/skills/specialist-injection/SKILL.md +41 -0
- package/.claude/skills/specialist-injection/recommend-specialist.sh +57 -0
- package/.claude/skills/sprint-execution/SKILL.md +27 -0
- package/.claude/skills/sprint-execution/execute-sprint-task.sh +59 -0
- package/.claude/skills/sprint-execution/execute-sprint.sh +65 -0
- package/.claude/skills/sprint-planner/SKILL.md +37 -0
- package/.claude/skills/sprint-planner/plan-sprint.sh +85 -0
- package/.claude/skills/standardized-error-handling/SKILL.md +56 -0
- package/.claude/skills/standardized-error-handling/capture-agent-error.sh +87 -0
- package/.claude/skills/standardized-error-handling/test-error-handling.sh +166 -0
- package/.claude/skills/task-classifier/SKILL.md +94 -0
- package/.claude/skills/task-classifier/classify-task.sh +115 -0
- package/.claude/skills/validation-templates/SKILL.md +47 -0
- package/.claude/skills/validation-templates/content.json +38 -0
- package/.claude/skills/validation-templates/data.json +38 -0
- package/.claude/skills/validation-templates/design.json +38 -0
- package/.claude/skills/validation-templates/infrastructure.json +38 -0
- package/.claude/skills/validation-templates/research.json +38 -0
- package/.claude/skills/validation-templates/software.json +38 -0
- package/.claude/skills/webapp-testing/README.md +142 -0
- package/.claude/skills/webapp-testing/SCREENSHOT_NAMING_CONVENTION.md +547 -0
- package/.claude/skills/webapp-testing/SKILL.md +877 -0
- package/.claude/skills/webapp-testing/capture-screenshot.sh +238 -0
- package/.claude/skills/webapp-testing/cfn-loop-integration.sh +265 -0
- package/.claude/skills/webapp-testing/compare-screenshots.sh +199 -0
- package/.claude/skills/webapp-testing/init-storage.sh +150 -0
- package/.claude/skills/webapp-testing/set-baseline.sh +196 -0
- package/.claude/skills/webapp-testing/test-webapp-testing.sh +233 -0
- package/.claude/spawn-pattern-examples.md +3 -3
- package/CLAUDE.md +319 -45
- package/README.md +598 -251
- package/dist/agents/agent-loader.js +146 -165
- package/dist/agents/agent-loader.js.map +1 -1
- package/dist/cli/agent-command.js +2 -0
- package/dist/cli/agent-command.js.map +1 -1
- package/dist/cli/agent-definition-parser.js +7 -0
- package/dist/cli/agent-definition-parser.js.map +1 -1
- package/dist/cli/agent-executor.js +145 -11
- package/dist/cli/agent-executor.js.map +1 -1
- package/dist/cli/agent-prompt-builder.js +81 -1
- package/dist/cli/agent-prompt-builder.js.map +1 -1
- package/dist/cli/agent-spawn.js +10 -1
- package/dist/cli/agent-spawn.js.map +1 -1
- package/dist/cli/anthropic-client.js +192 -13
- package/dist/cli/anthropic-client.js.map +1 -1
- package/dist/cli/cfn-context.js +150 -0
- package/dist/cli/cfn-context.js.map +1 -1
- package/dist/cli/cfn-fork.js +159 -0
- package/dist/cli/cfn-fork.js.map +1 -0
- package/dist/cli/cli-agent-context.js +8 -3
- package/dist/cli/cli-agent-context.js.map +1 -1
- package/dist/cli/config-manager.js +109 -91
- package/dist/cli/config-manager.js.map +1 -1
- package/dist/cli/conversation-fork.js +201 -0
- package/dist/cli/conversation-fork.js.map +1 -0
- package/dist/cli/index.js +4 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/tool-definitions.js +263 -0
- package/dist/cli/tool-definitions.js.map +1 -0
- package/dist/cli/tool-executor.js +247 -0
- package/dist/cli/tool-executor.js.map +1 -0
- package/dist/hello.js +8 -0
- package/dist/hello.js.map +1 -0
- package/package.json +14 -6
- package/scripts/README.md +68 -0
- package/scripts/cfn-intervention-example.sh +21 -0
- package/scripts/migrate-test-infrastructure.sh +40 -0
- package/scripts/validate-test-migration.sh +49 -0
- package/scripts/verify-no-secrets.sh +55 -0
- package/.claude/agents/architecture/system-architect.md.backup +0 -603
- package/.claude/agents/code-booster.md +0 -131
- package/.claude/agents/consensus/performance-benchmarker.md +0 -101
- package/.claude/agents/consensus/security-manager.md +0 -107
- package/.claude/agents/context-curator.md +0 -167
- package/.claude/agents/context-reflector.md +0 -65
- package/.claude/agents/core-agents/cfn-loop-coordinator.md +0 -134
- package/.claude/agents/core-agents/code-quality-validator.md +0 -149
- package/.claude/agents/core-agents/context-curator.md +0 -452
- package/.claude/agents/core-agents/context-reflector.md +0 -273
- package/.claude/agents/core-agents/cost-savings-cfn-loop-coordinator.md +0 -235
- package/.claude/agents/core-agents/tester.md +0 -170
- package/.claude/agents/development/backend-dev.md +0 -165
- package/.claude/agents/devops/devops-engineer.md +0 -148
- package/.claude/agents/frontend/interaction-tester.md +0 -139
- package/.claude/agents/frontend/react-frontend-engineer.md +0 -9
- package/.claude/agents/personas/accessibility-advocate-persona.md +0 -107
- package/.claude/agents/testing/production-validator.md +0 -179
- package/.claude/agents/testing/tdd-london-swarm.md +0 -209
- package/.claude/agents/testing/unit/tdd-london-swarm.md +0 -43
- package/.claude/agents/testing/validation/production-validator.md +0 -43
- package/.claude/api-configs/config-current-zai-config.env +0 -62
- package/.claude/api-configs/config-test-zai-config.env +0 -62
- package/.claude/api-configs/env-backups/before-anthropic-20251020-025404.env +0 -62
- package/.claude/api-configs/env-backups/before-restore-20251020-025431.env +0 -62
- package/.claude/skills/redis-coordination/orchestrate-cfn-loop.sh.backup-1760949407 +0 -933
- package/dist/cli/cli-agent-context.test.js +0 -451
- package/dist/cli/cli-agent-context.test.js.map +0 -1
- package/dist/coordination/fleet-manager.test.js +0 -141
- package/dist/coordination/fleet-manager.test.js.map +0 -1
- package/dist/middleware/transparency-middleware.test.js +0 -184
- package/dist/middleware/transparency-middleware.test.js.map +0 -1
- /package/.claude/agents/{core-agents → developers}/researcher.md +0 -0
- /package/.claude/agents/{consensus → specialists}/crdt-synchronizer.md +0 -0
- /package/.claude/agents/{consensus → specialists}/quorum-manager.md +0 -0
- /package/.claude/agents/{consensus → specialists}/raft-manager.md +0 -0
- /package/.claude/{agents/core-agents → agents-ignore}/coordinator.md +0 -0
- /package/.claude/{agents/core-agents/cost-savings-coordinator.md → agents-ignore/cost-savings-coordinator.md.backup} +0 -0
- /package/.claude/skills/redis-coordination/{phase4-wake-queue-test-report.md → demos/phase4-wake-queue-test-report.md} +0 -0
- /package/.claude/skills/redis-coordination/{test-bzpopmin-fix.sh → demos/test-bzpopmin-fix.sh} +0 -0
- /package/.claude/skills/redis-coordination/{test-cancel-swarm.sh → demos/test-cancel-swarm.sh} +0 -0
- /package/.claude/skills/redis-coordination/{test-dlq.sh → demos/test-dlq.sh} +0 -0
- /package/.claude/skills/redis-coordination/{test-iteration-feedback.sh → demos/test-iteration-feedback.sh} +0 -0
- /package/.claude/skills/redis-coordination/{test-priority-wake-phase4-unix.sh → demos/test-priority-wake-phase4-unix.sh} +0 -0
- /package/.claude/skills/redis-coordination/{test-priority-wake-phase4.sh → demos/test-priority-wake-phase4.sh} +0 -0
- /package/.claude/skills/redis-coordination/{test-priority-wake.sh → demos/test-priority-wake.sh} +0 -0
- /package/.claude/skills/redis-coordination/{test-quick-fix.sh → demos/test-quick-fix.sh} +0 -0
- /package/.claude/skills/redis-coordination/{test-quorum-absolute.sh → demos/test-quorum-absolute.sh} +0 -0
- /package/.claude/skills/redis-coordination/{test-quorum-fallback.sh → demos/test-quorum-fallback.sh} +0 -0
- /package/.claude/skills/redis-coordination/{test-quorum-percentage.sh → demos/test-quorum-percentage.sh} +0 -0
- /package/.claude/skills/redis-coordination/{test-quorum-with-retry.sh → demos/test-quorum-with-retry.sh} +0 -0
- /package/.claude/skills/redis-coordination/{test-quorum.sh → demos/test-quorum.sh} +0 -0
- /package/.claude/skills/redis-coordination/{test-shutdown-handling.sh → demos/test-shutdown-handling.sh} +0 -0
- /package/.claude/skills/redis-coordination/{test-shutdown.sh → demos/test-shutdown.sh} +0 -0
- /package/.claude/skills/redis-coordination/{test-utils-unix.sh → demos/test-utils-unix.sh} +0 -0
- /package/.claude/skills/redis-coordination/{test-utils.sh → demos/test-utils.sh} +0 -0
- /package/.claude/skills/redis-coordination/{test-waiting-mode.sh → demos/test-waiting-mode.sh} +0 -0
|
@@ -0,0 +1,877 @@
|
|
|
1
|
+
# Webapp Testing Skill
|
|
2
|
+
|
|
3
|
+
**Version:** 1.0.0
|
|
4
|
+
**Purpose:** Visual regression testing with screenshot capture, comparison, and baseline management
|
|
5
|
+
**Integration:** Playwright + SQLite + Redis coordination
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
This skill provides comprehensive web application testing with visual regression detection, screenshot management, and CFN Loop integration. Adapted from Anthropic's webapp-testing skill for Claude Flow Novice's distributed architecture.
|
|
12
|
+
|
|
13
|
+
### Key Features
|
|
14
|
+
|
|
15
|
+
- 📸 **Screenshot Capture** - Multi-viewport, multi-state capture with Playwright
|
|
16
|
+
- 🔍 **Visual Comparison** - Pixel-level diff detection with similarity scoring
|
|
17
|
+
- 📦 **Baseline Management** - Version-controlled reference images with audit trail
|
|
18
|
+
- 🔄 **CFN Loop Integration** - Automatic validation in Loop 2, Product Owner review
|
|
19
|
+
- 🗄️ **SQLite Storage** - Metadata persistence with efficient querying
|
|
20
|
+
- ⚡ **Redis Coordination** - Zero-token agent synchronization
|
|
21
|
+
- 🎯 **Naming Convention** - Hierarchical organization for discoverability
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Architecture
|
|
26
|
+
|
|
27
|
+
### Components
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
webapp-testing/
|
|
31
|
+
├── SKILL.md # This file
|
|
32
|
+
├── SCREENSHOT_NAMING_CONVENTION.md # Naming and storage strategy
|
|
33
|
+
├── capture-screenshot.sh # Playwright screenshot capture
|
|
34
|
+
├── compare-screenshots.sh # Visual diff generation
|
|
35
|
+
├── set-baseline.sh # Baseline management
|
|
36
|
+
├── update-baseline.sh # Baseline updates with audit
|
|
37
|
+
├── init-storage.sh # SQLite schema initialization
|
|
38
|
+
├── query-screenshots.sh # Screenshot search/retrieval
|
|
39
|
+
├── cleanup-ephemeral.sh # Remove temporary files
|
|
40
|
+
└── test-webapp-testing.sh # Skill validation tests
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Data Flow
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
1. Agent requests screenshot capture
|
|
47
|
+
↓
|
|
48
|
+
2. capture-screenshot.sh
|
|
49
|
+
- Launch Playwright
|
|
50
|
+
- Capture viewport/state
|
|
51
|
+
- Save to .screenshots/current/
|
|
52
|
+
- Store metadata in SQLite
|
|
53
|
+
- Push Redis notification
|
|
54
|
+
↓
|
|
55
|
+
3. compare-screenshots.sh (if baseline exists)
|
|
56
|
+
- Retrieve baseline from SQLite
|
|
57
|
+
- Calculate pixel diff
|
|
58
|
+
- Generate diff image (.screenshots/diffs/)
|
|
59
|
+
- Store comparison result in Redis (TTL: 1h)
|
|
60
|
+
↓
|
|
61
|
+
4. CFN Loop 2 Validator
|
|
62
|
+
- Retrieve comparison results from Redis
|
|
63
|
+
- Review visual diffs
|
|
64
|
+
- Report consensus (approve/iterate)
|
|
65
|
+
↓
|
|
66
|
+
5. Product Owner Decision
|
|
67
|
+
- If changes approved: update-baseline.sh
|
|
68
|
+
- If changes rejected: iterate Loop 3
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Usage
|
|
74
|
+
|
|
75
|
+
### 1. Initialize Storage
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Create SQLite schema and directory structure
|
|
79
|
+
./.claude/skills/webapp-testing/init-storage.sh
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Output:**
|
|
83
|
+
- SQLite table: `webapp_screenshots`
|
|
84
|
+
- Directories: `.screenshots/{baselines,current,diffs,archive}/`
|
|
85
|
+
- Redis keys initialized
|
|
86
|
+
|
|
87
|
+
### 2. Capture Screenshot
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
./.claude/skills/webapp-testing/capture-screenshot.sh \
|
|
91
|
+
--project "auth-system" \
|
|
92
|
+
--component "login-form" \
|
|
93
|
+
--viewport "1920x1080" \
|
|
94
|
+
--state "default" \
|
|
95
|
+
--variant "light-mode" \
|
|
96
|
+
--url "http://localhost:3000/login" \
|
|
97
|
+
--task-id "cfn-task-123" \
|
|
98
|
+
--agent-id "playwright-tester-456"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Parameters:**
|
|
102
|
+
|
|
103
|
+
| Parameter | Required | Description | Example |
|
|
104
|
+
|-----------|----------|-------------|---------|
|
|
105
|
+
| `--project` | Yes | Application/feature namespace | `auth-system` |
|
|
106
|
+
| `--component` | Yes | UI component or page | `login-form` |
|
|
107
|
+
| `--viewport` | Yes | Screen dimensions | `1920x1080`, `375x667` |
|
|
108
|
+
| `--state` | Yes | Interaction state | `default`, `hover`, `error` |
|
|
109
|
+
| `--variant` | No | Theme/A-B variant (default: `default`) | `light-mode`, `dark-mode` |
|
|
110
|
+
| `--url` | Yes | Page URL | `http://localhost:3000/login` |
|
|
111
|
+
| `--task-id` | No | CFN task ID | `cfn-task-123` |
|
|
112
|
+
| `--agent-id` | No | Agent identifier | `playwright-tester-456` |
|
|
113
|
+
| `--selector` | No | Specific element to capture | `.login-form` |
|
|
114
|
+
| `--wait-for` | No | Selector to wait for before capture | `.submit-button` |
|
|
115
|
+
| `--timeout` | No | Playwright timeout (ms, default: 30000) | `60000` |
|
|
116
|
+
|
|
117
|
+
**Output:**
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{
|
|
121
|
+
"screenshot_key": "auth-system/login-form/1920x1080/default/light-mode",
|
|
122
|
+
"file_path": ".screenshots/current/auth-system/login-form/1920x1080/default/light-mode_20251024143022.png",
|
|
123
|
+
"file_hash": "sha256:abc123...",
|
|
124
|
+
"viewport_actual": { "width": 1920, "height": 1080 },
|
|
125
|
+
"captured_at": 1729781422,
|
|
126
|
+
"baseline_exists": false
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### 3. Compare to Baseline
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
./.claude/skills/webapp-testing/compare-screenshots.sh \
|
|
134
|
+
--screenshot-key "auth-system/login-form/1920x1080/default/light-mode" \
|
|
135
|
+
--task-id "cfn-task-123"
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Parameters:**
|
|
139
|
+
|
|
140
|
+
| Parameter | Required | Description |
|
|
141
|
+
|-----------|----------|-------------|
|
|
142
|
+
| `--screenshot-key` | Yes | Screenshot identifier (from capture output) |
|
|
143
|
+
| `--task-id` | Yes | CFN task ID |
|
|
144
|
+
| `--threshold` | No | Similarity threshold 0-1 (default: 0.95) |
|
|
145
|
+
| `--ignore-regions` | No | JSON array of regions to ignore |
|
|
146
|
+
|
|
147
|
+
**Output:**
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"screenshot_key": "auth-system/login-form/1920x1080/default/light-mode",
|
|
152
|
+
"similarity_score": 0.987,
|
|
153
|
+
"diff_pixels": 1234,
|
|
154
|
+
"total_pixels": 2073600,
|
|
155
|
+
"diff_percentage": 0.06,
|
|
156
|
+
"status": "passed",
|
|
157
|
+
"diff_path": ".screenshots/diffs/cfn-task-123/auth-system_login-form_1920x1080_default_light-mode_diff.png",
|
|
158
|
+
"baseline_path": ".screenshots/baselines/auth-system/login-form/1920x1080/default/light-mode.png",
|
|
159
|
+
"current_path": ".screenshots/current/auth-system/login-form/1920x1080/default/light-mode_20251024143022.png"
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Status Values:**
|
|
164
|
+
- `passed` - Similarity ≥ threshold
|
|
165
|
+
- `failed` - Similarity < threshold
|
|
166
|
+
- `no-baseline` - No baseline exists for comparison
|
|
167
|
+
|
|
168
|
+
### 4. Set Baseline
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
./.claude/skills/webapp-testing/set-baseline.sh \
|
|
172
|
+
--screenshot-key "auth-system/login-form/1920x1080/default/light-mode" \
|
|
173
|
+
--reason "Initial baseline for login form component"
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Effect:**
|
|
177
|
+
1. Copy from `current/` to `baselines/` (remove timestamp)
|
|
178
|
+
2. Update SQLite: `baseline = 1`
|
|
179
|
+
3. Update Redis cache
|
|
180
|
+
4. Archive any previous baseline
|
|
181
|
+
|
|
182
|
+
### 5. Update Baseline
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
./.claude/skills/webapp-testing/update-baseline.sh \
|
|
186
|
+
--screenshot-key "auth-system/login-form/1920x1080/default/light-mode" \
|
|
187
|
+
--new-file ".screenshots/current/auth-system/login-form/1920x1080/default/light-mode_20251024150000.png" \
|
|
188
|
+
--reason "Updated button style per design review (PR #456)" \
|
|
189
|
+
--approved-by "product-owner-agent-789"
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**Effect:**
|
|
193
|
+
1. Archive old baseline to `.screenshots/archive/{YYYY-MM}/`
|
|
194
|
+
2. Copy new file to `baselines/`
|
|
195
|
+
3. Update SQLite record
|
|
196
|
+
4. Clear Redis cache
|
|
197
|
+
5. Log to audit trail
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## CFN Loop Integration
|
|
202
|
+
|
|
203
|
+
### Loop 3: Implementation
|
|
204
|
+
|
|
205
|
+
**Frontend developer agent:**
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
# Capture screenshots during development
|
|
209
|
+
for STATE in default hover error; do
|
|
210
|
+
./.claude/skills/webapp-testing/capture-screenshot.sh \
|
|
211
|
+
--project "auth-system" \
|
|
212
|
+
--component "login-form" \
|
|
213
|
+
--viewport "1920x1080" \
|
|
214
|
+
--state "$STATE" \
|
|
215
|
+
--variant "light-mode" \
|
|
216
|
+
--url "http://localhost:3000/login" \
|
|
217
|
+
--task-id "$TASK_ID" \
|
|
218
|
+
--agent-id "$AGENT_ID"
|
|
219
|
+
done
|
|
220
|
+
|
|
221
|
+
# Report confidence
|
|
222
|
+
CONFIDENCE=0.85
|
|
223
|
+
./.claude/skills/redis-coordination/invoke-waiting-mode.sh report \
|
|
224
|
+
--task-id "$TASK_ID" \
|
|
225
|
+
--agent-id "$AGENT_ID" \
|
|
226
|
+
--confidence "$CONFIDENCE" \
|
|
227
|
+
--iteration 1
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Loop 2: Validation
|
|
231
|
+
|
|
232
|
+
**Reviewer agent:**
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
# Compare all screenshots to baselines
|
|
236
|
+
COMPARISONS=$(redis-cli keys "screenshot:queue:${TASK_ID}:*" | while read KEY; do
|
|
237
|
+
SCREENSHOT_KEY=$(redis-cli get "$KEY")
|
|
238
|
+
./.claude/skills/webapp-testing/compare-screenshots.sh \
|
|
239
|
+
--screenshot-key "$SCREENSHOT_KEY" \
|
|
240
|
+
--task-id "$TASK_ID" \
|
|
241
|
+
--threshold 0.95
|
|
242
|
+
done)
|
|
243
|
+
|
|
244
|
+
# Calculate consensus
|
|
245
|
+
FAILED_COUNT=$(echo "$COMPARISONS" | jq -r 'select(.status == "failed") | .screenshot_key' | wc -l)
|
|
246
|
+
TOTAL_COUNT=$(echo "$COMPARISONS" | jq -s 'length')
|
|
247
|
+
|
|
248
|
+
if [ "$FAILED_COUNT" -eq 0 ]; then
|
|
249
|
+
CONFIDENCE=0.95
|
|
250
|
+
FEEDBACK="All visual regression tests passed"
|
|
251
|
+
else
|
|
252
|
+
CONFIDENCE=0.70
|
|
253
|
+
FEEDBACK="Visual regressions detected in $FAILED_COUNT/$TOTAL_COUNT screenshots. Review diffs in .screenshots/diffs/${TASK_ID}/"
|
|
254
|
+
fi
|
|
255
|
+
|
|
256
|
+
# Report consensus
|
|
257
|
+
./.claude/skills/redis-coordination/invoke-waiting-mode.sh report \
|
|
258
|
+
--task-id "$TASK_ID" \
|
|
259
|
+
--agent-id "$AGENT_ID" \
|
|
260
|
+
--confidence "$CONFIDENCE" \
|
|
261
|
+
--iteration 1
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Product Owner Decision
|
|
265
|
+
|
|
266
|
+
**After Loop 2 consensus ≥ 0.90:**
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
# Product Owner reviews visual diffs
|
|
270
|
+
DIFF_PATHS=$(redis-cli keys "screenshot:diff:${TASK_ID}:*" | while read KEY; do
|
|
271
|
+
redis-cli get "$KEY" | jq -r '.diff_path'
|
|
272
|
+
done)
|
|
273
|
+
|
|
274
|
+
# Decision logic
|
|
275
|
+
if [[ $(echo "$DIFF_PATHS" | wc -l) -eq 0 ]]; then
|
|
276
|
+
# No diffs, proceed
|
|
277
|
+
DECISION="PROCEED"
|
|
278
|
+
else
|
|
279
|
+
# Review diffs (Product Owner logic here)
|
|
280
|
+
# For now: if diffs exist, require approval
|
|
281
|
+
echo "Visual changes detected. Review diffs:"
|
|
282
|
+
echo "$DIFF_PATHS"
|
|
283
|
+
|
|
284
|
+
# Simulate approval (in production, this would be manual review)
|
|
285
|
+
DECISION="ITERATE" # or "PROCEED" after approval
|
|
286
|
+
fi
|
|
287
|
+
|
|
288
|
+
# If approved, update baselines
|
|
289
|
+
if [ "$DECISION" = "PROCEED" ]; then
|
|
290
|
+
redis-cli keys "screenshot:diff:${TASK_ID}:*" | while read KEY; do
|
|
291
|
+
SCREENSHOT_KEY=$(echo "$KEY" | sed 's/screenshot:diff:[^:]*://')
|
|
292
|
+
CURRENT_FILE=$(redis-cli get "$KEY" | jq -r '.current_path')
|
|
293
|
+
|
|
294
|
+
./.claude/skills/webapp-testing/update-baseline.sh \
|
|
295
|
+
--screenshot-key "$SCREENSHOT_KEY" \
|
|
296
|
+
--new-file "$CURRENT_FILE" \
|
|
297
|
+
--reason "Approved visual changes from task $TASK_ID" \
|
|
298
|
+
--approved-by "product-owner"
|
|
299
|
+
done
|
|
300
|
+
fi
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Redis Coordination
|
|
306
|
+
|
|
307
|
+
### Keys and Patterns
|
|
308
|
+
|
|
309
|
+
**Screenshot Capture Queue:**
|
|
310
|
+
|
|
311
|
+
```bash
|
|
312
|
+
# Add screenshot to capture queue
|
|
313
|
+
redis-cli lpush "screenshot:queue:${TASK_ID}" \
|
|
314
|
+
"auth-system/login-form/1920x1080/default/light-mode"
|
|
315
|
+
|
|
316
|
+
# Wait for captures to complete (orchestrator)
|
|
317
|
+
redis-cli blpop "screenshot:queue:${TASK_ID}:done" 0
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
**Comparison Results (TTL: 1 hour):**
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
# Store comparison result
|
|
324
|
+
redis-cli setex "screenshot:diff:${TASK_ID}:${SCREENSHOT_KEY}" 3600 \
|
|
325
|
+
'{"similarity_score": 0.987, "status": "passed", "diff_path": "..."}'
|
|
326
|
+
|
|
327
|
+
# Retrieve all comparisons for task
|
|
328
|
+
redis-cli keys "screenshot:diff:${TASK_ID}:*" | while read KEY; do
|
|
329
|
+
redis-cli get "$KEY"
|
|
330
|
+
done | jq -s '.'
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**Baseline Cache (TTL: 24 hours):**
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
# Cache baseline file hash
|
|
337
|
+
redis-cli setex "screenshot:baseline:${SCREENSHOT_KEY}" 86400 \
|
|
338
|
+
"sha256:abc123..."
|
|
339
|
+
|
|
340
|
+
# Retrieve cached hash
|
|
341
|
+
CACHED_HASH=$(redis-cli get "screenshot:baseline:${SCREENSHOT_KEY}")
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
**Agent Coordination:**
|
|
345
|
+
|
|
346
|
+
```bash
|
|
347
|
+
# Signal screenshot capture complete
|
|
348
|
+
redis-cli lpush "swarm:${TASK_ID}:${AGENT_ID}:screenshot-complete" "1"
|
|
349
|
+
|
|
350
|
+
# Wait for all agents to complete captures
|
|
351
|
+
redis-cli blpop "swarm:${TASK_ID}:all-screenshots-complete" 0
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## SQLite Schema
|
|
357
|
+
|
|
358
|
+
### Table: `webapp_screenshots`
|
|
359
|
+
|
|
360
|
+
```sql
|
|
361
|
+
CREATE TABLE IF NOT EXISTS webapp_screenshots (
|
|
362
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
363
|
+
screenshot_key TEXT UNIQUE NOT NULL,
|
|
364
|
+
project TEXT NOT NULL,
|
|
365
|
+
component TEXT NOT NULL,
|
|
366
|
+
viewport TEXT NOT NULL,
|
|
367
|
+
state TEXT NOT NULL,
|
|
368
|
+
variant TEXT NOT NULL DEFAULT 'default',
|
|
369
|
+
file_path TEXT NOT NULL,
|
|
370
|
+
file_hash TEXT NOT NULL,
|
|
371
|
+
baseline BOOLEAN DEFAULT 0,
|
|
372
|
+
captured_at INTEGER NOT NULL,
|
|
373
|
+
task_id TEXT,
|
|
374
|
+
agent_id TEXT,
|
|
375
|
+
metadata TEXT, -- JSON
|
|
376
|
+
UNIQUE(project, component, viewport, state, variant, baseline)
|
|
377
|
+
);
|
|
378
|
+
|
|
379
|
+
CREATE INDEX idx_baseline ON webapp_screenshots(project, component, viewport, state, variant, baseline);
|
|
380
|
+
CREATE INDEX idx_task ON webapp_screenshots(task_id);
|
|
381
|
+
CREATE INDEX idx_component ON webapp_screenshots(project, component);
|
|
382
|
+
CREATE INDEX idx_captured ON webapp_screenshots(captured_at DESC);
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### Table: `screenshot_audit_log`
|
|
386
|
+
|
|
387
|
+
```sql
|
|
388
|
+
CREATE TABLE IF NOT EXISTS screenshot_audit_log (
|
|
389
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
390
|
+
screenshot_key TEXT NOT NULL,
|
|
391
|
+
action TEXT NOT NULL, -- 'created', 'updated', 'archived', 'deleted'
|
|
392
|
+
reason TEXT,
|
|
393
|
+
old_file_hash TEXT,
|
|
394
|
+
new_file_hash TEXT,
|
|
395
|
+
approved_by TEXT,
|
|
396
|
+
created_at INTEGER NOT NULL,
|
|
397
|
+
task_id TEXT,
|
|
398
|
+
metadata TEXT -- JSON
|
|
399
|
+
);
|
|
400
|
+
|
|
401
|
+
CREATE INDEX idx_audit_screenshot ON screenshot_audit_log(screenshot_key);
|
|
402
|
+
CREATE INDEX idx_audit_created ON screenshot_audit_log(created_at DESC);
|
|
403
|
+
CREATE INDEX idx_audit_task ON screenshot_audit_log(task_id);
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## Skill Scripts
|
|
409
|
+
|
|
410
|
+
### `capture-screenshot.sh`
|
|
411
|
+
|
|
412
|
+
**Purpose:** Capture screenshot with Playwright
|
|
413
|
+
|
|
414
|
+
**Implementation:**
|
|
415
|
+
|
|
416
|
+
```bash
|
|
417
|
+
#!/bin/bash
|
|
418
|
+
set -e
|
|
419
|
+
|
|
420
|
+
# Parse arguments
|
|
421
|
+
while [[ $# -gt 0 ]]; do
|
|
422
|
+
case $1 in
|
|
423
|
+
--project) PROJECT="$2"; shift 2 ;;
|
|
424
|
+
--component) COMPONENT="$2"; shift 2 ;;
|
|
425
|
+
--viewport) VIEWPORT="$2"; shift 2 ;;
|
|
426
|
+
--state) STATE="$2"; shift 2 ;;
|
|
427
|
+
--variant) VARIANT="${2:-default}"; shift 2 ;;
|
|
428
|
+
--url) URL="$2"; shift 2 ;;
|
|
429
|
+
--task-id) TASK_ID="$2"; shift 2 ;;
|
|
430
|
+
--agent-id) AGENT_ID="$2"; shift 2 ;;
|
|
431
|
+
--selector) SELECTOR="$2"; shift 2 ;;
|
|
432
|
+
--wait-for) WAIT_FOR="$2"; shift 2 ;;
|
|
433
|
+
--timeout) TIMEOUT="${2:-30000}"; shift 2 ;;
|
|
434
|
+
*) echo "Unknown parameter: $1"; exit 1 ;;
|
|
435
|
+
esac
|
|
436
|
+
done
|
|
437
|
+
|
|
438
|
+
# Validate required parameters
|
|
439
|
+
if [ -z "$PROJECT" ] || [ -z "$COMPONENT" ] || [ -z "$VIEWPORT" ] || [ -z "$STATE" ] || [ -z "$URL" ]; then
|
|
440
|
+
echo "Error: Missing required parameters"
|
|
441
|
+
echo "Usage: $0 --project <project> --component <component> --viewport <viewport> --state <state> --url <url>"
|
|
442
|
+
exit 1
|
|
443
|
+
fi
|
|
444
|
+
|
|
445
|
+
# Generate screenshot key and paths
|
|
446
|
+
VARIANT="${VARIANT:-default}"
|
|
447
|
+
TIMESTAMP=$(date +%Y%m%d%H%M%S)
|
|
448
|
+
SCREENSHOT_KEY="${PROJECT}/${COMPONENT}/${VIEWPORT}/${STATE}/${VARIANT}"
|
|
449
|
+
OUTPUT_DIR=".screenshots/current/${PROJECT}/${COMPONENT}/${VIEWPORT}/${STATE}"
|
|
450
|
+
OUTPUT_FILE="${OUTPUT_DIR}/${VARIANT}_${TIMESTAMP}.png"
|
|
451
|
+
|
|
452
|
+
mkdir -p "$OUTPUT_DIR"
|
|
453
|
+
|
|
454
|
+
# Parse viewport dimensions
|
|
455
|
+
IFS='x' read -r WIDTH HEIGHT <<< "$VIEWPORT"
|
|
456
|
+
|
|
457
|
+
# Capture screenshot with Playwright (inline Node.js script)
|
|
458
|
+
node -e "
|
|
459
|
+
const { chromium } = require('playwright');
|
|
460
|
+
|
|
461
|
+
(async () => {
|
|
462
|
+
const browser = await chromium.launch();
|
|
463
|
+
const context = await browser.newContext({
|
|
464
|
+
viewport: { width: ${WIDTH}, height: ${HEIGHT} }
|
|
465
|
+
});
|
|
466
|
+
const page = await context.newPage();
|
|
467
|
+
|
|
468
|
+
await page.goto('${URL}', { waitUntil: 'networkidle', timeout: ${TIMEOUT:-30000} });
|
|
469
|
+
|
|
470
|
+
${WAIT_FOR:+await page.waitForSelector('${WAIT_FOR}', { timeout: ${TIMEOUT:-30000} });}
|
|
471
|
+
|
|
472
|
+
// Simulate state if needed
|
|
473
|
+
${SELECTOR:+const element = await page.locator('${SELECTOR}');}
|
|
474
|
+
if ('${STATE}' === 'hover') {
|
|
475
|
+
await ${SELECTOR:+element}${SELECTOR:-.locator('body')}.hover();
|
|
476
|
+
} else if ('${STATE}' === 'focus') {
|
|
477
|
+
await ${SELECTOR:+element}${SELECTOR:-.locator('input').first()}.focus();
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
await page.screenshot({
|
|
481
|
+
path: '${OUTPUT_FILE}',
|
|
482
|
+
${SELECTOR:+clip: await ${SELECTOR:+element}.boundingBox(),}
|
|
483
|
+
fullPage: ${SELECTOR:+false}${SELECTOR:-true}
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
await browser.close();
|
|
487
|
+
|
|
488
|
+
console.log(JSON.stringify({
|
|
489
|
+
screenshot_key: '${SCREENSHOT_KEY}',
|
|
490
|
+
file_path: '${OUTPUT_FILE}',
|
|
491
|
+
viewport_actual: { width: ${WIDTH}, height: ${HEIGHT} },
|
|
492
|
+
captured_at: Math.floor(Date.now() / 1000)
|
|
493
|
+
}));
|
|
494
|
+
})();
|
|
495
|
+
"
|
|
496
|
+
|
|
497
|
+
# Calculate file hash
|
|
498
|
+
FILE_HASH=$(sha256sum "$OUTPUT_FILE" | awk '{print $1}')
|
|
499
|
+
|
|
500
|
+
# Check if baseline exists
|
|
501
|
+
BASELINE_EXISTS=$(sqlite3 ~/.claude/memory/adaptive-context.db \
|
|
502
|
+
"SELECT COUNT(*) FROM webapp_screenshots WHERE screenshot_key = '${SCREENSHOT_KEY}' AND baseline = 1")
|
|
503
|
+
|
|
504
|
+
# Store metadata in SQLite
|
|
505
|
+
METADATA=$(cat <<EOF
|
|
506
|
+
{
|
|
507
|
+
"browser": "chromium",
|
|
508
|
+
"viewport_actual": { "width": ${WIDTH}, "height": ${HEIGHT} },
|
|
509
|
+
"url": "${URL}",
|
|
510
|
+
"task_id": "${TASK_ID}",
|
|
511
|
+
"agent_id": "${AGENT_ID}",
|
|
512
|
+
"git_commit": "$(git rev-parse --short HEAD 2>/dev/null || echo 'unknown')",
|
|
513
|
+
"git_branch": "$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown')"
|
|
514
|
+
}
|
|
515
|
+
EOF
|
|
516
|
+
)
|
|
517
|
+
|
|
518
|
+
sqlite3 ~/.claude/memory/adaptive-context.db <<EOF
|
|
519
|
+
INSERT INTO webapp_screenshots (
|
|
520
|
+
screenshot_key, project, component, viewport, state, variant,
|
|
521
|
+
file_path, file_hash, baseline, captured_at, task_id, agent_id, metadata
|
|
522
|
+
) VALUES (
|
|
523
|
+
'${SCREENSHOT_KEY}', '${PROJECT}', '${COMPONENT}', '${VIEWPORT}', '${STATE}', '${VARIANT}',
|
|
524
|
+
'${OUTPUT_FILE}', 'sha256:${FILE_HASH}', 0, $(date +%s), '${TASK_ID}', '${AGENT_ID}', '${METADATA}'
|
|
525
|
+
);
|
|
526
|
+
EOF
|
|
527
|
+
|
|
528
|
+
# Push to Redis queue (for orchestrator tracking)
|
|
529
|
+
if [ -n "$TASK_ID" ]; then
|
|
530
|
+
redis-cli lpush "screenshot:queue:${TASK_ID}" "$SCREENSHOT_KEY" > /dev/null
|
|
531
|
+
fi
|
|
532
|
+
|
|
533
|
+
# Output result
|
|
534
|
+
cat <<EOF
|
|
535
|
+
{
|
|
536
|
+
"screenshot_key": "${SCREENSHOT_KEY}",
|
|
537
|
+
"file_path": "${OUTPUT_FILE}",
|
|
538
|
+
"file_hash": "sha256:${FILE_HASH}",
|
|
539
|
+
"viewport_actual": { "width": ${WIDTH}, "height": ${HEIGHT} },
|
|
540
|
+
"captured_at": $(date +%s),
|
|
541
|
+
"baseline_exists": $([[ "$BASELINE_EXISTS" -eq 1 ]] && echo "true" || echo "false")
|
|
542
|
+
}
|
|
543
|
+
EOF
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
### `compare-screenshots.sh`
|
|
547
|
+
|
|
548
|
+
**Purpose:** Compare captured screenshot to baseline
|
|
549
|
+
|
|
550
|
+
**Implementation:**
|
|
551
|
+
|
|
552
|
+
```bash
|
|
553
|
+
#!/bin/bash
|
|
554
|
+
set -e
|
|
555
|
+
|
|
556
|
+
# Parse arguments
|
|
557
|
+
while [[ $# -gt 0 ]]; do
|
|
558
|
+
case $1 in
|
|
559
|
+
--screenshot-key) SCREENSHOT_KEY="$2"; shift 2 ;;
|
|
560
|
+
--task-id) TASK_ID="$2"; shift 2 ;;
|
|
561
|
+
--threshold) THRESHOLD="${2:-0.95}"; shift 2 ;;
|
|
562
|
+
*) echo "Unknown parameter: $1"; exit 1 ;;
|
|
563
|
+
esac
|
|
564
|
+
done
|
|
565
|
+
|
|
566
|
+
# Validate
|
|
567
|
+
if [ -z "$SCREENSHOT_KEY" ] || [ -z "$TASK_ID" ]; then
|
|
568
|
+
echo "Error: Missing required parameters"
|
|
569
|
+
exit 1
|
|
570
|
+
fi
|
|
571
|
+
|
|
572
|
+
# Get baseline and current paths from SQLite
|
|
573
|
+
BASELINE_PATH=$(sqlite3 ~/.claude/memory/adaptive-context.db \
|
|
574
|
+
"SELECT file_path FROM webapp_screenshots WHERE screenshot_key = '${SCREENSHOT_KEY}' AND baseline = 1")
|
|
575
|
+
|
|
576
|
+
CURRENT_PATH=$(sqlite3 ~/.claude/memory/adaptive-context.db \
|
|
577
|
+
"SELECT file_path FROM webapp_screenshots WHERE screenshot_key = '${SCREENSHOT_KEY}' AND baseline = 0 ORDER BY captured_at DESC LIMIT 1")
|
|
578
|
+
|
|
579
|
+
if [ -z "$BASELINE_PATH" ]; then
|
|
580
|
+
# No baseline exists
|
|
581
|
+
echo '{"status": "no-baseline", "screenshot_key": "'$SCREENSHOT_KEY'"}'
|
|
582
|
+
exit 0
|
|
583
|
+
fi
|
|
584
|
+
|
|
585
|
+
if [ -z "$CURRENT_PATH" ]; then
|
|
586
|
+
echo "Error: No current screenshot found for key: $SCREENSHOT_KEY"
|
|
587
|
+
exit 1
|
|
588
|
+
fi
|
|
589
|
+
|
|
590
|
+
# Generate diff path
|
|
591
|
+
DIFF_DIR=".screenshots/diffs/${TASK_ID}"
|
|
592
|
+
mkdir -p "$DIFF_DIR"
|
|
593
|
+
SCREENSHOT_KEY_FLAT=$(echo "$SCREENSHOT_KEY" | tr '/' '_')
|
|
594
|
+
DIFF_PATH="${DIFF_DIR}/${SCREENSHOT_KEY_FLAT}_diff.png"
|
|
595
|
+
|
|
596
|
+
# Compare using pixelmatch (Node.js)
|
|
597
|
+
COMPARISON=$(node -e "
|
|
598
|
+
const fs = require('fs');
|
|
599
|
+
const PNG = require('pngjs').PNG;
|
|
600
|
+
const pixelmatch = require('pixelmatch');
|
|
601
|
+
|
|
602
|
+
const baseline = PNG.sync.read(fs.readFileSync('${BASELINE_PATH}'));
|
|
603
|
+
const current = PNG.sync.read(fs.readFileSync('${CURRENT_PATH}'));
|
|
604
|
+
const { width, height } = baseline;
|
|
605
|
+
const diff = new PNG({ width, height });
|
|
606
|
+
|
|
607
|
+
const numDiffPixels = pixelmatch(
|
|
608
|
+
baseline.data, current.data, diff.data, width, height,
|
|
609
|
+
{ threshold: 0.1 }
|
|
610
|
+
);
|
|
611
|
+
|
|
612
|
+
fs.writeFileSync('${DIFF_PATH}', PNG.sync.write(diff));
|
|
613
|
+
|
|
614
|
+
const totalPixels = width * height;
|
|
615
|
+
const diffPercentage = (numDiffPixels / totalPixels) * 100;
|
|
616
|
+
const similarityScore = 1 - (numDiffPixels / totalPixels);
|
|
617
|
+
const status = similarityScore >= ${THRESHOLD} ? 'passed' : 'failed';
|
|
618
|
+
|
|
619
|
+
console.log(JSON.stringify({
|
|
620
|
+
screenshot_key: '${SCREENSHOT_KEY}',
|
|
621
|
+
similarity_score: similarityScore.toFixed(4),
|
|
622
|
+
diff_pixels: numDiffPixels,
|
|
623
|
+
total_pixels: totalPixels,
|
|
624
|
+
diff_percentage: diffPercentage.toFixed(2),
|
|
625
|
+
status: status,
|
|
626
|
+
diff_path: '${DIFF_PATH}',
|
|
627
|
+
baseline_path: '${BASELINE_PATH}',
|
|
628
|
+
current_path: '${CURRENT_PATH}'
|
|
629
|
+
}));
|
|
630
|
+
")
|
|
631
|
+
|
|
632
|
+
# Store in Redis (TTL: 1 hour)
|
|
633
|
+
redis-cli setex "screenshot:diff:${TASK_ID}:${SCREENSHOT_KEY}" 3600 "$COMPARISON" > /dev/null
|
|
634
|
+
|
|
635
|
+
# Output result
|
|
636
|
+
echo "$COMPARISON"
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
### `set-baseline.sh`
|
|
640
|
+
|
|
641
|
+
**Purpose:** Set a screenshot as baseline
|
|
642
|
+
|
|
643
|
+
**Implementation:**
|
|
644
|
+
|
|
645
|
+
```bash
|
|
646
|
+
#!/bin/bash
|
|
647
|
+
set -e
|
|
648
|
+
|
|
649
|
+
# Parse arguments
|
|
650
|
+
while [[ $# -gt 0 ]]; do
|
|
651
|
+
case $1 in
|
|
652
|
+
--screenshot-key) SCREENSHOT_KEY="$2"; shift 2 ;;
|
|
653
|
+
--reason) REASON="$2"; shift 2 ;;
|
|
654
|
+
*) echo "Unknown parameter: $1"; exit 1 ;;
|
|
655
|
+
esac
|
|
656
|
+
done
|
|
657
|
+
|
|
658
|
+
# Validate
|
|
659
|
+
if [ -z "$SCREENSHOT_KEY" ]; then
|
|
660
|
+
echo "Error: Missing --screenshot-key"
|
|
661
|
+
exit 1
|
|
662
|
+
fi
|
|
663
|
+
|
|
664
|
+
# Parse screenshot key
|
|
665
|
+
IFS='/' read -r PROJECT COMPONENT VIEWPORT STATE VARIANT <<< "$SCREENSHOT_KEY"
|
|
666
|
+
|
|
667
|
+
# Get current screenshot from SQLite
|
|
668
|
+
CURRENT_PATH=$(sqlite3 ~/.claude/memory/adaptive-context.db \
|
|
669
|
+
"SELECT file_path FROM webapp_screenshots WHERE screenshot_key = '${SCREENSHOT_KEY}' AND baseline = 0 ORDER BY captured_at DESC LIMIT 1")
|
|
670
|
+
|
|
671
|
+
if [ -z "$CURRENT_PATH" ]; then
|
|
672
|
+
echo "Error: No current screenshot found for key: $SCREENSHOT_KEY"
|
|
673
|
+
exit 1
|
|
674
|
+
fi
|
|
675
|
+
|
|
676
|
+
# Create baseline directory
|
|
677
|
+
BASELINE_DIR=".screenshots/baselines/${PROJECT}/${COMPONENT}/${VIEWPORT}/${STATE}"
|
|
678
|
+
mkdir -p "$BASELINE_DIR"
|
|
679
|
+
BASELINE_PATH="${BASELINE_DIR}/${VARIANT}.png"
|
|
680
|
+
|
|
681
|
+
# Copy to baselines (remove timestamp from filename)
|
|
682
|
+
cp "$CURRENT_PATH" "$BASELINE_PATH"
|
|
683
|
+
|
|
684
|
+
# Get file hash
|
|
685
|
+
FILE_HASH=$(sha256sum "$BASELINE_PATH" | awk '{print $1}')
|
|
686
|
+
|
|
687
|
+
# Update SQLite (set as baseline)
|
|
688
|
+
sqlite3 ~/.claude/memory/adaptive-context.db <<EOF
|
|
689
|
+
INSERT OR REPLACE INTO webapp_screenshots (
|
|
690
|
+
screenshot_key, project, component, viewport, state, variant,
|
|
691
|
+
file_path, file_hash, baseline, captured_at, task_id, agent_id, metadata
|
|
692
|
+
)
|
|
693
|
+
SELECT
|
|
694
|
+
screenshot_key, project, component, viewport, state, variant,
|
|
695
|
+
'${BASELINE_PATH}', 'sha256:${FILE_HASH}', 1, $(date +%s), task_id, agent_id, metadata
|
|
696
|
+
FROM webapp_screenshots
|
|
697
|
+
WHERE screenshot_key = '${SCREENSHOT_KEY}' AND baseline = 0
|
|
698
|
+
ORDER BY captured_at DESC LIMIT 1;
|
|
699
|
+
|
|
700
|
+
-- Audit log
|
|
701
|
+
INSERT INTO screenshot_audit_log (
|
|
702
|
+
screenshot_key, action, reason, new_file_hash, created_at
|
|
703
|
+
) VALUES (
|
|
704
|
+
'${SCREENSHOT_KEY}', 'created', '${REASON}', 'sha256:${FILE_HASH}', $(date +%s)
|
|
705
|
+
);
|
|
706
|
+
EOF
|
|
707
|
+
|
|
708
|
+
# Clear Redis cache
|
|
709
|
+
redis-cli del "screenshot:baseline:${SCREENSHOT_KEY}" > /dev/null
|
|
710
|
+
|
|
711
|
+
echo '{"status": "baseline-set", "screenshot_key": "'$SCREENSHOT_KEY'", "baseline_path": "'$BASELINE_PATH'"}'
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
---
|
|
715
|
+
|
|
716
|
+
## Configuration
|
|
717
|
+
|
|
718
|
+
### `.claude/skills/webapp-testing/config.json`
|
|
719
|
+
|
|
720
|
+
```json
|
|
721
|
+
{
|
|
722
|
+
"storage": {
|
|
723
|
+
"baselines_dir": ".screenshots/baselines",
|
|
724
|
+
"current_dir": ".screenshots/current",
|
|
725
|
+
"diffs_dir": ".screenshots/diffs",
|
|
726
|
+
"archive_dir": ".screenshots/archive",
|
|
727
|
+
"db_path": "~/.claude/memory/adaptive-context.db"
|
|
728
|
+
},
|
|
729
|
+
"defaults": {
|
|
730
|
+
"viewport": "1920x1080",
|
|
731
|
+
"threshold": 0.95,
|
|
732
|
+
"timeout": 30000,
|
|
733
|
+
"variant": "default"
|
|
734
|
+
},
|
|
735
|
+
"viewports": {
|
|
736
|
+
"desktop": "1920x1080",
|
|
737
|
+
"laptop": "1366x768",
|
|
738
|
+
"tablet": "768x1024",
|
|
739
|
+
"mobile": "375x667",
|
|
740
|
+
"mobile-large": "390x844"
|
|
741
|
+
},
|
|
742
|
+
"redis": {
|
|
743
|
+
"ttl_comparison": 3600,
|
|
744
|
+
"ttl_baseline_cache": 86400
|
|
745
|
+
},
|
|
746
|
+
"cleanup": {
|
|
747
|
+
"archive_retention_days": 90,
|
|
748
|
+
"current_retention_hours": 24,
|
|
749
|
+
"diff_retention_hours": 48
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
---
|
|
755
|
+
|
|
756
|
+
## Best Practices
|
|
757
|
+
|
|
758
|
+
### 1. Screenshot Naming
|
|
759
|
+
|
|
760
|
+
✅ **DO:**
|
|
761
|
+
- Use consistent project/component names
|
|
762
|
+
- Follow kebab-case convention
|
|
763
|
+
- Include all relevant states
|
|
764
|
+
|
|
765
|
+
❌ **DON'T:**
|
|
766
|
+
- Use spaces or special characters
|
|
767
|
+
- Mix naming conventions
|
|
768
|
+
- Skip variant specification
|
|
769
|
+
|
|
770
|
+
### 2. Baseline Management
|
|
771
|
+
|
|
772
|
+
✅ **DO:**
|
|
773
|
+
- Review visual changes before updating baselines
|
|
774
|
+
- Document baseline change reasons
|
|
775
|
+
- Version control baselines directory
|
|
776
|
+
- Archive old baselines before updates
|
|
777
|
+
|
|
778
|
+
❌ **DON'T:**
|
|
779
|
+
- Auto-approve baseline changes without review
|
|
780
|
+
- Update baselines without audit trail
|
|
781
|
+
- Delete old baselines immediately
|
|
782
|
+
- Skip Product Owner approval for visual changes
|
|
783
|
+
|
|
784
|
+
### 3. CFN Loop Integration
|
|
785
|
+
|
|
786
|
+
✅ **DO:**
|
|
787
|
+
- Capture screenshots in Loop 3 (implementation)
|
|
788
|
+
- Compare in Loop 2 (validation)
|
|
789
|
+
- Require Product Owner approval for baseline updates
|
|
790
|
+
- Store comparison results in Redis for validator review
|
|
791
|
+
|
|
792
|
+
❌ **DON'T:**
|
|
793
|
+
- Update baselines in Loop 3 without validation
|
|
794
|
+
- Skip visual regression checks in Loop 2
|
|
795
|
+
- Proceed with failed visual tests without iteration
|
|
796
|
+
- Mix capture and comparison in same loop
|
|
797
|
+
|
|
798
|
+
### 4. Performance
|
|
799
|
+
|
|
800
|
+
✅ **DO:**
|
|
801
|
+
- Compress screenshots (pngquant, oxipng)
|
|
802
|
+
- Set appropriate Redis TTLs
|
|
803
|
+
- Clean up ephemeral files regularly
|
|
804
|
+
- Use Redis BLPOP for zero-token coordination
|
|
805
|
+
|
|
806
|
+
❌ **DON'T:**
|
|
807
|
+
- Store uncompressed screenshots
|
|
808
|
+
- Keep all test runs indefinitely
|
|
809
|
+
- Poll Redis for completion
|
|
810
|
+
- Duplicate baselines across tasks
|
|
811
|
+
|
|
812
|
+
---
|
|
813
|
+
|
|
814
|
+
## Troubleshooting
|
|
815
|
+
|
|
816
|
+
### Playwright Installation
|
|
817
|
+
|
|
818
|
+
```bash
|
|
819
|
+
# Install Playwright browsers
|
|
820
|
+
npx playwright install chromium
|
|
821
|
+
|
|
822
|
+
# Verify installation
|
|
823
|
+
npx playwright --version
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
### SQLite Schema Issues
|
|
827
|
+
|
|
828
|
+
```bash
|
|
829
|
+
# Reinitialize schema
|
|
830
|
+
./.claude/skills/webapp-testing/init-storage.sh --force
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
### Missing Screenshots
|
|
834
|
+
|
|
835
|
+
```bash
|
|
836
|
+
# Query for screenshot
|
|
837
|
+
sqlite3 ~/.claude/memory/adaptive-context.db \
|
|
838
|
+
"SELECT * FROM webapp_screenshots WHERE screenshot_key = 'your-key-here'"
|
|
839
|
+
|
|
840
|
+
# Check filesystem
|
|
841
|
+
ls -lah .screenshots/current/your-project/your-component/
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
### Comparison Failures
|
|
845
|
+
|
|
846
|
+
```bash
|
|
847
|
+
# Check if baseline exists
|
|
848
|
+
sqlite3 ~/.claude/memory/adaptive-context.db \
|
|
849
|
+
"SELECT file_path FROM webapp_screenshots WHERE screenshot_key = 'your-key' AND baseline = 1"
|
|
850
|
+
|
|
851
|
+
# Manually set baseline
|
|
852
|
+
./.claude/skills/webapp-testing/set-baseline.sh \
|
|
853
|
+
--screenshot-key "your-key" \
|
|
854
|
+
--reason "Initial baseline"
|
|
855
|
+
```
|
|
856
|
+
|
|
857
|
+
---
|
|
858
|
+
|
|
859
|
+
## Future Enhancements
|
|
860
|
+
|
|
861
|
+
### Phase 2
|
|
862
|
+
- [ ] Multi-viewport capture (single command)
|
|
863
|
+
- [ ] Animation frame capture (GIF/video)
|
|
864
|
+
- [ ] Component isolation (auto-crop)
|
|
865
|
+
- [ ] Playwright trace integration
|
|
866
|
+
|
|
867
|
+
### Phase 3
|
|
868
|
+
- [ ] ML-based anomaly detection
|
|
869
|
+
- [ ] Smart diff highlighting
|
|
870
|
+
- [ ] Figma → screenshot generation
|
|
871
|
+
- [ ] Natural language screenshot queries
|
|
872
|
+
|
|
873
|
+
---
|
|
874
|
+
|
|
875
|
+
**Status:** Ready for Implementation
|
|
876
|
+
**Dependencies:** Playwright, pngjs, pixelmatch, SQLite, Redis
|
|
877
|
+
**Documentation:** See `SCREENSHOT_NAMING_CONVENTION.md`
|