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,292 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Baseline mutation-report reuse for the mutant-kill loop's Round 1 (#1545).
|
|
3
|
+
|
|
4
|
+
The mutant-kill loop's per-file Round 1 always triggers a fresh scoped
|
|
5
|
+
mutation run, even when a fresh baseline report (captured once, before the
|
|
6
|
+
per-file loop starts) already covers that file. This module owns the
|
|
7
|
+
eligibility decision and the consumption bookkeeping so a file's Round 1 can
|
|
8
|
+
be safely seeded from the baseline via ``--report`` instead of paying for a
|
|
9
|
+
redundant run — as real, unit-tested code, not agent-followed prose.
|
|
10
|
+
|
|
11
|
+
Eligibility is a two-part test:
|
|
12
|
+
1. an **ancestor check** — is the file's last commit an ancestor of the
|
|
13
|
+
baseline's capture commit? (git itself treats a commit as its own
|
|
14
|
+
ancestor, so a file last committed exactly at the capture commit is
|
|
15
|
+
eligible too — the "self-ancestor boundary".) A file with no
|
|
16
|
+
discoverable last-commit SHA (untracked/never committed), or a
|
|
17
|
+
non-ancestor relationship, is never eligible.
|
|
18
|
+
2. a **consumption check** — has this file already consumed *this exact*
|
|
19
|
+
baseline capture commit? If so it is not eligible again until a
|
|
20
|
+
different (not-yet-consumed) baseline capture commit comes along.
|
|
21
|
+
|
|
22
|
+
Concurrency (#1920): ``mark_consumed`` is the sole writer of the tracking
|
|
23
|
+
file, and its read-modify-write span is serialized by
|
|
24
|
+
``atomic_state.locked_state(strict=True)`` so two concurrent callers can
|
|
25
|
+
never lose one another's update to the tracking FILE. ``resolve``/
|
|
26
|
+
``read_tracking`` are deliberately lock-free — a stale read there can only
|
|
27
|
+
under-count eligibility (miss a consumption recorded moments ago and report
|
|
28
|
+
a file eligible when it is about to be marked consumed elsewhere).
|
|
29
|
+
|
|
30
|
+
That serialization, on its own, does NOT guarantee a file is never
|
|
31
|
+
double-consumed: two concurrent ``resolve`` calls for the SAME file would
|
|
32
|
+
both observe pre-consumption state and both seed Round 1, regardless of how
|
|
33
|
+
serialized ``mark_consumed``'s writes are — serialization protects the
|
|
34
|
+
tracking file's integrity across *different* files' writes, not the
|
|
35
|
+
ordering between one file's ``resolve`` calls and its own eventual
|
|
36
|
+
``mark_consumed``. The "never double-consume" property this module relies
|
|
37
|
+
on instead comes from an explicit assumption held by its callers: each file
|
|
38
|
+
is resolved and consumed by at most one worker per run (the ``--all``
|
|
39
|
+
fan-out assigns files disjointly across workers, so two workers never race
|
|
40
|
+
on the same file to begin with).
|
|
41
|
+
|
|
42
|
+
Stdlib-only. (ADR 0014/0015).
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
from __future__ import annotations
|
|
46
|
+
|
|
47
|
+
import argparse
|
|
48
|
+
import json
|
|
49
|
+
import subprocess
|
|
50
|
+
import sys
|
|
51
|
+
from collections.abc import Sequence
|
|
52
|
+
from datetime import datetime, timezone
|
|
53
|
+
from pathlib import Path
|
|
54
|
+
|
|
55
|
+
import mutation_report
|
|
56
|
+
|
|
57
|
+
# skills/mutation-testing/scripts -> skills/mutation-testing -> skills
|
|
58
|
+
# -> plugin root -> hooks/lib
|
|
59
|
+
_HOOKS_LIB_DIR = Path(__file__).resolve().parents[3] / "hooks" / "lib"
|
|
60
|
+
if str(_HOOKS_LIB_DIR) not in sys.path:
|
|
61
|
+
sys.path.insert(0, str(_HOOKS_LIB_DIR))
|
|
62
|
+
|
|
63
|
+
try:
|
|
64
|
+
import atomic_state # type: ignore[import-not-found]
|
|
65
|
+
except ImportError: # pragma: no cover - degraded fallback, hooks/lib unreachable
|
|
66
|
+
atomic_state = None
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class _AtomicStateUnavailableError(RuntimeError):
|
|
70
|
+
"""Raised by ``mark_consumed`` when ``hooks/lib``'s ``atomic_state``
|
|
71
|
+
module could not be imported — refusing to run the read-modify-write
|
|
72
|
+
cycle unlocked rather than silently proceeding without it."""
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# The exception type ``mark_consumed``'s ``except`` clause narrows to
|
|
76
|
+
# (#1920 correctness review): ``atomic_state.LockAcquisitionError`` when the
|
|
77
|
+
# module imported successfully, or the local fallback above when it didn't.
|
|
78
|
+
# Computed once here, at import time, so the ``except`` clause itself never
|
|
79
|
+
# has to attribute-access a possibly-``None`` ``atomic_state`` — evaluating
|
|
80
|
+
# ``atomic_state.LockAcquisitionError`` directly inside the ``except`` tuple
|
|
81
|
+
# would raise ``AttributeError`` instead of matching the real error whenever
|
|
82
|
+
# ``atomic_state is None``.
|
|
83
|
+
_LOCK_FAILURE_ERROR: type[Exception] = (
|
|
84
|
+
atomic_state.LockAcquisitionError
|
|
85
|
+
if atomic_state is not None
|
|
86
|
+
else _AtomicStateUnavailableError
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
# =============================================================================
|
|
91
|
+
# Tracking file — read / decide / write
|
|
92
|
+
# =============================================================================
|
|
93
|
+
def read_tracking(tracking_path) -> dict:
|
|
94
|
+
"""Return the parsed consumption-tracking JSON, or ``{}`` for an
|
|
95
|
+
absent, malformed, or non-dict-shaped file.
|
|
96
|
+
|
|
97
|
+
Delegates to ``mutation_report.load_report`` — this module used to
|
|
98
|
+
reimplement that function's absent/empty/malformed-JSON handling itself;
|
|
99
|
+
it now genuinely calls it, so the two stay behaviorally identical by
|
|
100
|
+
construction rather than by convention.
|
|
101
|
+
"""
|
|
102
|
+
return mutation_report.load_report(tracking_path)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def is_eligible_for_reuse(
|
|
106
|
+
tracking: dict, file_path: str, capture_commit: str, is_ancestor: bool
|
|
107
|
+
) -> bool:
|
|
108
|
+
"""Pure eligibility decision.
|
|
109
|
+
|
|
110
|
+
``False`` when the file's last commit is not an ancestor of the
|
|
111
|
+
baseline's capture commit (``is_ancestor`` is the caller's already-
|
|
112
|
+
resolved git ancestor check — this function does no git work itself).
|
|
113
|
+
Otherwise ``False`` only when ``tracking`` already records ``file_path``
|
|
114
|
+
as consumed at this exact ``capture_commit``; ``True`` in every other
|
|
115
|
+
case, including a file consumed at some *other*, older baseline capture
|
|
116
|
+
commit it hasn't yet consumed.
|
|
117
|
+
"""
|
|
118
|
+
if not is_ancestor:
|
|
119
|
+
return False
|
|
120
|
+
entry = tracking.get(file_path)
|
|
121
|
+
return entry is None or entry.get("capture_commit") != capture_commit
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def mark_consumed(tracking_path, file_path: str, capture_commit: str) -> dict:
|
|
125
|
+
"""Atomically record ``file_path``'s consumption of ``capture_commit``.
|
|
126
|
+
|
|
127
|
+
The full read-tracking -> mutate-dict -> atomic-write sequence runs
|
|
128
|
+
inside ``atomic_state.locked_state(tracking_path, strict=True)`` (#1920),
|
|
129
|
+
so a second concurrent caller's read can never observe a state older than
|
|
130
|
+
the first caller's completed write — closing the lost-update race two
|
|
131
|
+
processes racing on the same tracking file could otherwise hit. Within
|
|
132
|
+
that lock, the write itself delegates to ``atomic_state.atomic_write(...,
|
|
133
|
+
fail_open=False)`` (#1920 review) rather than hand-rolling a second
|
|
134
|
+
``tempfile.mkstemp``/``os.fdopen``/``os.replace`` sequence here — one
|
|
135
|
+
shared, unique-per-call-tmp-file implementation instead of two forks that
|
|
136
|
+
could drift apart, and it closes an fd-leak-on-fdopen-failure gap this
|
|
137
|
+
module's own former hand-rolled version had (``atomic_write`` guards that
|
|
138
|
+
internally now). ``fail_open=False`` makes a write failure raise instead
|
|
139
|
+
of silently no-op'ing, so it still reaches this function's own ``except``
|
|
140
|
+
below and is reported exactly as it always was.
|
|
141
|
+
|
|
142
|
+
Never raises: a write failure (permission denied, unwritable directory,
|
|
143
|
+
a monkeypatched ``os.replace`` failure, ...) *or* a failed lock
|
|
144
|
+
acquisition (``strict=True`` raises ``atomic_state.LockAcquisitionError``
|
|
145
|
+
instead of running unlocked — or the local ``_AtomicStateUnavailableError``
|
|
146
|
+
when ``atomic_state`` itself could not be imported) is caught and
|
|
147
|
+
reported as ``{"success": False, "error": str(exc)}``, leaving the
|
|
148
|
+
on-disk file (if any) untouched — the file stays recorded as
|
|
149
|
+
not-yet-consumed. ``atomic_write``'s own best-effort tmp-file cleanup
|
|
150
|
+
(unique-per-call via ``tempfile.mkstemp``, so a failed call can never
|
|
151
|
+
delete a different, still-in-flight caller's temp file) runs before the
|
|
152
|
+
OSError re-raises, so no cleanup logic is duplicated here.
|
|
153
|
+
|
|
154
|
+
``resolve``/``read_tracking`` stay lock-free by design — see the module
|
|
155
|
+
docstring's ``Concurrency`` note for why a stale read there is safe, and
|
|
156
|
+
for the explicit assumption behind "never double-consume" (single
|
|
157
|
+
worker per file per run, not serialization alone).
|
|
158
|
+
"""
|
|
159
|
+
tracking_path = Path(tracking_path)
|
|
160
|
+
try:
|
|
161
|
+
if atomic_state is None:
|
|
162
|
+
raise _AtomicStateUnavailableError(
|
|
163
|
+
"atomic_state unavailable (hooks/lib unreachable); refusing "
|
|
164
|
+
"to run mark_consumed's read-modify-write unlocked"
|
|
165
|
+
)
|
|
166
|
+
with atomic_state.locked_state(tracking_path, strict=True):
|
|
167
|
+
tracking = read_tracking(tracking_path)
|
|
168
|
+
tracking[file_path] = {
|
|
169
|
+
"capture_commit": capture_commit,
|
|
170
|
+
"recorded_at": datetime.now(timezone.utc)
|
|
171
|
+
.isoformat()
|
|
172
|
+
.replace("+00:00", "Z"),
|
|
173
|
+
}
|
|
174
|
+
atomic_state.atomic_write(
|
|
175
|
+
tracking_path, json.dumps(tracking, indent=2), fail_open=False
|
|
176
|
+
)
|
|
177
|
+
except (OSError, _LOCK_FAILURE_ERROR) as exc:
|
|
178
|
+
return {"success": False, "error": str(exc)}
|
|
179
|
+
return {"success": True}
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
# =============================================================================
|
|
183
|
+
# Git-backed ancestor check
|
|
184
|
+
# =============================================================================
|
|
185
|
+
def _run_git(args: list[str], *, cwd=None) -> subprocess.CompletedProcess | None:
|
|
186
|
+
"""Run a git subcommand, returning ``None`` on a missing git binary, a
|
|
187
|
+
non-repo ``cwd``, or a 30s timeout — never raises."""
|
|
188
|
+
try:
|
|
189
|
+
return subprocess.run(
|
|
190
|
+
args,
|
|
191
|
+
cwd=cwd,
|
|
192
|
+
capture_output=True,
|
|
193
|
+
text=True,
|
|
194
|
+
check=False,
|
|
195
|
+
timeout=30,
|
|
196
|
+
)
|
|
197
|
+
except (OSError, FileNotFoundError, subprocess.TimeoutExpired):
|
|
198
|
+
return None
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def _git_last_commit_sha(file_path, *, cwd=None) -> str | None:
|
|
202
|
+
"""Return ``file_path``'s last-commit SHA, or ``None`` when git is
|
|
203
|
+
unavailable (missing binary, not a repo, timeout) or the file has no
|
|
204
|
+
commit history at all (empty ``git log`` result — untracked/never
|
|
205
|
+
committed). Never raises."""
|
|
206
|
+
result = _run_git(
|
|
207
|
+
["git", "log", "-1", "--format=%H", "--", str(file_path)], cwd=cwd
|
|
208
|
+
)
|
|
209
|
+
if result is None:
|
|
210
|
+
return None
|
|
211
|
+
sha = result.stdout.strip()
|
|
212
|
+
return sha or None
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def _git_is_ancestor(commit_a: str, commit_b: str, *, cwd=None) -> bool:
|
|
216
|
+
"""True when ``commit_a`` is an ancestor of (or equal to) ``commit_b``
|
|
217
|
+
(``git merge-base --is-ancestor``). ``False`` when git is unavailable
|
|
218
|
+
(missing binary, not a repo, timeout) rather than letting the exception
|
|
219
|
+
propagate. Never raises."""
|
|
220
|
+
result = _run_git(
|
|
221
|
+
["git", "merge-base", "--is-ancestor", "--", commit_a, commit_b], cwd=cwd
|
|
222
|
+
)
|
|
223
|
+
if result is None:
|
|
224
|
+
return False
|
|
225
|
+
return result.returncode == 0
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
# =============================================================================
|
|
229
|
+
# CLI — resolve / mark-consumed
|
|
230
|
+
# =============================================================================
|
|
231
|
+
def _resolve(args) -> dict:
|
|
232
|
+
tracking = read_tracking(args.tracking)
|
|
233
|
+
last_commit = _git_last_commit_sha(args.file, cwd=args.cwd)
|
|
234
|
+
is_ancestor = (
|
|
235
|
+
_git_is_ancestor(last_commit, args.capture_commit, cwd=args.cwd)
|
|
236
|
+
if last_commit is not None
|
|
237
|
+
else False
|
|
238
|
+
)
|
|
239
|
+
eligible = is_eligible_for_reuse(
|
|
240
|
+
tracking, args.file, args.capture_commit, is_ancestor
|
|
241
|
+
)
|
|
242
|
+
return {
|
|
243
|
+
"eligible": eligible,
|
|
244
|
+
"file": args.file,
|
|
245
|
+
"capture_commit": args.capture_commit,
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def _mark_consumed(args) -> dict:
|
|
250
|
+
return mark_consumed(args.tracking, args.file, args.capture_commit)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def _cli(argv: Sequence[str]) -> int:
|
|
254
|
+
parser = argparse.ArgumentParser(
|
|
255
|
+
description="Resolve baseline-reuse eligibility, or mark a file's "
|
|
256
|
+
"consumption of a baseline capture commit."
|
|
257
|
+
)
|
|
258
|
+
sub = parser.add_subparsers(dest="command", required=True)
|
|
259
|
+
|
|
260
|
+
parent_parser = argparse.ArgumentParser(add_help=False)
|
|
261
|
+
parent_parser.add_argument("--file", required=True)
|
|
262
|
+
parent_parser.add_argument("--capture-commit", required=True)
|
|
263
|
+
parent_parser.add_argument("--tracking", required=True)
|
|
264
|
+
|
|
265
|
+
resolve_parser = sub.add_parser(
|
|
266
|
+
"resolve",
|
|
267
|
+
help="resolve whether a file may reuse the baseline report",
|
|
268
|
+
parents=[parent_parser],
|
|
269
|
+
)
|
|
270
|
+
resolve_parser.add_argument("--cwd", default=None)
|
|
271
|
+
|
|
272
|
+
sub.add_parser(
|
|
273
|
+
"mark-consumed",
|
|
274
|
+
help="record a file's consumption of a baseline",
|
|
275
|
+
parents=[parent_parser],
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
args = parser.parse_args(list(argv))
|
|
279
|
+
|
|
280
|
+
if args.command == "resolve":
|
|
281
|
+
payload = _resolve(args)
|
|
282
|
+
else:
|
|
283
|
+
payload = _mark_consumed(args)
|
|
284
|
+
|
|
285
|
+
print(json.dumps(payload))
|
|
286
|
+
# Exit 0 either way — advisory/informational, matching
|
|
287
|
+
# mutation_feasibility_gate.py's "advisory arbiter, not a gate" convention.
|
|
288
|
+
return 0
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
if __name__ == "__main__": # pragma: no cover
|
|
292
|
+
sys.exit(_cli(sys.argv[1:]))
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""mutation_exclude_policy.py — committed, human-approved mutation
|
|
3
|
+
exclude-policy bootstrap (#1757).
|
|
4
|
+
|
|
5
|
+
`mutation-kill`'s "Infrastructure exclusion detection"
|
|
6
|
+
(agents/mutation-kill.md) already flags likely-infrastructure files at run
|
|
7
|
+
time — DI wiring, exception handlers, middleware, generated code — but its
|
|
8
|
+
decision persists only to a typically-gitignored build-output path
|
|
9
|
+
(`StrykerOutput/mutation-kill-convergence.json`), so it's lost across a
|
|
10
|
+
fresh clone or a new CI runner. This module drafts the SAME two-signal
|
|
11
|
+
judgment as a standalone, committed, source-controlled policy file instead —
|
|
12
|
+
durable across machines.
|
|
13
|
+
|
|
14
|
+
**Never writes the committed policy file without human approval.** This is
|
|
15
|
+
the one hard constraint the whole module exists to satisfy: an unattended
|
|
16
|
+
night-watch run can *draft* a proposal (``draft_policy`` + a plain
|
|
17
|
+
``write_json`` to any path the caller chooses), but the ONLY code path that
|
|
18
|
+
writes ``mutation-exclude-policy.json`` at the repo root is :func:`approve`,
|
|
19
|
+
invoked deliberately via ``--approve`` — never called from
|
|
20
|
+
``mutation_nightwatch.py``'s unattended loop.
|
|
21
|
+
|
|
22
|
+
Two-signal rule, ported verbatim from `mutation-kill`'s own "Infrastructure
|
|
23
|
+
exclusion detection" section — BOTH must hold before a file is even
|
|
24
|
+
considered; neither alone is sufficient:
|
|
25
|
+
|
|
26
|
+
- ``honest score < 15%``
|
|
27
|
+
- ``NoCoverage > 50%`` of effective mutants (killed + survived + no_coverage)
|
|
28
|
+
|
|
29
|
+
A filename match against a known DI/wiring/generated-code naming convention
|
|
30
|
+
is a **hint that strengthens the tier**, never a requirement: it promotes a
|
|
31
|
+
flagged file from ``propose_and_ask`` to ``always``, but its absence never
|
|
32
|
+
blocks the numeric signals from flagging a file in the first place — mirrors
|
|
33
|
+
`mutation-kill.md`'s "named convention vs. signal-only" framing exactly.
|
|
34
|
+
|
|
35
|
+
Stdlib-only. See ADR 0014.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
from __future__ import annotations
|
|
39
|
+
|
|
40
|
+
import argparse
|
|
41
|
+
import fnmatch
|
|
42
|
+
import json
|
|
43
|
+
import sys
|
|
44
|
+
from enum import Enum
|
|
45
|
+
from pathlib import Path
|
|
46
|
+
|
|
47
|
+
import mutation_report
|
|
48
|
+
|
|
49
|
+
POLICY_FILENAME = "mutation-exclude-policy.json"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class ExclusionTier(str, Enum):
|
|
53
|
+
"""The two mutation exclude-policy tiers a flagged file can land in
|
|
54
|
+
(issue #1904 item 4) — a closed vocabulary previously carried as bare
|
|
55
|
+
string literals (`"always"`/`"propose_and_ask"`) compared with `==`, so
|
|
56
|
+
a typo silently read as "not the always tier" rather than failing
|
|
57
|
+
loudly. `str, Enum` — deliberately NOT `coverage_config.TestClassification`'s
|
|
58
|
+
convention, which is a plain `Enum` chosen so an accidental attempt to
|
|
59
|
+
JSON-serialize it fails loudly instead of silently succeeding. This
|
|
60
|
+
enum diverges on purpose: its values ARE meant to serialize to JSON
|
|
61
|
+
(`write_json`/`draft_policy`'s output) and to keep matching existing
|
|
62
|
+
bare-string `== "always"`-style call sites, so the `str` mixin is the
|
|
63
|
+
correct choice here, not a mirrored one."""
|
|
64
|
+
|
|
65
|
+
ALWAYS = "always"
|
|
66
|
+
PROPOSE_AND_ASK = "propose_and_ask"
|
|
67
|
+
|
|
68
|
+
# Ported verbatim from agents/mutation-kill.md's "Infrastructure exclusion
|
|
69
|
+
# detection" section — the single source of truth for these two numbers.
|
|
70
|
+
SCORE_THRESHOLD_PCT = 15.0
|
|
71
|
+
NO_COVERAGE_THRESHOLD_PCT = 50.0
|
|
72
|
+
|
|
73
|
+
# Filename hints per stack. The C# list is copied verbatim from
|
|
74
|
+
# mutation-kill.md; the javascript list is a parallel, analogous set for a
|
|
75
|
+
# second stack mutation_report.py can already score — see SUPPORTED_STACKS
|
|
76
|
+
# in mutation_nightwatch_stacks.py.
|
|
77
|
+
#
|
|
78
|
+
# Coverage is intentionally partial. ``"csharp"`` and ``"javascript"`` have
|
|
79
|
+
# curated filename hints today; ``"python"``, ``"java"``, and ``"go"`` — all
|
|
80
|
+
# recognized by mutation_nightwatch_stacks.py's STACK_DETECTORS/MEASURERS —
|
|
81
|
+
# do not yet. That is not an oversight: a file flagged for one of those
|
|
82
|
+
# stacks by the two-signal rule alone still lands in the ``propose_and_ask``
|
|
83
|
+
# tier (never dropped), it just never gets promoted to ``always`` until
|
|
84
|
+
# someone writes its filename-hint list. See KNOWN_STACKS_WITHOUT_HINTS
|
|
85
|
+
# below, which makes that gap explicit rather than indistinguishable from a
|
|
86
|
+
# typo'd/unrecognized stack name (#1854).
|
|
87
|
+
FILENAME_HINTS: dict[str, list[str]] = {
|
|
88
|
+
"csharp": [
|
|
89
|
+
"Startup.cs",
|
|
90
|
+
"Program.cs",
|
|
91
|
+
"*Filter.cs",
|
|
92
|
+
"*Middleware.cs",
|
|
93
|
+
"*Logger*.cs",
|
|
94
|
+
"*HealthCheck*.cs",
|
|
95
|
+
"*.Designer.cs",
|
|
96
|
+
"*Module.cs",
|
|
97
|
+
"*Container.cs",
|
|
98
|
+
"*Registration.cs",
|
|
99
|
+
"*Bootstrap*.cs",
|
|
100
|
+
"*DependencyInjection*.cs",
|
|
101
|
+
],
|
|
102
|
+
"javascript": [
|
|
103
|
+
"main.ts",
|
|
104
|
+
"main.js",
|
|
105
|
+
"*.module.ts",
|
|
106
|
+
"*.config.js",
|
|
107
|
+
"*.config.ts",
|
|
108
|
+
"*Middleware.ts",
|
|
109
|
+
"*Logger*.ts",
|
|
110
|
+
"*Container.ts",
|
|
111
|
+
],
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
# Stacks recognized by mutation_nightwatch_stacks.py that deliberately have
|
|
115
|
+
# no curated FILENAME_HINTS entry yet (not written, not a typo). A stack in
|
|
116
|
+
# neither this set nor FILENAME_HINTS is genuinely unknown — see
|
|
117
|
+
# _matching_hint below.
|
|
118
|
+
KNOWN_STACKS_WITHOUT_HINTS: frozenset[str] = frozenset({"python", "java", "go"})
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _matching_hint(filename: str, stack: str) -> str | None:
|
|
122
|
+
"""Return the first filename-hint pattern that matches, or ``None``.
|
|
123
|
+
|
|
124
|
+
Raises ``ValueError`` when ``stack`` is neither in ``FILENAME_HINTS`` nor
|
|
125
|
+
``KNOWN_STACKS_WITHOUT_HINTS`` — a genuinely unrecognized/typo'd stack
|
|
126
|
+
name must surface loudly rather than silently returning no hints (#1854).
|
|
127
|
+
"""
|
|
128
|
+
if stack not in FILENAME_HINTS and stack not in KNOWN_STACKS_WITHOUT_HINTS:
|
|
129
|
+
raise ValueError(
|
|
130
|
+
f"unknown stack: {stack!r} (known: "
|
|
131
|
+
f"{sorted(set(FILENAME_HINTS) | KNOWN_STACKS_WITHOUT_HINTS)})"
|
|
132
|
+
)
|
|
133
|
+
for pattern in FILENAME_HINTS.get(stack, ()):
|
|
134
|
+
if fnmatch.fnmatch(filename, pattern):
|
|
135
|
+
return pattern
|
|
136
|
+
return None
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def draft_entries(report_path: Path, stack: str) -> list[dict]:
|
|
140
|
+
"""Apply the two-signal rule to every file in `report_path`'s native
|
|
141
|
+
report, returning one ``{file, stack, tier, reason}`` entry per flagged
|
|
142
|
+
file. A file with zero effective mutants (killed+survived+no_coverage)
|
|
143
|
+
yields no scoring signal and is never flagged."""
|
|
144
|
+
data = mutation_report.load_report(report_path)
|
|
145
|
+
entries = []
|
|
146
|
+
for file_key in sorted(data.get("files", {})):
|
|
147
|
+
summary = mutation_report.score_report_for_file(report_path, file_key)
|
|
148
|
+
effective = summary.killed + summary.survived + summary.no_coverage
|
|
149
|
+
if effective == 0:
|
|
150
|
+
continue
|
|
151
|
+
no_coverage_pct = (summary.no_coverage / effective) * 100
|
|
152
|
+
# Both signals must hold — failing either alone must never flag.
|
|
153
|
+
if summary.honest_score >= SCORE_THRESHOLD_PCT:
|
|
154
|
+
continue
|
|
155
|
+
if no_coverage_pct <= NO_COVERAGE_THRESHOLD_PCT:
|
|
156
|
+
continue
|
|
157
|
+
|
|
158
|
+
hint = _matching_hint(Path(file_key).name, stack)
|
|
159
|
+
if hint:
|
|
160
|
+
tier = ExclusionTier.ALWAYS
|
|
161
|
+
reason = (
|
|
162
|
+
f"named convention: {hint} (score {summary.honest_score:.1f}%, "
|
|
163
|
+
f"NoCoverage {no_coverage_pct:.1f}%)"
|
|
164
|
+
)
|
|
165
|
+
else:
|
|
166
|
+
tier = ExclusionTier.PROPOSE_AND_ASK
|
|
167
|
+
reason = (
|
|
168
|
+
f"signal-only: score {summary.honest_score:.1f}%, NoCoverage "
|
|
169
|
+
f"{no_coverage_pct:.1f}% (no filename match)"
|
|
170
|
+
)
|
|
171
|
+
entries.append({"file": file_key, "stack": stack, "tier": tier, "reason": reason})
|
|
172
|
+
return entries
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def draft_policy(report_paths: dict[str, Path]) -> dict:
|
|
176
|
+
"""Draft a two-tier exclude policy from one native report per stack.
|
|
177
|
+
|
|
178
|
+
``report_paths`` maps stack name -> native report path. A stack with no
|
|
179
|
+
on-disk native report path (mutmut/python — see
|
|
180
|
+
``mutation_nightwatch_stacks.StackResult.report_path``'s docstring) is
|
|
181
|
+
simply absent from the mapping; it is never guessed at.
|
|
182
|
+
"""
|
|
183
|
+
always: list[dict] = []
|
|
184
|
+
propose_and_ask: list[dict] = []
|
|
185
|
+
for stack, report_path in sorted(report_paths.items()):
|
|
186
|
+
for entry in draft_entries(report_path, stack):
|
|
187
|
+
(always if entry["tier"] == ExclusionTier.ALWAYS else propose_and_ask).append(entry)
|
|
188
|
+
return {
|
|
189
|
+
"schema_version": 1,
|
|
190
|
+
ExclusionTier.ALWAYS.value: always,
|
|
191
|
+
ExclusionTier.PROPOSE_AND_ASK.value: propose_and_ask,
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def write_json(path: Path, payload: dict) -> None:
|
|
196
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
197
|
+
path.write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8")
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def approve(draft_path: Path, repo_root: Path) -> Path:
|
|
201
|
+
"""Write the approved draft as the committed policy file at
|
|
202
|
+
`repo_root`. The ONLY code path that writes `POLICY_FILENAME` at the
|
|
203
|
+
repo root — see the module docstring's approval-gate constraint."""
|
|
204
|
+
draft = json.loads(draft_path.read_text(encoding="utf-8"))
|
|
205
|
+
policy_path = repo_root / POLICY_FILENAME
|
|
206
|
+
write_json(policy_path, draft)
|
|
207
|
+
return policy_path
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def parse_args(argv) -> argparse.Namespace:
|
|
211
|
+
p = argparse.ArgumentParser(
|
|
212
|
+
prog="mutation_exclude_policy.py",
|
|
213
|
+
description=(
|
|
214
|
+
"Draft (never auto-write) a two-tier mutation exclude policy from "
|
|
215
|
+
"native mutation reports; write the committed policy file only "
|
|
216
|
+
"on --approve."
|
|
217
|
+
),
|
|
218
|
+
)
|
|
219
|
+
p.add_argument(
|
|
220
|
+
"--report",
|
|
221
|
+
action="append",
|
|
222
|
+
default=[],
|
|
223
|
+
metavar="STACK=PATH",
|
|
224
|
+
help="One native report path per stack, e.g. "
|
|
225
|
+
"javascript=reports/mutation/mutation.json. Repeatable.",
|
|
226
|
+
)
|
|
227
|
+
p.add_argument("--draft", action="store_true", help="Draft mode.")
|
|
228
|
+
p.add_argument("--out", help="Where to write the draft (--draft mode).")
|
|
229
|
+
p.add_argument(
|
|
230
|
+
"--approve", metavar="DRAFT_PATH", help="Approve a draft, writing the committed policy file."
|
|
231
|
+
)
|
|
232
|
+
p.add_argument(
|
|
233
|
+
"--repo-root", default=".", help="Repo root (--approve mode; default: cwd)"
|
|
234
|
+
)
|
|
235
|
+
return p.parse_args(list(argv))
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def main(argv: list[str] | None = None) -> int:
|
|
239
|
+
argv = list(sys.argv[1:] if argv is None else argv)
|
|
240
|
+
args = parse_args(argv)
|
|
241
|
+
|
|
242
|
+
if args.approve:
|
|
243
|
+
policy_path = approve(Path(args.approve), Path(args.repo_root).resolve())
|
|
244
|
+
print(f"approved: wrote {policy_path}")
|
|
245
|
+
return 0
|
|
246
|
+
|
|
247
|
+
if args.draft:
|
|
248
|
+
if not args.out:
|
|
249
|
+
sys.stderr.write("error: --draft requires --out\n")
|
|
250
|
+
return 2
|
|
251
|
+
report_paths = {}
|
|
252
|
+
for item in args.report:
|
|
253
|
+
if "=" not in item:
|
|
254
|
+
sys.stderr.write(f"error: --report must be STACK=PATH, got {item!r}\n")
|
|
255
|
+
return 2
|
|
256
|
+
stack, _, path_str = item.partition("=")
|
|
257
|
+
report_paths[stack] = Path(path_str)
|
|
258
|
+
policy = draft_policy(report_paths)
|
|
259
|
+
write_json(Path(args.out), policy)
|
|
260
|
+
print(f"drafted: wrote {args.out}")
|
|
261
|
+
return 0
|
|
262
|
+
|
|
263
|
+
sys.stderr.write("error: pass --draft or --approve\n")
|
|
264
|
+
return 2
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
if __name__ == "__main__":
|
|
268
|
+
sys.exit(main())
|