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,592 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""mutation_kill_retry.py — retry-then-downgrade on repeated headless-generation
|
|
3
|
+
failures (#1908), extracted out of ``mutation_kill_shared.py`` (#1925).
|
|
4
|
+
|
|
5
|
+
``mutation_kill_shared.py`` had grown into a grab-bag of five separate
|
|
6
|
+
concerns (git revert/commit mechanics, the stop-round predicate, headless-CLI
|
|
7
|
+
invocation glue, this retry/downgrade policy, and the cross-language
|
|
8
|
+
``InsertOutcome``/``InsertionRefused`` shapes). A fix to git-revert semantics
|
|
9
|
+
and a fix to the downgrade ladder shared the same file and the same review
|
|
10
|
+
blast radius, with neither small enough to read in one pass and confirm it
|
|
11
|
+
doesn't touch the other's state. This module owns exactly the retry/downgrade
|
|
12
|
+
concern; ``mutation_kill_shared.py`` keeps git mechanics, ``_timeout_from_env``,
|
|
13
|
+
``stop_reason``, ``resolve_model``/``resolve_fallback_model`` and the headless
|
|
14
|
+
``claude --print`` invocation glue, and the ``InsertOutcome``/``InsertionRefused``
|
|
15
|
+
shapes.
|
|
16
|
+
|
|
17
|
+
The type precondition for the 502/gateway-class error definition is EXACT: a
|
|
18
|
+
:class:`mutation_kill_shared.HeadlessCallFailed` raised by
|
|
19
|
+
``run_claude_headless``'s non-zero-exit shape (never its
|
|
20
|
+
``TimeoutExpired``-derived shape, which raises a plain ``RuntimeError`` — a
|
|
21
|
+
local generation timeout, not an upstream provider signal). Within that type,
|
|
22
|
+
the classifier reads the full, untruncated ``stderr``, case-insensitively,
|
|
23
|
+
for either one of the non-numeric markers below or the anchored numeral
|
|
24
|
+
pattern (``_GATEWAY_STATUS_RE``) — a bare ``"502"``/``"503"``/``"504"``
|
|
25
|
+
substring is not enough on its own (#1938). That marker/regex match is a
|
|
26
|
+
best-effort heuristic, not an exhaustive one: it does not yet recognize
|
|
27
|
+
``error_code: 503``-style underscore-joined tokens, status 529, or errors
|
|
28
|
+
that only appear on stdout — filed and deliberately deferred rather than
|
|
29
|
+
fixed in this slice, see #1950.
|
|
30
|
+
|
|
31
|
+
This module's dependencies on ``mutation_kill_shared`` are
|
|
32
|
+
``run_claude_headless``/``resolve_fallback_model`` — both accessed via the
|
|
33
|
+
module object (``mutation_kill_shared.run_claude_headless(...)``), not a
|
|
34
|
+
``from ... import`` binding, so a test's ``monkeypatch.setattr(mutation_kill_shared,
|
|
35
|
+
"run_claude_headless", fake)`` takes effect here too (mirrors the existing
|
|
36
|
+
same-module-globals contract ``_mutation_test_helpers.sequenced_run_claude_headless``
|
|
37
|
+
already documents) — plus ``HeadlessCallFailed``, referenced only as a type
|
|
38
|
+
(``isinstance(exc, mutation_kill_shared.HeadlessCallFailed)``), which carries
|
|
39
|
+
no monkeypatch sensitivity of its own since nothing here calls it.
|
|
40
|
+
``run_claude_headless`` is reached on every generation attempt unless the
|
|
41
|
+
caller injects ``call_headless`` (#1918), in which case it is never reached —
|
|
42
|
+
see :meth:`_RetryCallContext.resolve_call_headless`. (This
|
|
43
|
+
mirrors the dependency inventory documented from the other direction in
|
|
44
|
+
``mutation_kill_shared.py``'s own module docstring — keep the two in sync.)
|
|
45
|
+
|
|
46
|
+
Stdlib-only. See ADR 0014.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
from __future__ import annotations
|
|
50
|
+
|
|
51
|
+
import re
|
|
52
|
+
import time
|
|
53
|
+
from collections.abc import Callable
|
|
54
|
+
from dataclasses import dataclass
|
|
55
|
+
from pathlib import Path
|
|
56
|
+
|
|
57
|
+
import mutation_kill_shared
|
|
58
|
+
|
|
59
|
+
_GATEWAY_CLASS_MARKERS = (
|
|
60
|
+
"bad gateway",
|
|
61
|
+
"service unavailable",
|
|
62
|
+
"gateway timeout",
|
|
63
|
+
"overloaded_error",
|
|
64
|
+
"upstream connect error",
|
|
65
|
+
"connection reset",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# Anchored numeral markers (#1938, widened by #1950): a bare "502"/"503"/"504"
|
|
69
|
+
# substring false-positives on unrelated numbers (a request id, a byte count).
|
|
70
|
+
# Requires a status-context word (status/http/code) close before the digits, so
|
|
71
|
+
# "HTTP 502", "status: 503", and "error code 504" all match but
|
|
72
|
+
# "request id 502391" does not.
|
|
73
|
+
#
|
|
74
|
+
# Three #1950 corrections to the original `\b(?:status|http|code)[^0-9]{0,12}50[234]\b`:
|
|
75
|
+
#
|
|
76
|
+
# 1. `\b` REJECTED UNDERSCORE-JOINED KEYS. `_` is a `\w` character, so `\b`
|
|
77
|
+
# requires a NON-word character immediately before status/http/code — and
|
|
78
|
+
# the `_c` in `error_code: 503` and the `rC` in `errorCode=504` are both
|
|
79
|
+
# word-to-word transitions. Underscore- and camel-joined status keys are
|
|
80
|
+
# routine in real provider payloads. The lookbehind is now
|
|
81
|
+
# `(?<![A-Za-z0-9])`, which treats `_` (and a camel boundary) as a
|
|
82
|
+
# separator while still refusing to match inside a longer alphanumeric run.
|
|
83
|
+
# 2. `HTTP/1.1 502` FAILED because the version token puts digits in the gap,
|
|
84
|
+
# which `[^0-9]{0,12}` forbids. An optional `/<major>[.<minor>]` is now
|
|
85
|
+
# consumed explicitly rather than by widening the gap to allow digits —
|
|
86
|
+
# widening would have re-admitted exactly the "request id 502391" class
|
|
87
|
+
# #1938 anchored the pattern to exclude.
|
|
88
|
+
# 3. STATUS 529 (Anthropic's own overload code) was absent from the numeral
|
|
89
|
+
# alternation. The downgrade ladder this policy drives is Anthropic-specific,
|
|
90
|
+
# so 529 is plausibly the most common real "retry me" signal this classifier
|
|
91
|
+
# will ever see. It was covered only via the `overloaded_error` marker
|
|
92
|
+
# string, which a rendered `API Error: 529 Overloaded` does not contain
|
|
93
|
+
# verbatim.
|
|
94
|
+
#
|
|
95
|
+
# The trailing `(?![0-9])` replaces `\b` for the same reason as the lookbehind,
|
|
96
|
+
# and still rejects "502391" (the `2` is followed by `3`).
|
|
97
|
+
#
|
|
98
|
+
# 4. A CAMEL-JOINED key (`errorCode=504`) still fails a plain lookbehind: the
|
|
99
|
+
# `rC` transition is letter-to-letter, and the pattern is IGNORECASE so the
|
|
100
|
+
# lookbehind cannot itself distinguish case. Rather than relaxing the
|
|
101
|
+
# lookbehind to allow any preceding letter — which would admit "barcode 502"
|
|
102
|
+
# and "decode 503" — camel humps are split to `_` first, reducing the camel
|
|
103
|
+
# case to the underscore case already handled.
|
|
104
|
+
# 5. `error` joins the context words so a rendered `API Error: 529 Overloaded`
|
|
105
|
+
# anchors at all; it carries none of status/http/code. The trailing
|
|
106
|
+
# `(?![0-9])` keeps this from admitting "error after 5024 ms".
|
|
107
|
+
_CAMEL_SPLIT_RE = re.compile(r"(?<=[a-z0-9])(?=[A-Z])")
|
|
108
|
+
|
|
109
|
+
_GATEWAY_STATUS_RE = re.compile(
|
|
110
|
+
r"(?<![A-Za-z0-9])(?:status|http|code|error)(?:/\d+(?:\.\d+)?)?"
|
|
111
|
+
r"[^0-9]{0,12}(?:50[234]|529)(?![0-9])",
|
|
112
|
+
re.IGNORECASE,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _anchorable(text: str) -> str:
|
|
117
|
+
"""Normalize camel humps to `_` so a camel-joined status key anchors.
|
|
118
|
+
|
|
119
|
+
Pure and deterministic: `errorCode=504` -> `error_Code=504`, which the
|
|
120
|
+
pattern's `(?<![A-Za-z0-9])` lookbehind then accepts.
|
|
121
|
+
"""
|
|
122
|
+
return _CAMEL_SPLIT_RE.sub("_", text)
|
|
123
|
+
|
|
124
|
+
# 3 consecutive gateway-class failures on the same model earn exactly one
|
|
125
|
+
# same-model retry before a downgrade is considered (#1908).
|
|
126
|
+
_GATEWAY_FAILURE_THRESHOLD = 3
|
|
127
|
+
|
|
128
|
+
# Backoff formula for the pre-threshold retries: min(_BACKOFF_BASE **
|
|
129
|
+
# (streak - 1), _BACKOFF_CAP_S) seconds (#1908 review).
|
|
130
|
+
_BACKOFF_BASE = 2
|
|
131
|
+
_BACKOFF_CAP_S = 10
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def is_gateway_class_error(exc: BaseException) -> bool:
|
|
135
|
+
"""True iff ``exc`` is a :class:`mutation_kill_shared.HeadlessCallFailed`
|
|
136
|
+
raised by :func:`mutation_kill_shared.run_claude_headless`'s non-zero-exit
|
|
137
|
+
shape whose full, untruncated ``stderr``, case-insensitively, contains a
|
|
138
|
+
non-numeric gateway-class marker or matches the anchored numeral pattern
|
|
139
|
+
(#1938).
|
|
140
|
+
|
|
141
|
+
Everything else — a plain ``RuntimeError`` (the
|
|
142
|
+
``subprocess.TimeoutExpired``-derived shape is a local generation
|
|
143
|
+
timeout, not an upstream provider signal, and never raises
|
|
144
|
+
``HeadlessCallFailed``) and a ``HeadlessCallFailed`` whose stderr matches
|
|
145
|
+
none of the markers — is non-gateway-class.
|
|
146
|
+
"""
|
|
147
|
+
if not isinstance(exc, mutation_kill_shared.HeadlessCallFailed):
|
|
148
|
+
return False
|
|
149
|
+
# #1950: classify over stderr AND stdout. The claude CLI renders some
|
|
150
|
+
# upstream failures to stdout while stderr carries only a generic
|
|
151
|
+
# non-zero-exit line; a stderr-only classifier calls those non-gateway-class
|
|
152
|
+
# and spends the file's whole budget on a genuinely retryable overload.
|
|
153
|
+
# `getattr` rather than attribute access so a HeadlessCallFailed built by
|
|
154
|
+
# an older two-argument call site (or a test fake) still classifies.
|
|
155
|
+
combined = f"{exc.stderr}\n{getattr(exc, 'stdout', '') or ''}"
|
|
156
|
+
lowered = combined.lower()
|
|
157
|
+
return any(marker in lowered for marker in _GATEWAY_CLASS_MARKERS) or bool(
|
|
158
|
+
_GATEWAY_STATUS_RE.search(_anchorable(combined))
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
# Shared exit code for the clean-continuable outcome class (#1908 review):
|
|
163
|
+
# either a fully spent retry-then-downgrade budget (GenerationExhausted) or
|
|
164
|
+
# any other provably-clean-of-inserted-content generation/infrastructure
|
|
165
|
+
# failure that isn't a failed revert. Used by both headless CLIs' main() and
|
|
166
|
+
# stryker_shard_pipeline.py's shard driver so the meaning of "5" lives in one
|
|
167
|
+
# place instead of three duplicated literals.
|
|
168
|
+
#
|
|
169
|
+
# EXIT_CLEAN_UNFIXED is the primary, outcome-shaped name (#1956): the value
|
|
170
|
+
# has named two distinct causes since #1939 (true GenerationExhausted, or any
|
|
171
|
+
# other clean RuntimeError such as a generation timeout), and the original
|
|
172
|
+
# name only describes one of them. EXIT_GENERATION_EXHAUSTED is kept as an
|
|
173
|
+
# alias — same value, zero behavior change — because every existing call
|
|
174
|
+
# site (stryker_shard_pipeline.py, mutation_kill_headless.py,
|
|
175
|
+
# mutation_kill_loop_python.py) and their tests already import it by that
|
|
176
|
+
# name; renaming those call sites too was judged not worth the diff for a
|
|
177
|
+
# purely cosmetic rename with no behavior change (#1956 explicitly frames
|
|
178
|
+
# this as "consider," not a mandate). New code should prefer
|
|
179
|
+
# EXIT_CLEAN_UNFIXED.
|
|
180
|
+
EXIT_CLEAN_UNFIXED = 5
|
|
181
|
+
EXIT_GENERATION_EXHAUSTED = EXIT_CLEAN_UNFIXED
|
|
182
|
+
|
|
183
|
+
# Shared exit code for the fatal, working-tree-possibly-mutated outcome class
|
|
184
|
+
# (#1930): a failed revert (or a failed-commit round-abandonment's own
|
|
185
|
+
# revert) leaves the tree in an unknown state. Used by both headless CLIs'
|
|
186
|
+
# main() functions so the meaning of "4" lives in one place instead of two
|
|
187
|
+
# duplicated literals. stryker_shard_pipeline.py's shard driver never
|
|
188
|
+
# imports this constant — it decodes exit 4 by exclusion (any non-zero,
|
|
189
|
+
# non-EXIT_GENERATION_EXHAUSTED exit is treated as fatal) and only names "4"
|
|
190
|
+
# in prose/log wording.
|
|
191
|
+
EXIT_REVERT_FAILED = 4
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class GenerationExhausted(RuntimeError):
|
|
195
|
+
"""Raised when the fallback tier's own generation call also exhausts its
|
|
196
|
+
3-consecutive-gateway-class-failures/1-same-model-retry budget (#1908).
|
|
197
|
+
|
|
198
|
+
This file gets exactly one downgrade, ever — reaching this exception
|
|
199
|
+
means no second downgrade will be attempted, regardless of whether the
|
|
200
|
+
exhausted tier is the true ladder floor (``haiku``), a mid-ladder tier
|
|
201
|
+
(e.g. ``sonnet``), or an operator override. Callers (the ``--headless``
|
|
202
|
+
CLIs' ``main()``) catch this subclass ahead of ``RevertFailed`` and the
|
|
203
|
+
generic ``RuntimeError`` and report it via the existing exit-code
|
|
204
|
+
taxonomy — the message names the file, round, model, and error class,
|
|
205
|
+
plus an explicit "no further downgrade will be attempted" statement.
|
|
206
|
+
"""
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
@dataclass(frozen=True)
|
|
210
|
+
class DowngradeEvent:
|
|
211
|
+
"""One downgrade (or final-exhaustion) decision from the
|
|
212
|
+
retry-then-downgrade mechanism (#1908).
|
|
213
|
+
|
|
214
|
+
This is the seam Step 3.2b's audit-trail write hangs off of: pass an
|
|
215
|
+
``on_downgrade`` callback to :func:`make_retrying_headless_call` (or
|
|
216
|
+
:func:`make_headless_generator`) to record this event durably. Nothing
|
|
217
|
+
in this module writes an audit trail itself yet.
|
|
218
|
+
"""
|
|
219
|
+
|
|
220
|
+
source_file: str
|
|
221
|
+
round_num: int | None
|
|
222
|
+
from_model: str | None
|
|
223
|
+
to_model: str | None
|
|
224
|
+
error_class: str
|
|
225
|
+
#: Whether this file had ALREADY spent its one downgrade before this
|
|
226
|
+
#: failure. #1952: on an exhausted event this is the actual reason the
|
|
227
|
+
#: caller computed and then discarded, forcing
|
|
228
|
+
#: :func:`_format_downgrade_message` to re-infer it from a proxy (is
|
|
229
|
+
#: ``from_model`` a known ladder model?) that a valid non-ladder
|
|
230
|
+
#: ``--model``/``DEV_TEAM_MUTATION_FALLBACK_MODEL`` override defeats.
|
|
231
|
+
#: Defaulted so every existing construction keeps working; the one
|
|
232
|
+
#: internal call site sets it explicitly.
|
|
233
|
+
already_downgraded: bool = False
|
|
234
|
+
|
|
235
|
+
@property
|
|
236
|
+
def exhausted(self) -> bool:
|
|
237
|
+
"""True iff no fallback tier was available — derived from
|
|
238
|
+
``to_model`` rather than stored separately, so the two can never
|
|
239
|
+
disagree (#1918 Step 2.3)."""
|
|
240
|
+
return self.to_model is None
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def _format_downgrade_message(event: DowngradeEvent) -> str:
|
|
244
|
+
source_file = " ".join(str(event.source_file).split())
|
|
245
|
+
if event.exhausted:
|
|
246
|
+
model_label = event.from_model if event.from_model is not None else "unspecified"
|
|
247
|
+
# #1952: branch on the reason the caller actually computed, not on
|
|
248
|
+
# whether from_model happens to be a ladder name. `fable` is a VALID
|
|
249
|
+
# --model / DEV_TEAM_MUTATION_FALLBACK_MODEL override that deliberately
|
|
250
|
+
# has no _MODEL_DOWNGRADE_LADDER entry, so a file that started on opus,
|
|
251
|
+
# downgraded once to fable, and then exhausted was reported as "no
|
|
252
|
+
# downgrade ladder position available for this model" when the true
|
|
253
|
+
# cause was "this file already spent its one downgrade".
|
|
254
|
+
if event.already_downgraded:
|
|
255
|
+
return (
|
|
256
|
+
f"generation for {source_file} (round {event.round_num}) "
|
|
257
|
+
f"exhausted its retry budget on model {model_label!r} after "
|
|
258
|
+
f"a {event.error_class} retry failure — no further downgrade "
|
|
259
|
+
"will be attempted"
|
|
260
|
+
)
|
|
261
|
+
return (
|
|
262
|
+
f"generation for {source_file} (round {event.round_num}) "
|
|
263
|
+
f"exhausted its retry budget on model {model_label!r} after a "
|
|
264
|
+
f"{event.error_class} retry failure — no downgrade ladder "
|
|
265
|
+
"position available for this model, surfacing to operator"
|
|
266
|
+
)
|
|
267
|
+
return (
|
|
268
|
+
f"downgrading generation for {source_file} (round "
|
|
269
|
+
f"{event.round_num}) from {event.from_model!r} to {event.to_model!r} "
|
|
270
|
+
f"after a {event.error_class} retry failure"
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
@dataclass
|
|
275
|
+
class _RetryState:
|
|
276
|
+
"""Mutable per-file retry/downgrade state for one
|
|
277
|
+
:func:`make_retrying_headless_call` closure (#1908 review).
|
|
278
|
+
|
|
279
|
+
Replaces an untyped ``dict[str, object]`` that forced
|
|
280
|
+
``# type: ignore[arg-type]`` at two call sites and an ``int(...)`` cast on
|
|
281
|
+
every streak read — a plain dataclass carries its own types, so neither
|
|
282
|
+
workaround is needed. Not frozen: every field is mutated in place as the
|
|
283
|
+
closure runs.
|
|
284
|
+
"""
|
|
285
|
+
|
|
286
|
+
model: str | None
|
|
287
|
+
streak: int = 0
|
|
288
|
+
downgraded: bool = False
|
|
289
|
+
|
|
290
|
+
def record_gateway_failure(self) -> int:
|
|
291
|
+
"""Increment the consecutive-gateway-failure streak and return the
|
|
292
|
+
new count."""
|
|
293
|
+
self.streak += 1
|
|
294
|
+
return self.streak
|
|
295
|
+
|
|
296
|
+
def reset_streak(self) -> None:
|
|
297
|
+
"""Zero the consecutive-gateway-failure streak."""
|
|
298
|
+
self.streak = 0
|
|
299
|
+
|
|
300
|
+
def spend_downgrade(self, to_model: str) -> None:
|
|
301
|
+
"""Spend this file's one-and-only downgrade, moving to ``to_model``.
|
|
302
|
+
|
|
303
|
+
Raises :class:`RuntimeError` if this state has already spent its one
|
|
304
|
+
downgrade — a file gets exactly one downgrade, ever (#1908).
|
|
305
|
+
"""
|
|
306
|
+
if self.downgraded:
|
|
307
|
+
raise RuntimeError(
|
|
308
|
+
f"file already spent its one downgrade (current model {self.model!r})"
|
|
309
|
+
)
|
|
310
|
+
self.model = to_model
|
|
311
|
+
self.downgraded = True
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
@dataclass(frozen=True)
|
|
315
|
+
class _RetryCallContext:
|
|
316
|
+
"""Call-invariant collaborators for one file's retry/downgrade closure
|
|
317
|
+
(#1908 review). Bundles ``cwd``/``log``/``on_downgrade`` — none of which
|
|
318
|
+
change between calls or rounds — so :func:`_retry_once_then_maybe_downgrade`
|
|
319
|
+
takes one object instead of three separate keyword parameters.
|
|
320
|
+
|
|
321
|
+
``call_headless`` is ``None`` when the caller didn't inject a transport
|
|
322
|
+
(#1918 Step 2.2) — :meth:`resolve_call_headless` looks up
|
|
323
|
+
``mutation_kill_shared.run_claude_headless`` fresh on every actual call,
|
|
324
|
+
not once here at construction time, so a test that monkeypatches the
|
|
325
|
+
module attribute *after* constructing the closure (but before invoking
|
|
326
|
+
it) still observes the patch — exactly the dynamic-lookup contract the
|
|
327
|
+
pre-injection code had via its direct
|
|
328
|
+
``mutation_kill_shared.run_claude_headless(...)`` call sites."""
|
|
329
|
+
|
|
330
|
+
cwd: Path | None
|
|
331
|
+
log: Callable[[str], None]
|
|
332
|
+
on_downgrade: Callable[[DowngradeEvent], None] | None
|
|
333
|
+
call_headless: Callable[..., str] | None
|
|
334
|
+
|
|
335
|
+
def resolve_call_headless(self) -> Callable[..., str]:
|
|
336
|
+
"""Return the injected transport, or
|
|
337
|
+
``mutation_kill_shared.run_claude_headless`` looked up dynamically
|
|
338
|
+
via the module object when none was injected."""
|
|
339
|
+
return (
|
|
340
|
+
self.call_headless
|
|
341
|
+
if self.call_headless is not None
|
|
342
|
+
else mutation_kill_shared.run_claude_headless
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
def invoke(self, prompt: str, model: str | None) -> str:
|
|
346
|
+
"""Call the resolved transport with this context's ``cwd`` — the one
|
|
347
|
+
call expression both :func:`_retry_once_then_maybe_downgrade` and
|
|
348
|
+
:func:`make_retrying_headless_call`'s ``call`` closure need, so it's
|
|
349
|
+
defined once instead of duplicated verbatim at both sites (#1938
|
|
350
|
+
review)."""
|
|
351
|
+
return self.resolve_call_headless()(prompt, model=model, cwd=self.cwd)
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def _retry_once_then_maybe_downgrade(
|
|
355
|
+
state: _RetryState,
|
|
356
|
+
prompt: str,
|
|
357
|
+
source_file: str,
|
|
358
|
+
round_num: int | None,
|
|
359
|
+
*,
|
|
360
|
+
ctx: _RetryCallContext,
|
|
361
|
+
) -> str | None:
|
|
362
|
+
"""The 3rd-consecutive-failure branch: exactly one same-model retry, then
|
|
363
|
+
decide downgrade-or-exhausted (#1908). Extracted out of
|
|
364
|
+
:func:`make_retrying_headless_call`'s ``call`` closure to keep it under
|
|
365
|
+
size/nesting/complexity thresholds — ``ctx`` carries the same
|
|
366
|
+
``on_downgrade``/``log``/``cwd`` the caller already has (passed
|
|
367
|
+
explicitly, not captured by closure, so this function stays testable in
|
|
368
|
+
isolation), and mutates ``state`` in place exactly as the inline branch
|
|
369
|
+
it replaces did.
|
|
370
|
+
|
|
371
|
+
Returns the retry's result string on a successful retry. Returns
|
|
372
|
+
``None`` when a downgrade was applied instead — the caller's
|
|
373
|
+
``while True`` loop re-enters :func:`mutation_kill_shared.run_claude_headless`
|
|
374
|
+
on the new model. Raises :class:`GenerationExhausted` on exhaustion (no
|
|
375
|
+
fallback tier available, or this file already spent its one downgrade).
|
|
376
|
+
"""
|
|
377
|
+
already_downgraded = state.downgraded
|
|
378
|
+
try:
|
|
379
|
+
return ctx.invoke(prompt, state.model)
|
|
380
|
+
except RuntimeError as retry_exc:
|
|
381
|
+
error_class = (
|
|
382
|
+
"gateway-class" if is_gateway_class_error(retry_exc) else "non-gateway-class"
|
|
383
|
+
)
|
|
384
|
+
from_model = state.model
|
|
385
|
+
to_model = (
|
|
386
|
+
None
|
|
387
|
+
if already_downgraded
|
|
388
|
+
else mutation_kill_shared.resolve_fallback_model(from_model)
|
|
389
|
+
)
|
|
390
|
+
event = DowngradeEvent(
|
|
391
|
+
source_file=source_file,
|
|
392
|
+
round_num=round_num,
|
|
393
|
+
from_model=from_model,
|
|
394
|
+
to_model=to_model,
|
|
395
|
+
error_class=error_class,
|
|
396
|
+
already_downgraded=already_downgraded,
|
|
397
|
+
)
|
|
398
|
+
ctx.log(_format_downgrade_message(event))
|
|
399
|
+
if ctx.on_downgrade is not None:
|
|
400
|
+
ctx.on_downgrade(event)
|
|
401
|
+
if to_model is None:
|
|
402
|
+
raise GenerationExhausted(_format_downgrade_message(event)) from retry_exc
|
|
403
|
+
state.spend_downgrade(to_model)
|
|
404
|
+
return None
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
def make_retrying_headless_call(
|
|
408
|
+
*,
|
|
409
|
+
initial_model: str | None,
|
|
410
|
+
cwd: Path | None = None,
|
|
411
|
+
log: Callable[[str], None] = print,
|
|
412
|
+
on_downgrade: Callable[[DowngradeEvent], None] | None = None,
|
|
413
|
+
sleep: Callable[[float], None] = time.sleep,
|
|
414
|
+
call_headless: Callable[..., str] | None = None,
|
|
415
|
+
) -> Callable[[str, str, int | None], str]:
|
|
416
|
+
"""Return a per-file, stateful wrapper around
|
|
417
|
+
:func:`mutation_kill_shared.run_claude_headless` implementing the
|
|
418
|
+
retry-then-downgrade rule (#1908): 3 consecutive gateway-class failures
|
|
419
|
+
on the model in use earn exactly one same-model retry; if that retry
|
|
420
|
+
ALSO fails (of any error class — the retry's own outcome is a plain
|
|
421
|
+
pass/fail, never re-filtered by error class), this file spends its
|
|
422
|
+
one-and-only downgrade and continues on the next ladder tier
|
|
423
|
+
(:func:`mutation_kill_shared.resolve_fallback_model`). A success resets
|
|
424
|
+
the consecutive-failure counter to 0; a non-gateway-class failure also
|
|
425
|
+
resets it to 0 (it never counts toward the threshold, and it breaks an
|
|
426
|
+
in-progress gateway-class streak). If the fallback tier's own budget is
|
|
427
|
+
ALSO exhausted (or there is no fallback tier to move to), this raises
|
|
428
|
+
:class:`GenerationExhausted` — no second downgrade is ever attempted.
|
|
429
|
+
|
|
430
|
+
**This is all intra-call, not cross-round (#1908 review, correcting an
|
|
431
|
+
earlier revision of this docstring/the plan).** Every retry and the
|
|
432
|
+
at-most-one downgrade happen inside a single invocation of the returned
|
|
433
|
+
``call`` — the same ``generate()`` call one round makes. ``state``
|
|
434
|
+
persists across rounds only because the closure itself does; for every
|
|
435
|
+
``RuntimeError``-mediated exit path (a return, or a raise) the streak is
|
|
436
|
+
reset first, so no round mediated that way ever actually leaves a
|
|
437
|
+
non-zero streak behind. A non-``RuntimeError`` escape from
|
|
438
|
+
:func:`mutation_kill_shared.run_claude_headless` (e.g.
|
|
439
|
+
``FileNotFoundError``/``OSError`` if the CLI binary disappears mid-run)
|
|
440
|
+
is NOT caught by the ``except RuntimeError`` below, so it skips the
|
|
441
|
+
reset — but that escape is fatal to the process, so a residual streak
|
|
442
|
+
from it is never observed. So while the counter is *structurally*
|
|
443
|
+
shared across a file's rounds, in practice a partial streak never
|
|
444
|
+
survives past one round's call — describing this as "carried across
|
|
445
|
+
rounds" overstates what's observable.
|
|
446
|
+
|
|
447
|
+
**Backoff between pre-threshold retries (#1908 review).** Silently
|
|
448
|
+
retrying the 1st and 2nd consecutive gateway-class failures with zero
|
|
449
|
+
delay let one ``generate()`` call fire up to 4 same-model attempts back
|
|
450
|
+
to back at an already-overloaded upstream. ``sleep`` (real
|
|
451
|
+
:func:`time.sleep` by default, injectable for tests) is now called with
|
|
452
|
+
an increasing, capped delay — ``min(2 ** (streak - 1), 10)`` seconds —
|
|
453
|
+
before each of those two retries (streak 1 -> ~1s, streak 2 -> ~2s). The
|
|
454
|
+
3rd-failure same-model retry itself (handled by
|
|
455
|
+
:func:`_retry_once_then_maybe_downgrade`) is unpaced — it already earned
|
|
456
|
+
its attempt via the threshold, and a downgrade beyond it changes model,
|
|
457
|
+
not just repeats the same call.
|
|
458
|
+
|
|
459
|
+
**State ownership (Design & Architecture Critic's review, #1908).** The
|
|
460
|
+
consecutive-failure counter, the model currently in use, and whether
|
|
461
|
+
this file has already spent its one downgrade all live in THIS
|
|
462
|
+
closure's :class:`_RetryState` — meant to be constructed once per file,
|
|
463
|
+
inside each language loop's own ``make_headless_generator`` factory —
|
|
464
|
+
never at module scope. :func:`mutation_kill_shared.run_claude_headless`
|
|
465
|
+
itself stays the stateless, language-neutral single-shot call it
|
|
466
|
+
already is; this wrapper adds retry/downgrade semantics entirely from
|
|
467
|
+
the caller's side, so a new file's closure always starts fresh at the
|
|
468
|
+
top of the ladder and concurrent files (each with their own closure)
|
|
469
|
+
never leak state to one another.
|
|
470
|
+
|
|
471
|
+
The returned callable takes ``(prompt, source_file, round_num)`` and
|
|
472
|
+
returns the generated text — exactly what a single
|
|
473
|
+
:func:`mutation_kill_shared.run_claude_headless` call would return.
|
|
474
|
+
Every retry and downgrade happens transparently inside one call: neither
|
|
475
|
+
loop's round machinery (``_run_round``/``run_for_file``) needs to
|
|
476
|
+
change, since a call either eventually succeeds or raises (a plain
|
|
477
|
+
``RuntimeError`` for a non-gateway-class failure, unchanged from today;
|
|
478
|
+
:class:`GenerationExhausted` only once the retry-then-downgrade budget
|
|
479
|
+
is fully spent).
|
|
480
|
+
|
|
481
|
+
**Injectable transport (#1918 Step 2.2).** ``call_headless`` defaults to
|
|
482
|
+
``None``, resolved by :meth:`_RetryCallContext.resolve_call_headless` to
|
|
483
|
+
:func:`mutation_kill_shared.run_claude_headless` fresh on every actual
|
|
484
|
+
generation attempt rather than once here at construction time — a
|
|
485
|
+
signature-level default (``call_headless: Callable[..., str] =
|
|
486
|
+
mutation_kill_shared.run_claude_headless``) would bind that reference
|
|
487
|
+
once, at module-import time, and a construction-time resolution would
|
|
488
|
+
still be a single stale snapshot; either way, a test's
|
|
489
|
+
``monkeypatch.setattr(mutation_kill_shared, "run_claude_headless", fake)``
|
|
490
|
+
made after this factory returns its closure (but before the closure is
|
|
491
|
+
invoked) would silently miss the patch (this module's own docstring
|
|
492
|
+
dependency-inventory note above depends on the module-attribute lookup
|
|
493
|
+
staying dynamic on every call, matching the pre-injection code's direct
|
|
494
|
+
``mutation_kill_shared.run_claude_headless(...)`` call sites). Every
|
|
495
|
+
generation attempt this closure makes — the initial attempt and the
|
|
496
|
+
3rd-failure same-model retry — goes through ``call_headless``, so a test
|
|
497
|
+
can also substitute a fake transport directly via this parameter without
|
|
498
|
+
monkeypatching the shared module at all. ``resolve_fallback_model`` is
|
|
499
|
+
unaffected — it stays a direct
|
|
500
|
+
:func:`mutation_kill_shared.resolve_fallback_model` reference.
|
|
501
|
+
"""
|
|
502
|
+
state = _RetryState(model=initial_model)
|
|
503
|
+
ctx = _RetryCallContext(cwd=cwd, log=log, on_downgrade=on_downgrade, call_headless=call_headless)
|
|
504
|
+
|
|
505
|
+
def call(prompt: str, source_file: str, round_num: int | None = None) -> str:
|
|
506
|
+
while True:
|
|
507
|
+
try:
|
|
508
|
+
result = ctx.invoke(prompt, state.model)
|
|
509
|
+
except RuntimeError as exc:
|
|
510
|
+
if not is_gateway_class_error(exc):
|
|
511
|
+
# Never counts toward the threshold, and breaks an
|
|
512
|
+
# in-progress gateway-class streak rather than being
|
|
513
|
+
# skipped over.
|
|
514
|
+
state.reset_streak()
|
|
515
|
+
raise
|
|
516
|
+
current_streak = state.record_gateway_failure()
|
|
517
|
+
if current_streak < _GATEWAY_FAILURE_THRESHOLD:
|
|
518
|
+
sleep(min(_BACKOFF_BASE ** (current_streak - 1), _BACKOFF_CAP_S))
|
|
519
|
+
continue # transparently retry, same model
|
|
520
|
+
# 3rd consecutive gateway-class failure: exactly one
|
|
521
|
+
# same-model retry before considering downgrade.
|
|
522
|
+
state.reset_streak()
|
|
523
|
+
retry_result = _retry_once_then_maybe_downgrade(
|
|
524
|
+
state,
|
|
525
|
+
prompt,
|
|
526
|
+
source_file,
|
|
527
|
+
round_num,
|
|
528
|
+
ctx=ctx,
|
|
529
|
+
)
|
|
530
|
+
if retry_result is None:
|
|
531
|
+
continue # downgraded — retry the 3-then-1 sequence on the new model
|
|
532
|
+
return retry_result
|
|
533
|
+
else:
|
|
534
|
+
state.reset_streak()
|
|
535
|
+
return result
|
|
536
|
+
|
|
537
|
+
return call
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
def _format_downgrade_label(event: DowngradeEvent) -> str:
|
|
541
|
+
"""Compact ``Generator:`` audit-trailer label for a downgrade event
|
|
542
|
+
(#1908 Step 3.2b) — the same four facts as :func:`_format_downgrade_message`
|
|
543
|
+
(source file, round, from-model, to-model, error class), worded for a
|
|
544
|
+
commit trailer rather than a live log line.
|
|
545
|
+
"""
|
|
546
|
+
return (
|
|
547
|
+
f"headless (downgraded {event.from_model!r} -> {event.to_model!r} "
|
|
548
|
+
f"for {event.source_file} at round {event.round_num}, "
|
|
549
|
+
f"{event.error_class})"
|
|
550
|
+
)
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
def make_downgrade_audit_hook() -> (
|
|
554
|
+
tuple[Callable[[DowngradeEvent], None], Callable[[], str | None]]
|
|
555
|
+
):
|
|
556
|
+
"""Return an ``(on_downgrade, get_label_override)`` pair that carries a
|
|
557
|
+
downgrade event into the commit-message audit trail (#1908 Step 3.2b).
|
|
558
|
+
|
|
559
|
+
``RunContext.generator_label`` is ``frozen=True`` and set once per
|
|
560
|
+
file's run, read unchanged by every round's commit — it cannot carry a
|
|
561
|
+
downgrade's per-round dynamic content (from-model, to-model, round)
|
|
562
|
+
without breaking that invariant. This pair is the seam instead:
|
|
563
|
+
|
|
564
|
+
- Pass ``on_downgrade`` straight through as
|
|
565
|
+
:func:`make_retrying_headless_call`'s ``on_downgrade`` kwarg —
|
|
566
|
+
construct both, once per file, inside each language loop's own
|
|
567
|
+
``make_headless_generator`` factory (never at module scope, matching
|
|
568
|
+
that function's own per-file state-ownership contract).
|
|
569
|
+
- Wire ``get_label_override`` into ``RunContext.label_override_provider``
|
|
570
|
+
so each loop's ``_commit_message`` passes its result to
|
|
571
|
+
:func:`mutation_safety_gate.append_generator_trailer` as
|
|
572
|
+
``label_override`` — which wins over the frozen ``generator_label``
|
|
573
|
+
whenever it is not ``None``.
|
|
574
|
+
|
|
575
|
+
Before any downgrade, ``get_label_override()`` returns ``None`` and the
|
|
576
|
+
frozen ``generator_label`` default is used, unchanged. The "exhausted, no
|
|
577
|
+
further downgrade" event is deliberately NOT recorded here — no round
|
|
578
|
+
ever completes after it (the caller raises :class:`GenerationExhausted`
|
|
579
|
+
before generation returns), so there is nothing left to commit that
|
|
580
|
+
override could ever reach.
|
|
581
|
+
"""
|
|
582
|
+
state: dict[str, str | None] = {"label": None}
|
|
583
|
+
|
|
584
|
+
def on_downgrade(event: DowngradeEvent) -> None:
|
|
585
|
+
if event.exhausted:
|
|
586
|
+
return
|
|
587
|
+
state["label"] = _format_downgrade_label(event)
|
|
588
|
+
|
|
589
|
+
def get_label_override() -> str | None:
|
|
590
|
+
return state["label"]
|
|
591
|
+
|
|
592
|
+
return on_downgrade, get_label_override
|