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,620 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""mutation_kill_shared.py — cross-language loop mechanics shared verbatim
|
|
3
|
+
between ``mutation_kill_loop.py`` (C#/Stryker.NET) and
|
|
4
|
+
``mutation_kill_loop_python.py`` (Python/mutmut) (#1583).
|
|
5
|
+
|
|
6
|
+
Pieces were hand-duplicated between the two loops with identical behavior —
|
|
7
|
+
not just similar, identical argv shapes, identical error messages, identical
|
|
8
|
+
timeout semantics — before this module existed:
|
|
9
|
+
|
|
10
|
+
- ``_timeout_from_env`` — the env-var-driven timeout parser both loops (and
|
|
11
|
+
the headless-generation timeouts below) rely on.
|
|
12
|
+
- ``git_revert`` / ``git_reset_and_revert`` / ``git_commit`` — discard,
|
|
13
|
+
unstage-then-discard, and stage-then-commit exactly one test file, under a
|
|
14
|
+
bounded timeout with the ``--literal-pathspecs``/``--`` pathspec guards
|
|
15
|
+
hardened in #1598/#1599.
|
|
16
|
+
- ``RevertFailed`` — raised when a cleanup or insertion revert itself fails,
|
|
17
|
+
leaving the working tree in an unknown, possibly-mutated state (#1930).
|
|
18
|
+
- ``stop_reason`` — the "zero survivors, or no improvement over the previous
|
|
19
|
+
round" predicate that ends a file's kill loop.
|
|
20
|
+
- ``resolve_model`` / ``strip_code_fences`` / ``claude_cli_available`` /
|
|
21
|
+
``CLAUDE_CLI`` / ``run_claude_headless`` / ``HeadlessCallFailed`` (moved
|
|
22
|
+
here from ``mutation_kill_headless.py`` in #1601) — the ``claude --print`` invocation
|
|
23
|
+
glue neither loop's scoring/insertion/orchestration logic actually needs,
|
|
24
|
+
but that ``mutation_kill_loop_python.py`` previously reused by importing
|
|
25
|
+
``mutation_kill_headless.py`` at module scope. That module is NOT a neutral
|
|
26
|
+
one — it imports ``mutation_kill_loop`` (the C#/Stryker.NET loop) and owns
|
|
27
|
+
the C#-only ``--config``/``--stryker-bin`` CLI surface — so importing it
|
|
28
|
+
from the Python loop transitively pulled in the entire C# stack just to
|
|
29
|
+
reuse five language-neutral names. Both loops now import these directly
|
|
30
|
+
from here instead.
|
|
31
|
+
- ``InsertOutcome`` / ``InsertionRefused`` (moved here from
|
|
32
|
+
``mutation_safety_gate.py`` in #1602) — neither is a safety concept
|
|
33
|
+
(``mutation_safety_gate.py`` is scoped to the unattended-commit
|
|
34
|
+
prompt-injection threat model); they're the plain, framework-agnostic
|
|
35
|
+
result/exception shape both loops' insertion mechanics
|
|
36
|
+
(``mutation_kill_insert.py``, ``mutation_kill_insert_python.py``) return,
|
|
37
|
+
identical in shape between the two languages.
|
|
38
|
+
The retry-then-downgrade policy on repeated headless-generation failures
|
|
39
|
+
(``is_gateway_class_error``, ``make_retrying_headless_call``,
|
|
40
|
+
``GenerationExhausted``, ``DowngradeEvent``, ``make_downgrade_audit_hook``,
|
|
41
|
+
#1908) lives in ``mutation_kill_retry.py`` instead — extracted out of this
|
|
42
|
+
module (#1925) once it grew into a five-concern grab-bag; that module's
|
|
43
|
+
dependencies on this one are ``run_claude_headless``/``resolve_fallback_model``,
|
|
44
|
+
plus ``HeadlessCallFailed`` referenced only as a type
|
|
45
|
+
(``isinstance(exc, mutation_kill_shared.HeadlessCallFailed)``), not a
|
|
46
|
+
monkeypatch-sensitive callable. ``run_claude_headless`` is reached on every
|
|
47
|
+
generation attempt unless the caller injects ``call_headless`` (#1918), in
|
|
48
|
+
which case it is never reached. (Keep this in sync with the
|
|
49
|
+
mirrored dependency inventory in ``mutation_kill_retry.py``'s own module
|
|
50
|
+
docstring.)
|
|
51
|
+
|
|
52
|
+
Centralizing the pieces below here means a future hardening fix lands once instead of
|
|
53
|
+
drifting between two copies (the exact drift risk #1598/#1599 already
|
|
54
|
+
demonstrated in practice). Language-specific scoring, insertion mechanics,
|
|
55
|
+
and round orchestration stay in each loop's own module.
|
|
56
|
+
|
|
57
|
+
Stdlib-only. See ADR 0014.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
from __future__ import annotations
|
|
61
|
+
|
|
62
|
+
import math
|
|
63
|
+
import os
|
|
64
|
+
import re
|
|
65
|
+
import subprocess
|
|
66
|
+
import sys
|
|
67
|
+
from dataclasses import dataclass
|
|
68
|
+
from pathlib import Path
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _timeout_from_env(name: str, default: int) -> int:
|
|
72
|
+
"""Parse a positive-integer timeout (seconds) from an env var.
|
|
73
|
+
|
|
74
|
+
Fails fast with a message naming the offending env var, rather than the
|
|
75
|
+
bare, unattributed ``ValueError`` a naked ``int(os.environ.get(...))``
|
|
76
|
+
would raise on a malformed override.
|
|
77
|
+
"""
|
|
78
|
+
raw = os.environ.get(name)
|
|
79
|
+
if raw is None:
|
|
80
|
+
return default
|
|
81
|
+
try:
|
|
82
|
+
value = int(raw)
|
|
83
|
+
except ValueError:
|
|
84
|
+
raise ValueError(
|
|
85
|
+
f"{name} must be an integer number of seconds, got {raw!r}"
|
|
86
|
+
) from None
|
|
87
|
+
if value <= 0:
|
|
88
|
+
raise ValueError(f"{name} must be a positive number of seconds, got {value}")
|
|
89
|
+
return value
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# 30s — near-instant local git operations against a repo that's presumably
|
|
93
|
+
# already responsive. Overridable via env var for a legitimately slow
|
|
94
|
+
# repo/filesystem. Shared by both loops (#1583) — previously two separately
|
|
95
|
+
# maintained (but identically named and valued) constants.
|
|
96
|
+
GIT_TIMEOUT_S = _timeout_from_env("DEV_TEAM_MUTATION_GIT_TIMEOUT_S", 30)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def git_revert(
|
|
100
|
+
test_file: Path, *, cwd: Path | None = None, env: dict[str, str] | None = None
|
|
101
|
+
) -> bool:
|
|
102
|
+
"""Discard working-tree changes to one file (``git checkout -- <file>``).
|
|
103
|
+
|
|
104
|
+
Returns True on a successful revert, False on a non-zero exit or a
|
|
105
|
+
timeout — callers can no longer mistake a failed/timed-out revert for a
|
|
106
|
+
successful one (#1598); a leftover, uncommitted mutation left on disk
|
|
107
|
+
after a revert *claims* success is exactly the integrity gap this fixes.
|
|
108
|
+
|
|
109
|
+
``env`` defaults to ``None`` (inherit the ambient environment); tests
|
|
110
|
+
pass a scrubbed env so this real git subprocess can't be redirected by
|
|
111
|
+
an inherited ``GIT_DIR``/``GIT_WORK_TREE`` (#1598/#1584 review, item 4
|
|
112
|
+
follow-up).
|
|
113
|
+
|
|
114
|
+
Tolerates a ``None`` result from ``subprocess.run`` (in addition to a
|
|
115
|
+
non-zero returncode) as a failure rather than raising — mirrors the old
|
|
116
|
+
C#-loop-only ``_run_with_timeout``-based implementation's behavior
|
|
117
|
+
(pre-#1583), which several existing tests' minimal test doubles
|
|
118
|
+
incidentally depend on (a ``lambda`` whose body is a bare
|
|
119
|
+
``list.append(...)``/``dict.update(...)`` call returns ``None``, not a
|
|
120
|
+
``CompletedProcess``).
|
|
121
|
+
|
|
122
|
+
Callers must inspect the return value; a failed revert is typically
|
|
123
|
+
treated as fatal (see :class:`RevertFailed`).
|
|
124
|
+
"""
|
|
125
|
+
try:
|
|
126
|
+
result = subprocess.run(
|
|
127
|
+
["git", "--literal-pathspecs", "checkout", "--", str(test_file)],
|
|
128
|
+
cwd=cwd,
|
|
129
|
+
check=False,
|
|
130
|
+
timeout=GIT_TIMEOUT_S,
|
|
131
|
+
env=env,
|
|
132
|
+
)
|
|
133
|
+
except subprocess.TimeoutExpired:
|
|
134
|
+
sys.stderr.write(
|
|
135
|
+
f"error: git checkout reverting {test_file} timed out after "
|
|
136
|
+
f"{GIT_TIMEOUT_S}s (set DEV_TEAM_MUTATION_GIT_TIMEOUT_S to "
|
|
137
|
+
"raise it)\n"
|
|
138
|
+
)
|
|
139
|
+
return False
|
|
140
|
+
if result is None:
|
|
141
|
+
return False
|
|
142
|
+
return result.returncode == 0
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def git_reset_and_revert(
|
|
146
|
+
test_file: Path, *, cwd: Path | None = None, env: dict[str, str] | None = None
|
|
147
|
+
) -> bool:
|
|
148
|
+
"""Unstage AND restore ``test_file`` — the correct revert after a FAILED
|
|
149
|
+
commit specifically, distinct from :func:`git_revert`.
|
|
150
|
+
|
|
151
|
+
``git_commit`` runs ``git add -- <test_file>`` *before* attempting the
|
|
152
|
+
commit. If the commit itself then fails, ``test_file`` is left staged
|
|
153
|
+
with the mutated content. A plain ``git checkout -- <file>`` (what
|
|
154
|
+
:func:`git_revert` does) restores the working tree **from the index**,
|
|
155
|
+
which still holds the mutation — so that revert *reports* success while
|
|
156
|
+
the mutated content survives on disk, staged. This is exactly the
|
|
157
|
+
integrity gap #1598 was meant to close. Unstaging first
|
|
158
|
+
(``git reset -q HEAD -- <file>``) before the checkout makes HEAD, the
|
|
159
|
+
index, and the working tree all agree afterward.
|
|
160
|
+
|
|
161
|
+
Returns True only if both the unstage step and the restore step succeed.
|
|
162
|
+
|
|
163
|
+
Both loops call this specifically on the after-a-failed-commit path
|
|
164
|
+
(``_revert_or_raise(..., after_commit=True)``); a build failure or test
|
|
165
|
+
failure calls plain :func:`git_revert` instead — their index already
|
|
166
|
+
equals HEAD in that case (nothing was ever staged), so there's no reason
|
|
167
|
+
to pay the extra ``git reset`` subprocess.
|
|
168
|
+
"""
|
|
169
|
+
try:
|
|
170
|
+
reset_result = subprocess.run(
|
|
171
|
+
["git", "--literal-pathspecs", "reset", "-q", "HEAD", "--", str(test_file)],
|
|
172
|
+
cwd=cwd,
|
|
173
|
+
check=False,
|
|
174
|
+
timeout=GIT_TIMEOUT_S,
|
|
175
|
+
env=env,
|
|
176
|
+
)
|
|
177
|
+
except subprocess.TimeoutExpired:
|
|
178
|
+
sys.stderr.write(
|
|
179
|
+
f"error: git reset unstaging {test_file} timed out after "
|
|
180
|
+
f"{GIT_TIMEOUT_S}s (set DEV_TEAM_MUTATION_GIT_TIMEOUT_S to "
|
|
181
|
+
"raise it)\n"
|
|
182
|
+
)
|
|
183
|
+
return False
|
|
184
|
+
if reset_result is None or reset_result.returncode != 0:
|
|
185
|
+
return False
|
|
186
|
+
return git_revert(test_file, cwd=cwd, env=env)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
class RevertFailed(RuntimeError):
|
|
190
|
+
"""Raised when a git revert itself fails: the working tree may be left in
|
|
191
|
+
an unknown/possibly-mutated state, distinct from every other
|
|
192
|
+
``RuntimeError`` this codebase raises, which are clean with respect to
|
|
193
|
+
inserted test content — generation precedes insertion, and a failed
|
|
194
|
+
insertion-revert is this class, not a plain ``RuntimeError``. Also raised
|
|
195
|
+
by ``mutation_kill_loop.py``'s ``run_scoped_stryker`` when the C#
|
|
196
|
+
solution-file restore (``wrapper.restore_sln``, which now returns a bool
|
|
197
|
+
outcome rather than reporting nothing — #1955) fails: a stray hidden
|
|
198
|
+
``.sln`` is the same "working tree left in an unknown state" shape as a
|
|
199
|
+
failed git revert, just for a different file.
|
|
200
|
+
"""
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def git_commit(
|
|
204
|
+
message: str,
|
|
205
|
+
test_file: Path,
|
|
206
|
+
*,
|
|
207
|
+
cwd: Path | None = None,
|
|
208
|
+
env: dict[str, str] | None = None,
|
|
209
|
+
) -> bool:
|
|
210
|
+
"""Stage and commit only ``test_file``. Returns True on a successful commit.
|
|
211
|
+
|
|
212
|
+
Does not inspect ``git add``'s own returncode (only its timeout) — a
|
|
213
|
+
non-timeout ``git add`` failure (e.g. bad pathspec) still falls through
|
|
214
|
+
to attempting the commit, which will then itself fail and report False.
|
|
215
|
+
|
|
216
|
+
``--`` guards against a ``test_file`` path that happens to start with
|
|
217
|
+
``-`` being parsed as a git flag instead of a path.
|
|
218
|
+
``--literal-pathspecs`` (right after ``git``) forces every pathspec
|
|
219
|
+
argument below — including this one — to be treated as a literal path,
|
|
220
|
+
not a pathspec: ``--`` alone does NOT disable pathspec magic (``:/``,
|
|
221
|
+
``:(exclude)``, ``:!``, etc.) for the argument that follows it, so a
|
|
222
|
+
``test_file`` value containing those characters could otherwise silently
|
|
223
|
+
broaden what a git command actually touches (#1598/#1584 review, item 5).
|
|
224
|
+
"""
|
|
225
|
+
try:
|
|
226
|
+
subprocess.run(
|
|
227
|
+
["git", "--literal-pathspecs", "add", "--", str(test_file)],
|
|
228
|
+
cwd=cwd,
|
|
229
|
+
check=False,
|
|
230
|
+
timeout=GIT_TIMEOUT_S,
|
|
231
|
+
env=env,
|
|
232
|
+
)
|
|
233
|
+
except subprocess.TimeoutExpired:
|
|
234
|
+
sys.stderr.write(
|
|
235
|
+
f"error: git add for {test_file} timed out after "
|
|
236
|
+
f"{GIT_TIMEOUT_S}s (set DEV_TEAM_MUTATION_GIT_TIMEOUT_S to "
|
|
237
|
+
"raise it)\n"
|
|
238
|
+
)
|
|
239
|
+
return False
|
|
240
|
+
# Scoped with the same `-- <path>` pathspec as `git add` above: without
|
|
241
|
+
# it, `git commit -m message` commits the *entire* index, not just
|
|
242
|
+
# test_file — silently sweeping in whatever else happens to be staged
|
|
243
|
+
# (#1598).
|
|
244
|
+
try:
|
|
245
|
+
commit_result = subprocess.run(
|
|
246
|
+
["git", "--literal-pathspecs", "commit", "-m", message, "--", str(test_file)],
|
|
247
|
+
capture_output=True,
|
|
248
|
+
text=True,
|
|
249
|
+
cwd=cwd,
|
|
250
|
+
check=False,
|
|
251
|
+
timeout=GIT_TIMEOUT_S,
|
|
252
|
+
env=env,
|
|
253
|
+
)
|
|
254
|
+
except subprocess.TimeoutExpired:
|
|
255
|
+
sys.stderr.write(
|
|
256
|
+
f"error: git commit for {test_file} timed out after "
|
|
257
|
+
f"{GIT_TIMEOUT_S}s (set DEV_TEAM_MUTATION_GIT_TIMEOUT_S to "
|
|
258
|
+
"raise it)\n"
|
|
259
|
+
)
|
|
260
|
+
return False
|
|
261
|
+
if commit_result is None:
|
|
262
|
+
return False
|
|
263
|
+
return commit_result.returncode == 0
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
@dataclass(frozen=True)
|
|
267
|
+
class StopDecision:
|
|
268
|
+
"""Why a round stopped, and whether that stop is the loop's own call.
|
|
269
|
+
|
|
270
|
+
``terminal`` is the distinction #2030 turns on. Three of the four stop
|
|
271
|
+
paths are **terminal**: the loop has established the file is done and
|
|
272
|
+
stopping needs no operator involvement. The fourth — the marginal-yield
|
|
273
|
+
floor — is **advisory**: the round did make progress, just less than the
|
|
274
|
+
floor, and the file may still be below its mutation target. Stopping
|
|
275
|
+
there is a judgement about whether another round is worth its price, and
|
|
276
|
+
per #2030 that judgement stays with the operator, routed through the
|
|
277
|
+
``[c]ontinue / [r]etry / [w]aive / [q]uit`` prompt Phase 5 already
|
|
278
|
+
defines for residual survivors.
|
|
279
|
+
|
|
280
|
+
Collapsing the two into a bare string is exactly the conflation #1951 and
|
|
281
|
+
#1956 document elsewhere in this pipeline: a caller that cannot tell
|
|
282
|
+
"done" from "stopped early, your call" reports the wrong thing to the
|
|
283
|
+
operator, and an advisory stop silently becomes a terminal one.
|
|
284
|
+
"""
|
|
285
|
+
|
|
286
|
+
reason: str
|
|
287
|
+
terminal: bool = True
|
|
288
|
+
|
|
289
|
+
def __str__(self) -> str: # so `f" {decision}"` logs the reason alone
|
|
290
|
+
return self.reason
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def resolve_kill_floor(
|
|
294
|
+
min_kills_per_round: float | None, starting_survivors: int
|
|
295
|
+
) -> int | None:
|
|
296
|
+
"""Resolve the marginal-yield floor to an absolute kill count.
|
|
297
|
+
|
|
298
|
+
A value **>= 1** is an absolute kill count, used verbatim. A value
|
|
299
|
+
**strictly between 0 and 1** is a fraction of the round's starting
|
|
300
|
+
survivor count, rounded up so a non-zero fraction of a non-zero survivor
|
|
301
|
+
set never resolves to a floor of 0 (which would disable the check while
|
|
302
|
+
looking configured). ``None``, 0, or a negative value disables the floor.
|
|
303
|
+
|
|
304
|
+
Rounding up is the safe direction here: it can only surface a round to
|
|
305
|
+
the operator earlier, never suppress one that should have surfaced.
|
|
306
|
+
"""
|
|
307
|
+
if min_kills_per_round is None or min_kills_per_round <= 0:
|
|
308
|
+
return None
|
|
309
|
+
if min_kills_per_round >= 1:
|
|
310
|
+
return int(min_kills_per_round)
|
|
311
|
+
if starting_survivors <= 0:
|
|
312
|
+
return None
|
|
313
|
+
return math.ceil(min_kills_per_round * starting_survivors)
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def stop_reason(
|
|
317
|
+
survivor_count: int,
|
|
318
|
+
prev_survivor_count: int | None,
|
|
319
|
+
*,
|
|
320
|
+
honest_score: float | None = None,
|
|
321
|
+
target_honest_score: float | None = None,
|
|
322
|
+
min_kills_per_round: float | None = None,
|
|
323
|
+
) -> StopDecision | None:
|
|
324
|
+
"""Return the reason a round should stop, or ``None`` to continue to
|
|
325
|
+
generation.
|
|
326
|
+
|
|
327
|
+
Shared, byte-for-byte-identical predicate between the two loops (#1583).
|
|
328
|
+
The two original clauses are unchanged: a file is done when zero
|
|
329
|
+
survivors remain, and a round that didn't improve on the previous round's
|
|
330
|
+
survivor count also stops the loop (the "no improvement across rounds"
|
|
331
|
+
guard that prevents chasing the same survivors forever).
|
|
332
|
+
|
|
333
|
+
#2030 adds two opt-in clauses, both **default-off** — with
|
|
334
|
+
``target_honest_score`` and ``min_kills_per_round`` both ``None`` this
|
|
335
|
+
function's verdicts are identical to the pre-#2030 behavior for every
|
|
336
|
+
input, which is what lets a bare ``mutation-kill`` invocation stay
|
|
337
|
+
unchanged while ``/test-improve`` Phase 5 threads the target through:
|
|
338
|
+
|
|
339
|
+
``target_honest_score`` — stop once the file's honest score reaches the
|
|
340
|
+
number Phase 8 (``/quality-targets-converge``) actually gates on. Work
|
|
341
|
+
done past that threshold cannot change the gate's verdict, so this is
|
|
342
|
+
risk-neutral by construction: the honest score remains the only gate,
|
|
343
|
+
Phase 8 still measures it independently, and stopping *at* the threshold
|
|
344
|
+
cannot turn a pass into a fail. The score is already computed every round
|
|
345
|
+
by ``mutation_report.score_report_for_file`` — this reads a number that
|
|
346
|
+
is on hand rather than adding a measurement.
|
|
347
|
+
|
|
348
|
+
``min_kills_per_round`` — a marginal-yield floor. A round that kills 1 of
|
|
349
|
+
40 survivors costs the same as the first, most productive round (scoped
|
|
350
|
+
mutation run + generation + build + scoped test + commit), so without a
|
|
351
|
+
floor the loop chases the long tail at full price. Unlike the other
|
|
352
|
+
three, this returns a **non-terminal** decision: it is surfaced to the
|
|
353
|
+
operator, never acted on unilaterally. It is also skipped entirely once
|
|
354
|
+
the target is met, since the target clause has already stopped the loop
|
|
355
|
+
for a better reason.
|
|
356
|
+
"""
|
|
357
|
+
if survivor_count == 0:
|
|
358
|
+
return StopDecision("no survivors — done")
|
|
359
|
+
if (
|
|
360
|
+
target_honest_score is not None
|
|
361
|
+
and honest_score is not None
|
|
362
|
+
and honest_score >= target_honest_score
|
|
363
|
+
):
|
|
364
|
+
return StopDecision(
|
|
365
|
+
f"honest score {honest_score:.1f}% has reached the "
|
|
366
|
+
f"{target_honest_score:.1f}% mutation target — done "
|
|
367
|
+
f"({survivor_count} survivor(s) left deliberately unaddressed; "
|
|
368
|
+
"further rounds cannot change the Phase-8 verdict)"
|
|
369
|
+
)
|
|
370
|
+
if prev_survivor_count is not None and survivor_count >= prev_survivor_count:
|
|
371
|
+
return StopDecision("no improvement this round — stopping")
|
|
372
|
+
if prev_survivor_count is not None:
|
|
373
|
+
floor = resolve_kill_floor(min_kills_per_round, prev_survivor_count)
|
|
374
|
+
if floor is not None:
|
|
375
|
+
killed_this_round = prev_survivor_count - survivor_count
|
|
376
|
+
if killed_this_round < floor:
|
|
377
|
+
return StopDecision(
|
|
378
|
+
f"marginal yield: killed {killed_this_round} of "
|
|
379
|
+
f"{prev_survivor_count} survivor(s) this round, below the "
|
|
380
|
+
f"floor of {floor} — another round costs the same as the "
|
|
381
|
+
"first. Operator decides: [c]ontinue / [r]etry / [w]aive / "
|
|
382
|
+
"[q]uit",
|
|
383
|
+
terminal=False,
|
|
384
|
+
)
|
|
385
|
+
return None
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
# =============================================================================
|
|
389
|
+
# Headless generation glue — shelling to `claude --print`. Moved here from
|
|
390
|
+
# mutation_kill_headless.py (#1601): both mutation_kill_headless.py (the
|
|
391
|
+
# C# CLI) and mutation_kill_loop_python.py (the Python loop) reuse this
|
|
392
|
+
# verbatim; neither loop's own scoring/insertion/orchestration logic is
|
|
393
|
+
# C#- or Python-specific here.
|
|
394
|
+
# =============================================================================
|
|
395
|
+
|
|
396
|
+
# Timeout for the `claude --print` generation subprocess. Overridable via env
|
|
397
|
+
# var since a legitimately slow/large prompt may need a larger budget than
|
|
398
|
+
# this default — unlike the 30s used by this module's git-shelling helpers
|
|
399
|
+
# above, this subprocess routinely runs for tens of seconds to minutes.
|
|
400
|
+
CLAUDE_GENERATION_TIMEOUT_S = _timeout_from_env("DEV_TEAM_MUTATION_GENERATION_TIMEOUT_S", 300)
|
|
401
|
+
|
|
402
|
+
# Timeout for the `claude --version` availability probe — small, since it's a
|
|
403
|
+
# startup check, not a generation call.
|
|
404
|
+
CLAUDE_VERSION_TIMEOUT_S = _timeout_from_env("DEV_TEAM_MUTATION_VERSION_TIMEOUT_S", 30)
|
|
405
|
+
|
|
406
|
+
# The Claude CLI binary. Overridable via CLAUDE_BIN so a non-PATH install can
|
|
407
|
+
# be pointed at without editing this module.
|
|
408
|
+
CLAUDE_CLI = os.environ.get("CLAUDE_BIN", "claude")
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
def resolve_model(explicit: str | None = None) -> str | None:
|
|
412
|
+
"""Resolve the generation model: ``--model`` > ``DEV_TEAM_MUTATION_MODEL``
|
|
413
|
+
> ``None``. When ``None``, ``--model`` is omitted from the ``claude --print``
|
|
414
|
+
invocation and the Claude CLI uses its own default — the plugin never pins a
|
|
415
|
+
model snapshot id in source (models are resolved dynamically, not literalized;
|
|
416
|
+
see ``tests/repo/test_no_pinned_snapshots.py``, the enforcing authority for
|
|
417
|
+
that rule)."""
|
|
418
|
+
if explicit:
|
|
419
|
+
return explicit
|
|
420
|
+
return os.environ.get("DEV_TEAM_MUTATION_MODEL") or None
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
# One-step model-downgrade ladder (#1908): opus -> sonnet -> haiku -> floor.
|
|
424
|
+
# No ``None`` entry: resolve_model()'s "unspecified, let the CLI pick its own
|
|
425
|
+
# default" result has no observable ladder position from this codebase (the
|
|
426
|
+
# CLI's actual default model is not knowable here), so treating it as
|
|
427
|
+
# equivalent to "opus" would be an unverified assumption. ``.get()`` returning
|
|
428
|
+
# ``None`` for an unresolved model, the floor (``haiku``), AND any
|
|
429
|
+
# operator-supplied model string outside {opus, sonnet, haiku} all mean the
|
|
430
|
+
# same thing to this ladder: no known position to step down from. Every round
|
|
431
|
+
# before a downgrade is otherwise unaffected: no --model flag is added, no
|
|
432
|
+
# snapshot id is pinned (see ``tests/repo/test_no_pinned_snapshots.py``)
|
|
433
|
+
# unless/until a downgrade actually happens.
|
|
434
|
+
_MODEL_DOWNGRADE_LADDER: dict[str, str] = {
|
|
435
|
+
"opus": "sonnet",
|
|
436
|
+
"sonnet": "haiku",
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
# Mirrors plugins/marketplace-dev/knowledge/agent-contract.json's
|
|
440
|
+
# ``model.enum`` minus ``inherit`` (which doesn't make sense as a fallback
|
|
441
|
+
# target). ``fable`` is a display-latency variant, not a capability tier, so
|
|
442
|
+
# it is a valid --model/DEV_TEAM_MUTATION_FALLBACK_MODEL override value but
|
|
443
|
+
# deliberately has no entry in _MODEL_DOWNGRADE_LADDER above — it is not part
|
|
444
|
+
# of the opus->sonnet->haiku capability step-down.
|
|
445
|
+
_VALID_FALLBACK_MODELS = frozenset({"opus", "sonnet", "haiku", "fable"})
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
def resolve_fallback_model(current: str | None) -> str | None:
|
|
449
|
+
"""Resolve the next model one step down the downgrade ladder from
|
|
450
|
+
``current``, or the ``DEV_TEAM_MUTATION_FALLBACK_MODEL`` override when
|
|
451
|
+
it names a valid tier.
|
|
452
|
+
|
|
453
|
+
``current`` is expected to be ``resolve_model()``'s result: ``None``,
|
|
454
|
+
``"opus"``, ``"sonnet"``, or ``"haiku"`` (matched case-insensitively).
|
|
455
|
+
``None`` (unresolved), ``"haiku"`` (the floor), and any other value not
|
|
456
|
+
on the ladder (an unrecognized model string) all return ``None`` — "no
|
|
457
|
+
known ladder position to step down to." The three cases are
|
|
458
|
+
indistinguishable to ``resolve_fallback_model`` itself; a caller that
|
|
459
|
+
needs to tell them apart for messaging purposes (e.g.
|
|
460
|
+
:func:`_format_downgrade_message`) does so separately, from the
|
|
461
|
+
``DowngradeEvent`` it already has in hand.
|
|
462
|
+
|
|
463
|
+
``DEV_TEAM_MUTATION_FALLBACK_MODEL``, when set, is checked first and
|
|
464
|
+
wins outright — accepted at ANY ladder position, with no check that it
|
|
465
|
+
is actually a downgrade from ``current``: an explicit operator override
|
|
466
|
+
is authoritative operator intent, not validated against the ladder
|
|
467
|
+
position it replaces (#1908). Matched case-insensitively against
|
|
468
|
+
``{opus, sonnet, haiku, fable}``. A value outside that enum is never
|
|
469
|
+
silently accepted or silently ignored: it's reported on stderr and this
|
|
470
|
+
call falls back to the one-step ladder default instead.
|
|
471
|
+
"""
|
|
472
|
+
override = os.environ.get("DEV_TEAM_MUTATION_FALLBACK_MODEL")
|
|
473
|
+
if override:
|
|
474
|
+
normalized_override = override.strip().lower()
|
|
475
|
+
if normalized_override in _VALID_FALLBACK_MODELS:
|
|
476
|
+
return normalized_override
|
|
477
|
+
sys.stderr.write(
|
|
478
|
+
f"warning: DEV_TEAM_MUTATION_FALLBACK_MODEL={override!r} is not "
|
|
479
|
+
"one of opus/sonnet/haiku/fable — ignoring the override and "
|
|
480
|
+
"using the one-step ladder default instead\n"
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
normalized_current = current.strip().lower() if current else None
|
|
484
|
+
return _MODEL_DOWNGRADE_LADDER.get(normalized_current)
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
_FENCE_OPEN_RE = re.compile(r"^```[\w-]*\n?")
|
|
488
|
+
_FENCE_CLOSE_RE = re.compile(r"\n?```$")
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
def strip_code_fences(text: str) -> str:
|
|
492
|
+
"""Strip one leading and one trailing markdown code fence, if present.
|
|
493
|
+
|
|
494
|
+
Claude may wrap generated methods in a ```` ```csharp ```` (or
|
|
495
|
+
```` ```python ````) block; the loop inserts raw method/test text, so the
|
|
496
|
+
fence is removed on both ends.
|
|
497
|
+
"""
|
|
498
|
+
text = _FENCE_OPEN_RE.sub("", text.strip())
|
|
499
|
+
text = _FENCE_CLOSE_RE.sub("", text.strip())
|
|
500
|
+
return text.strip()
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
class HeadlessCallFailed(RuntimeError):
|
|
504
|
+
"""Raised by :func:`run_claude_headless` when ``claude --print`` exits
|
|
505
|
+
non-zero.
|
|
506
|
+
|
|
507
|
+
Carries the full, untruncated ``returncode``/``stderr`` as public
|
|
508
|
+
attributes for callers that need to inspect them directly; ``__str__``
|
|
509
|
+
truncates ``stderr`` to 500 bytes to stay byte-for-byte identical to the
|
|
510
|
+
plain ``RuntimeError`` message this type replaces, so any consumer that
|
|
511
|
+
only formats/prints the exception (``str(exc)``) sees the same message as
|
|
512
|
+
before.
|
|
513
|
+
"""
|
|
514
|
+
|
|
515
|
+
def __init__(self, returncode: int, stderr: str, stdout: str = "") -> None:
|
|
516
|
+
self.returncode = returncode
|
|
517
|
+
self.stderr = stderr
|
|
518
|
+
# #1950: the classifier was structurally blind to stdout. The claude
|
|
519
|
+
# CLI renders some upstream failures to stdout (a rendered
|
|
520
|
+
# "API Error: 529 Overloaded" body) while stderr carries only a
|
|
521
|
+
# generic non-zero-exit line, so a stderr-only classifier calls a
|
|
522
|
+
# genuinely retryable overload non-gateway-class and burns the file's
|
|
523
|
+
# whole budget on it. Defaulted so every existing two-argument
|
|
524
|
+
# construction — including test fakes — keeps working unchanged.
|
|
525
|
+
self.stdout = stdout
|
|
526
|
+
super().__init__(str(self))
|
|
527
|
+
|
|
528
|
+
def __str__(self) -> str:
|
|
529
|
+
return f"claude CLI failed (exit {self.returncode}): {self.stderr[:500]}"
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
def claude_cli_available() -> bool:
|
|
533
|
+
"""True if the Claude CLI responds to ``--version``."""
|
|
534
|
+
try:
|
|
535
|
+
result = subprocess.run(
|
|
536
|
+
[CLAUDE_CLI, "--version"],
|
|
537
|
+
capture_output=True,
|
|
538
|
+
text=True,
|
|
539
|
+
check=False,
|
|
540
|
+
timeout=CLAUDE_VERSION_TIMEOUT_S,
|
|
541
|
+
)
|
|
542
|
+
except (FileNotFoundError, OSError, subprocess.TimeoutExpired):
|
|
543
|
+
return False
|
|
544
|
+
return result.returncode == 0
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
def run_claude_headless(prompt: str, *, model: str | None, cwd: Path | None = None) -> str:
|
|
548
|
+
"""Shell to ``claude --print`` with an already-built ``prompt``; return
|
|
549
|
+
stdout with markdown code fences stripped.
|
|
550
|
+
|
|
551
|
+
The single shared invocation glue behind both languages'
|
|
552
|
+
``make_headless_generator`` factories (#1583). ``--model`` is passed only
|
|
553
|
+
when ``model`` is set; when ``None`` the Claude CLI uses its own default
|
|
554
|
+
(the plugin pins no model snapshot id — see
|
|
555
|
+
``tests/repo/test_no_pinned_snapshots.py``).
|
|
556
|
+
|
|
557
|
+
``prompt`` is passed over stdin (``input=prompt``), not as a trailing
|
|
558
|
+
argv element (#1607): an argv-passed prompt is both parsed for
|
|
559
|
+
dash-prefixed option injection by the CLI's own arg parser and visible to
|
|
560
|
+
any other process on the host via ``ps``/procfs for the subprocess's
|
|
561
|
+
lifetime — stdin avoids both.
|
|
562
|
+
"""
|
|
563
|
+
cmd = [CLAUDE_CLI, "--print"]
|
|
564
|
+
if model:
|
|
565
|
+
cmd += ["--model", model]
|
|
566
|
+
try:
|
|
567
|
+
result = subprocess.run(
|
|
568
|
+
cmd,
|
|
569
|
+
input=prompt,
|
|
570
|
+
capture_output=True,
|
|
571
|
+
text=True,
|
|
572
|
+
cwd=cwd,
|
|
573
|
+
check=False,
|
|
574
|
+
timeout=CLAUDE_GENERATION_TIMEOUT_S,
|
|
575
|
+
)
|
|
576
|
+
except subprocess.TimeoutExpired as exc:
|
|
577
|
+
raise RuntimeError(
|
|
578
|
+
f"claude --print generation timed out after "
|
|
579
|
+
f"{CLAUDE_GENERATION_TIMEOUT_S}s (set "
|
|
580
|
+
"DEV_TEAM_MUTATION_GENERATION_TIMEOUT_S to raise it)"
|
|
581
|
+
) from exc
|
|
582
|
+
if result.returncode != 0:
|
|
583
|
+
raise HeadlessCallFailed(result.returncode, result.stderr, result.stdout or "")
|
|
584
|
+
return strip_code_fences(result.stdout)
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
# =============================================================================
|
|
588
|
+
# Insertion result shape — shared verbatim between mutation_kill_insert.py
|
|
589
|
+
# (C#) and mutation_kill_insert_python.py (Python). Moved here from
|
|
590
|
+
# mutation_safety_gate.py (#1602): neither type is a safety concept — that
|
|
591
|
+
# module is scoped to the unattended-commit prompt-injection threat model,
|
|
592
|
+
# and InsertOutcome/InsertionRefused are returned/raised for plain structural
|
|
593
|
+
# refusals too (duplicate names, no methods generated, unrecognized file
|
|
594
|
+
# layout).
|
|
595
|
+
# =============================================================================
|
|
596
|
+
class InsertionRefused(Exception):
|
|
597
|
+
"""Raised when a language-specific insertion heuristic can't safely
|
|
598
|
+
locate where to insert generated tests/methods, and refuses rather than
|
|
599
|
+
guess and risk a mis-insertion.
|
|
600
|
+
|
|
601
|
+
Framework-agnostic and shared verbatim between ``mutation_kill_insert.py``
|
|
602
|
+
(C# — refuses on a file-scoped namespace or non-4-space class indentation)
|
|
603
|
+
and ``mutation_kill_insert_python.py`` (Python — refuses on a test file
|
|
604
|
+
with no top-level ``def test_*():``) (#1583).
|
|
605
|
+
"""
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
@dataclass(frozen=True)
|
|
609
|
+
class InsertOutcome:
|
|
610
|
+
"""Result of attempting to apply generated tests/methods to a test file.
|
|
611
|
+
|
|
612
|
+
``inserted`` is False when the file was left untouched; ``reason`` says
|
|
613
|
+
why. Framework-agnostic and shared verbatim between
|
|
614
|
+
``mutation_kill_insert.py`` and ``mutation_kill_insert_python.py``
|
|
615
|
+
(#1583) — the two languages' insertion heuristics differ, but the result
|
|
616
|
+
shape each reports back to its loop is identical.
|
|
617
|
+
"""
|
|
618
|
+
|
|
619
|
+
inserted: bool
|
|
620
|
+
reason: str
|