pi-dev-team 0.2.0
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/LICENSE +21 -0
- package/PORTING.md +134 -0
- package/README.md +207 -0
- package/UPSTREAM.json +64 -0
- package/agents/Explore.md +15 -0
- package/agents/a11y-review.md +118 -0
- package/agents/adr-author.md +70 -0
- package/agents/ai-provenance-review.md +120 -0
- package/agents/angular-reactivity-review.md +95 -0
- package/agents/arch-review.md +135 -0
- package/agents/architect.md +78 -0
- package/agents/autoship-batch-proposer.md +69 -0
- package/agents/claude-setup-review.md +136 -0
- package/agents/codebase-recon.md +184 -0
- package/agents/component-architecture-review.md +119 -0
- package/agents/concurrency-review.md +109 -0
- package/agents/correctness-review.md +290 -0
- package/agents/data-flow-tracer.md +120 -0
- package/agents/doc-review.md +165 -0
- package/agents/domain-review.md +136 -0
- package/agents/general-purpose.md +10 -0
- package/agents/gherkin-quality-critic.md +113 -0
- package/agents/js-fp-review.md +114 -0
- package/agents/mutation-kill.md +684 -0
- package/agents/naming-review.md +142 -0
- package/agents/orchestrator.md +339 -0
- package/agents/performance-review.md +105 -0
- package/agents/plan-review-acceptance.md +115 -0
- package/agents/plan-review-design.md +90 -0
- package/agents/plan-review-parallelization.md +84 -0
- package/agents/plan-review-strategic.md +96 -0
- package/agents/plan-review-ux.md +110 -0
- package/agents/platform-engineer.md +64 -0
- package/agents/product-manager.md +68 -0
- package/agents/progress-guardian.md +79 -0
- package/agents/qa-engineer.md +289 -0
- package/agents/quality-reviewer.md +132 -0
- package/agents/react-reactivity-review.md +102 -0
- package/agents/refactor-opportunity-review.md +128 -0
- package/agents/security-engineer.md +60 -0
- package/agents/security-review.md +218 -0
- package/agents/session-analysis.md +95 -0
- package/agents/software-engineer.md +105 -0
- package/agents/spec-compliance-review.md +100 -0
- package/agents/spec-reviewer.md +114 -0
- package/agents/structure-review.md +146 -0
- package/agents/tech-writer.md +84 -0
- package/agents/test-review.md +246 -0
- package/agents/test-smell-review.md +188 -0
- package/agents/token-efficiency-review.md +139 -0
- package/agents/ui-ux-designer.md +54 -0
- package/agents/vue-reactivity-review.md +95 -0
- package/bin/__pycache__/claudecpython-314.pyc +0 -0
- package/bin/claude +258 -0
- package/docs/upstream/.pages +1 -0
- package/docs/upstream/CHANGELOG.md +2586 -0
- package/docs/upstream/README.md +155 -0
- package/docs/upstream/agent-architecture.md +214 -0
- package/docs/upstream/agent_info.md +187 -0
- package/docs/upstream/artifact-migration.md +124 -0
- package/docs/upstream/code-intelligence-nudge.md +149 -0
- package/docs/upstream/code-review-process.md +294 -0
- package/docs/upstream/concurrent-use.md +73 -0
- package/docs/upstream/context-management.md +111 -0
- package/docs/upstream/developer-notes.md +280 -0
- package/docs/upstream/diagrams/architecture-overview.svg +101 -0
- package/docs/upstream/diagrams/review-dispatch.svg +139 -0
- package/docs/upstream/diagrams/team-agents.svg +128 -0
- package/docs/upstream/diagrams/test-improve-flow.svg +166 -0
- package/docs/upstream/diagrams/workflow-linear.svg +66 -0
- package/docs/upstream/diagrams/workflow-three-phase.svg +200 -0
- package/docs/upstream/eval-maintenance.md +95 -0
- package/docs/upstream/eval-running-guide.md +147 -0
- package/docs/upstream/eval-system.md +291 -0
- package/docs/upstream/session-review-oss-complements.md +75 -0
- package/docs/upstream/session-review.md +212 -0
- package/docs/upstream/skills.md +188 -0
- package/docs/upstream/team-structure.md +21 -0
- package/docs/upstream/telemetry-ci-access.md +129 -0
- package/docs/upstream/telemetry-repo-security.md +120 -0
- package/docs/upstream/test-evaluation.md +277 -0
- package/docs/upstream/test-improve.md +154 -0
- package/docs/upstream/triage-workflow.md +282 -0
- package/docs/upstream/workflows.md +289 -0
- package/extensions/dev-team/index.ts +539 -0
- package/extensions/dev-team/lib/agents.ts +272 -0
- package/extensions/dev-team/lib/ai-credits.ts +92 -0
- package/extensions/dev-team/lib/autocompact.ts +81 -0
- package/extensions/dev-team/lib/child-run.ts +102 -0
- package/extensions/dev-team/lib/config.ts +236 -0
- package/extensions/dev-team/lib/gh-command.ts +103 -0
- package/extensions/dev-team/lib/github-style.ts +307 -0
- package/extensions/dev-team/lib/hooks.ts +350 -0
- package/extensions/dev-team/lib/metrics.ts +115 -0
- package/extensions/dev-team/lib/safe-read.ts +49 -0
- package/extensions/dev-team/lib/session-files.ts +57 -0
- package/extensions/dev-team/lib/session-spend.ts +123 -0
- package/extensions/dev-team/lib/shell-scan.ts +205 -0
- package/extensions/dev-team/lib/skills.ts +213 -0
- package/extensions/dev-team/lib/subagent-render.ts +245 -0
- package/extensions/dev-team/lib/subagent-types.ts +164 -0
- package/extensions/dev-team/lib/subagent.ts +596 -0
- package/extensions/dev-team/lib/terminal-text.ts +54 -0
- package/extensions/dev-team/lib/tools-misc.ts +152 -0
- package/extensions/dev-team/lib/transcript.ts +110 -0
- package/extensions/dev-team/lib/trust.ts +52 -0
- package/extensions/dev-team/lib/usage-breakdown.ts +176 -0
- package/extensions/dev-team/lib/usage-chart.ts +153 -0
- package/extensions/dev-team/lib/usage-command.ts +107 -0
- package/extensions/dev-team/lib/usage-history.ts +203 -0
- package/extensions/dev-team/lib/usage-render.ts +225 -0
- package/extensions/dev-team/lib/usage-split-bar.ts +127 -0
- package/extensions/dev-team/lib/usage-state.ts +116 -0
- package/extensions/dev-team/lib/usage-text.ts +159 -0
- package/extensions/dev-team/lib/usage-view.ts +109 -0
- package/hooks/__pycache__/refactor_test_freeze_guard.cpython-314.pyc +0 -0
- package/hooks/agent_dispatch_ledger.py +190 -0
- package/hooks/autocompact_setup_nudge.py +99 -0
- package/hooks/bash_retry_guard.py +228 -0
- package/hooks/boundary_events_write_guard.py +352 -0
- package/hooks/code_intelligence_nudge.py +293 -0
- package/hooks/code_intelligence_turn_mark.py +317 -0
- package/hooks/codegraph_bootstrap.py +139 -0
- package/hooks/contract_version_guard.py +362 -0
- package/hooks/cost_meter.py +106 -0
- package/hooks/destructive-commands.json +62 -0
- package/hooks/destructive_guard.py +477 -0
- package/hooks/eval_compliance_check.py +440 -0
- package/hooks/guards.json +17 -0
- package/hooks/hooks.json +323 -0
- package/hooks/internal_double_gate.py +296 -0
- package/hooks/js_fp_review.py +212 -0
- package/hooks/knowledge_index.py +119 -0
- package/hooks/lib/__pycache__/artifact_paths.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/atomic_state.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/autocompact_config.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/boundary_events.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/doc_classification.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/gh_pr_create_detect.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/git_safe_diff.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/instrument_log.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/metrics_query.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/plugin_version.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/pre_commit_doc_classifier.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/review_agent_registry.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/review_gate_corroboration.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/review_gate_hash.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/review_verdicts.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/stdin_json.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/stryker_invocation.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/telemetry_consent.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/test_file_classify.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/token_efficiency_limits.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/verify_guard_state.cpython-314.pyc +0 -0
- package/hooks/lib/__pycache__/xunit_v3_operator_gate.cpython-314.pyc +0 -0
- package/hooks/lib/agent_skill_hints.py +74 -0
- package/hooks/lib/artifact_paths.py +263 -0
- package/hooks/lib/atomic_state.py +557 -0
- package/hooks/lib/autocompact_config.py +103 -0
- package/hooks/lib/autoship_log.py +106 -0
- package/hooks/lib/banned_scripts_policy.py +51 -0
- package/hooks/lib/boundary_events.py +436 -0
- package/hooks/lib/build_knowledge_index.py +504 -0
- package/hooks/lib/build_skills_index.py +361 -0
- package/hooks/lib/build_state.py +116 -0
- package/hooks/lib/classify_ship_outcome.py +126 -0
- package/hooks/lib/config_changelog_schema.py +115 -0
- package/hooks/lib/cost_meter.py +955 -0
- package/hooks/lib/doc_classification.py +116 -0
- package/hooks/lib/gh_pr_create_detect.py +136 -0
- package/hooks/lib/git_safe_diff.py +123 -0
- package/hooks/lib/instrument_log.py +66 -0
- package/hooks/lib/iteration_journal_gate.py +197 -0
- package/hooks/lib/knowledge_index_paths.py +88 -0
- package/hooks/lib/mcp_json_repowise.py +177 -0
- package/hooks/lib/metrics_query.py +202 -0
- package/hooks/lib/minimal_yaml.py +434 -0
- package/hooks/lib/plugin_version.py +142 -0
- package/hooks/lib/pre_commit_detect.py +537 -0
- package/hooks/lib/pre_commit_doc_classifier.py +126 -0
- package/hooks/lib/pricing.py +118 -0
- package/hooks/lib/report_pdf.py +371 -0
- package/hooks/lib/review_agent_registry.py +142 -0
- package/hooks/lib/review_dispatch_ledger.py +101 -0
- package/hooks/lib/review_gate_corroboration.py +521 -0
- package/hooks/lib/review_gate_hash.py +252 -0
- package/hooks/lib/review_gate_normalized_hash.py +1115 -0
- package/hooks/lib/review_verdicts.py +301 -0
- package/hooks/lib/run_report.py +160 -0
- package/hooks/lib/skill_categories.yaml +125 -0
- package/hooks/lib/stdin_json.py +57 -0
- package/hooks/lib/stryker_invocation.py +102 -0
- package/hooks/lib/telemetry_consent.py +41 -0
- package/hooks/lib/telemetry_report.py +108 -0
- package/hooks/lib/test_file_classify.py +160 -0
- package/hooks/lib/token_efficiency_limits.py +51 -0
- package/hooks/lib/turn_identity.py +77 -0
- package/hooks/lib/verify_guard_state.py +110 -0
- package/hooks/lib/workflow_state.py +206 -0
- package/hooks/lib/xunit_v3_operator_gate.py +596 -0
- package/hooks/mcp_json_repowise_nudge.py +74 -0
- package/hooks/mutation_adapters/__init__.py +7 -0
- package/hooks/mutation_adapters/__pycache__/__init__.cpython-314.pyc +0 -0
- package/hooks/mutation_adapters/__pycache__/lib.cpython-314.pyc +0 -0
- package/hooks/mutation_adapters/__pycache__/mutmut.cpython-314.pyc +0 -0
- package/hooks/mutation_adapters/__pycache__/pitest.cpython-314.pyc +0 -0
- package/hooks/mutation_adapters/__pycache__/stryker.cpython-314.pyc +0 -0
- package/hooks/mutation_adapters/__pycache__/stryker_net.cpython-314.pyc +0 -0
- package/hooks/mutation_adapters/lib.py +478 -0
- package/hooks/mutation_adapters/mutmut.py +188 -0
- package/hooks/mutation_adapters/pitest.py +266 -0
- package/hooks/mutation_adapters/stryker.py +157 -0
- package/hooks/mutation_adapters/stryker_net.py +264 -0
- package/hooks/mutation_gate.py +193 -0
- package/hooks/mutation_testing_smoke_gate.py +371 -0
- package/hooks/pending_review_notify.py +121 -0
- package/hooks/phase_marker.py +138 -0
- package/hooks/post_compact_state_reinject.py +180 -0
- package/hooks/post_format.py +115 -0
- package/hooks/pre_commit_knowledge_index.py +128 -0
- package/hooks/pre_commit_review.py +66 -0
- package/hooks/pre_pr_review.py +694 -0
- package/hooks/pre_tool_guard.py +405 -0
- package/hooks/py.sh +73 -0
- package/hooks/refactor-bash-write-patterns.json +29 -0
- package/hooks/refactor_test_bash_guard.py +253 -0
- package/hooks/refactor_test_freeze_guard.py +139 -0
- package/hooks/refactor_test_revert_guard.py +186 -0
- package/hooks/repo_review_nudge.py +287 -0
- package/hooks/review_verdict_recorder.py +464 -0
- package/hooks/scan_bash_command_for_banned_scripts.py +428 -0
- package/hooks/scan_worktree_for_banned_scripts.py +238 -0
- package/hooks/session_learning_trigger.py +248 -0
- package/hooks/skills_index.py +126 -0
- package/hooks/stryker_xunit_shim_guard.py +571 -0
- package/hooks/subagent_completion_guard.py +309 -0
- package/hooks/subagent_skill_context.py +139 -0
- package/hooks/task_completion_metrics.py +216 -0
- package/hooks/tdd_guard.py +229 -0
- package/hooks/telemetry.py +341 -0
- package/hooks/token_efficiency_review.py +194 -0
- package/hooks/verify_guard.py +183 -0
- package/hooks/verify_guard_edit_marker.py +73 -0
- package/hooks/version_check.py +173 -0
- package/knowledge/accepted-risks-schema.md +98 -0
- package/knowledge/adr-decision-criteria.md +64 -0
- package/knowledge/adversarial-review-protocol.md +139 -0
- package/knowledge/agent-registry.md +228 -0
- package/knowledge/agent-review-methodology.md +80 -0
- package/knowledge/ai-friendly-repo-guidelines.md +67 -0
- package/knowledge/architecture-assessment.md +96 -0
- package/knowledge/artifact-lifecycle.md +57 -0
- package/knowledge/cd-maturity-model.md +82 -0
- package/knowledge/cd-test-architecture.md +190 -0
- package/knowledge/ci-cd-file-scope.md +24 -0
- package/knowledge/codegraph-vs-graphify.md +192 -0
- package/knowledge/component-test-patterns.md +139 -0
- package/knowledge/database-change-management.md +80 -0
- package/knowledge/database-test-patterns.md +79 -0
- package/knowledge/decision-defaults.md +88 -0
- package/knowledge/dependency-breaking-techniques.md +116 -0
- package/knowledge/deployment-pipeline.md +86 -0
- package/knowledge/design-smells.md +122 -0
- package/knowledge/directory-enumeration.md +38 -0
- package/knowledge/domain-modeling.md +123 -0
- package/knowledge/evidence-bundle.md +90 -0
- package/knowledge/exploratory-testing-field-guide.md +122 -0
- package/knowledge/failure-routing.md +28 -0
- package/knowledge/fixture-construction.md +56 -0
- package/knowledge/frontend-component-architecture.md +139 -0
- package/knowledge/gherkin-quality-review-dispatch.md +135 -0
- package/knowledge/index.json +6766 -0
- package/knowledge/internal-collaborator-doubling.md +101 -0
- package/knowledge/legacy-test-strategy.md +71 -0
- package/knowledge/long-run-waiting.md +66 -0
- package/knowledge/microservice-testing.md +71 -0
- package/knowledge/model-pricing.json +23 -0
- package/knowledge/mutation-score-formulas.md +60 -0
- package/knowledge/object-calisthenics.md +147 -0
- package/knowledge/oracle-provenance.md +94 -0
- package/knowledge/orchestrator-script-implementation.md +185 -0
- package/knowledge/owasp-detection.md +148 -0
- package/knowledge/plan-review-rubric.md +56 -0
- package/knowledge/proxy-connectivity.md +62 -0
- package/knowledge/reactive-effect-patterns.md +73 -0
- package/knowledge/recon-inventory-excludes.txt +32 -0
- package/knowledge/references/bdd-value-guide.md +61 -0
- package/knowledge/references/csharp-http-client-testing.md +264 -0
- package/knowledge/release-strategies.md +74 -0
- package/knowledge/report-output-location.md +117 -0
- package/knowledge/report-pdf-integration.md +63 -0
- package/knowledge/report-print.css +129 -0
- package/knowledge/report-template.md +114 -0
- package/knowledge/report-to-pdf.md +69 -0
- package/knowledge/request-processing-flow.md +63 -0
- package/knowledge/result-verification.md +52 -0
- package/knowledge/review-agent-output-contract.md +121 -0
- package/knowledge/review-lens-classification.md +113 -0
- package/knowledge/review-rubric.md +62 -0
- package/knowledge/review-template.md +104 -0
- package/knowledge/rule-fixtures/A02.insecure-random-js/negative.js +1 -0
- package/knowledge/rule-fixtures/A02.insecure-random-js/positive.js +1 -0
- package/knowledge/rule-fixtures/A02.weak-hashing-md5/negative.py +1 -0
- package/knowledge/rule-fixtures/A02.weak-hashing-md5/positive.py +1 -0
- package/knowledge/rule-fixtures/A03.command-injection/negative.js +1 -0
- package/knowledge/rule-fixtures/A03.command-injection/positive.js +1 -0
- package/knowledge/rule-fixtures/A03.sql-injection/negative.js +1 -0
- package/knowledge/rule-fixtures/A03.sql-injection/positive.js +1 -0
- package/knowledge/rule-fixtures/A03.xss-innerhtml/negative.js +1 -0
- package/knowledge/rule-fixtures/A03.xss-innerhtml/positive.js +1 -0
- package/knowledge/rule-fixtures/A05.cors-wildcard/negative.js +1 -0
- package/knowledge/rule-fixtures/A05.cors-wildcard/positive.js +1 -0
- package/knowledge/rule-fixtures/A05.default-credentials/negative.js +1 -0
- package/knowledge/rule-fixtures/A05.default-credentials/positive.js +1 -0
- package/knowledge/rule-fixtures/A07.jwt-alg-none/negative.js +1 -0
- package/knowledge/rule-fixtures/A07.jwt-alg-none/positive.js +1 -0
- package/knowledge/rule-fixtures/A08.binary-formatter/negative.cs +1 -0
- package/knowledge/rule-fixtures/A08.binary-formatter/positive.cs +1 -0
- package/knowledge/rule-fixtures/A08.js-eval/negative.js +1 -0
- package/knowledge/rule-fixtures/A08.js-eval/positive.js +1 -0
- package/knowledge/rule-fixtures/A08.object-input-stream/negative.java +1 -0
- package/knowledge/rule-fixtures/A08.object-input-stream/positive.java +1 -0
- package/knowledge/schemas/disposition-register-v1.json +65 -0
- package/knowledge/schemas/recon-envelope-v1.json +198 -0
- package/knowledge/schemas/unified-finding-v1.json +72 -0
- package/knowledge/security-primitives-contract.md +301 -0
- package/knowledge/security-review-rule-map.yaml +107 -0
- package/knowledge/skills-registry.md +72 -0
- package/knowledge/task-size-classifier.md +103 -0
- package/knowledge/telemetry-schema.md +881 -0
- package/knowledge/test-automation-maturity.md +56 -0
- package/knowledge/test-automation-principles.md +71 -0
- package/knowledge/test-cadence-tradeoffs.md +68 -0
- package/knowledge/test-doubles.md +105 -0
- package/knowledge/test-file-indicators.md +22 -0
- package/knowledge/test-layer-gates.md +35 -0
- package/knowledge/test-matrix-examples/django-batch.md +24 -0
- package/knowledge/test-matrix-examples/dotnet-grpc-fronting-api.md +90 -0
- package/knowledge/test-matrix-examples/dotnet-http-consumer.md +131 -0
- package/knowledge/test-matrix-examples/react-node-spa.md +24 -0
- package/knowledge/test-matrix-examples/spring-boot-service.md +25 -0
- package/knowledge/test-matrix-examples/ssr-htmx.md +24 -0
- package/knowledge/test-organization.md +70 -0
- package/knowledge/test-pyramid.md +84 -0
- package/knowledge/test-refactoring.md +67 -0
- package/knowledge/test-review-division-of-labor.md +85 -0
- package/knowledge/test-smells.md +80 -0
- package/knowledge/test-stack-profiles/bdd-frameworks.md +235 -0
- package/knowledge/test-stack-profiles/django.md +13 -0
- package/knowledge/test-stack-profiles/dotnet.md +18 -0
- package/knowledge/test-stack-profiles/go.md +16 -0
- package/knowledge/test-stack-profiles/node.md +16 -0
- package/knowledge/test-stack-profiles/react.md +12 -0
- package/knowledge/test-stack-profiles/spring-boot.md +16 -0
- package/knowledge/test-stack-profiles/ssr-htmx.md +14 -0
- package/knowledge/test-stack-profiles/vue.md +12 -0
- package/knowledge/test-strategy.md +70 -0
- package/knowledge/testability-patterns.md +240 -0
- package/knowledge/testing-quadrants.md +44 -0
- package/knowledge/testing-techniques/approval.md +15 -0
- package/knowledge/testing-techniques/chaos.md +17 -0
- package/knowledge/testing-techniques/fuzz.md +15 -0
- package/knowledge/testing-techniques/property-based.md +15 -0
- package/knowledge/testing-techniques/schema-validation.md +15 -0
- package/knowledge/testing-techniques/screenshot.md +15 -0
- package/knowledge/three-phase-workflow.md +198 -0
- package/knowledge/value-patterns.md +55 -0
- package/knowledge/verification-mode.md +116 -0
- package/knowledge/virtual-service-libraries.md +75 -0
- package/knowledge/wave-consolidation-guidance.md +21 -0
- package/overrides/agents/Explore.md +15 -0
- package/overrides/agents/general-purpose.md +10 -0
- package/overrides/notes/autoship.md +6 -0
- package/overrides/notes/issues-from-assessment.md +3 -0
- package/overrides/notes/issues-from-plan.md +3 -0
- package/overrides/notes/mutation-night-watch.md +3 -0
- package/overrides/notes/mutation-testing.md +3 -0
- package/overrides/notes/pr.md +7 -0
- package/overrides/notes/project-init.md +6 -0
- package/overrides/notes/setup.md +13 -0
- package/overrides/notes/specs.md +3 -0
- package/overrides/skills/headless-run/SKILL.md +45 -0
- package/overrides/skills/upgrade/SKILL.md +30 -0
- package/overrides/skills/version/SKILL.md +25 -0
- package/package.json +36 -0
- package/scripts/authoring_digest.py +93 -0
- package/scripts/autoship_discover.py +121 -0
- package/scripts/autoship_group.py +409 -0
- package/scripts/autoship_proposals.py +494 -0
- package/scripts/autoship_queue.py +291 -0
- package/scripts/autoship_reclaim.py +495 -0
- package/scripts/build_jobs.py +108 -0
- package/scripts/build_rollback_point.py +240 -0
- package/scripts/build_slice_scope.py +157 -0
- package/scripts/build_wave.py +109 -0
- package/scripts/build_wave_reconcile.py +252 -0
- package/scripts/build_worktree_baseref.py +113 -0
- package/scripts/check_agent_scope.py +117 -0
- package/scripts/check_agent_tool_mapping.py +213 -0
- package/scripts/check_review_agent_mcp_tools.py +317 -0
- package/scripts/check_security_assessment_mcp_tools.py +165 -0
- package/scripts/checkpoint_abort.py +502 -0
- package/scripts/claude_setup_review.py +438 -0
- package/scripts/codebase_recon.py +556 -0
- package/scripts/coverage_config.py +623 -0
- package/scripts/coverage_delta_steering.py +330 -0
- package/scripts/coverage_discovery_dotnet.py +315 -0
- package/scripts/coverage_discovery_java.py +742 -0
- package/scripts/coverage_discovery_js.py +546 -0
- package/scripts/coverage_gap_ranking.py +556 -0
- package/scripts/coverage_readiness.py +455 -0
- package/scripts/coverage_report_parse.py +521 -0
- package/scripts/detect_bdd_convention.py +252 -0
- package/scripts/eval_ablation.py +376 -0
- package/scripts/gherkin_analysis_coverage_gate.py +306 -0
- package/scripts/gherkin_cross_feature_duplicate_titles_gate.py +173 -0
- package/scripts/gherkin_effectiveness_rollup.py +238 -0
- package/scripts/gherkin_failure_path_gate.py +206 -0
- package/scripts/gherkin_feature_merge.py +720 -0
- package/scripts/gherkin_stub_gate.py +163 -0
- package/scripts/gherkin_stub_merge.py +479 -0
- package/scripts/git_origin_host.py +88 -0
- package/scripts/install-java-static-analysis.py +110 -0
- package/scripts/issue_deps.py +74 -0
- package/scripts/lib/_bdd_markers.py +28 -0
- package/scripts/lib/_gherkin_text.py +93 -0
- package/scripts/lib/_vendored_tree.py +70 -0
- package/scripts/lib/autoship_state.py +397 -0
- package/scripts/lib/claude_md_guard.py +226 -0
- package/scripts/lib/deterministic_recon.py +446 -0
- package/scripts/lib/mcp_tool_grants.py +211 -0
- package/scripts/lib/plan_parse.py +386 -0
- package/scripts/lib/review_result.py +84 -0
- package/scripts/lib/review_roster.py +86 -0
- package/scripts/lib/session_log/__init__.py +34 -0
- package/scripts/lib/session_log/__pycache__/__init__.cpython-314.pyc +0 -0
- package/scripts/lib/session_log/__pycache__/records.cpython-314.pyc +0 -0
- package/scripts/lib/session_log/classify.py +231 -0
- package/scripts/lib/session_log/corrections.py +194 -0
- package/scripts/lib/session_log/discovery.py +108 -0
- package/scripts/lib/session_log/records.py +218 -0
- package/scripts/lib/session_log/redact.py +76 -0
- package/scripts/lib/session_log/signals.py +373 -0
- package/scripts/lib/session_report_downstream.py +614 -0
- package/scripts/lib/session_report_maintainer.py +1273 -0
- package/scripts/lib/session_report_shared.py +262 -0
- package/scripts/lib/settings_hook_guard.py +157 -0
- package/scripts/lib/slug.py +33 -0
- package/scripts/lib/stub_extractors/__init__.py +82 -0
- package/scripts/lib/stub_extractors/_common.py +328 -0
- package/scripts/lib/stub_extractors/csharp.py +19 -0
- package/scripts/lib/stub_extractors/go.py +173 -0
- package/scripts/lib/stub_extractors/java.py +18 -0
- package/scripts/lib/stub_extractors/jsts.py +126 -0
- package/scripts/mutation_stack_sections.py +149 -0
- package/scripts/mutation_yield_steering.py +345 -0
- package/scripts/orchestrator.py +895 -0
- package/scripts/plan_gherkin_export.py +227 -0
- package/scripts/plan_waves.py +208 -0
- package/scripts/pr_close_keyword_lint.py +108 -0
- package/scripts/progress_guardian.py +888 -0
- package/scripts/recon_inventory.py +273 -0
- package/scripts/review_findings_log.py +93 -0
- package/scripts/run_invariants.py +124 -0
- package/scripts/select_lenses.py +640 -0
- package/scripts/session_report.py +486 -0
- package/scripts/set_autocompact_env.py +221 -0
- package/scripts/ship_resume_guard.py +135 -0
- package/scripts/ship_review_gate.py +63 -0
- package/scripts/specs_convention_marker.py +103 -0
- package/scripts/test_improve_resume.py +277 -0
- package/scripts/test_review_mechanics.py +958 -0
- package/scripts/token_efficiency_review.py +322 -0
- package/scripts/verdict_scope.py +285 -0
- package/scripts/verify_gherkin_quality_critic_isolation.py +296 -0
- package/scripts/verify_tier.py +157 -0
- package/skills/adr-tools/SKILL.md +118 -0
- package/skills/agent-readiness/SKILL.md +105 -0
- package/skills/agent-readiness/ai_friendly_analyzers.py +326 -0
- package/skills/agent-readiness/scanner.py +441 -0
- package/skills/agent-readiness/scorecard.yaml +88 -0
- package/skills/api-design/SKILL.md +115 -0
- package/skills/apply-fixes/SKILL.md +171 -0
- package/skills/apply-test-doubles/SKILL.md +321 -0
- package/skills/artifact-lifecycle/SKILL.md +127 -0
- package/skills/autoship/SKILL.md +1124 -0
- package/skills/benchmark/SKILL.md +105 -0
- package/skills/branch-workflow/SKILL.md +89 -0
- package/skills/browse/SKILL.md +184 -0
- package/skills/browser-testing/SKILL.md +62 -0
- package/skills/browser-testing/references/playwright-patterns.md +216 -0
- package/skills/build/SKILL.md +422 -0
- package/skills/build/references/static-self-heal.md +245 -0
- package/skills/careful/SKILL.md +72 -0
- package/skills/cd-test-architecture/SKILL.md +371 -0
- package/skills/ci-debugging/SKILL.md +105 -0
- package/skills/co-evolution-audit/SKILL.md +269 -0
- package/skills/code-review/SKILL.md +1015 -0
- package/skills/code-review/examples/aggregated-sample.json +56 -0
- package/skills/code-review/examples/sample-report.md +41 -0
- package/skills/code-review/output-format.md +478 -0
- package/skills/code-review/scripts/activation.py +86 -0
- package/skills/code-review/scripts/change_impact.py +357 -0
- package/skills/code-review/scripts/change_shape.py +372 -0
- package/skills/code-review/scripts/change_size.py +212 -0
- package/skills/code-review/scripts/changed_file_list.py +141 -0
- package/skills/code-review/scripts/closing_pass.py +187 -0
- package/skills/code-review/scripts/consolidate.py +277 -0
- package/skills/code-review/scripts/contract_failure_report.py +185 -0
- package/skills/code-review/scripts/dispatch_reconcile.py +66 -0
- package/skills/code-review/scripts/dispatch_waves.py +164 -0
- package/skills/code-review/scripts/finding_signature.py +446 -0
- package/skills/code-review/scripts/ledger.py +283 -0
- package/skills/code-review/scripts/partition.py +169 -0
- package/skills/code-review/scripts/render_tiered_findings.py +274 -0
- package/skills/code-review/scripts/repo_invariants.py +1066 -0
- package/skills/code-review/scripts/review_context_pack.py +306 -0
- package/skills/code-review/scripts/review_round_log.py +345 -0
- package/skills/code-review/scripts/review_value_coverage.py +297 -0
- package/skills/code-review/scripts/validate_review_output.py +467 -0
- package/skills/code-review/sliced-mode.md +205 -0
- package/skills/competitive-analysis/SKILL.md +191 -0
- package/skills/context-loading-protocol/SKILL.md +157 -0
- package/skills/continue/SKILL.md +90 -0
- package/skills/cost-report/SKILL.md +178 -0
- package/skills/coverage-baseline/SKILL.md +335 -0
- package/skills/coverage-baseline/references/multi-project-discovery.md +202 -0
- package/skills/coverage-delta/SKILL.md +181 -0
- package/skills/coverage-delta/references/mutation-gate.md +70 -0
- package/skills/design-doc/SKILL.md +95 -0
- package/skills/design-interrogation/SKILL.md +89 -0
- package/skills/design-it-twice/SKILL.md +91 -0
- package/skills/docker-image-audit/SKILL.md +108 -0
- package/skills/docker-image-audit/references/install-guide.md +64 -0
- package/skills/docker-image-audit/references/report-template.md +73 -0
- package/skills/docker-image-create/SKILL.md +185 -0
- package/skills/domain-analysis/SKILL.md +183 -0
- package/skills/domain-driven-design/SKILL.md +194 -0
- package/skills/exploratory-testing/SKILL.md +108 -0
- package/skills/explore/SKILL.md +51 -0
- package/skills/farley-score/SKILL.md +165 -0
- package/skills/feature-file-validation/SKILL.md +78 -0
- package/skills/feature-file-validation/references/validation-rules.md +115 -0
- package/skills/feedback-learning/SKILL.md +414 -0
- package/skills/fix/SKILL.md +450 -0
- package/skills/freeze/SKILL.md +68 -0
- package/skills/frontend-architecture/SKILL.md +113 -0
- package/skills/gherkin-derive/SKILL.md +630 -0
- package/skills/gherkin-public/SKILL.md +266 -0
- package/skills/governance-compliance/SKILL.md +150 -0
- package/skills/guard/SKILL.md +75 -0
- package/skills/handoff/SKILL.md +139 -0
- package/skills/handoff/references/summary-templates.md +242 -0
- package/skills/harness-audit/SKILL.md +751 -0
- package/skills/harness-audit/scripts/lesson_validate.py +386 -0
- package/skills/harness-audit/scripts/redundancy_criterion.py +188 -0
- package/skills/headless-run/SKILL.md +45 -0
- package/skills/headless-run/scripts/isolated_dispatch.py +381 -0
- package/skills/help/SKILL.md +72 -0
- package/skills/hexagonal-architecture/SKILL.md +85 -0
- package/skills/human-oversight-protocol/SKILL.md +224 -0
- package/skills/issues-from-assessment/SKILL.md +223 -0
- package/skills/issues-from-plan/SKILL.md +133 -0
- package/skills/legacy-code/SKILL.md +132 -0
- package/skills/mermaid-diagramming/SKILL.md +120 -0
- package/skills/mutation-night-watch/SKILL.md +154 -0
- package/skills/mutation-night-watch/references/scheduling.md +135 -0
- package/skills/mutation-testing/SKILL.md +396 -0
- package/skills/mutation-testing/references/languages/csharp-stryker-net.md +676 -0
- package/skills/mutation-testing/references/languages/go-go-mutesting.md +95 -0
- package/skills/mutation-testing/references/languages/java-pitest.md +77 -0
- package/skills/mutation-testing/references/languages/javascript-stryker.md +188 -0
- package/skills/mutation-testing/references/languages/python-mutmut.md +97 -0
- package/skills/mutation-testing/references/time-estimation.md +34 -0
- package/skills/mutation-testing/references/tool-detection.md +15 -0
- package/skills/mutation-testing/references/workflow-callers.md +23 -0
- package/skills/mutation-testing/scripts/__pycache__/xunit_v3_feature_detector.cpython-314.pyc +0 -0
- package/skills/mutation-testing/scripts/csharp_stryker_net_slice_runner.py +635 -0
- package/skills/mutation-testing/scripts/csharp_stryker_net_status_loop.py +525 -0
- package/skills/mutation-testing/scripts/csharp_stryker_net_wrapper.py +681 -0
- package/skills/mutation-testing/scripts/mutation_baseline_reuse.py +292 -0
- package/skills/mutation-testing/scripts/mutation_exclude_policy.py +268 -0
- package/skills/mutation-testing/scripts/mutation_feasibility_gate.py +463 -0
- package/skills/mutation-testing/scripts/mutation_kill_headless.py +331 -0
- package/skills/mutation-testing/scripts/mutation_kill_insert.py +199 -0
- package/skills/mutation-testing/scripts/mutation_kill_insert_python.py +150 -0
- package/skills/mutation-testing/scripts/mutation_kill_loop.py +869 -0
- package/skills/mutation-testing/scripts/mutation_kill_loop_python.py +949 -0
- package/skills/mutation-testing/scripts/mutation_kill_retry.py +592 -0
- package/skills/mutation-testing/scripts/mutation_kill_shared.py +620 -0
- package/skills/mutation-testing/scripts/mutation_nightwatch.py +462 -0
- package/skills/mutation-testing/scripts/mutation_nightwatch_stacks.py +425 -0
- package/skills/mutation-testing/scripts/mutation_report.py +743 -0
- package/skills/mutation-testing/scripts/mutation_report_cli.py +175 -0
- package/skills/mutation-testing/scripts/mutation_safety_gate.py +69 -0
- package/skills/mutation-testing/scripts/stryker_shard_pipeline.py +847 -0
- package/skills/mutation-testing/scripts/stryker_shard_setup.py +440 -0
- package/skills/mutation-testing/scripts/stryker_timeout_retry.py +142 -0
- package/skills/mutation-testing/scripts/xunit_v3_feature_detector.py +341 -0
- package/skills/performance-benchmark/SKILL.md +174 -0
- package/skills/performance-benchmark/examples/report-format.md +43 -0
- package/skills/performance-benchmark/references/benchmark-script.md +169 -0
- package/skills/performance-metrics/SKILL.md +265 -0
- package/skills/plan/SKILL.md +199 -0
- package/skills/plan/references/gherkin-persistence.md +43 -0
- package/skills/plan/references/plan-template.md +182 -0
- package/skills/pr/SKILL.md +289 -0
- package/skills/pr/scripts/gate_retry_state.py +368 -0
- package/skills/project-init/README.md +141 -0
- package/skills/project-init/SKILL.md +1197 -0
- package/skills/project-init/evals/evals.json +200 -0
- package/skills/project-init/references/capability-tools.md +55 -0
- package/skills/project-init/references/configs.md +221 -0
- package/skills/property-based-testing/SKILL.md +121 -0
- package/skills/property-based-testing/fixtures/invariant_fixture.py +15 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/README.md +42 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/LICENSE +21 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/README.md +263 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/cjs/fast-check.d.ts +5165 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/cjs/fast-check.js +12147 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/cjs/package.json +3 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/cjs/types57/fast-check.d.ts +5165 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/fast-check.d.ts +5165 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/fast-check.js +12011 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/rolldown-runtime-D7D4PA-g.js +13 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/types57/fast-check.d.ts +5165 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/package.json +94 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/LICENSE +21 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/README.md +168 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/RandomGenerator-DcXj09Ch.d.ts +14 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformBigInt.d.ts +15 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformBigInt.js +38 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformFloat32.d.ts +15 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformFloat32.js +18 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformFloat64.d.ts +15 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformFloat64.js +22 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformInt.d.ts +15 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformInt.js +134 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/RandomGenerator-DcXj09Ch.d.ts +14 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformBigInt.d.ts +15 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformBigInt.js +37 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformFloat32.d.ts +15 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformFloat32.js +17 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformFloat64.d.ts +15 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformFloat64.js +21 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformInt.d.ts +15 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformInt.js +133 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/congruential32.d.ts +7 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/congruential32.js +44 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/mersenne.d.ts +7 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/mersenne.js +90 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/xoroshiro128plus.d.ts +7 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/xoroshiro128plus.js +80 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/xorshift128plus.d.ts +7 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/xorshift128plus.js +78 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/package.json +3 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/types/JumpableRandomGenerator.d.ts +16 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/types/JumpableRandomGenerator.js +0 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/types/RandomGenerator.d.ts +2 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/types/RandomGenerator.js +0 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/generateN.d.ts +6 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/generateN.js +8 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/purify.d.ts +12 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/purify.js +9 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/skipN.d.ts +6 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/skipN.js +6 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/congruential32.d.ts +7 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/congruential32.js +46 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/mersenne.d.ts +7 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/mersenne.js +92 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/xoroshiro128plus.d.ts +7 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/xoroshiro128plus.js +82 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/xorshift128plus.d.ts +7 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/xorshift128plus.js +80 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/types/JumpableRandomGenerator.d.ts +16 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/types/JumpableRandomGenerator.js +0 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/types/RandomGenerator.d.ts +2 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/types/RandomGenerator.js +0 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/generateN.d.ts +6 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/generateN.js +9 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/purify.d.ts +12 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/purify.js +10 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/skipN.d.ts +6 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/skipN.js +7 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/package.json +133 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/package-lock.json +1179 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/package.json +14 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/roundtrip.js +29 -0
- package/skills/property-based-testing/fixtures/js-roundtrip/roundtrip.properties.test.js +16 -0
- package/skills/property-based-testing/fixtures/no_property_fixture.py +10 -0
- package/skills/property-based-testing/fixtures/roundtrip_fixture.py +16 -0
- package/skills/property-based-testing/references/languages/javascript.md +54 -0
- package/skills/property-based-testing/scripts/detect_and_dispatch.py +80 -0
- package/skills/property-based-testing/scripts/hypothesis_scaffold.py +276 -0
- package/skills/proxy-resilience/SKILL.md +84 -0
- package/skills/quality-gate-pipeline/SKILL.md +184 -0
- package/skills/quality-targets-converge/SKILL.md +254 -0
- package/skills/repo-review/SKILL.md +159 -0
- package/skills/report-pdf/SKILL.md +66 -0
- package/skills/review/SKILL.md +47 -0
- package/skills/review-agent/SKILL.md +152 -0
- package/skills/review-summary/SKILL.md +73 -0
- package/skills/run-report/SKILL.md +70 -0
- package/skills/semantic-duplication-scan/SKILL.md +337 -0
- package/skills/semantic-scan/SKILL.md +53 -0
- package/skills/semgrep-analyze/SKILL.md +139 -0
- package/skills/setup/SKILL.md +1122 -0
- package/skills/ship/SKILL.md +240 -0
- package/skills/source-verification/SKILL.md +210 -0
- package/skills/source-verification/scripts/claim_extractor.py +155 -0
- package/skills/specs/.size-baseline.json +4 -0
- package/skills/specs/SKILL.md +243 -0
- package/skills/specs/references/completeness-checklist.md +83 -0
- package/skills/specs/references/extraction.md +58 -0
- package/skills/specs/references/glossary.md +59 -0
- package/skills/specs/references/persistence.md +115 -0
- package/skills/specs/references/predictability-check.md +77 -0
- package/skills/static-analysis-integration/SKILL.md +235 -0
- package/skills/static-analysis-integration/adapters/_envelope.py +26 -0
- package/skills/static-analysis-integration/adapters/jscpd-adapter.py +66 -0
- package/skills/static-analysis-integration/adapters/lizard-adapter.py +81 -0
- package/skills/static-analysis-integration/adapters/mypy-adapter.py +50 -0
- package/skills/static-analysis-integration/adapters/mypy-src-layout.py +93 -0
- package/skills/static-analysis-integration/adapters/security-review-adapter.py +212 -0
- package/skills/static-analysis-integration/maintenance.md +23 -0
- package/skills/static-analysis-integration/references/language-setup.md +228 -0
- package/skills/static-analysis-integration/references/sarif-parser.md +124 -0
- package/skills/static-analysis-integration/references/security-review-adapter.md +118 -0
- package/skills/static-analysis-integration/references/tool-configs.md +617 -0
- package/skills/static-analysis-integration/rulesets/pmd-quickstart.xml +24 -0
- package/skills/stryker-xunit-v2-shim/SKILL.md +274 -0
- package/skills/stryker-xunit-v2-shim/references/shim-howto.md +256 -0
- package/skills/stryker-xunit-v2-shim/scripts/generate_shim.py +143 -0
- package/skills/systematic-debugging/SKILL.md +130 -0
- package/skills/telemetry/SKILL.md +75 -0
- package/skills/test-audit-disable/SKILL.md +129 -0
- package/skills/test-design/SKILL.md +177 -0
- package/skills/test-design/scripts/__pycache__/internal_double_detector.cpython-314.pyc +0 -0
- package/skills/test-design/scripts/internal_double_detector.py +631 -0
- package/skills/test-design-advisor/SKILL.md +166 -0
- package/skills/test-driven-development/SKILL.md +169 -0
- package/skills/test-health/SKILL.md +262 -0
- package/skills/test-improve/SKILL.md +239 -0
- package/skills/test-improve/references/phase-0-approach-contract.md +228 -0
- package/skills/test-improve/references/phase-1-analyze.md +131 -0
- package/skills/test-improve/references/phase-2-baseline.md +121 -0
- package/skills/test-improve/references/phase-3-derive-gherkin.md +53 -0
- package/skills/test-improve/references/phase-4-plan-fixes.md +34 -0
- package/skills/test-improve/references/phase-5-improve.md +215 -0
- package/skills/test-improve/references/phase-6-refactor-decision.md +45 -0
- package/skills/test-improve/references/phase-7-refactor.md +44 -0
- package/skills/test-improve/references/phase-8-validate.md +66 -0
- package/skills/test-improve/references/phase-9-close-out-prompt.md +11 -0
- package/skills/test-improve/references/phase-9-report.md +62 -0
- package/skills/test-improve/references/review-loop.md +92 -0
- package/skills/test-improve/templates/executive-summary.md +123 -0
- package/skills/threat-modeling/SKILL.md +108 -0
- package/skills/triage/SKILL.md +211 -0
- package/skills/ubiquitous-language/SKILL.md +192 -0
- package/skills/ubiquitous-language/scripts/collect_domain_signals.py +300 -0
- package/skills/unfreeze/SKILL.md +37 -0
- package/skills/upgrade/SKILL.md +31 -0
- package/skills/upgrade/scripts/check_version_drift.py +113 -0
- package/skills/upgrade/scripts/enable_autoupdate.py +149 -0
- package/skills/version/SKILL.md +25 -0
- package/sync/__pycache__/sync_upstream.cpython-314.pyc +0 -0
- package/sync/sync_upstream.py +293 -0
- package/templates/ACCEPTED-RISKS.md.tmpl +46 -0
- package/templates/agents/agent-template.md +151 -0
- package/templates/agents/angular-testing.md +66 -0
- package/templates/agents/csharp-quality.md +63 -0
- package/templates/agents/esm-enforcer.md +52 -0
- package/templates/agents/front-end-testing.md +65 -0
- package/templates/agents/go-quality.md +65 -0
- package/templates/agents/python-quality.md +62 -0
- package/templates/agents/react-testing.md +61 -0
- package/templates/agents/ts-enforcer.md +60 -0
- package/templates/agents/twelve-factor-audit.md +49 -0
- package/tools/entropy-check.py +250 -0
- package/tools/model-hash-verify.py +213 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Test Automation Maturity
|
|
2
|
+
|
|
3
|
+
Reference file for `test-review` and the `test-health` skill (project-wide audit). It answers one question: **how maintainable is this suite as it grows, and where does it sit on the maturity curve?**
|
|
4
|
+
|
|
5
|
+
**Scope boundary — three files share "test automation"; keep them disjoint:**
|
|
6
|
+
|
|
7
|
+
- `test-strategy.md` owns the automation **strategy** axis (Scripted / Data-Driven / Recorded, fixture lifecycle, SUT interaction). Do not restate it here — cross-link.
|
|
8
|
+
- `test-refactoring.md` owns the **goals & principles** (self-checking, isolated, one-condition-per-test, design-for-testability). Do not restate them here — cross-link.
|
|
9
|
+
- **This file** owns only the **maturity diagnostic** and the **abstraction patterns** below.
|
|
10
|
+
|
|
11
|
+
Source: Meszaros *xUnit Test Patterns*; Crispin & Gregory; Page Object (Fowler/Selenium); Screenplay (Marcano). Stack-agnostic.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Maturity scale (diagnose from evidence, lowest rung first)
|
|
16
|
+
|
|
17
|
+
| Rung | Signal in the suite | Risk |
|
|
18
|
+
|------|---------------------|------|
|
|
19
|
+
| **0 — Manual / recorded** | record-and-replay scripts, no hand-written assertions | brittle; re-record on every UI change |
|
|
20
|
+
| **1 — Scripted, raw** | hand-written tests, but selectors/URLs/payloads inline in every test | one change touches many files |
|
|
21
|
+
| **2 — Abstracted** | a layer between tests and the SUT (Page Objects / API client / DSL); tests read in domain terms | maintainable; the target for most suites |
|
|
22
|
+
| **3 — Screenplay / actor** | behaviour expressed as actor tasks/questions, reusable across suites | worth it only for large E2E suites; over-engineering below ~50 E2E tests |
|
|
23
|
+
|
|
24
|
+
Report the rung from observed evidence (grep for duplicated selectors/literals, presence of a `pages/`/`support/` layer), then recommend the **next** rung — never skip ahead.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Single-Point-of-Change test
|
|
29
|
+
|
|
30
|
+
Pick one volatile detail (a CSS selector, an endpoint path, a field name). Count how many test files would change if it changed once.
|
|
31
|
+
|
|
32
|
+
- **N files → broken by one rename** is the headline maturity metric. N=1 is healthy; N≫1 is rung 1.
|
|
33
|
+
- Fix: extract that detail behind one abstraction (Page Object method, API client, builder) so the rename lands in **one** place.
|
|
34
|
+
|
|
35
|
+
## Abstraction patterns
|
|
36
|
+
|
|
37
|
+
- **Page Object / API client / DSL** — a façade exposing domain actions (`loginAs(user)`, `placeOrder(...)`), hiding selectors/HTTP. The standard rung-2 move.
|
|
38
|
+
- **Screenplay** — actors perform tasks and ask questions; tasks compose. Use for large, cross-cutting E2E suites only.
|
|
39
|
+
|
|
40
|
+
## Smell: UI-based setup
|
|
41
|
+
|
|
42
|
+
Driving the **UI** to establish preconditions (clicking through signup just to test checkout) is slow and flaky. Set state through the back door — API, fixture, or seeded DB — and reserve UI steps for the behaviour under test. (Back-door *setup* is legitimate; see `test-strategy.md` → SUT Interaction. It is not the banned "test logic in production" smell.)
|
|
43
|
+
|
|
44
|
+
## Graduated disclosure (don't over-build)
|
|
45
|
+
|
|
46
|
+
Scale abstraction to suite size, not aspiration:
|
|
47
|
+
|
|
48
|
+
| Test count (a given type) | Recommend |
|
|
49
|
+
|---------------------------|-----------|
|
|
50
|
+
| < ~10 | inline is fine; abstracting early is premature |
|
|
51
|
+
| ~10–50 | extract Page Objects / a client / builders (rung 2) |
|
|
52
|
+
| > ~50 E2E | consider Screenplay (rung 3) |
|
|
53
|
+
|
|
54
|
+
## Boundaries
|
|
55
|
+
|
|
56
|
+
Maturity is about **maintainability under change**, not coverage or correctness — those are `farley-score` and `test-review`. A small suite at rung 1 is fine; flag low maturity only when suite size makes the single-point-of-change cost real.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Test Automation Goals & Principles
|
|
2
|
+
|
|
3
|
+
Reference file for the `test-design-advisor`, `test-health`, and `cd-test-architecture` skills and the `test-smell-review` agent. This is the **value system** behind every other test knowledge file: the goals a test suite exists to serve and the principles that, when followed, keep it serving them. Use it as the **rubric** when *evaluating* a suite ("is this test good, and why/why not?") and as the **design constraints** when *recommending* a target architecture.
|
|
4
|
+
|
|
5
|
+
Source: Gerard Meszaros, *xUnit Test Patterns* (xunitpatterns.com) — Ch. 3 *Goals of Test Automation* and Ch. 5 *Principles of Test Automation*. Language- and framework-agnostic.
|
|
6
|
+
|
|
7
|
+
Core idea: every smell in `test-smells.md` is a **violated principle**, and every pattern in the other files is a **way to honor one**. A finding is more credible when it names the goal it protects and the principle it restores — not just "this is a smell."
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Goals — what the suite is *for*
|
|
12
|
+
|
|
13
|
+
A test is worth its maintenance cost only if it advances these. Grade each goal **served / weak / absent**.
|
|
14
|
+
|
|
15
|
+
| Goal | What it means | Lost when… |
|
|
16
|
+
|------|---------------|------------|
|
|
17
|
+
| **Tests as Specification** | The test states intended behavior before/while the code is written | Tests are written after the fact to match what the code already does |
|
|
18
|
+
| **Tests as Documentation** | A reader learns the SUT's behavior from the test alone | Obscure Test — intent buried in setup, helpers, magic values |
|
|
19
|
+
| **Defect Localization** | A failure points at *which* behavior broke, narrowly | Eager Test / shared fixtures — many tests fail together, none pinpoints |
|
|
20
|
+
| **Bug Repellent** | Tests catch regressions, so defects don't recur | Coverage gaps; tests that can't fail (see Buggy Tests) |
|
|
21
|
+
| **Fully Automated Test** | Runs with no human steps | Manual Intervention — someone seeds data or flips config |
|
|
22
|
+
| **Self-Checking Test** | The test decides pass/fail itself, no eyeballing output | Asserts missing; result printed but not verified |
|
|
23
|
+
| **Repeatable Test** | Same result every run, any order, anywhere | Erratic Test — clock/RNG/order/shared-resource dependence |
|
|
24
|
+
| **Robust Test** | Survives changes unrelated to the behavior it checks | Fragile Test — bound to internals, signatures, or call sequences |
|
|
25
|
+
| **Simple / Expressive Test** | Minimal, readable, one concern | Conditional logic, duplication, over-mocked interaction checks |
|
|
26
|
+
|
|
27
|
+
The first three are the *return* on the suite; the rest are the *conditions* that keep that return from leaking away. A suite that is green but **not Repeatable or not Robust** is a liability, not an asset — flag it as such.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## The Principles — how to honor the goals
|
|
32
|
+
|
|
33
|
+
The named principles, each with the test it should pass and the smell it prevents. When evaluating a test, walk this list; when designing one, treat it as a checklist.
|
|
34
|
+
|
|
35
|
+
| Principle | The rule | Honoring move | Violation smell |
|
|
36
|
+
|-----------|----------|---------------|-----------------|
|
|
37
|
+
| **Write the Test First** | Let the test drive the design; testability falls out for free | TDD red-green-refactor (`test-driven-development` skill) | Hard-to-Test Code retrofitted later |
|
|
38
|
+
| **Design for Testability** | The code must be reachable through a clean seam | Seams from `testability-patterns.md` | Hard-to-Test Code |
|
|
39
|
+
| **Use the Front Door First** | Exercise via the public API; verify via observable state | Round-trip test + State Verification | Overcoupled/Overspecified Software (Back Door overuse) |
|
|
40
|
+
| **Communicate Intent** | The test reads as a statement of behavior (≤ ~10 lines of logic) | Intent-revealing names, Test Utility Methods | Obscure Test |
|
|
41
|
+
| **Don't Modify the SUT** | Test the code you'll actually ship, in a representative config | Double *collaborators*, never the SUT itself | testing a stand-in instead of the SUT |
|
|
42
|
+
| **Keep Tests Independent** | Each test runs alone and in any order | Fresh Fixture per test; no shared writable state | Interacting Tests / Erratic Test |
|
|
43
|
+
| **Isolate the SUT** | Control every input by replacing what you don't test | Injection / lookup + the right double | Context Sensitivity (Fragile Test) |
|
|
44
|
+
| **Minimize Test Overlap** | Each condition covered by exactly one test | Test concerns separately; prune redundant tests | High Test Maintenance Cost |
|
|
45
|
+
| **Minimize Untestable Code** | Move logic out of hard-to-instantiate shells | Humble Object (`testability-patterns.md`) | Untested Code → Production Bugs |
|
|
46
|
+
| **Keep Test Logic Out of Production** | No `if (testing)` paths in shipped code | Seams, not back doors | Test Logic in Production |
|
|
47
|
+
| **Verify One Condition per Test** | One exercise, one logical assertion's worth of verification | Split tests; Custom Assertion to keep one call | Eager Test / Assertion Roulette |
|
|
48
|
+
| **Test Concerns Separately** | One behavior per test method/class | One Testcase Class per concern | Eager Test; poor Defect Localization |
|
|
49
|
+
| **Ensure Commensurate Effort** | Test effort/tooling ≤ feature effort/tooling | Data-Driven Test for config-shaped behavior | tests harder to write than the code |
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Using this as a rubric (evaluation)
|
|
54
|
+
|
|
55
|
+
For a given test or suite:
|
|
56
|
+
|
|
57
|
+
1. **Name the goals at risk.** Is it Repeatable? Robust? Does a failure localize? If any are *absent*, that is the headline finding — the suite is not yet trustworthy.
|
|
58
|
+
2. **Trace each finding to a principle.** "This is fragile" → *Isolate the SUT* / *Use the Front Door First* violated. The principle names the fix's direction.
|
|
59
|
+
3. **Reach for the pattern that restores it.** The remedy lives in `fixture-construction.md`, `result-verification.md`, `test-organization.md`, `test-doubles.md`, `value-patterns.md`, or `testability-patterns.md`.
|
|
60
|
+
|
|
61
|
+
A useful order of severity when grading: a suite that **can't fail** or **can't be trusted** (Buggy/Erratic) outranks one that is merely **hard to read or maintain** (Obscure/Fragile), which outranks **stylistic** issues.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## How this connects to the rest of the toolkit
|
|
66
|
+
|
|
67
|
+
- **`test-smells.md`** — each smell is the negative image of a principle here; that file is the detection layer, this is the *why*.
|
|
68
|
+
- **`test-refactoring.md`** — the behavior-preserving moves from a violated principle to an honored one.
|
|
69
|
+
- **`fixture-construction.md` / `result-verification.md` / `test-organization.md` / `value-patterns.md`** — the patterns that honor specific principles.
|
|
70
|
+
- **`testability-patterns.md`** — *Design for Testability*, *Minimize Untestable Code*, *Isolate the SUT* as production-code seams.
|
|
71
|
+
- **`cd-test-architecture.md` / `test-pyramid.md`** — *Keep Tests Independent* and *Repeatable Test* scaled up to pipeline determinism.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Test-Cadence Tradeoffs: Evidence Bar for Displacing the Standing Cadence
|
|
2
|
+
|
|
3
|
+
`/build` runs exactly one cadence today — Code-First Small Batches — per
|
|
4
|
+
[ADR 0017](../../../docs/adr/0017-single-build-cadence-remove-classic-tdd-opt-in.md),
|
|
5
|
+
which removed the `--tdd` opt-in. Its stated reopening condition is scoped
|
|
6
|
+
to Classic TDD specifically ("a future, larger-corpus run of Experiment 5
|
|
7
|
+
... shows Classic TDD closing the cost gap"), but the principle behind it —
|
|
8
|
+
"that is a new decision to make with new evidence" — applies by the same
|
|
9
|
+
logic to any other cadence claim. This file is the operational note for
|
|
10
|
+
applying that bar to one such claim — batch-red-per-class (issue #1702) —
|
|
11
|
+
and for any future claim of the same shape.
|
|
12
|
+
|
|
13
|
+
## The standing default: Code-First Small Batches
|
|
14
|
+
|
|
15
|
+
**Code-First Small Batches** (IMPLEMENT → TEST → REFACTOR per behavior,
|
|
16
|
+
refactor on every green) is `/build`'s sole cadence (`plugins/dev-team/CLAUDE.md`
|
|
17
|
+
Core Principle 6, decided in ADR 0017). The decision rests on Experiment 5
|
|
18
|
+
(`docs/experiments/05-final-results.md`, n=24 cells/arm): $0.99/cell at
|
|
19
|
+
quality 0.961, versus Classic TDD's $1.59/cell at quality 0.966 —
|
|
20
|
+
statistically indistinguishable on maintainability, though Classic TDD
|
|
21
|
+
posts slightly lower mutation coverage — and Classic TDD is explicitly
|
|
22
|
+
endorsed by `docs/experiments/RECOMMENDATIONS.md` as a "sound second
|
|
23
|
+
choice." The big-batch and split-authorship shapes
|
|
24
|
+
tested in the same experiment line cost 2-4.5x more with worse
|
|
25
|
+
changeability (`docs/experiments/RECOMMENDATIONS.md` § 3) — a materially
|
|
26
|
+
larger gap than Classic TDD's ~60%, and not the comparison a new cadence
|
|
27
|
+
claim needs to clear.
|
|
28
|
+
|
|
29
|
+
## The external claim: batch-red-per-class
|
|
30
|
+
|
|
31
|
+
claude-flow's batch-vs-strict-TDD experiment (see the competitive analysis
|
|
32
|
+
in issue #1702) reports that batch-red-per-class testing (the source calls
|
|
33
|
+
it "batch-per-class") — write all tests for a unit, verify they fail as a
|
|
34
|
+
batch, then implement — is 46% cheaper and 61% more efficient (by test-run
|
|
35
|
+
count) than *plain strict row-by-row TDD*, with equivalent quality
|
|
36
|
+
(mutation-testing parity). That baseline is not this repo's Classic TDD
|
|
37
|
+
arm (`tdd-refactor`, which mandates a refactor after every green), and the
|
|
38
|
+
corpus and harness are claude-flow's, not this repo's.
|
|
39
|
+
Nothing in this repo's own experiment line measured
|
|
40
|
+
batch-red-per-class, so the claim doesn't yet compare to either of our two
|
|
41
|
+
validated cadences.
|
|
42
|
+
|
|
43
|
+
## The decision rule
|
|
44
|
+
|
|
45
|
+
**Do not adopt batch-red-per-class, and do not remove or deprecate
|
|
46
|
+
`skills/test-driven-development/SKILL.md`, on the strength of the external
|
|
47
|
+
claim alone.** This mirrors a working rule the repo already holds itself to
|
|
48
|
+
(root `CLAUDE.md` → "Deterministic tools over inference" /
|
|
49
|
+
"Verify a runtime property by exercising it at runtime"): an unreplicated
|
|
50
|
+
external report is a hypothesis, not a result, for a question this repo's
|
|
51
|
+
own experiment harness can answer directly.
|
|
52
|
+
|
|
53
|
+
| Question | Answer |
|
|
54
|
+
| --- | --- |
|
|
55
|
+
| Does an unreplicated external cadence claim, by itself, meet ADR 0017's reopening bar? | **No** — that bar is "a new decision to make with new evidence" from this repo's own harness, not a citation of someone else's. |
|
|
56
|
+
| Should `/build` switch its default cadence to batch-red-per-class? | **Not yet** — no local evidence exists. See `docs/experiments/test-cadence-validation-plan.md` for what a local run would require (monorepo-only — that path is dev-repo process and isn't present in an installed plugin). |
|
|
57
|
+
| Should strict TDD (`skills/test-driven-development`) be removed? | **Not yet** — same reason; it remains available advisory guidance per ADR 0017. |
|
|
58
|
+
| Should a `batch-red-verified` gate be added to `/build`? | **Not yet** — contingent on a local result, including "don't adopt it" as a valid outcome. Tracked as issue #1727. |
|
|
59
|
+
|
|
60
|
+
## Local measurement, once you have a result
|
|
61
|
+
|
|
62
|
+
Use `.claude/metrics/` (see `skills/performance-metrics/SKILL.md`) to keep
|
|
63
|
+
measuring cost/efficiency on real `/build` runs after adopting any cadence
|
|
64
|
+
change, the same way the plugin already tracks cost regressions elsewhere
|
|
65
|
+
(`skills/cost-report/SKILL.md`). A cadence change that looked good in a
|
|
66
|
+
local experiment must keep looking good in production use, or it gets
|
|
67
|
+
revisited — and, per ADR 0017, any change to the standing cadence is itself
|
|
68
|
+
a new ADR, not a knowledge-file edit.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Test Doubles
|
|
2
|
+
|
|
3
|
+
Reference file for `test-smell-review`, `test-review`, and the `test-design-advisor` skill. A test double is any object that stands in for a real collaborator in a test. Choosing the wrong kind of double is the most common cause of fragile, over-specified tests.
|
|
4
|
+
|
|
5
|
+
Source taxonomy: Gerard Meszaros, *xUnit Test Patterns* (xunitpatterns.com). Language-agnostic — described by role, not by any mocking library's API.
|
|
6
|
+
|
|
7
|
+
Core principle: **prefer the simplest double that lets the test verify the behavior.** Reach for a Mock only when the interaction *is* the behavior under test. Over-mocking couples tests to implementation and produces the Overspecified Software smell (see `test-smells.md`).
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## The Five Doubles
|
|
12
|
+
|
|
13
|
+
| Double | What it does | Verification style | Use when |
|
|
14
|
+
|--------|-------------|-------------------|----------|
|
|
15
|
+
| **Dummy** | Passed but never used; fills a required parameter | none | A constructor/method signature demands an argument the test path never touches |
|
|
16
|
+
| **Stub** | Returns canned answers to calls made during the test | **state** (assert on the SUT's output/state) | The SUT *reads* from a collaborator and you need to control what it reads (config, query result, clock) |
|
|
17
|
+
| **Spy** | A stub that also records how it was called, for later inspection | **behavior** (assert after the act) | You need to confirm an outgoing call happened, but want to assert *after* the action, not pre-program expectations |
|
|
18
|
+
| **Mock** | Pre-programmed with expectations; fails the test if calls don't match | **behavior** (expectations verified) | The interaction itself is the observable behavior (e.g., "an email *is sent*") and there's no state to assert on |
|
|
19
|
+
| **Fake** | A working but lightweight implementation (in-memory DB, in-memory queue) | **state** | A stub/mock would need so much call-by-call setup that a real-ish implementation is simpler and more faithful |
|
|
20
|
+
|
|
21
|
+
A **Test Spy** and a **Mock** both do behavior verification; the difference is *when* and *how* you specify expectations. Spy = act, then assert on recorded calls. Mock = set expectations up front, library verifies them. Spies usually read better and fail less cryptically.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## State Verification vs. Behavior Verification
|
|
26
|
+
|
|
27
|
+
| | State verification | Behavior verification |
|
|
28
|
+
|---|---|---|
|
|
29
|
+
| **Asserts on** | The SUT's return value or resulting state | The calls the SUT made to collaborators |
|
|
30
|
+
| **Doubles used** | Stub, Fake | Mock, Spy |
|
|
31
|
+
| **Coupling** | Low — survives refactors that preserve outcome | High — breaks when the *how* changes, even if outcome is identical |
|
|
32
|
+
| **Default?** | **Yes — prefer this** | Only when there's no observable state to assert |
|
|
33
|
+
|
|
34
|
+
Rule of thumb: if you *can* assert on a result or a state change, do that and use a Stub/Fake. Use a Mock/Spy only for genuine side-effect-only boundaries — sending a message, writing to a log/queue, calling a payment gateway — where the call is the whole point.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Choosing a Double (decision flow)
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
Does the SUT READ from the collaborator (needs a controlled answer)?
|
|
42
|
+
├─ YES → can you then assert on the SUT's output or state?
|
|
43
|
+
│ ├─ YES → Stub (state verification). Done.
|
|
44
|
+
│ └─ NO, the read drives a side effect you must confirm → Spy
|
|
45
|
+
│
|
|
46
|
+
Does the SUT only WRITE to the collaborator (side-effect-only boundary)?
|
|
47
|
+
├─ YES → is the call itself the behavior under test (email sent, event published)?
|
|
48
|
+
│ ├─ YES → Mock or Spy (behavior verification)
|
|
49
|
+
│ └─ NO, it's incidental → Dummy or a no-op Stub; don't assert on it
|
|
50
|
+
│
|
|
51
|
+
Is per-call stub/mock setup so heavy it obscures the test?
|
|
52
|
+
└─ YES → Fake (in-memory implementation), assert on its resulting state
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## How the double is built: Configurable vs. Hard-Coded
|
|
58
|
+
|
|
59
|
+
The five doubles above are *roles*; this is the orthogonal question of *how the double gets its canned answers*. Both forms are legitimate — the choice is about reuse vs. transparency.
|
|
60
|
+
|
|
61
|
+
| Form | What it is | Use when | Watch for |
|
|
62
|
+
|------|-----------|----------|-----------|
|
|
63
|
+
| **Configurable Test Double** | A reusable double the test programs at run time with the values to return / calls to expect (what Mockito/JMock/NSubstitute/Sinon generate) | The same collaborator is doubled across many tests with different canned values; you want one mechanism, configured per test | Configuration becomes so verbose it obscures the test — a sign to extract a builder or downgrade a Mock to a Stub |
|
|
64
|
+
| **Hard-Coded Test Double** | A purpose-built class (or *Inner Test Double* — a nested/anonymous class, or a Test-Specific Subclass) with the canned values **baked into its code** | The behavior is specific to one or a few tests; a framework can't express it; or you want a named, self-documenting stand-in | Proliferation of one-off double classes; if it recurs with varying data, switch to a Configurable form |
|
|
65
|
+
|
|
66
|
+
Neither is "better." Reach for a **Configurable** double when one collaborator is stubbed many ways across the suite; reach for a **Hard-Coded** double when a specific, named behavior reads more clearly than per-test configuration (or the framework can't produce it).
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Test-Specific Subclass
|
|
71
|
+
|
|
72
|
+
When you can't substitute a collaborator from outside — the dependency is created internally, or the thing you need to control is a *method of the SUT itself* — subclass the real class **in the test** and override just the seam method to inject an indirect input or null out an unwanted side effect.
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
// Override only the narrow seam; inherit everything else real
|
|
76
|
+
class TestableOrderService extends OrderService:
|
|
77
|
+
override fetchRate(): return 1.25 // control one indirect input
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Use it to: gain control of an indirect input without a full injection refactor; expose a protected hook for the test; or stand up a Hard-Coded double by subclassing a real collaborator. **Constraints** (from *Don't Modify the SUT*, `test-automation-principles.md`): override **only** what the test must control — never a method whose behavior this test is verifying, or you're testing the override, not the code. Treat it as a bridge toward a real seam (`testability-patterns.md`), not a permanent design.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Common Misuses (flag these)
|
|
85
|
+
|
|
86
|
+
| Misuse | Why it's wrong | Fix |
|
|
87
|
+
|--------|---------------|-----|
|
|
88
|
+
| Mocking a value object or pure function | Nothing to verify; adds coupling for zero benefit | Use the real object |
|
|
89
|
+
| Mocking the type under test | You're testing the mock, not the code | Use the real SUT; double only its *collaborators* |
|
|
90
|
+
| Asserting exact call order/count when order doesn't matter | Overspecified Software smell; fragile | State verification, or assert only the call that matters |
|
|
91
|
+
| Stub returns drive an `if` that's never asserted | Dead control; the test proves nothing about that branch | Assert the branch's effect, or remove the setup |
|
|
92
|
+
| A Mock where a Stub would do (no side-effect being verified) | Tests implementation detail instead of outcome | Downgrade to Stub + state assertion |
|
|
93
|
+
| Mocking a concrete class instead of an interface/port | Couples to the implementation type; see `testability-patterns.md` | Extract an interface/port; double that |
|
|
94
|
+
| Mocking a collaborator internal to / owned by the same component or bounded context as the SUT | This is a boundary-selection error, distinct from the injection-mechanism problem above — the collaborator isn't a true external-boundary system (third-party API, another team's service, infra the team doesn't control), it's part of what should be under test. Applies at or below the component layer regardless of whether the test declares itself solitary or sociable — no unit-test exemption exists | Assemble the real component and exercise the collaborator as real (sociable unit/component test); double only when the collaborator matches a named blocker — see `internal-collaborator-doubling.md` for the full rule and `component-test-patterns.md`'s core principle |
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Relationship to testability
|
|
99
|
+
|
|
100
|
+
If a collaborator can't be substituted at all (new-ed up internally, static singleton, hidden global), that's a **production-code** problem, not a test problem — introduce a seam per `testability-patterns.md` (constructor injection, interface extraction) before choosing a double. The double taxonomy assumes the collaborator is already injectable.
|
|
101
|
+
|
|
102
|
+
## Boundaries
|
|
103
|
+
|
|
104
|
+
- Don't flag a Fake (in-memory repo/DB) as "not testing the real thing" — at unit/integration level a Fake is a legitimate, often *better*, choice than a heavily-stubbed real dependency. Real-dependency fidelity is the job of contract and integration tests (see `test-pyramid.md`, `microservice-testing.md`).
|
|
105
|
+
- A single Mock at a true side-effect boundary is correct, not a smell. The smell is *pervasive* mocking that pins down internal call sequences.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Test File Indicators
|
|
2
|
+
|
|
3
|
+
Canonical list of how to recognize a test file by language. Agents and skills
|
|
4
|
+
that need to decide "is this a test?" (for skip logic or for scoping a Farley
|
|
5
|
+
Score) cite this file rather than restating the list, so a newly-supported
|
|
6
|
+
framework annotation is added in one place.
|
|
7
|
+
|
|
8
|
+
A `.feature` file always counts as a test file — never skip a target that
|
|
9
|
+
contains feature files.
|
|
10
|
+
|
|
11
|
+
## Indicators by language
|
|
12
|
+
|
|
13
|
+
| Language | A file is a test when it… |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| **JS/TS** | matches `*.test.*`, `*.spec.*`, or lives inside `__tests__/` |
|
|
16
|
+
| **C#** | is a `.cs` file containing `[Fact]`, `[Theory]`, `[Test]`, `[TestCase]`, `[TestMethod]`, or `[TestClass]` |
|
|
17
|
+
| **Java** | is a `.java` file containing `@Test`, `@ParameterizedTest`, `@TestFactory`, or a class name ending in `Test`, `Tests`, `TestCase`, or `Spec` |
|
|
18
|
+
| **Python** | matches `test_*.py` or `*_test.py` (pytest/unittest convention) |
|
|
19
|
+
| **BDD/Gherkin** | is a `.feature` file, or a step-definition file (`*.steps.*`, `*StepDefinitions.*`, `*Steps.*`) |
|
|
20
|
+
|
|
21
|
+
When a target contains none of the above, an agent scoped to test files
|
|
22
|
+
returns its `skip` status.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Test Layer Gates
|
|
2
|
+
|
|
3
|
+
Reference file for the `test-design-advisor` skill. The pyramid heuristic (`test-pyramid.md`) picks the *lowest* layer that verifies a behavior. These **pre-gates** run first and **escalate upward only** — never lower the pick — when a behavior can break in a way the lowest layer misses (Swiss-cheese model).
|
|
4
|
+
|
|
5
|
+
Layers match `test-pyramid.md` (unit / integration / component / contract / E2E) and map to `cd-test-architecture.md`'s six test types — see its *Terminology Reconciliation* section.
|
|
6
|
+
|
|
7
|
+
**business-critical** = labelled so in the input, or confirmed when the advisor asks. The redundancy check fires only on a positive determination.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## The gates (before pyramid placement)
|
|
12
|
+
|
|
13
|
+
**Gate A — user-facing dynamic.** The user acts and must *see* a rendered result. → E2E **alongside** lower layers. State the slow/flaky cost; amortize by extending or grouping into a journey test.
|
|
14
|
+
|
|
15
|
+
**Gate B — bug-fix regression.** → regression at the **layer the bug was discovered** (browser → E2E; unit-debug → unit). Must fail on old code, pass on the fix. Never escalates above the discovery layer.
|
|
16
|
+
|
|
17
|
+
**Gate C — dynamic-swap delivery chain.** An HTMX / Alpine / Turbo / LiveWire swap. → browser test **REQUIRED** (not "recommended"); integration is complementary, not sufficient. Holds with no server state change too (structural seam: wrong `hx-target`, stale swap, re-init).
|
|
18
|
+
|
|
19
|
+
**Gate D — visual fidelity.** Output whose layout/appearance matters (PDF, print, email, receipt). With a reference: approval (text) and/or screenshot (CSS/layout), surfacing maintenance cost. No reference: manual review + suggest creating one.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Redundancy check (business-critical only, after placement)
|
|
24
|
+
|
|
25
|
+
A business-critical behavior at only one layer → flag it, name a second layer with a **different failure mode**, and give a concrete recommendation. Catches/misses:
|
|
26
|
+
|
|
27
|
+
| Layer | Catches | Misses |
|
|
28
|
+
|-------|---------|--------|
|
|
29
|
+
| Unit | logic, edge cases | wiring, integration, UI |
|
|
30
|
+
| Integration | routing, persistence, security | client behavior, rendering |
|
|
31
|
+
| Component/Frontend | wiring, DOM, attributes | backend logic, real network |
|
|
32
|
+
| Contract | API-shape drift | semantic/business bugs |
|
|
33
|
+
| E2E | full-stack, real browser | slow, flaky, poor localization |
|
|
34
|
+
|
|
35
|
+
When a gate mandates application-level E2E, **flag the seam (`→ cd-test-architecture`) and defer the harness/pipeline design** to `cd-test-architecture`. This file stays at unit/module altitude.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Worked example — Django API + scheduled batch job
|
|
2
|
+
|
|
3
|
+
Few-shot template for `test-design-advisor`. Adapt the rows. Feature: **a nightly job reads pending invoices, charges a payment gateway through an owned adapter, and emails receipts**. Orchestration/adapter-heavy, little domain logic → **diamond** shape (`test-pyramid.md`).
|
|
4
|
+
|
|
5
|
+
## Pyramid placement (advisor output shape)
|
|
6
|
+
|
|
7
|
+
| Behavior | Layer | Gate | Tool (`test-stack-profiles/django`) | Why |
|
|
8
|
+
|----------|-------|------|-------------------------------------|-----|
|
|
9
|
+
| "Invoice is due" predicate | Unit | — | pytest | the one bit of real logic |
|
|
10
|
+
| Job selects due invoices, skips paid, marks charged | Component | — | pytest + Django test DB, gateway/email **adapters doubled** | the orchestration — run pre-merge without real gateway |
|
|
11
|
+
| Payment adapter speaks the gateway's real protocol | Integration | — | pytest + recorded/contract sandbox | the adapter actually works (own your boundaries — `cd-test-architecture.md`) |
|
|
12
|
+
| Receipt PDF/email layout is correct | — | ↑ (Gate D) | approval (text) / screenshot (layout) | visual-fidelity artifact (`test-layer-gates.md`) |
|
|
13
|
+
|
|
14
|
+
## Quadrants (`testing-quadrants.md`)
|
|
15
|
+
|
|
16
|
+
Q1 thin (correctly — little logic) · Q2 acceptance example for the "skip already-paid" rule · Q3 N/A · **Q4 important** → resilience: what happens when the gateway times out mid-run? → **chaos**.
|
|
17
|
+
|
|
18
|
+
## Techniques (`testing-techniques/`, on match)
|
|
19
|
+
|
|
20
|
+
Gateway timeout/partial-failure resilience → **chaos**. Receipt email body vs a golden file → **approval**. Idempotency of a re-run after a crash → property/scenario coverage.
|
|
21
|
+
|
|
22
|
+
## Notes
|
|
23
|
+
|
|
24
|
+
The wide component middle is right for a diamond — the value is in orchestration, not unit logic; don't pad the unit base with tests that just exercise the framework. Double the **owned adapter**, never the gateway SDK directly (`cd-test-architecture.md` → the adapter rule).
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Worked example — ASP.NET Core API fronting gRPC microservices
|
|
2
|
+
|
|
3
|
+
Few-shot template for `test-design-advisor`. Adapt the rows. Feature:
|
|
4
|
+
**an ASP.NET Core 8 Web API fronts several owned gRPC microservices
|
|
5
|
+
(`AccountService`, `PaymentService`, `LedgerService`) behind hand-written
|
|
6
|
+
adapter ports; a SQL store via Dapper persists ledger entries; a
|
|
7
|
+
`POST /payments` endpoint authorizes the caller, debits the account via
|
|
8
|
+
`PaymentService`, writes a ledger entry via Dapper, and returns a result**.
|
|
9
|
+
This is a common payments / banking / e-commerce shape: rich domain logic
|
|
10
|
+
fronts multiple owned remote dependencies; the gate must stay deterministic
|
|
11
|
+
without standing up the back-end services.
|
|
12
|
+
|
|
13
|
+
Layer names use the MinimumCD six test types from
|
|
14
|
+
`knowledge/cd-test-architecture.md` § *The Six Test Types*.
|
|
15
|
+
|
|
16
|
+
## Pyramid placement (advisor output shape)
|
|
17
|
+
|
|
18
|
+
| Behavior | Layer | Gate | Tool (`test-stack-profiles/dotnet`) | Why this layer (not the one above or below) |
|
|
19
|
+
|----------|-------|------|--------------------------------------|---------------------------------------------|
|
|
20
|
+
| Authorization policy denies non-payer caller | Unit | — | xUnit + `AuthorizationHandlerContext` | pure policy logic; a component test would only re-execute the same code through HTTP middleware |
|
|
21
|
+
| `PaymentDomainService` orchestrates rule + debit + ledger (no over-limit) | Unit (sociable) | — | xUnit + stub adapters | wires collaborators; a component test would re-execute the same orchestration through HTTP for no extra signal |
|
|
22
|
+
| `IPaymentServiceAdapter` translates `DebitRequest` → gRPC request and `Ack` → domain reply | Contract | — | xUnit + in-memory gRPC channel (`Grpc.Core.Testing`) or stubbed `CallInvoker` | pin the request/response shape at the boundary; a unit test of the adapter would not exercise gRPC serialization, an integration test would couple the gate to a running provider |
|
|
23
|
+
| `PaymentServiceAdapter` survives a provider timeout / cancellation / malformed reply | Resilience | — | xUnit + simulated `CallInvoker` returning `RpcException`/timeout | failure-mode coverage at the seam; lower than a component test (no HTTP path needed), higher than a unit test (the adapter's failure translation IS the behavior under test) |
|
|
24
|
+
| `ILedgerRepository` (Dapper) writes + reads back a ledger row | Contract | — | xUnit + in-memory SQL fake (e.g. SQLite in-memory) | pins the SQL the adapter emits without the gate depending on a real container; a unit test cannot exercise SQL, an integration test moves it off the gate |
|
|
25
|
+
| `LedgerRepository` against the real SQL flavor (column types, isolation) | Integration (Stage 1 / 2, NOT pre-merge) | off-gate | xUnit + Testcontainers (MS SQL / PG) | the contract test pins shape but cannot prove the real engine accepts the SQL; non-deterministic / requires a container ⇒ never gates the merge per MinimumCD |
|
|
26
|
+
| `POST /payments` end-to-end through middleware, validation, controller, doubled adapters | Component | — | `WebApplicationFactory<Program>` + `HttpClient` + in-process double registrations (Test doubles for `IPaymentServiceAdapter`, `ILedgerRepository`) | exercises the assembled in-process app deterministically; a contract test cannot cover request validation + controller wiring + auth pipeline together; an E2E test would need the back-end services |
|
|
27
|
+
| Cross-cutting filter / exception middleware translates `DomainException` → 422 | Unit | — | xUnit + constructed `HttpContext` | the middleware IS the unit; a component test would only re-prove the same translation through HTTP |
|
|
28
|
+
| Other consumers still accept our `PaymentResult` response shape (and we still accept `PaymentService` reply shape) | Contract | — | Pact / Protobuf schema check against the provider's generated `.proto` (see `microservice-testing.md`) | cross-boundary agreement — never E2E; provider cooperation is not required |
|
|
29
|
+
| Provider adapters' in-memory doubles match the real provider | Scheduled provider verification | out-of-band | nightly job hitting provider test env | proves the in-memory double has not drifted from reality; lower-layer contract tests are insufficient on their own |
|
|
30
|
+
| Critical user journey: a successful payment + ledger write + downstream consumer sees the event (post-deploy) | E2E | post-deploy smoke | one Playwright/HTTP scenario in a deployed environment | (1) contract tests cannot cover the *real* multi-service propagation; (2) component test stubs all adapters; (3) resilience covers failure modes, not the happy path across real services; (4) the payment-confirmed journey is a critical real-component crossing — non-deterministic, NEVER pre-merge per MinimumCD |
|
|
31
|
+
|
|
32
|
+
## E2E justification (only the last row)
|
|
33
|
+
|
|
34
|
+
The advisor's E2E justification block for this matrix lists exactly one
|
|
35
|
+
behavior. The other rows show how the four-condition gate forces every
|
|
36
|
+
other behavior into a lower layer.
|
|
37
|
+
|
|
38
|
+
## Quadrants (`testing-quadrants.md`)
|
|
39
|
+
|
|
40
|
+
Q1 strong ✓ · Q2 add a BDD acceptance example for "deny over-limit" before
|
|
41
|
+
coding · Q3 minimal (API, no UI) · **Q4** → security-review the auth on
|
|
42
|
+
`/payments`; load-test if it's a hot path. For payments specifically:
|
|
43
|
+
PCI-DSS / SOC 2 coverage of the boundary level (contract pins, resilience
|
|
44
|
+
under provider outage, characterization for any legacy SQL touching
|
|
45
|
+
cardholder data) — flag to security-engineer if a `security-primitives`
|
|
46
|
+
contract is not yet in place.
|
|
47
|
+
|
|
48
|
+
## Doubles strategy
|
|
49
|
+
|
|
50
|
+
| Test | Collaborator | Double | Verify by |
|
|
51
|
+
|------|--------------|--------|-----------|
|
|
52
|
+
| `PaymentDomainService` unit | `IPaymentServiceAdapter` | Stub | State (returned `PaymentResult`) |
|
|
53
|
+
| `PaymentDomainService` unit | `ILedgerRepository` | Stub | State (returned `PaymentResult`) |
|
|
54
|
+
| `IPaymentServiceAdapter` contract | gRPC `CallInvoker` | In-memory fake / stubbed invoker | State (returned domain `Ack`) |
|
|
55
|
+
| `IPaymentServiceAdapter` resilience | gRPC `CallInvoker` | Stub that throws `RpcException`/timeout | State (translated domain error) |
|
|
56
|
+
| `ILedgerRepository` contract | SQL connection | In-memory SQL fake (SQLite) | State (round-trip row) |
|
|
57
|
+
| `POST /payments` component | `IPaymentServiceAdapter` | Stub registered in `WebApplicationFactory` | State (HTTP 200 + body) |
|
|
58
|
+
| `POST /payments` component | `ILedgerRepository` | Stub | State (HTTP 200 + body) |
|
|
59
|
+
| Provider contract | the real `PaymentService` provider | None (real provider in scheduled job) | Schema agreement |
|
|
60
|
+
|
|
61
|
+
Default to state verification and the simplest double per
|
|
62
|
+
`knowledge/test-doubles.md`. Use a mock/spy only when a true side-effect
|
|
63
|
+
boundary requires it (e.g. asserting "an audit event was published" when
|
|
64
|
+
the publisher is fire-and-forget).
|
|
65
|
+
|
|
66
|
+
## Techniques (`testing-techniques/`, on match)
|
|
67
|
+
|
|
68
|
+
Money math invariants (sum preserved across a transfer) →
|
|
69
|
+
**property-based**. Resilience claim "degrades if `PaymentService` is
|
|
70
|
+
down" → **chaos** at the adapter seam. Generated wire formats (proto3) →
|
|
71
|
+
**schema-validation** at the contract layer.
|
|
72
|
+
|
|
73
|
+
## Notes
|
|
74
|
+
|
|
75
|
+
- Keep the authorization policy a **unit** test, not a component test —
|
|
76
|
+
driving HTTP middleware to prove the same `requirement.Succeed()` call
|
|
77
|
+
is "testing through the UI for logic" anti-pattern.
|
|
78
|
+
- The **contract** tests for adapters pin shape and behavior; they are
|
|
79
|
+
always pre-merge. The **integration** tests against Testcontainers /
|
|
80
|
+
real providers prove the adapter's understanding of the real engine
|
|
81
|
+
matches reality, and are always **off the gate**.
|
|
82
|
+
- The single **E2E** test exists because no other layer can prove the
|
|
83
|
+
payment + ledger + downstream propagation across multiple owned
|
|
84
|
+
services in a real environment. It runs post-deploy as smoke. Adding
|
|
85
|
+
a second E2E "to be thorough" would fail the E2E justification gate.
|
|
86
|
+
- For regulated payment paths (card data, account numbers, secrets),
|
|
87
|
+
confirm coverage at the boundary level — contract pins, resilience
|
|
88
|
+
tests, and characterization tests for any legacy SQL paths handling
|
|
89
|
+
cardholder data. Cite `knowledge/security-primitives-contract.md` if
|
|
90
|
+
present; else flag the gap to `security-engineer`.
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Worked example — ASP.NET Core service calling a third-party HTTP API
|
|
2
|
+
|
|
3
|
+
Few-shot template for `test-design-advisor`. Adapt the rows. Feature:
|
|
4
|
+
**an ASP.NET Core 8 service exposes `POST /orders`; the order handler calls
|
|
5
|
+
an upstream third-party Pricing API over HTTPS (JSON), then persists the
|
|
6
|
+
order to its own SQL store via EF Core; the Pricing API is owned by another
|
|
7
|
+
company — no provider cooperation, no CDC tooling on their side — and is
|
|
8
|
+
flakier than the team's own services**. This is the common
|
|
9
|
+
[API Consumer pattern](../component-test-patterns.md#api-consumer); the
|
|
10
|
+
pre-merge gate must not depend on the upstream being reachable, and the
|
|
11
|
+
consumer must survive provider breakage without notice.
|
|
12
|
+
|
|
13
|
+
Layer names use the MinimumCD six test types from
|
|
14
|
+
`knowledge/cd-test-architecture.md` § *The Six Test Types*. Mechanics for
|
|
15
|
+
the outbound HTTP layer are from
|
|
16
|
+
`knowledge/references/csharp-http-client-testing.md`; tool resolution is from
|
|
17
|
+
`knowledge/test-stack-profiles/dotnet.md`.
|
|
18
|
+
|
|
19
|
+
## Adapter shape (the seam under test)
|
|
20
|
+
|
|
21
|
+
`IPricingClient` is the team-owned thin adapter (Adapter Rule, see
|
|
22
|
+
`knowledge/cd-test-architecture.md#the-adapter-rule-own-your-boundaries`):
|
|
23
|
+
|
|
24
|
+
```csharp
|
|
25
|
+
public interface IPricingClient
|
|
26
|
+
{
|
|
27
|
+
Task<Money> QuoteAsync(Sku sku, CancellationToken ct);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
internal sealed class PricingClient : IPricingClient
|
|
31
|
+
{
|
|
32
|
+
private readonly HttpClient _http; // injected; primary handler is swappable
|
|
33
|
+
private readonly TimeProvider _time; // determinism (Polly + tests)
|
|
34
|
+
public PricingClient(HttpClient http, TimeProvider time) { _http = http; _time = time; }
|
|
35
|
+
// ...
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Wired in production with `services.AddHttpClient<IPricingClient, PricingClient>(...)`;
|
|
40
|
+
in tests, `ConfigurePrimaryHttpMessageHandler(() => stub)` swaps only the
|
|
41
|
+
leaf. The adapter is the single place every "the real thing changed" failure
|
|
42
|
+
localizes to.
|
|
43
|
+
|
|
44
|
+
## Pyramid placement (advisor output shape)
|
|
45
|
+
|
|
46
|
+
| Behavior | Layer | Gate | Tool (`test-stack-profiles/dotnet`) | Why this layer (not the one above or below) |
|
|
47
|
+
|----------|-------|------|--------------------------------------|---------------------------------------------|
|
|
48
|
+
| `Money` arithmetic invariants (sum preserved, no negative quotes) | Unit | — | xUnit + FluentAssertions; **property-based** via FsCheck on the invariant | pure value-object logic; a component test would only re-execute the same arithmetic through HTTP |
|
|
49
|
+
| `OrderDomainService` orchestrates pricing + persistence (no over-limit) | Unit (sociable) | — | xUnit + stub `IPricingClient`, in-memory repo | wires collaborators; a component test would re-execute the same orchestration through HTTP for no extra signal |
|
|
50
|
+
| `PricingClient` builds the correct request (method, path, query, auth header, `Idempotency-Key`, JSON body) and parses the success response | **Contract** | — | xUnit + `StubHttpMessageHandler` capturing `Requests`; structural JSON compare (`knowledge/references/csharp-http-client-testing.md`) | pins request/response shape at the boundary; a unit test of the adapter would not exercise serialization/headers, an integration test would couple the gate to a running provider we don't control |
|
|
51
|
+
| `PricingClient` maps non-2xx (`401`, `404`, `422`, `500`) to typed domain errors | **Contract** | — | xUnit + `StubHttpMessageHandler` returning each status | failure-mapping IS the contract; a component test would only re-prove the same mapping through HTTP |
|
|
52
|
+
| `PricingClient` survives provider flake: retries `503` per Polly policy, opens circuit-breaker after sustained failure, enforces deadline, fast-fails on half-open | **Component** (resilience) | — | xUnit + `StubHttpMessageHandler` queue `[503,503,200]` etc. + `FakeTimeProvider` + Polly v8 pipeline bound to that `TimeProvider` | the resilience policy is the behavior under test; running against the real provider is non-deterministic and would never be a gate; lower than full HTTP component test because no inbound HTTP is needed to verify the outbound seam |
|
|
53
|
+
| `POST /orders` end-to-end through middleware, validation, controller, doubled pricing adapter, in-memory repo | Component | — | `WebApplicationFactory<Program>` + `HttpClient`; register stub `IPricingClient` in `ConfigureTestServices` | exercises the assembled in-process app deterministically; a contract test cannot cover request validation + controller wiring + auth pipeline together; an E2E test would need the real Pricing API |
|
|
54
|
+
| EF Core `OrderRepository` SQL against the real SQL flavor (column types, isolation, EF-generated SQL) | Integration (Stage 1 / 2, NOT pre-merge) | off-gate | xUnit + Testcontainers (PG / SQL Server) | the in-memory EF provider hides SQL bugs; the real engine is non-deterministic / requires a container ⇒ never gates the merge per MinimumCD |
|
|
55
|
+
| The team's hand-rolled `PricingClient` double has not drifted from the real Pricing API | **Scheduled provider verification** | out-of-band (nightly) | xUnit run vs the provider's real *non-prod* endpoint, decoupled from deploys (`cd-test-architecture.md#double-validation-keeping-doubles-honest`) | proves the double still matches reality; lower-layer contract tests cannot, by construction, observe provider drift; we **do not assume provider cooperation** so consumer-owned detection is the only defense |
|
|
56
|
+
| Critical user journey: a successful order across the real deployed system (pricing + persistence + downstream notification) | E2E | post-deploy smoke | one Playwright/HTTP scenario in a deployed environment | (1) contract tests cannot cover real multi-service propagation; (2) component test stubs the pricing adapter; (3) resilience covers failure modes, not the happy path across real services; (4) the order-confirmed journey is a critical real-component crossing — non-deterministic, NEVER pre-merge per MinimumCD |
|
|
57
|
+
|
|
58
|
+
## E2E justification (only the last row)
|
|
59
|
+
|
|
60
|
+
The advisor's E2E justification block for this matrix lists exactly one
|
|
61
|
+
behavior. Every other row above shows how the four-condition gate forces a
|
|
62
|
+
lower layer.
|
|
63
|
+
|
|
64
|
+
## Doubles strategy
|
|
65
|
+
|
|
66
|
+
| Test | Collaborator | Double | Verify by |
|
|
67
|
+
|------|--------------|--------|-----------|
|
|
68
|
+
| `OrderDomainService` unit | `IPricingClient` | Stub | State (returned `Order`) |
|
|
69
|
+
| `OrderDomainService` unit | `IOrderRepository` | Stub | State (returned `Order`) |
|
|
70
|
+
| `PricingClient` contract — success | `HttpMessageHandler` | `StubHttpMessageHandler` returning canned 200 | State: captured `Requests[0]` (method/path/headers/JSON body) + returned `Money` |
|
|
71
|
+
| `PricingClient` contract — non-2xx | `HttpMessageHandler` | Stub returning each status | State: typed domain error thrown |
|
|
72
|
+
| `PricingClient` resilience | `HttpMessageHandler` + `TimeProvider` | Stub queue + `FakeTimeProvider`; Polly bound to it | State: final outcome + `Requests.Count` (proves retry count) |
|
|
73
|
+
| `POST /orders` component | `IPricingClient` | Stub registered via `ConfigureTestServices` | State (HTTP 200 + persisted order via in-memory repo) |
|
|
74
|
+
| `POST /orders` component | `IOrderRepository` | In-memory fake | State (persisted row) |
|
|
75
|
+
| Scheduled provider verification | the real Pricing API | None — real provider, real network, non-prod env | Schema + status agreement |
|
|
76
|
+
|
|
77
|
+
Default to state verification and the simplest double per
|
|
78
|
+
`knowledge/test-doubles.md`. The stub handler's captured `Requests` list IS
|
|
79
|
+
the state surface — never reach for a behavior mock on `HttpMessageHandler`.
|
|
80
|
+
|
|
81
|
+
## Techniques overlay (`testing-techniques/`)
|
|
82
|
+
|
|
83
|
+
- Money arithmetic invariants → **property-based** (`property-based.md`).
|
|
84
|
+
- Pricing API responds with JSON governed by an OpenAPI schema →
|
|
85
|
+
**schema-validation** at the contract layer (`schema-validation.md`).
|
|
86
|
+
- "Service degrades but stays up when Pricing is down for 30s" →
|
|
87
|
+
**chaos** at the adapter seam (`chaos.md`), realized by the
|
|
88
|
+
`StubHttpMessageHandler` returning timeouts/errors.
|
|
89
|
+
|
|
90
|
+
## Smells to refactor away first
|
|
91
|
+
|
|
92
|
+
Cross-referenced with
|
|
93
|
+
`knowledge/references/csharp-http-client-testing.md` §
|
|
94
|
+
*Common smells in C# HTTP-consumer tests*:
|
|
95
|
+
|
|
96
|
+
- A `Mock<HttpClient>` in any test → wrap in an adapter and double the
|
|
97
|
+
`HttpMessageHandler`.
|
|
98
|
+
- A `Mock<IThirdPartyPricingSdk>` directly → own the adapter; double the
|
|
99
|
+
adapter or its `HttpMessageHandler`.
|
|
100
|
+
- `Thread.Sleep(...)` or `await Task.Delay(...)` waiting for a retry →
|
|
101
|
+
introduce `TimeProvider` + Polly v8 bound to `FakeTimeProvider`.
|
|
102
|
+
- `Assert.Equal("""{"sku":"X"}""", actualJson)` → deserialize and compare
|
|
103
|
+
structurally.
|
|
104
|
+
- A test that needs `appsettings.Test.json` with a real Pricing API URL →
|
|
105
|
+
the test is mis-typed; route it to the scheduled provider verification
|
|
106
|
+
job, not the pre-merge gate.
|
|
107
|
+
|
|
108
|
+
## Quadrants (`testing-quadrants.md`)
|
|
109
|
+
|
|
110
|
+
Q1 strong ✓ · Q2 add a BDD acceptance example for "order rejected when
|
|
111
|
+
pricing fails three times" (Reqnroll; see
|
|
112
|
+
`../test-stack-profiles/dotnet.md` BDD row) · Q3 minimal (API, no UI) ·
|
|
113
|
+
**Q4** → security-review auth/secret handling on the Pricing API
|
|
114
|
+
connection; resilience claims under provider outage cited in any SLO
|
|
115
|
+
documentation.
|
|
116
|
+
|
|
117
|
+
## Notes
|
|
118
|
+
|
|
119
|
+
- The contract tests for `PricingClient` are always pre-merge — they're
|
|
120
|
+
deterministic, in-process, microsecond-fast. The provider-verification
|
|
121
|
+
job is always **off the gate** — it's the *detection* loop for drift,
|
|
122
|
+
and it must run on a clock the build doesn't depend on.
|
|
123
|
+
- Resilience component tests with `FakeTimeProvider` complete in
|
|
124
|
+
microseconds even when the policy says "wait 30s then retry" — the
|
|
125
|
+
Polly pipeline must be configured with that `TimeProvider` for this to
|
|
126
|
+
hold. If a resilience test takes longer than the others, the wiring is
|
|
127
|
+
wrong, not the policy.
|
|
128
|
+
- The single E2E test exists because no lower layer can prove order
|
|
129
|
+
propagation across the real Pricing API and real downstream notification.
|
|
130
|
+
Adding a second E2E "to be thorough" would fail the four-condition gate
|
|
131
|
+
(`cd-test-architecture.md#the-e2e-justification-gate`).
|