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,571 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Stryker xunit.v3 shim gate — PreToolUse hook (#1083, version-gated #2184).
|
|
3
|
+
|
|
4
|
+
Stryker.NET **< 5.0.0** cannot observe mutant kills through xunit.v3:
|
|
5
|
+
xunit.v3 runs on the Microsoft Testing Platform (MTP) and Stryker's per-test
|
|
6
|
+
coverage/kill mapping does not work across it (stryker-net issues 3237/3629/3094).
|
|
7
|
+
A run against a real xunit.v3 test project completes but reports a false near-zero
|
|
8
|
+
score with almost everything "Survived" — silently, since the initial test run
|
|
9
|
+
passes. The fix, on those versions, is a xunit.v2 shim project (see the
|
|
10
|
+
stryker-xunit-v2-shim skill).
|
|
11
|
+
|
|
12
|
+
**Stryker.NET >= 5.0.0 closed this gap** (stryker-net#3752: MTP `perTest`/
|
|
13
|
+
`perTestInIsolation` coverage analysis) — `-t mtp` alone now gives a real
|
|
14
|
+
per-test score against the real xunit.v3 suite, no shim needed. This gate
|
|
15
|
+
detects the installed version via `hooks/mutation_adapters/stryker_net.py`'s
|
|
16
|
+
`stryker_net_version()` and silent-passes an xunit.v3 run on >= 5.0.0 rather
|
|
17
|
+
than scaffolding a shim or blocking (`_version_exempt()`). An undetermined
|
|
18
|
+
version (no `dotnet` on PATH, or unparseable `--version` output) fails closed
|
|
19
|
+
to the < 5.0.0 behavior below, with a note in the block body saying so. See
|
|
20
|
+
`skills/mutation-testing/references/languages/csharp-stryker-net.md`'s
|
|
21
|
+
"Stryker >= 5.0.0" section for the `-t mtp` + `coverage-analysis: perTest` +
|
|
22
|
+
`concurrency: 1` recommendation this gate's silent-pass hands off to
|
|
23
|
+
(the `concurrency: 1` pin is for the OPEN stryker-net#3832 regression).
|
|
24
|
+
|
|
25
|
+
On a `dotnet stryker` run that would produce the false score, this gate
|
|
26
|
+
**auto-scaffolds the shim and reports what it wrote** (it is not silent), then
|
|
27
|
+
blocks the current invocation — a PreToolUse hook cannot change the directory the
|
|
28
|
+
in-flight command runs in, so the shim must be run from its own directory as the
|
|
29
|
+
next step. It guards the two invocations that produce the false score:
|
|
30
|
+
|
|
31
|
+
* `dotnet stryker` in a directory whose test project references xunit.v3
|
|
32
|
+
(project mode bound to v3);
|
|
33
|
+
* `dotnet stryker` at a solution root whose solution contains a xunit.v3 test
|
|
34
|
+
project (solution mode binds to it).
|
|
35
|
+
|
|
36
|
+
It does NOT scaffold blindly: it runs the scope probe first and refuses when the
|
|
37
|
+
sources use v3-only constructs that need manual porting, and it never regenerates
|
|
38
|
+
over a shim that already exists. A run launched from a `*.Mutation` xunit.v2 shim
|
|
39
|
+
directory passes untouched.
|
|
40
|
+
|
|
41
|
+
When those constructs are present the block body is the **operator decision
|
|
42
|
+
gate** (#1791), not just a file list: `xunit_v3_feature_detector.py` classifies
|
|
43
|
+
each construct, `hooks/lib/xunit_v3_operator_gate.py` renders what is blocking
|
|
44
|
+
plus the four remediation options (port / exclude / skip / degrade) with their
|
|
45
|
+
tradeoffs, and the guard **stays blocked until the operator's choice is
|
|
46
|
+
recorded**. That recording is what makes the gate a guarantee rather than hook
|
|
47
|
+
stdout an agent may paraphrase or skip: before #1791 the shim could be silently
|
|
48
|
+
built, silently declined, or silently degraded, and the operator found out from
|
|
49
|
+
a report — if at all. Once recorded, the choice drives the outcome: `exclude`
|
|
50
|
+
scaffolds with `--compile-exclude` on the flagged files, `port`/`skip` block
|
|
51
|
+
until the sources are clean, `degrade` hands back the no-shim floor command.
|
|
52
|
+
|
|
53
|
+
Contract (docs/python-hook-contract.md):
|
|
54
|
+
Input : PreToolUse JSON on stdin
|
|
55
|
+
Output: exit 2 + `[BLOCK]`-prefixed body on stdout to BLOCK
|
|
56
|
+
exit 0 + no stdout for SILENT-PASS
|
|
57
|
+
Env : DEV_TEAM_STRYKER_XUNIT3_GATE_SKIP=1 -> silent bypass
|
|
58
|
+
|
|
59
|
+
Stdlib-only.
|
|
60
|
+
"""
|
|
61
|
+
from __future__ import annotations
|
|
62
|
+
|
|
63
|
+
import os
|
|
64
|
+
import re
|
|
65
|
+
import subprocess
|
|
66
|
+
import sys
|
|
67
|
+
from pathlib import Path
|
|
68
|
+
|
|
69
|
+
_HOOK_DIR = Path(__file__).resolve().parent
|
|
70
|
+
_PLUGIN_DIR = _HOOK_DIR.parent
|
|
71
|
+
_LIB_DIR = _HOOK_DIR / "lib"
|
|
72
|
+
|
|
73
|
+
sys.path.insert(0, str(_LIB_DIR))
|
|
74
|
+
sys.path.insert(0, str(_HOOK_DIR))
|
|
75
|
+
try:
|
|
76
|
+
from stdin_json import read_stdin_json # type: ignore[import-not-found]
|
|
77
|
+
except ImportError: # pragma: no cover - fallback keeps the hook self-contained
|
|
78
|
+
|
|
79
|
+
def read_stdin_json() -> dict | None: # type: ignore[misc]
|
|
80
|
+
import json
|
|
81
|
+
|
|
82
|
+
try:
|
|
83
|
+
return json.loads(sys.stdin.read() or "{}")
|
|
84
|
+
except (ValueError, OSError):
|
|
85
|
+
return None
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
from mutation_adapters.stryker_net import ( # type: ignore[import-not-found]
|
|
89
|
+
stryker_net_version,
|
|
90
|
+
)
|
|
91
|
+
except ImportError: # pragma: no cover - degraded fallback, adapter package unreachable
|
|
92
|
+
stryker_net_version = None # type: ignore[assignment]
|
|
93
|
+
|
|
94
|
+
#: Stryker.NET 5.0.0 (stryker-net#3752) restored real MTP per-test coverage,
|
|
95
|
+
#: closing the gap the xunit.v2 shim exists to work around (#2184).
|
|
96
|
+
_MTP_PER_TEST_COVERAGE_FLOOR = (5, 0, 0)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
from stryker_invocation import ( # type: ignore[import-not-found]
|
|
101
|
+
is_stryker_invocation as _is_stryker_invocation,
|
|
102
|
+
)
|
|
103
|
+
except ImportError: # pragma: no cover - degraded fallback, hooks/lib unreachable
|
|
104
|
+
# `dotnet stryker`, `dotnet-stryker`, or the plugin's wrapper — mirror the
|
|
105
|
+
# smoke-gate's pre-#2185 fallback so both gates degrade identically.
|
|
106
|
+
_STRYKER_TRIGGER_FALLBACK = re.compile(
|
|
107
|
+
r"(?:^|[^a-zA-Z0-9])dotnet[ \t-]+stryker(?:\b|$)|csharp[_-]stryker[_-]net[_-]wrapper"
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
def _is_stryker_invocation(cmd: str) -> bool: # type: ignore[misc]
|
|
111
|
+
return bool(cmd) and bool(_STRYKER_TRIGGER_FALLBACK.search(cmd))
|
|
112
|
+
|
|
113
|
+
_GENERATOR = _PLUGIN_DIR / "skills" / "stryker-xunit-v2-shim" / "scripts" / "generate_shim.py"
|
|
114
|
+
_PY_SH = _HOOK_DIR / "py.sh"
|
|
115
|
+
_OPERATOR_GATE_MODULE = _LIB_DIR / "xunit_v3_operator_gate.py"
|
|
116
|
+
|
|
117
|
+
# The detector lives with the mutation-testing skill; the guard reuses it rather
|
|
118
|
+
# than keeping a second, drifting classification of the same constructs.
|
|
119
|
+
_DETECTOR_DIR = _PLUGIN_DIR / "skills" / "mutation-testing" / "scripts"
|
|
120
|
+
if str(_DETECTOR_DIR) not in sys.path:
|
|
121
|
+
sys.path.insert(0, str(_DETECTOR_DIR))
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
import xunit_v3_feature_detector as _detector # type: ignore[import-not-found]
|
|
125
|
+
except ImportError: # pragma: no cover - degraded fallback, skill tree unreachable
|
|
126
|
+
_detector = None
|
|
127
|
+
|
|
128
|
+
try:
|
|
129
|
+
import xunit_v3_operator_gate as _operator_gate # type: ignore[import-not-found]
|
|
130
|
+
except ImportError: # pragma: no cover - degraded fallback, hooks/lib unreachable
|
|
131
|
+
_operator_gate = None
|
|
132
|
+
|
|
133
|
+
# Directories never worth walking when scanning for test projects/sources.
|
|
134
|
+
_SKIP_DIRS = {"bin", "obj", ".git", "node_modules", ".vs", "StrykerOutput"}
|
|
135
|
+
|
|
136
|
+
# v3-only constructs that must be ported to v2-compatible forms before a shim
|
|
137
|
+
# can compile the linked sources (see the skill's Step 1 scope probe).
|
|
138
|
+
_V3_ONLY = (
|
|
139
|
+
"AutoFixture.Xunit3", "[AutoData", "InlineAutoData", "AutoMoqData",
|
|
140
|
+
"MemberAutoData", "TestContext", "Assert.Skip", "Assert.Multiple",
|
|
141
|
+
"IAsyncLifetime", "Assert.Equivalent",
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def _read(path: Path) -> str:
|
|
146
|
+
try:
|
|
147
|
+
return path.read_text(encoding="utf-8", errors="ignore")
|
|
148
|
+
except OSError:
|
|
149
|
+
return ""
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _is_v2_shim(csproj: Path) -> bool:
|
|
153
|
+
if not csproj.name.endswith(".Mutation.csproj"):
|
|
154
|
+
return False
|
|
155
|
+
return bool(re.search(r'Include="xunit"\s+Version="2', _read(csproj)))
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _is_v3(csproj: Path) -> bool:
|
|
159
|
+
return "xunit.v3" in _read(csproj)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
_MTP_RUNNER_RE = re.compile(r"""(?:^|\s)(?:-t|--test-runner)[ =]+["']?mtp\b""")
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _uses_mtp_runner(command: str) -> bool:
|
|
166
|
+
"""True when the command explicitly selects Stryker's Microsoft Testing
|
|
167
|
+
Platform runner (`-t mtp` / `--test-runner mtp`) — the sanctioned no-shim
|
|
168
|
+
floor (#1156/#1159): it drives the real xunit.v3 suite and yields a real
|
|
169
|
+
(if slow, whole-suite-per-mutant) score, so the false-~0% premise this gate
|
|
170
|
+
guards against does not apply."""
|
|
171
|
+
return bool(_MTP_RUNNER_RE.search(command))
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def _resolve_run_dir(command: str, cwd: str) -> Path:
|
|
175
|
+
"""Honour a leading `cd <dir> && ...` so the gate reasons about where Stryker
|
|
176
|
+
actually runs, not where the shell started."""
|
|
177
|
+
match = re.search(r"\bcd\s+([^\s&;|]+)", command)
|
|
178
|
+
if match:
|
|
179
|
+
target = match.group(1).strip("'\"")
|
|
180
|
+
return (Path(cwd) / target).resolve()
|
|
181
|
+
return Path(cwd).resolve()
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _find_v3_test_projects(root: Path, limit: int = 400) -> list[Path]:
|
|
185
|
+
"""Bounded walk for xunit.v3 test .csproj under a solution root."""
|
|
186
|
+
found: list[Path] = []
|
|
187
|
+
seen = 0
|
|
188
|
+
for dirpath, dirnames, filenames in os.walk(root):
|
|
189
|
+
dirnames[:] = [d for d in dirnames if d not in _SKIP_DIRS]
|
|
190
|
+
for name in filenames:
|
|
191
|
+
if name.endswith(".csproj"):
|
|
192
|
+
seen += 1
|
|
193
|
+
if seen > limit:
|
|
194
|
+
return found
|
|
195
|
+
path = Path(dirpath) / name
|
|
196
|
+
if not path.name.endswith(".Mutation.csproj") and _is_v3(path):
|
|
197
|
+
found.append(path)
|
|
198
|
+
return found
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def _classify(project_dir: Path) -> tuple[list[str], list[dict]]:
|
|
202
|
+
"""Scan the project's test sources for shim-breaking v3-only usage.
|
|
203
|
+
|
|
204
|
+
Returns ``(flagged_files, classified_findings)``, both keyed on paths
|
|
205
|
+
relative to ``project_dir`` so the operator-facing list and the
|
|
206
|
+
``--compile-exclude`` globs derived from it are stable regardless of where
|
|
207
|
+
the run was launched.
|
|
208
|
+
|
|
209
|
+
Two scans, deliberately: the detector supplies the *classification* the
|
|
210
|
+
operator gate needs (which construct, translatable or not, coverage-bearing
|
|
211
|
+
or neutral), while the older token list is broader — it catches v3-only
|
|
212
|
+
usage the detector has no construct for. Dropping a token-flagged file for
|
|
213
|
+
lacking a classification would silently narrow what the guard blocks on, so
|
|
214
|
+
those files stay in ``flagged_files`` and reach the operator labelled as
|
|
215
|
+
needing manual triage.
|
|
216
|
+
"""
|
|
217
|
+
flagged: list[str] = []
|
|
218
|
+
findings: list[dict] = []
|
|
219
|
+
for dirpath, dirnames, filenames in os.walk(project_dir):
|
|
220
|
+
dirnames[:] = [d for d in dirnames if d not in _SKIP_DIRS]
|
|
221
|
+
for name in sorted(filenames):
|
|
222
|
+
if not name.endswith(".cs"):
|
|
223
|
+
continue
|
|
224
|
+
path = Path(dirpath) / name
|
|
225
|
+
rel = str(path.relative_to(project_dir))
|
|
226
|
+
text = _read(path)
|
|
227
|
+
classified = []
|
|
228
|
+
if _detector is not None:
|
|
229
|
+
classified = [
|
|
230
|
+
{
|
|
231
|
+
"file": rel,
|
|
232
|
+
"line": f.line,
|
|
233
|
+
"construct": f.construct,
|
|
234
|
+
"compile_ability": f.compile_ability,
|
|
235
|
+
"coverage_impact": f.coverage_impact,
|
|
236
|
+
"snippet": f.snippet,
|
|
237
|
+
}
|
|
238
|
+
for f in _detector.scan_text(rel, text)
|
|
239
|
+
]
|
|
240
|
+
findings.extend(classified)
|
|
241
|
+
if classified or any(tok in text for tok in _V3_ONLY):
|
|
242
|
+
flagged.append(rel)
|
|
243
|
+
return flagged, findings
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def _shim_dir_for(real_csproj: Path) -> Path:
|
|
247
|
+
real_dir = real_csproj.parent
|
|
248
|
+
return real_dir.parent / (real_csproj.stem + ".Mutation")
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def _run_generator(
|
|
252
|
+
real_csproj: Path, cwd: Path, extra_args: list[str] | None = None
|
|
253
|
+
) -> tuple[int, str]:
|
|
254
|
+
if not _GENERATOR.is_file():
|
|
255
|
+
return 127, f"generator not found at {_GENERATOR}"
|
|
256
|
+
try:
|
|
257
|
+
proc = subprocess.run(
|
|
258
|
+
[sys.executable, str(_GENERATOR), str(real_csproj), *(extra_args or [])],
|
|
259
|
+
cwd=str(cwd), capture_output=True, text=True, check=False, timeout=30,
|
|
260
|
+
)
|
|
261
|
+
except (OSError, subprocess.SubprocessError) as exc: # pragma: no cover
|
|
262
|
+
return 1, str(exc)
|
|
263
|
+
return proc.returncode, (proc.stdout or "") + (proc.stderr or "")
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def _compile_exclude_globs(name: str, flagged: list[str]) -> list[str]:
|
|
267
|
+
"""`--compile-exclude` values for the flagged files.
|
|
268
|
+
|
|
269
|
+
Shaped to match what the generator emits, which is the only thing verifiable
|
|
270
|
+
from here: `generate_shim.py` writes `<Compile Include="..\\<Name>\\**\\*.cs"
|
|
271
|
+
Exclude="<;-joined values>">`, and its own default exclusions are spelled
|
|
272
|
+
`..\\<Name>\\obj\\**\\*.cs`. So an exclusion is expressed shim-relative and
|
|
273
|
+
backslashed, and the separator conversion below produces that on both POSIX
|
|
274
|
+
and Windows hosts. (Whether MSBuild would additionally normalise a
|
|
275
|
+
forward-slash value is not asserted here — the shape the generator already
|
|
276
|
+
uses is the one to match, and the emitted value is pinned by test.)
|
|
277
|
+
"""
|
|
278
|
+
return [f"..\\{name}\\" + rel.replace("/", "\\").replace(os.sep, "\\")
|
|
279
|
+
for rel in flagged]
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def _record_command(name: str, fingerprint: str) -> str:
|
|
283
|
+
"""The command that satisfies the gate once the operator has answered.
|
|
284
|
+
|
|
285
|
+
Routed through `hooks/py.sh` rather than a bare `python3` so it works where
|
|
286
|
+
`python3` is absent (Windows, #1078), and with absolute paths so it does not
|
|
287
|
+
depend on the cwd the agent happens to be in.
|
|
288
|
+
"""
|
|
289
|
+
return (
|
|
290
|
+
f'sh "{_PY_SH}" "{_OPERATOR_GATE_MODULE}" record '
|
|
291
|
+
f'--project {name} --choice <port|exclude|skip|degrade> '
|
|
292
|
+
f"--fingerprint {fingerprint}"
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def _floor_command(real_csproj: Path, cwd: Path) -> list[str]:
|
|
297
|
+
"""The sanctioned no-shim floor, spelled out.
|
|
298
|
+
|
|
299
|
+
`coverage-analysis` is config-file-only in Stryker.NET (no CLI flag), so the
|
|
300
|
+
instruction says to set it in the config — handing over a `--coverage-analysis`
|
|
301
|
+
flag would just produce a failed command and a retry (#1777).
|
|
302
|
+
"""
|
|
303
|
+
rel_project = os.path.relpath(real_csproj.parent, cwd)
|
|
304
|
+
# A `cd .` is noise the operator has to read past to find the real command.
|
|
305
|
+
lines = [] if rel_project == "." else [f" cd {rel_project}"]
|
|
306
|
+
return lines + [
|
|
307
|
+
(
|
|
308
|
+
' # set "coverage-analysis": "off" in stryker-config.json '
|
|
309
|
+
"(config-file-only — there is no CLI flag)"
|
|
310
|
+
),
|
|
311
|
+
" dotnet-stryker -t mtp",
|
|
312
|
+
]
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def _operator_gate_block(
|
|
316
|
+
header: str, real_csproj: Path, cwd: Path, flagged: list[str], findings: list[dict]
|
|
317
|
+
) -> list[str]:
|
|
318
|
+
"""The #1791 decision gate for one blocked project.
|
|
319
|
+
|
|
320
|
+
Returns the block body: the operator question when no decision covers the
|
|
321
|
+
current blocker set, otherwise the consequence of the recorded choice.
|
|
322
|
+
"""
|
|
323
|
+
name = real_csproj.stem
|
|
324
|
+
shim_dir = _shim_dir_for(real_csproj)
|
|
325
|
+
rel_shim = os.path.relpath(shim_dir, cwd)
|
|
326
|
+
unclassified = [f for f in flagged if all(d["file"] != f for d in findings)]
|
|
327
|
+
|
|
328
|
+
question = _operator_gate.build_question(name, findings, unclassified)
|
|
329
|
+
decision = _operator_gate.decision_for(question, cwd=cwd)
|
|
330
|
+
|
|
331
|
+
if decision is None:
|
|
332
|
+
return [
|
|
333
|
+
header + ", and the operator has to choose how to handle it:",
|
|
334
|
+
"",
|
|
335
|
+
] + _operator_gate.render_question(
|
|
336
|
+
question, record_command=_record_command(name, question.fingerprint)
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
choice = decision.get("choice")
|
|
340
|
+
if choice == "exclude":
|
|
341
|
+
code, out = _run_generator(
|
|
342
|
+
real_csproj,
|
|
343
|
+
cwd,
|
|
344
|
+
[arg for glob in _compile_exclude_globs(name, flagged)
|
|
345
|
+
for arg in ("--compile-exclude", glob)],
|
|
346
|
+
)
|
|
347
|
+
if code != 0:
|
|
348
|
+
return [
|
|
349
|
+
header + ", and scaffolding with the operator's exclusions failed:",
|
|
350
|
+
f" {out.strip()[:400]}",
|
|
351
|
+
]
|
|
352
|
+
return [
|
|
353
|
+
header + " — scaffolded a xunit.v2 shim with the operator's exclusions",
|
|
354
|
+
(
|
|
355
|
+
f"({len(flagged)} file(s) dropped from the shim's compile set, so "
|
|
356
|
+
"they stay UNMEASURED by mutation):"
|
|
357
|
+
),
|
|
358
|
+
] + [" " + ln for ln in out.strip().splitlines()] + [
|
|
359
|
+
"Run mutation FROM the shim dir:",
|
|
360
|
+
f" cd {rel_shim} && dotnet-stryker",
|
|
361
|
+
]
|
|
362
|
+
|
|
363
|
+
if choice == "degrade":
|
|
364
|
+
return [
|
|
365
|
+
(
|
|
366
|
+
header + " — the operator chose 'degrade': skip the shim and run "
|
|
367
|
+
"the no-shim floor instead."
|
|
368
|
+
),
|
|
369
|
+
(
|
|
370
|
+
"It drives the real xunit.v3 suite, so the score is real but "
|
|
371
|
+
"whole-suite-per-mutant (slow, single advisory pass, no kill loop):"
|
|
372
|
+
),
|
|
373
|
+
] + _floor_command(real_csproj, cwd)
|
|
374
|
+
|
|
375
|
+
# port / skip: the sources have to change before a shim can compile.
|
|
376
|
+
verb = (
|
|
377
|
+
"Port these to v2-compatible forms"
|
|
378
|
+
if choice == "port"
|
|
379
|
+
else "Deactivate/skip these tests for the duration of the measurement"
|
|
380
|
+
)
|
|
381
|
+
tail = [
|
|
382
|
+
"See the stryker-xunit-v2-shim skill, Step 3 for the v3->v2 replacements.",
|
|
383
|
+
]
|
|
384
|
+
if choice == "skip":
|
|
385
|
+
# Deactivating a test does not delete the construct from the file the shim
|
|
386
|
+
# links, so `skip` only clears this gate where the deactivation itself
|
|
387
|
+
# removes the offending syntax. Saying so here beats the operator
|
|
388
|
+
# re-running into the same block and concluding the gate is broken.
|
|
389
|
+
tail.append(
|
|
390
|
+
"NOTE: deactivating a test removes it from the RUN, not from the "
|
|
391
|
+
"SOURCE the shim compiles. It clears this gate only where the "
|
|
392
|
+
'deactivation removes the construct itself (e.g. [Fact(Explicit = '
|
|
393
|
+
'true)] -> [Fact(Skip = "...")]). For a construct in the test body '
|
|
394
|
+
"or on a data attribute, re-record as 'port' or 'exclude'."
|
|
395
|
+
)
|
|
396
|
+
return [
|
|
397
|
+
header + f" — the operator chose '{choice}', which is not done yet.",
|
|
398
|
+
(
|
|
399
|
+
f"{verb} in the REAL test project (the shim links the same sources, so "
|
|
400
|
+
"one edit serves both), then re-run — the guard scaffolds automatically "
|
|
401
|
+
"once the sources are clean:"
|
|
402
|
+
),
|
|
403
|
+
] + [
|
|
404
|
+
f" - {d['file']}:{d['line']} {d['construct']} {d['snippet']}"
|
|
405
|
+
for d in findings[:20]
|
|
406
|
+
] + [f" - {f} (unclassified — manual triage)" for f in unclassified[:20]] + tail
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
def _handle_v3_project(real_csproj: Path, cwd: Path) -> list[str]:
|
|
410
|
+
"""Auto-scaffold the shim for one xunit.v3 test project (or explain why not),
|
|
411
|
+
and return the block body reporting exactly what happened."""
|
|
412
|
+
name = real_csproj.stem
|
|
413
|
+
shim_dir = _shim_dir_for(real_csproj)
|
|
414
|
+
rel_shim = os.path.relpath(shim_dir, cwd)
|
|
415
|
+
header = f"[BLOCK] Stryker on the xunit.v3 project '{name}' reports a FALSE ~0% score"
|
|
416
|
+
|
|
417
|
+
# Never regenerate over an existing shim.
|
|
418
|
+
if (shim_dir / (name + ".Mutation.csproj")).exists():
|
|
419
|
+
return [
|
|
420
|
+
header + " — a v2 shim already exists.",
|
|
421
|
+
f"Run mutation FROM the shim dir: cd {rel_shim} && dotnet-stryker",
|
|
422
|
+
]
|
|
423
|
+
|
|
424
|
+
# Shim-breaking sources: this is the operator's decision, not the agent's
|
|
425
|
+
# (#1791). Never scaffold, decline, or degrade on their behalf.
|
|
426
|
+
flagged, findings = _classify(real_csproj.parent)
|
|
427
|
+
if flagged and _operator_gate is not None:
|
|
428
|
+
return _operator_gate_block(header, real_csproj, cwd, flagged, findings)
|
|
429
|
+
if flagged: # pragma: no cover - degraded fallback, hooks/lib unreachable
|
|
430
|
+
return [
|
|
431
|
+
header + ", and the shim can't be auto-built:",
|
|
432
|
+
"these sources use v3-only constructs that must be ported to v2-compatible",
|
|
433
|
+
"forms first (see the stryker-xunit-v2-shim skill, Step 3):",
|
|
434
|
+
] + [f" - {f}" for f in sorted(set(flagged))[:20]]
|
|
435
|
+
|
|
436
|
+
code, out = _run_generator(real_csproj, cwd)
|
|
437
|
+
if code != 0:
|
|
438
|
+
return [
|
|
439
|
+
header + ", and auto-scaffolding failed:",
|
|
440
|
+
f" {out.strip()[:400]}",
|
|
441
|
+
f"Build the shim by hand: python3 {os.path.relpath(_GENERATOR, cwd)} {os.path.relpath(real_csproj, cwd)}",
|
|
442
|
+
]
|
|
443
|
+
lines = [
|
|
444
|
+
header + " — auto-scaffolded a xunit.v2 shim (perTest, 30s timeout):",
|
|
445
|
+
]
|
|
446
|
+
lines += [" " + ln for ln in out.strip().splitlines()]
|
|
447
|
+
lines += [
|
|
448
|
+
"Review the generated shim, then run mutation FROM it:",
|
|
449
|
+
f" cd {rel_shim} && dotnet-stryker",
|
|
450
|
+
f'If the product uses InternalsVisibleTo, add [assembly: InternalsVisibleTo("{name}.Mutation")].',
|
|
451
|
+
(
|
|
452
|
+
"Nothing in these sources blocked the shim, so no operator decision "
|
|
453
|
+
"was needed. If you would rather not shim at all, the no-shim floor is:"
|
|
454
|
+
),
|
|
455
|
+
] + _floor_command(real_csproj, cwd)
|
|
456
|
+
return lines
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
_VERSION_UNKNOWN_NOTE = (
|
|
460
|
+
"Note: Stryker.NET's version could not be determined (`dotnet`/`dotnet "
|
|
461
|
+
"stryker --version` unavailable or unparseable) — failing closed to the "
|
|
462
|
+
"pre-5.0.0, shim-required assumption below. Set "
|
|
463
|
+
"DEV_TEAM_STRYKER_NET_VERSION=<X.Y.Z> to override if the installed "
|
|
464
|
+
"version is actually >= 5.0.0 (#2184)."
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
def _version_exempt() -> tuple[bool, bool]:
|
|
469
|
+
"""`(exempt, version_unknown)` for the installed Stryker.NET CLI.
|
|
470
|
+
|
|
471
|
+
`exempt=True` means the version is known to be >= 5.0.0, which restored
|
|
472
|
+
real MTP per-test coverage (stryker-net#3752) — the gap the xunit.v2
|
|
473
|
+
shim exists to work around is closed, so this gate should silent-pass
|
|
474
|
+
regardless of which runner flag the command uses (#2184).
|
|
475
|
+
|
|
476
|
+
`version_unknown=True` means the version could not be determined at
|
|
477
|
+
all (no `dotnet` on PATH, the probe failed, or its output didn't parse)
|
|
478
|
+
— the caller fails closed to the pre-5.0.0 shim-required behavior, but
|
|
479
|
+
should surface `_VERSION_UNKNOWN_NOTE` in the block body so the
|
|
480
|
+
operator can tell a real <5.0.0 detection apart from this fallback.
|
|
481
|
+
|
|
482
|
+
Deliberately called only where the guard is about to block (project or
|
|
483
|
+
solution mode, immediately before building the block body) — not
|
|
484
|
+
unconditionally at the top of `main()` — so the `dotnet stryker
|
|
485
|
+
--version` subprocess call never runs for the common case (no `.sln`
|
|
486
|
+
match, a v2 shim run, a non-Stryker command, or a project with no
|
|
487
|
+
xunit.v3 test project at all).
|
|
488
|
+
"""
|
|
489
|
+
if stryker_net_version is None: # pragma: no cover - degraded fallback, adapter unreachable
|
|
490
|
+
return False, True
|
|
491
|
+
version = stryker_net_version()
|
|
492
|
+
if version is None:
|
|
493
|
+
return False, True
|
|
494
|
+
return version >= _MTP_PER_TEST_COVERAGE_FLOOR, False
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
def _block(lines: list[str]) -> int:
|
|
498
|
+
print("\n".join(lines))
|
|
499
|
+
return 2
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
def main() -> int:
|
|
503
|
+
if os.environ.get("DEV_TEAM_STRYKER_XUNIT3_GATE_SKIP") == "1":
|
|
504
|
+
return 0
|
|
505
|
+
|
|
506
|
+
event = read_stdin_json() or {}
|
|
507
|
+
if event.get("tool_name") != "Bash":
|
|
508
|
+
return 0
|
|
509
|
+
command = (event.get("tool_input") or {}).get("command", "") or ""
|
|
510
|
+
if not _is_stryker_invocation(command):
|
|
511
|
+
return 0
|
|
512
|
+
|
|
513
|
+
# Sanctioned no-shim floor (#1156/#1159): an explicit MTP-runner run drives
|
|
514
|
+
# the real xunit.v3 suite and produces a real score, so it must not be
|
|
515
|
+
# blocked or shimmed. Let it through before any v3-project detection.
|
|
516
|
+
if _uses_mtp_runner(command):
|
|
517
|
+
return 0
|
|
518
|
+
|
|
519
|
+
cwd = event.get("cwd") or os.environ.get("CLAUDE_PROJECT_DIR") or os.getcwd()
|
|
520
|
+
run_dir = _resolve_run_dir(command, cwd)
|
|
521
|
+
if not run_dir.is_dir():
|
|
522
|
+
return 0
|
|
523
|
+
# Resolve: every path in the block body is computed relative to this, and
|
|
524
|
+
# `run_dir` (and so the shim dir derived from it) is already resolved. Mixing
|
|
525
|
+
# a raw cwd with resolved targets turns a sibling directory into a
|
|
526
|
+
# ../../../.. crawl back through the symlink's parent chain the moment the
|
|
527
|
+
# cwd traverses a link — macOS /var -> /private/var is the everyday case.
|
|
528
|
+
base = Path(cwd).resolve()
|
|
529
|
+
|
|
530
|
+
local = list(run_dir.glob("*.csproj"))
|
|
531
|
+
|
|
532
|
+
# Correct invocation: already inside a xunit.v2 shim dir. Let it run.
|
|
533
|
+
if any(_is_v2_shim(p) for p in local):
|
|
534
|
+
return 0
|
|
535
|
+
|
|
536
|
+
# Project mode bound directly to a xunit.v3 test project.
|
|
537
|
+
v3_local = [p for p in local if _is_v3(p)]
|
|
538
|
+
if v3_local:
|
|
539
|
+
exempt, version_unknown = _version_exempt()
|
|
540
|
+
if exempt:
|
|
541
|
+
return 0
|
|
542
|
+
lines = _handle_v3_project(v3_local[0], base)
|
|
543
|
+
if version_unknown:
|
|
544
|
+
lines = [_VERSION_UNKNOWN_NOTE, ""] + lines
|
|
545
|
+
return _block(lines)
|
|
546
|
+
|
|
547
|
+
# Solution mode: a bare run at a solution root binds to the v3 test project(s).
|
|
548
|
+
if list(run_dir.glob("*.sln")):
|
|
549
|
+
v3 = _find_v3_test_projects(run_dir)
|
|
550
|
+
if v3:
|
|
551
|
+
exempt, version_unknown = _version_exempt()
|
|
552
|
+
if exempt:
|
|
553
|
+
return 0
|
|
554
|
+
lines = [
|
|
555
|
+
"[BLOCK] `dotnet stryker` at this solution root enters solution mode and binds to",
|
|
556
|
+
"xunit.v3 test project(s), reporting a FALSE ~0% score (Stryker.NET can't observe",
|
|
557
|
+
"kills through xunit.v3 — MTP; stryker-net #3237/#3629/#3094). Handling each:",
|
|
558
|
+
"",
|
|
559
|
+
]
|
|
560
|
+
if version_unknown:
|
|
561
|
+
lines = [_VERSION_UNKNOWN_NOTE, ""] + lines
|
|
562
|
+
for proj in v3[:5]:
|
|
563
|
+
lines += _handle_v3_project(proj, base) + [""]
|
|
564
|
+
lines.append("Run each shim from its own directory (no .sln in scope forces project mode).")
|
|
565
|
+
return _block(lines)
|
|
566
|
+
|
|
567
|
+
return 0
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
if __name__ == "__main__":
|
|
571
|
+
sys.exit(main())
|