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,121 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""autoship_discover.py — deterministic issue discovery for `/dev-team:autoship` (#989).
|
|
3
|
+
|
|
4
|
+
Selects open, non-epic issues labeled `autoship:ready` (or `--label`) that
|
|
5
|
+
are not already `autoship:in-progress`/`autoship:blocked` and have no open
|
|
6
|
+
linked pull request, ordered oldest-first and capped at `--max-issues`. This
|
|
7
|
+
is deterministic filtering, not model judgment — see the plan's Architectural
|
|
8
|
+
Context (`plans/issue-989-autoship-discovery-reclaim.md`) for the precedent
|
|
9
|
+
this follows (`scripts/plan_waves.py`, `scripts/git_origin_host.py`).
|
|
10
|
+
|
|
11
|
+
The `gh` fetch, `--input-file` schema validation, and eligibility filter are
|
|
12
|
+
shared with `autoship_group.py` via `autoship_state.fetch_eligible_issues` —
|
|
13
|
+
this script's own concern is only the `--max-issues` cap on top of that
|
|
14
|
+
shared, full eligible pool.
|
|
15
|
+
|
|
16
|
+
`main()` applies that cap by slicing the shared pool directly
|
|
17
|
+
(`eligible[: args.max_issues]`) rather than through a dedicated
|
|
18
|
+
`select_eligible` helper — an earlier version of this module had both, but
|
|
19
|
+
`select_eligible` duplicated `is_eligible`/sort logic `fetch_eligible_issues`
|
|
20
|
+
already provides and had drifted to zero production callers (superseded by
|
|
21
|
+
`autoship_state.fetch_eligible_issues`, and no longer even called by this
|
|
22
|
+
file's own `main()`); it and its dedicated test suite were deleted rather
|
|
23
|
+
than kept as unreferenced surface area (#2075). `autoship_discover.py` itself
|
|
24
|
+
is NOT dead — `/dev-team:autoship`'s pipeline moved on to
|
|
25
|
+
`autoship_group.py`/`autoship_queue.py` (see `skills/autoship/SKILL.md`'s
|
|
26
|
+
Step 2, which states "`autoship_discover.py` is not part of this pipeline
|
|
27
|
+
anymore"), but this script's own CLI remains available unchanged as a
|
|
28
|
+
standalone operator tool: a single deterministic command to preview the
|
|
29
|
+
oldest-first, `--max-issues`-capped eligible pool without running the
|
|
30
|
+
grouping/queueing/dispatch machinery, useful for debugging eligibility
|
|
31
|
+
outside a live round.
|
|
32
|
+
|
|
33
|
+
Usage:
|
|
34
|
+
autoship_discover.py --max-issues 3 --max-cost-usd 25
|
|
35
|
+
autoship_discover.py --max-issues 3 --max-cost-usd 25 --label autoship:ready
|
|
36
|
+
autoship_discover.py --max-issues 3 --max-cost-usd 25 --input-file fixture.json
|
|
37
|
+
|
|
38
|
+
`--max-issues` and `--max-cost-usd` are both required — a missing cap is a
|
|
39
|
+
hard CLI failure, never a silently-assumed default, since an uncapped round
|
|
40
|
+
could dispatch unboundedly. `--input-file` bypasses the live `gh` fetch
|
|
41
|
+
entirely for tests/dry runs; production use relies on `gh`'s cwd-based repo
|
|
42
|
+
auto-detection (no `--repo` flag — see the plan's Decision-defaults stance).
|
|
43
|
+
|
|
44
|
+
Stdlib-only.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
from __future__ import annotations
|
|
48
|
+
|
|
49
|
+
import argparse
|
|
50
|
+
import json
|
|
51
|
+
import sys
|
|
52
|
+
from pathlib import Path
|
|
53
|
+
from typing import Any
|
|
54
|
+
|
|
55
|
+
_HERE = Path(__file__).resolve().parent
|
|
56
|
+
sys.path.insert(0, str(_HERE / "lib"))
|
|
57
|
+
|
|
58
|
+
import autoship_state
|
|
59
|
+
|
|
60
|
+
DEFAULT_LABEL = autoship_state.READY_LABEL
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
64
|
+
"""Build this CLI's `argparse.ArgumentParser`, isolated from `main()` so
|
|
65
|
+
tests can assert required/rejected values via
|
|
66
|
+
`build_parser().parse_args([...])` without exercising `main()`'s
|
|
67
|
+
file/`gh` I/O."""
|
|
68
|
+
parser = argparse.ArgumentParser(
|
|
69
|
+
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
|
|
70
|
+
)
|
|
71
|
+
parser.add_argument(
|
|
72
|
+
"--max-issues",
|
|
73
|
+
type=autoship_state.positive_int_validator("--max-issues"),
|
|
74
|
+
required=True,
|
|
75
|
+
help="Maximum number of issues to select this round. Must be > 0.",
|
|
76
|
+
)
|
|
77
|
+
parser.add_argument(
|
|
78
|
+
"--max-cost-usd",
|
|
79
|
+
type=autoship_state.positive_float_validator("--max-cost-usd"),
|
|
80
|
+
required=True,
|
|
81
|
+
help=(
|
|
82
|
+
"Budget cap in USD for the round, consumed by /dev-team:autoship's "
|
|
83
|
+
"own scheduler (not enforced by this script). Must be > 0."
|
|
84
|
+
),
|
|
85
|
+
)
|
|
86
|
+
parser.add_argument(
|
|
87
|
+
"--label",
|
|
88
|
+
default=DEFAULT_LABEL,
|
|
89
|
+
help=f"Label marking an issue eligible for autoship (default: {DEFAULT_LABEL!r}).",
|
|
90
|
+
)
|
|
91
|
+
autoship_state.add_input_seam_args(parser)
|
|
92
|
+
return parser
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def render_selection(issues: list[dict[str, Any]]) -> str:
|
|
96
|
+
"""Render the stable stdout contract `/dev-team:autoship` (#992) parses:
|
|
97
|
+
a JSON array of `{number, title}` objects."""
|
|
98
|
+
return json.dumps(
|
|
99
|
+
[{"number": issue["number"], "title": issue["title"]} for issue in issues]
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def main(argv: list[str] | None = None) -> int:
|
|
104
|
+
parser = build_parser()
|
|
105
|
+
args = parser.parse_args(argv)
|
|
106
|
+
|
|
107
|
+
try:
|
|
108
|
+
eligible = autoship_state.fetch_eligible_issues(
|
|
109
|
+
args.label, input_file=args.input_file
|
|
110
|
+
)
|
|
111
|
+
except autoship_state.FetchError as exc:
|
|
112
|
+
print(f"autoship_discover: {exc}", file=sys.stderr)
|
|
113
|
+
return 1
|
|
114
|
+
|
|
115
|
+
selected = eligible[: args.max_issues]
|
|
116
|
+
print(render_selection(selected))
|
|
117
|
+
return 0
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
if __name__ == "__main__": # pragma: no cover
|
|
121
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""autoship_group.py — deterministic issue grouping for `/dev-team:autoship` (Slice 1).
|
|
3
|
+
|
|
4
|
+
Groups eligible `autoship:ready` (or `--label`) issues into batches using
|
|
5
|
+
four signals, via union-find:
|
|
6
|
+
|
|
7
|
+
- **Native dependency**: issue A's `blockedBy`/`blocking` field names issue B,
|
|
8
|
+
and B is also in the eligible input set.
|
|
9
|
+
- **Shared parent**: two eligible issues name the same non-null `parent`
|
|
10
|
+
issue number.
|
|
11
|
+
- **Shared label**: two eligible issues carry any label in common outside
|
|
12
|
+
the `autoship:*` prefix AND outside the configured eligibility label
|
|
13
|
+
itself (every eligible issue carries that label by construction — see
|
|
14
|
+
`is_eligible` — so it can never be a grouping signal on its own,
|
|
15
|
+
regardless of whether it happens to start with `autoship:`).
|
|
16
|
+
- **Confirmed-batch override** (Step 4.3): two eligible issues both carry
|
|
17
|
+
`autoship:batch-confirmed` AND each one's `confirmed_batch_members` field
|
|
18
|
+
names the other's issue number — see `has_batch_confirmed_override`.
|
|
19
|
+
Supports partial confirmation of an agent-proposed batch (Step 2c,
|
|
20
|
+
`skills/autoship/SKILL.md`): the signal only fires between two members
|
|
21
|
+
that are both confirmed and both still list each other.
|
|
22
|
+
|
|
23
|
+
Issues with no signal at all land in `ungrouped`. Any batch larger than
|
|
24
|
+
`--max-batch-size` (default 5) is trimmed to its oldest N members; the
|
|
25
|
+
overflow members move to `ungrouped` rather than being dropped. The same
|
|
26
|
+
union-find design lets each signal be added as its own small,
|
|
27
|
+
independently-testable function (see `has_dependency_edge`/
|
|
28
|
+
`has_shared_parent`/`has_shared_label`) rather than one growing conditional.
|
|
29
|
+
|
|
30
|
+
Shares its `gh` fetch, `--input-file` schema validation, and eligibility
|
|
31
|
+
filter with `autoship_discover.py` via `autoship_state.fetch_eligible_issues`
|
|
32
|
+
— this script requests `blockedBy`/`blocking`/`parent` as `extra_fields` on
|
|
33
|
+
top of the base required fields, so a live `gh` call fetches them but an
|
|
34
|
+
`--input-file` fixture may omit them entirely (they're optional enrichment,
|
|
35
|
+
not required schema). Operates on the FULL eligible pool (no
|
|
36
|
+
`--max-issues`-style cap; that stays a downstream script's concern).
|
|
37
|
+
|
|
38
|
+
Usage:
|
|
39
|
+
autoship_group.py --label autoship:ready
|
|
40
|
+
autoship_group.py --label autoship:ready --input-file fixture.json
|
|
41
|
+
|
|
42
|
+
Stdlib-only.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
from __future__ import annotations
|
|
46
|
+
|
|
47
|
+
import argparse
|
|
48
|
+
import json
|
|
49
|
+
import sys
|
|
50
|
+
from pathlib import Path
|
|
51
|
+
from typing import Any
|
|
52
|
+
|
|
53
|
+
_HERE = Path(__file__).resolve().parent
|
|
54
|
+
sys.path.insert(0, str(_HERE / "lib"))
|
|
55
|
+
|
|
56
|
+
import autoship_state
|
|
57
|
+
|
|
58
|
+
DEFAULT_LABEL = autoship_state.READY_LABEL
|
|
59
|
+
DEFAULT_MAX_BATCH_SIZE = 5
|
|
60
|
+
|
|
61
|
+
# Every label starting with this prefix is excluded from the shared-label
|
|
62
|
+
# signal — never a naming carve-out for one specific label.
|
|
63
|
+
_AUTOSHIP_LABEL_PREFIX = "autoship:"
|
|
64
|
+
|
|
65
|
+
# The label a human confirmation applies (Step 2c, `skills/autoship/SKILL.md`)
|
|
66
|
+
# — recognized by `has_batch_confirmed_override`, its own independent signal
|
|
67
|
+
# function, never as a carve-out inside `has_shared_label`'s exclusion rule.
|
|
68
|
+
# Defined once in `autoship_state` alongside the other `autoship:*` label
|
|
69
|
+
# constants; `autoship_reclaim.py` imports the same shared constant.
|
|
70
|
+
BATCH_CONFIRMED_LABEL = autoship_state.BATCH_CONFIRMED_LABEL
|
|
71
|
+
|
|
72
|
+
# The dependency/parent fields this script's signals need, on top of
|
|
73
|
+
# autoship_state.BASE_REQUIRED_FIELDS. Requested as `extra_fields` (not
|
|
74
|
+
# `required_fields`) from `fetch_eligible_issues` — see `main()` — so they're
|
|
75
|
+
# fetched from a live `gh` call but stay OPTIONAL on the `--input-file` path,
|
|
76
|
+
# matching the plan's "no blockedBy/blocking data present" scenario.
|
|
77
|
+
_DEPENDENCY_FIELDS = ("blockedBy", "blocking", "parent")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
81
|
+
"""Build this CLI's `argparse.ArgumentParser`, isolated from `main()` so
|
|
82
|
+
tests can assert flag values via `build_parser().parse_args([...])`
|
|
83
|
+
without exercising `main()`'s file/`gh` I/O."""
|
|
84
|
+
parser = argparse.ArgumentParser(
|
|
85
|
+
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
|
|
86
|
+
)
|
|
87
|
+
parser.add_argument(
|
|
88
|
+
"--label",
|
|
89
|
+
default=DEFAULT_LABEL,
|
|
90
|
+
help=f"Label marking an issue eligible for autoship (default: {DEFAULT_LABEL!r}).",
|
|
91
|
+
)
|
|
92
|
+
parser.add_argument(
|
|
93
|
+
"--max-batch-size",
|
|
94
|
+
type=autoship_state.positive_int_validator("--max-batch-size"),
|
|
95
|
+
default=DEFAULT_MAX_BATCH_SIZE,
|
|
96
|
+
help=f"Maximum members per batch; overflow moves to ungrouped (default: {DEFAULT_MAX_BATCH_SIZE}).",
|
|
97
|
+
)
|
|
98
|
+
autoship_state.add_input_seam_args(parser)
|
|
99
|
+
return parser
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _referenced_numbers(field: Any) -> set[int]:
|
|
103
|
+
"""Extract issue numbers referenced by a `blockedBy`/`blocking` field.
|
|
104
|
+
|
|
105
|
+
A live `gh issue list --json blockedBy,blocking` returns a GraphQL
|
|
106
|
+
connection object shaped `{"nodes": [...], "totalCount": N}` — NOT a
|
|
107
|
+
bare list — so the primary case unwraps `field["nodes"]` before
|
|
108
|
+
iterating. `--input-file` fixtures may still reasonably use the
|
|
109
|
+
simpler bare-list-of-dicts (or bare-list-of-ints) shape documented in
|
|
110
|
+
the plan, so both are still tolerated as a fallback.
|
|
111
|
+
"""
|
|
112
|
+
if not field:
|
|
113
|
+
return set()
|
|
114
|
+
if isinstance(field, dict):
|
|
115
|
+
field = field.get("nodes") or []
|
|
116
|
+
numbers: set[int] = set()
|
|
117
|
+
for entry in field:
|
|
118
|
+
if isinstance(entry, dict):
|
|
119
|
+
if "number" in entry:
|
|
120
|
+
numbers.add(entry["number"])
|
|
121
|
+
elif isinstance(entry, int):
|
|
122
|
+
numbers.add(entry)
|
|
123
|
+
return numbers
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def has_dependency_edge(a: dict[str, Any], b: dict[str, Any]) -> bool:
|
|
127
|
+
"""True when `a` and `b` name each other via `blockedBy`/`blocking`, in
|
|
128
|
+
either direction.
|
|
129
|
+
|
|
130
|
+
Only ever true when both issues are present in the same eligible input
|
|
131
|
+
set passed to `group_issues` — a reference to an issue absent from that
|
|
132
|
+
set (e.g. filtered out upstream as ineligible) simply never matches any
|
|
133
|
+
other issue in the set, so the referencing issue naturally stays
|
|
134
|
+
ungrouped rather than needing a special case here.
|
|
135
|
+
"""
|
|
136
|
+
a_number, b_number = a["number"], b["number"]
|
|
137
|
+
if b_number in _referenced_numbers(a.get("blockedBy")):
|
|
138
|
+
return True
|
|
139
|
+
if b_number in _referenced_numbers(a.get("blocking")):
|
|
140
|
+
return True
|
|
141
|
+
if a_number in _referenced_numbers(b.get("blockedBy")):
|
|
142
|
+
return True
|
|
143
|
+
return a_number in _referenced_numbers(b.get("blocking"))
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _parent_number(issue: dict[str, Any]) -> int | None:
|
|
147
|
+
parent = issue.get("parent")
|
|
148
|
+
if isinstance(parent, dict):
|
|
149
|
+
return parent.get("number")
|
|
150
|
+
if isinstance(parent, int):
|
|
151
|
+
return parent
|
|
152
|
+
return None
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def has_shared_parent(a: dict[str, Any], b: dict[str, Any]) -> bool:
|
|
156
|
+
"""True when `a` and `b` name the same non-null `parent` issue number."""
|
|
157
|
+
a_parent = _parent_number(a)
|
|
158
|
+
b_parent = _parent_number(b)
|
|
159
|
+
return a_parent is not None and a_parent == b_parent
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _non_autoship_label_names(issue: dict[str, Any], exclude_label: str) -> set[str]:
|
|
163
|
+
"""Label names on `issue` outside the `autoship:*` prefix AND outside
|
|
164
|
+
`exclude_label`.
|
|
165
|
+
|
|
166
|
+
`exclude_label` is the CLI's configured eligibility label (`--label`,
|
|
167
|
+
not necessarily `autoship:*`-prefixed — see `build_parser`). Every
|
|
168
|
+
eligible issue carries it by construction (`is_eligible` requires it),
|
|
169
|
+
so without this exclusion every eligible pool would share it and
|
|
170
|
+
`has_shared_label` would collapse the entire pool into one batch.
|
|
171
|
+
|
|
172
|
+
The `autoship:*` exclusion is otherwise a plain, general rule — every
|
|
173
|
+
`autoship:*` label is excluded, with no carve-out for any specific one
|
|
174
|
+
(e.g. `autoship:batch-confirmed`). `has_batch_confirmed_override` (Step
|
|
175
|
+
4.3) is the wholly independent signal function that recognizes
|
|
176
|
+
`autoship:batch-confirmed`; this function must never special-case it.
|
|
177
|
+
"""
|
|
178
|
+
names = set()
|
|
179
|
+
for label in issue.get("labels") or []:
|
|
180
|
+
name = label.get("name") if isinstance(label, dict) else label
|
|
181
|
+
if (
|
|
182
|
+
name
|
|
183
|
+
and name != exclude_label
|
|
184
|
+
and not name.startswith(_AUTOSHIP_LABEL_PREFIX)
|
|
185
|
+
):
|
|
186
|
+
names.add(name)
|
|
187
|
+
return names
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def has_shared_label(a_labels: set[str], b_labels: set[str]) -> bool:
|
|
191
|
+
"""True when `a_labels` and `b_labels` (each already filtered by
|
|
192
|
+
`_non_autoship_label_names`) share any label name."""
|
|
193
|
+
return bool(a_labels & b_labels)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def _raw_label_names(issue: dict[str, Any]) -> set[str]:
|
|
197
|
+
"""Every label name on `issue`, unfiltered (unlike
|
|
198
|
+
`_non_autoship_label_names`, which excludes `autoship:*` and the
|
|
199
|
+
configured eligibility label) — used by `has_batch_confirmed_override`
|
|
200
|
+
to check for `autoship:batch-confirmed` itself."""
|
|
201
|
+
return {
|
|
202
|
+
label.get("name") if isinstance(label, dict) else label
|
|
203
|
+
for label in issue.get("labels") or []
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def _confirmed_member_numbers(issue: dict[str, Any]) -> set[int]:
|
|
208
|
+
"""Coerce `issue`'s `confirmed_batch_members` entries to `int`,
|
|
209
|
+
tolerating a digit-only string shape alongside a native int — the same
|
|
210
|
+
multi-shape tolerance `_referenced_numbers` already applies to
|
|
211
|
+
`blockedBy`/`blocking`.
|
|
212
|
+
|
|
213
|
+
The marker's parsed values (Step 2c, `skills/autoship/SKILL.md`) are
|
|
214
|
+
produced by an agent regex-extracting digits from a GitHub comment
|
|
215
|
+
(`^[0-9]+$` validation), whose natural implementation yields strings
|
|
216
|
+
(`["301", "302"]`), not ints. Without this coercion, a strict `int`-only
|
|
217
|
+
comparison would silently never match — the same class of silent
|
|
218
|
+
no-signal failure `_referenced_numbers` already guards against. Any
|
|
219
|
+
entry that is neither an int nor an ASCII digit-only string is skipped
|
|
220
|
+
rather than raising — `str.isdigit()` alone is `True` for non-decimal
|
|
221
|
+
Unicode digits (e.g. superscript "2") that `int()` then rejects with
|
|
222
|
+
`ValueError`; the `isascii()` guard keeps the "never an error" contract
|
|
223
|
+
(same pattern as `scripts/build_jobs.py`'s own digit-string validation).
|
|
224
|
+
"""
|
|
225
|
+
numbers: set[int] = set()
|
|
226
|
+
for entry in issue.get("confirmed_batch_members") or []:
|
|
227
|
+
if isinstance(entry, int):
|
|
228
|
+
numbers.add(entry)
|
|
229
|
+
elif isinstance(entry, str) and entry.isascii() and entry.isdigit():
|
|
230
|
+
numbers.add(int(entry))
|
|
231
|
+
return numbers
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def has_batch_confirmed_override(a: dict[str, Any], b: dict[str, Any]) -> bool:
|
|
235
|
+
"""True iff both `a` and `b` carry the `autoship:batch-confirmed` label
|
|
236
|
+
AND each one's `confirmed_batch_members` field contains the other's
|
|
237
|
+
issue number.
|
|
238
|
+
|
|
239
|
+
`confirmed_batch_members` is an optional field (a list of ints or
|
|
240
|
+
digit-only strings — see `_confirmed_member_numbers` — read via
|
|
241
|
+
`.get(...)` — same convention as `blockedBy`/`blocking`/`parent`); its
|
|
242
|
+
absence is "no signal", never an error. Requiring BOTH issues to be
|
|
243
|
+
labeled AND to still cross-reference each other is what supports partial
|
|
244
|
+
confirmation (Step 2c, `skills/autoship/SKILL.md`): a human confirming
|
|
245
|
+
only a subset of an agent-proposed batch unions exactly that subset,
|
|
246
|
+
never pulling in a member that was never relabeled or whose own marker
|
|
247
|
+
no longer lists its counterpart.
|
|
248
|
+
"""
|
|
249
|
+
if BATCH_CONFIRMED_LABEL not in _raw_label_names(a):
|
|
250
|
+
return False
|
|
251
|
+
if BATCH_CONFIRMED_LABEL not in _raw_label_names(b):
|
|
252
|
+
return False
|
|
253
|
+
a_members = _confirmed_member_numbers(a)
|
|
254
|
+
b_members = _confirmed_member_numbers(b)
|
|
255
|
+
return b["number"] in a_members and a["number"] in b_members
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def _matches_any_signal(
|
|
259
|
+
a: dict[str, Any],
|
|
260
|
+
b: dict[str, Any],
|
|
261
|
+
exclude_label: str,
|
|
262
|
+
label_names_by_number: dict[int, set[str]],
|
|
263
|
+
) -> bool:
|
|
264
|
+
"""True when `a` and `b` match any grouping signal: native dependency,
|
|
265
|
+
shared parent, confirmed-batch override, or a shared label (outside
|
|
266
|
+
`autoship:*` and `exclude_label`).
|
|
267
|
+
|
|
268
|
+
`label_names_by_number` is `group_issues`'s once-per-issue precomputed
|
|
269
|
+
label-name lookup — passed in rather than recomputed here so the O(n^2)
|
|
270
|
+
pairwise loop never re-scans an issue's label list more than once.
|
|
271
|
+
"""
|
|
272
|
+
if has_dependency_edge(a, b):
|
|
273
|
+
return True
|
|
274
|
+
if has_shared_parent(a, b):
|
|
275
|
+
return True
|
|
276
|
+
if has_batch_confirmed_override(a, b):
|
|
277
|
+
return True
|
|
278
|
+
return has_shared_label(
|
|
279
|
+
label_names_by_number[a["number"]], label_names_by_number[b["number"]]
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
class _UnionFind:
|
|
284
|
+
"""Minimal union-find over a fixed set of keys (issue numbers)."""
|
|
285
|
+
|
|
286
|
+
def __init__(self, keys: list[int]) -> None:
|
|
287
|
+
self._parent = {key: key for key in keys}
|
|
288
|
+
|
|
289
|
+
def find(self, key: int) -> int:
|
|
290
|
+
while self._parent[key] != key:
|
|
291
|
+
self._parent[key] = self._parent[self._parent[key]]
|
|
292
|
+
key = self._parent[key]
|
|
293
|
+
return key
|
|
294
|
+
|
|
295
|
+
def union(self, a: int, b: int) -> None:
|
|
296
|
+
root_a, root_b = self.find(a), self.find(b)
|
|
297
|
+
if root_a != root_b:
|
|
298
|
+
self._parent[root_b] = root_a
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def _member_view(issue: dict[str, Any]) -> dict[str, Any]:
|
|
302
|
+
return {
|
|
303
|
+
"number": issue["number"],
|
|
304
|
+
"title": issue["title"],
|
|
305
|
+
"createdAt": issue["createdAt"],
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def _trim_batch(
|
|
310
|
+
member_issues: list[dict[str, Any]], max_batch_size: int
|
|
311
|
+
) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]:
|
|
312
|
+
"""Split `member_issues` (already sorted oldest-first) into the kept
|
|
313
|
+
(oldest `max_batch_size`) and overflow (newest, beyond the cap) slices."""
|
|
314
|
+
return member_issues[:max_batch_size], member_issues[max_batch_size:]
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def group_issues(
|
|
318
|
+
issues: list[dict[str, Any]],
|
|
319
|
+
max_batch_size: int = DEFAULT_MAX_BATCH_SIZE,
|
|
320
|
+
label: str = DEFAULT_LABEL,
|
|
321
|
+
) -> dict[str, Any]:
|
|
322
|
+
"""Group `issues` into batches by native-dependency, shared-parent,
|
|
323
|
+
shared-label, and confirmed-batch-override signals, via union-find.
|
|
324
|
+
|
|
325
|
+
`label` is the CLI's configured eligibility label — excluded from the
|
|
326
|
+
shared-label signal alongside the `autoship:*` prefix, since every
|
|
327
|
+
eligible issue carries it by construction (see `_non_autoship_label_names`).
|
|
328
|
+
|
|
329
|
+
A batch whose member count exceeds `max_batch_size` is trimmed to its
|
|
330
|
+
oldest `max_batch_size` members; the overflow (newest) members move to
|
|
331
|
+
`ungrouped` rather than being dropped. A group trimmed down to a single
|
|
332
|
+
kept member is itself routed to `ungrouped` instead of emitted as a
|
|
333
|
+
1-member batch — consistent with the untrimmed `len(members) == 1` case
|
|
334
|
+
just below.
|
|
335
|
+
|
|
336
|
+
Returns the stdout contract shape: `{"batches": [...], "ungrouped":
|
|
337
|
+
[...]}`. Each batch's `batch_id` is `grp-<oldest-member-number>`,
|
|
338
|
+
derived from the oldest (by `createdAt`, tie-broken by issue `number`)
|
|
339
|
+
member of the TRIMMED batch — deterministic, never random. In practice
|
|
340
|
+
this is always the same member as the pre-trim oldest: trimming keeps
|
|
341
|
+
the oldest N of a sorted list, so the overall-oldest member is never the
|
|
342
|
+
one trimmed away.
|
|
343
|
+
"""
|
|
344
|
+
numbers = [issue["number"] for issue in issues]
|
|
345
|
+
by_number = {issue["number"]: issue for issue in issues}
|
|
346
|
+
label_names_by_number = {
|
|
347
|
+
issue["number"]: _non_autoship_label_names(issue, label) for issue in issues
|
|
348
|
+
}
|
|
349
|
+
union_find = _UnionFind(numbers)
|
|
350
|
+
|
|
351
|
+
for i, a in enumerate(issues):
|
|
352
|
+
for b in issues[i + 1 :]:
|
|
353
|
+
if _matches_any_signal(a, b, label, label_names_by_number):
|
|
354
|
+
union_find.union(a["number"], b["number"])
|
|
355
|
+
|
|
356
|
+
groups: dict[int, list[int]] = {}
|
|
357
|
+
for number in numbers:
|
|
358
|
+
root = union_find.find(number)
|
|
359
|
+
groups.setdefault(root, []).append(number)
|
|
360
|
+
|
|
361
|
+
batches = []
|
|
362
|
+
ungrouped = []
|
|
363
|
+
for members in groups.values():
|
|
364
|
+
if len(members) == 1:
|
|
365
|
+
ungrouped.append(_member_view(by_number[members[0]]))
|
|
366
|
+
continue
|
|
367
|
+
member_issues = sorted(
|
|
368
|
+
(by_number[number] for number in members),
|
|
369
|
+
key=lambda issue: (issue["createdAt"], issue["number"]),
|
|
370
|
+
)
|
|
371
|
+
kept, overflow = _trim_batch(member_issues, max_batch_size)
|
|
372
|
+
ungrouped.extend(_member_view(issue) for issue in overflow)
|
|
373
|
+
if len(kept) == 1:
|
|
374
|
+
ungrouped.append(_member_view(kept[0]))
|
|
375
|
+
continue
|
|
376
|
+
batches.append(
|
|
377
|
+
{
|
|
378
|
+
"batch_id": f"grp-{kept[0]['number']}",
|
|
379
|
+
"members": [_member_view(issue) for issue in kept],
|
|
380
|
+
}
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
return {"batches": batches, "ungrouped": ungrouped}
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
def main(argv: list[str] | None = None) -> int:
|
|
387
|
+
parser = build_parser()
|
|
388
|
+
args = parser.parse_args(argv)
|
|
389
|
+
|
|
390
|
+
try:
|
|
391
|
+
eligible = autoship_state.fetch_eligible_issues(
|
|
392
|
+
args.label,
|
|
393
|
+
input_file=args.input_file,
|
|
394
|
+
extra_fields=_DEPENDENCY_FIELDS,
|
|
395
|
+
)
|
|
396
|
+
except autoship_state.FetchError as exc:
|
|
397
|
+
print(f"autoship_group: {exc}", file=sys.stderr)
|
|
398
|
+
return 1
|
|
399
|
+
|
|
400
|
+
print(
|
|
401
|
+
json.dumps(
|
|
402
|
+
group_issues(eligible, max_batch_size=args.max_batch_size, label=args.label)
|
|
403
|
+
)
|
|
404
|
+
)
|
|
405
|
+
return 0
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
if __name__ == "__main__": # pragma: no cover
|
|
409
|
+
raise SystemExit(main())
|