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,494 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""autoship_proposals.py — deterministic transforms for `/dev-team:autoship`'s
|
|
3
|
+
Step 2b/2c agent-proposed-batch pipeline (`skills/autoship/SKILL.md`).
|
|
4
|
+
|
|
5
|
+
Three transforms were previously specified only as prose an agent had to
|
|
6
|
+
re-execute correctly every round (#2072). Each is mechanically checkable, so
|
|
7
|
+
each gets its own pure function plus a small CLI subcommand:
|
|
8
|
+
|
|
9
|
+
- ``validate-proposals`` — Step 2b's response-validation rules 1-4: discard
|
|
10
|
+
any proposed issue number outside the current `ungrouped` set, discard a
|
|
11
|
+
duplicate issue number (keeping only its first occurrence across
|
|
12
|
+
proposals), trim an oversized proposal to its oldest `--max-batch-size`
|
|
13
|
+
members (overflow returns to ungrouped — the SAME oldest-first rule
|
|
14
|
+
`autoship_group.py`'s `_trim_batch` applies to deterministic batches), and
|
|
15
|
+
discard any proposal left with fewer than 2 members.
|
|
16
|
+
- ``remove-blocked`` — Step 2c Fix A's `ungrouped`-array rewrite, PLUS the
|
|
17
|
+
issue-number validation (`^[0-9]+$`) that decides which proposed batches
|
|
18
|
+
were actually blockable at all: a batch containing any issue number that
|
|
19
|
+
fails validation is rejected in its entirety (its members stay in
|
|
20
|
+
`ungrouped`); every other batch's members are removed from `ungrouped`,
|
|
21
|
+
since they were (or will be) actually labeled `autoship:blocked`.
|
|
22
|
+
- ``parse-marker`` — the `confirmed_batch_members` marker parse/validate:
|
|
23
|
+
extract the most recent `<!-- autoship-batch-members: n1,n2,... -->`
|
|
24
|
+
marker from a comment authored by the invoking identity, validate every
|
|
25
|
+
value matches `^[0-9]+$`, and drop the WHOLE marker (never a partial
|
|
26
|
+
list) if any value fails or no matching comment/marker exists.
|
|
27
|
+
|
|
28
|
+
Every subcommand is non-fatal on a malformed **agent response**
|
|
29
|
+
(`validate-proposals`'s `--agent-response-file`) — an unparseable response is
|
|
30
|
+
treated as zero proposals, matching Step 1 reclaim's "failure is non-fatal"
|
|
31
|
+
convention documented in `skills/autoship/SKILL.md`. A malformed **pipeline**
|
|
32
|
+
input (`--ungrouped-file`/`--batches-file`/`--comments-file` — data this
|
|
33
|
+
script's own upstream steps produced, not third-party agent/comment text)
|
|
34
|
+
still raises a clear `ProposalsError`, mirroring `autoship_queue.py`'s
|
|
35
|
+
`QueueError` convention.
|
|
36
|
+
|
|
37
|
+
Usage:
|
|
38
|
+
autoship_proposals.py validate-proposals \\
|
|
39
|
+
--agent-response-file response.json \\
|
|
40
|
+
--ungrouped-file scratch-grouping.json \\
|
|
41
|
+
--max-batch-size 5
|
|
42
|
+
autoship_proposals.py remove-blocked \\
|
|
43
|
+
--ungrouped-file scratch-grouping.json \\
|
|
44
|
+
--batches-file proposed-batches.json
|
|
45
|
+
autoship_proposals.py parse-marker \\
|
|
46
|
+
--comments-file comments.json \\
|
|
47
|
+
--invoking-login the-bot-login
|
|
48
|
+
|
|
49
|
+
Stdlib-only.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
from __future__ import annotations
|
|
53
|
+
|
|
54
|
+
import argparse
|
|
55
|
+
import json
|
|
56
|
+
import re
|
|
57
|
+
import sys
|
|
58
|
+
from typing import Any
|
|
59
|
+
|
|
60
|
+
#: Step 2c's issue-number validation regex — see `is_valid_issue_number`.
|
|
61
|
+
_ISSUE_NUMBER_RE = re.compile(r"^[0-9]+$")
|
|
62
|
+
|
|
63
|
+
#: The hidden marker Step 2c posts and later reads back (see `parse_marker`).
|
|
64
|
+
_MARKER_RE = re.compile(r"<!--\s*autoship-batch-members:\s*([0-9,\s]*)-->")
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class ProposalsError(Exception):
|
|
68
|
+
"""A malformed pipeline input (`--ungrouped-file`/`--batches-file`/
|
|
69
|
+
`--comments-file`) that must surface as a clear CLI error message, not
|
|
70
|
+
an uncaught exception/traceback. Never raised for a malformed AGENT
|
|
71
|
+
response — see `_load_agent_response`'s "treat as zero proposals" rule.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# ---------------------------------------------------------------------------
|
|
76
|
+
# Shared: issue-number validation (Step 2c "Issue-number validation (security)")
|
|
77
|
+
# ---------------------------------------------------------------------------
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def is_valid_issue_number(value: Any) -> bool:
|
|
81
|
+
"""True iff `value` (int or str) represents a bare non-negative integer
|
|
82
|
+
matching `^[0-9]+$` — Step 2c's validation gate before any issue number
|
|
83
|
+
is used in a `gh` command, a marker value, or the `ungrouped`-array
|
|
84
|
+
rewrite. Rejects negative ints (`str(-5)` is `"-5"`, not all-digit),
|
|
85
|
+
floats, and non-digit strings; never raises on unexpected input shapes.
|
|
86
|
+
"""
|
|
87
|
+
if isinstance(value, bool): # bool is an int subclass — exclude explicitly
|
|
88
|
+
return False
|
|
89
|
+
if isinstance(value, int):
|
|
90
|
+
return value >= 0
|
|
91
|
+
if isinstance(value, str):
|
|
92
|
+
return bool(_ISSUE_NUMBER_RE.match(value))
|
|
93
|
+
return False
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# ---------------------------------------------------------------------------
|
|
97
|
+
# Transform 1 — Step 2b response validation (rules 1-4)
|
|
98
|
+
# ---------------------------------------------------------------------------
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _load_ungrouped(data: Any) -> list[dict[str, Any]]:
|
|
102
|
+
"""Unwrap `<scratch-grouping.json>`'s `ungrouped` array from either a
|
|
103
|
+
bare JSON array or the full `{"batches": [...], "ungrouped": [...]}`
|
|
104
|
+
scratch-file shape, so callers can point either subcommand's
|
|
105
|
+
`--ungrouped-file` at the whole scratch file without an extra `jq`
|
|
106
|
+
step.
|
|
107
|
+
|
|
108
|
+
Raises `ProposalsError` naming the offending entry when the shape is
|
|
109
|
+
malformed (missing `number`/`createdAt`, wrong types).
|
|
110
|
+
"""
|
|
111
|
+
if isinstance(data, dict):
|
|
112
|
+
if "ungrouped" not in data:
|
|
113
|
+
raise ProposalsError(
|
|
114
|
+
'--ungrouped-file is a JSON object but has no "ungrouped" key'
|
|
115
|
+
)
|
|
116
|
+
entries = data["ungrouped"]
|
|
117
|
+
else:
|
|
118
|
+
entries = data
|
|
119
|
+
|
|
120
|
+
if not isinstance(entries, list):
|
|
121
|
+
raise ProposalsError(
|
|
122
|
+
f'"ungrouped" must be a JSON array, got {type(entries).__name__}'
|
|
123
|
+
)
|
|
124
|
+
for idx, entry in enumerate(entries):
|
|
125
|
+
if not isinstance(entry, dict):
|
|
126
|
+
raise ProposalsError(
|
|
127
|
+
f"malformed ungrouped entry at index {idx}: not a JSON object"
|
|
128
|
+
)
|
|
129
|
+
identifier = f"#{entry['number']}" if "number" in entry else f"index {idx}"
|
|
130
|
+
missing = [field for field in ("number", "createdAt") if field not in entry]
|
|
131
|
+
if missing:
|
|
132
|
+
raise ProposalsError(
|
|
133
|
+
f"malformed ungrouped entry ({identifier}): missing required "
|
|
134
|
+
f"field(s) {', '.join(missing)}"
|
|
135
|
+
)
|
|
136
|
+
return entries
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _load_agent_response(raw: str) -> list[dict[str, Any]]:
|
|
140
|
+
"""Parse an agent's raw response text into its `proposals` list.
|
|
141
|
+
|
|
142
|
+
Rule 5 (unparseable response): ANY failure here — invalid JSON, a
|
|
143
|
+
non-object payload, a missing/non-list `proposals` key, or a non-list
|
|
144
|
+
`issues` entry inside a proposal — returns `[]` rather than raising.
|
|
145
|
+
This is deliberately lenient (never a `ProposalsError`): the agent's
|
|
146
|
+
response is third-party model output, not this pipeline's own data, and
|
|
147
|
+
Step 2b's doc requires treating an unparseable response as zero
|
|
148
|
+
proposals, non-fatal, exactly like Step 1 reclaim's failure handling.
|
|
149
|
+
"""
|
|
150
|
+
try:
|
|
151
|
+
data = json.loads(raw)
|
|
152
|
+
except json.JSONDecodeError:
|
|
153
|
+
return []
|
|
154
|
+
if not isinstance(data, dict):
|
|
155
|
+
return []
|
|
156
|
+
proposals = data.get("proposals")
|
|
157
|
+
if not isinstance(proposals, list):
|
|
158
|
+
return []
|
|
159
|
+
cleaned = []
|
|
160
|
+
for proposal in proposals:
|
|
161
|
+
if not isinstance(proposal, dict):
|
|
162
|
+
continue
|
|
163
|
+
issues = proposal.get("issues")
|
|
164
|
+
if not isinstance(issues, list):
|
|
165
|
+
continue
|
|
166
|
+
cleaned.append({"rationale": proposal.get("rationale", ""), "issues": issues})
|
|
167
|
+
return cleaned
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def validate_proposals(
|
|
171
|
+
proposals: list[dict[str, Any]],
|
|
172
|
+
ungrouped: list[dict[str, Any]],
|
|
173
|
+
max_batch_size: int,
|
|
174
|
+
) -> dict[str, Any]:
|
|
175
|
+
"""Apply Step 2b's response-validation rules 1-4, in order, to an
|
|
176
|
+
agent's already-parsed `proposals` list against the current `ungrouped`
|
|
177
|
+
pool.
|
|
178
|
+
|
|
179
|
+
`ungrouped` is `<scratch-grouping.json>`'s own `ungrouped` array (each
|
|
180
|
+
entry carrying `number`/`title`/`createdAt`) — the oldest-first trim
|
|
181
|
+
(rule 3) needs `createdAt`, which a raw proposal (issue numbers only)
|
|
182
|
+
does not carry.
|
|
183
|
+
|
|
184
|
+
Returns `{"batches": [{"rationale": ..., "issues": [...]}], "ungrouped":
|
|
185
|
+
[...]}` — `batches` is every proposal surviving all four rules, each
|
|
186
|
+
trimmed to oldest-first member order; `ungrouped` is every entry from
|
|
187
|
+
the input `ungrouped` array NOT claimed by a surviving batch, in its
|
|
188
|
+
original order — Step 2b's own "issues not included in any surviving
|
|
189
|
+
proposal ... remain ungrouped and proceed ... as solo dispatch units"
|
|
190
|
+
rule.
|
|
191
|
+
"""
|
|
192
|
+
by_number = {entry["number"]: entry for entry in ungrouped}
|
|
193
|
+
valid_numbers = set(by_number)
|
|
194
|
+
|
|
195
|
+
claimed: set[int] = set()
|
|
196
|
+
survivors: list[dict[str, Any]] = []
|
|
197
|
+
|
|
198
|
+
for proposal in proposals:
|
|
199
|
+
# Rule 1: discard any issue number not in the current ungrouped set.
|
|
200
|
+
candidates = [n for n in proposal.get("issues", []) if n in valid_numbers]
|
|
201
|
+
# Rule 2: discard an issue already claimed by an earlier proposal —
|
|
202
|
+
# first occurrence wins, by proposal order.
|
|
203
|
+
candidates = [n for n in candidates if n not in claimed]
|
|
204
|
+
|
|
205
|
+
if not candidates:
|
|
206
|
+
continue
|
|
207
|
+
|
|
208
|
+
# Rule 3: trim to the oldest --max-batch-size members — the SAME
|
|
209
|
+
# oldest-first-trim/overflow-to-ungrouped rule autoship_group.py's
|
|
210
|
+
# _trim_batch applies to deterministic batches. Overflow members are
|
|
211
|
+
# simply left unclaimed here (never added to `claimed`), which is
|
|
212
|
+
# what returns them to `ungrouped` below.
|
|
213
|
+
member_issues = sorted(
|
|
214
|
+
(by_number[n] for n in candidates),
|
|
215
|
+
key=lambda issue: (issue["createdAt"], issue["number"]),
|
|
216
|
+
)
|
|
217
|
+
kept = member_issues[:max_batch_size]
|
|
218
|
+
|
|
219
|
+
# Rule 4: discard any proposal with fewer than 2 members after 1-3.
|
|
220
|
+
if len(kept) < 2:
|
|
221
|
+
continue
|
|
222
|
+
|
|
223
|
+
claimed.update(issue["number"] for issue in kept)
|
|
224
|
+
survivors.append(
|
|
225
|
+
{
|
|
226
|
+
"rationale": proposal.get("rationale", ""),
|
|
227
|
+
"issues": [issue["number"] for issue in kept],
|
|
228
|
+
}
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
remaining = [entry for entry in ungrouped if entry["number"] not in claimed]
|
|
232
|
+
return {"batches": survivors, "ungrouped": remaining}
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
# ---------------------------------------------------------------------------
|
|
236
|
+
# Transform 2 — Step 2c Fix A: remove blocked-batch members from ungrouped
|
|
237
|
+
# ---------------------------------------------------------------------------
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def _load_batches(data: Any) -> list[dict[str, Any]]:
|
|
241
|
+
"""Validate a `--batches-file` payload: a JSON array of `{"rationale":
|
|
242
|
+
..., "issues": [...]}` objects (`validate_proposals`'s own `batches`
|
|
243
|
+
output shape). Raises `ProposalsError` naming the offending entry."""
|
|
244
|
+
if not isinstance(data, list):
|
|
245
|
+
raise ProposalsError(
|
|
246
|
+
f'"--batches-file" must be a JSON array, got {type(data).__name__}'
|
|
247
|
+
)
|
|
248
|
+
for idx, batch in enumerate(data):
|
|
249
|
+
if not isinstance(batch, dict):
|
|
250
|
+
raise ProposalsError(
|
|
251
|
+
f"malformed batch at index {idx}: not a JSON object"
|
|
252
|
+
)
|
|
253
|
+
issues = batch.get("issues")
|
|
254
|
+
if not isinstance(issues, list) or not issues:
|
|
255
|
+
raise ProposalsError(
|
|
256
|
+
f"malformed batch at index {idx}: \"issues\" must be a "
|
|
257
|
+
"non-empty JSON array"
|
|
258
|
+
)
|
|
259
|
+
return data
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def partition_and_filter_blocked(
|
|
263
|
+
ungrouped: list[dict[str, Any]],
|
|
264
|
+
batches: list[dict[str, Any]],
|
|
265
|
+
) -> dict[str, Any]:
|
|
266
|
+
"""Split proposed `batches` into `blocked_batches` (every issue number
|
|
267
|
+
passes `is_valid_issue_number`) and `rejected_batches` (any number
|
|
268
|
+
fails), then remove `blocked_batches`' members from `ungrouped` — Step
|
|
269
|
+
2c's Fix A rewrite, scoped to batches that were actually BLOCKED.
|
|
270
|
+
|
|
271
|
+
A `rejected_batches` entry's members are left untouched in `ungrouped`
|
|
272
|
+
— "its members MUST stay in `ungrouped` and proceed to
|
|
273
|
+
`autoship_queue.py` as solo dispatch units", per the doc's security
|
|
274
|
+
carve-out. `blocked_batches` is the list the skill should actually apply
|
|
275
|
+
the `autoship:blocked` label/comment mutation to.
|
|
276
|
+
"""
|
|
277
|
+
blocked_batches = []
|
|
278
|
+
rejected_batches = []
|
|
279
|
+
blocked_numbers: set[int] = set()
|
|
280
|
+
|
|
281
|
+
for batch in batches:
|
|
282
|
+
numbers = batch["issues"]
|
|
283
|
+
if all(is_valid_issue_number(n) for n in numbers):
|
|
284
|
+
blocked_batches.append(batch)
|
|
285
|
+
blocked_numbers.update(numbers)
|
|
286
|
+
else:
|
|
287
|
+
rejected_batches.append(batch)
|
|
288
|
+
|
|
289
|
+
remaining = [entry for entry in ungrouped if entry["number"] not in blocked_numbers]
|
|
290
|
+
return {
|
|
291
|
+
"blocked_batches": blocked_batches,
|
|
292
|
+
"rejected_batches": rejected_batches,
|
|
293
|
+
"ungrouped": remaining,
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
# ---------------------------------------------------------------------------
|
|
298
|
+
# Transform 3 — confirmed_batch_members marker parse/validate
|
|
299
|
+
# ---------------------------------------------------------------------------
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def _load_comments(data: Any) -> list[dict[str, Any]]:
|
|
303
|
+
"""Validate a `--comments-file` payload: a JSON array of `{"author":
|
|
304
|
+
{"login": ...}, "body": ...}` objects — `gh issue view <n> --json
|
|
305
|
+
comments`'s own shape. Raises `ProposalsError` naming the offending
|
|
306
|
+
entry."""
|
|
307
|
+
if not isinstance(data, list):
|
|
308
|
+
raise ProposalsError(
|
|
309
|
+
f'"--comments-file" must be a JSON array, got {type(data).__name__}'
|
|
310
|
+
)
|
|
311
|
+
for idx, comment in enumerate(data):
|
|
312
|
+
if not isinstance(comment, dict):
|
|
313
|
+
raise ProposalsError(
|
|
314
|
+
f"malformed comment at index {idx}: not a JSON object"
|
|
315
|
+
)
|
|
316
|
+
if "body" not in comment:
|
|
317
|
+
raise ProposalsError(
|
|
318
|
+
f'malformed comment at index {idx}: missing required field "body"'
|
|
319
|
+
)
|
|
320
|
+
return data
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def parse_marker(
|
|
324
|
+
comments: list[dict[str, Any]], invoking_login: str
|
|
325
|
+
) -> list[int] | None:
|
|
326
|
+
"""Extract and validate the `confirmed_batch_members` marker from
|
|
327
|
+
`comments`, per Step 2's "Resolving `confirmed_batch_members`" /
|
|
328
|
+
"Author and value validation (security)" rules.
|
|
329
|
+
|
|
330
|
+
Only comments whose `author.login` equals `invoking_login` are
|
|
331
|
+
considered (fail-closed: an unresolvable/absent author never matches).
|
|
332
|
+
Among matching comments, the LAST one (by array order — `gh issue view
|
|
333
|
+
--json comments` returns oldest-first, so this is the most recent) that
|
|
334
|
+
contains the `<!-- autoship-batch-members: ... -->` marker wins.
|
|
335
|
+
|
|
336
|
+
Every parsed value must match `^[0-9]+$` (`is_valid_issue_number`); if
|
|
337
|
+
ANY value fails, the WHOLE marker is dropped (never a partially-valid
|
|
338
|
+
list) — returns `None`, the same "absent" outcome as no matching
|
|
339
|
+
comment/marker at all.
|
|
340
|
+
"""
|
|
341
|
+
latest_match: str | None = None
|
|
342
|
+
for comment in comments:
|
|
343
|
+
author = comment.get("author")
|
|
344
|
+
login = author.get("login") if isinstance(author, dict) else None
|
|
345
|
+
if login != invoking_login:
|
|
346
|
+
continue
|
|
347
|
+
match = _MARKER_RE.search(comment.get("body", ""))
|
|
348
|
+
if match:
|
|
349
|
+
latest_match = match.group(1)
|
|
350
|
+
|
|
351
|
+
if latest_match is None:
|
|
352
|
+
return None
|
|
353
|
+
|
|
354
|
+
raw_values = [v.strip() for v in latest_match.split(",") if v.strip()]
|
|
355
|
+
if not raw_values:
|
|
356
|
+
return None
|
|
357
|
+
if not all(is_valid_issue_number(v) for v in raw_values):
|
|
358
|
+
return None
|
|
359
|
+
return [int(v) for v in raw_values]
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
# ---------------------------------------------------------------------------
|
|
363
|
+
# CLI
|
|
364
|
+
# ---------------------------------------------------------------------------
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
368
|
+
"""Build this CLI's `argparse.ArgumentParser`, isolated from `main()` so
|
|
369
|
+
tests can assert flag values via `build_parser().parse_args([...])`
|
|
370
|
+
without exercising `main()`'s file I/O (mirrors `autoship_group.py`'s
|
|
371
|
+
`build_parser()`/`main()` split)."""
|
|
372
|
+
parser = argparse.ArgumentParser(
|
|
373
|
+
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
|
|
374
|
+
)
|
|
375
|
+
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
376
|
+
|
|
377
|
+
validate = subparsers.add_parser(
|
|
378
|
+
"validate-proposals",
|
|
379
|
+
help="Step 2b response validation (rules 1-4) against the current ungrouped set.",
|
|
380
|
+
)
|
|
381
|
+
validate.add_argument(
|
|
382
|
+
"--agent-response-file",
|
|
383
|
+
required=True,
|
|
384
|
+
help="Path to the agent's raw response text (or '-' for stdin).",
|
|
385
|
+
)
|
|
386
|
+
validate.add_argument(
|
|
387
|
+
"--ungrouped-file",
|
|
388
|
+
required=True,
|
|
389
|
+
help="Path to <scratch-grouping.json> (or a bare ungrouped-array JSON file).",
|
|
390
|
+
)
|
|
391
|
+
validate.add_argument(
|
|
392
|
+
"--max-batch-size",
|
|
393
|
+
type=int,
|
|
394
|
+
default=5,
|
|
395
|
+
help="Oversized-proposal trim cap (default: 5, matching autoship_group.py).",
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
remove_blocked = subparsers.add_parser(
|
|
399
|
+
"remove-blocked",
|
|
400
|
+
help="Step 2c Fix A: partition batches by issue-number validity, "
|
|
401
|
+
"then remove actually-blocked members from ungrouped.",
|
|
402
|
+
)
|
|
403
|
+
remove_blocked.add_argument(
|
|
404
|
+
"--ungrouped-file",
|
|
405
|
+
required=True,
|
|
406
|
+
help="Path to <scratch-grouping.json> (or a bare ungrouped-array JSON file).",
|
|
407
|
+
)
|
|
408
|
+
remove_blocked.add_argument(
|
|
409
|
+
"--batches-file",
|
|
410
|
+
required=True,
|
|
411
|
+
help="Path to a JSON array of proposed batches (validate-proposals's "
|
|
412
|
+
'"batches" output shape).',
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
parse_marker_cmd = subparsers.add_parser(
|
|
416
|
+
"parse-marker",
|
|
417
|
+
help="Parse and validate the confirmed_batch_members marker from an "
|
|
418
|
+
"issue's comments.",
|
|
419
|
+
)
|
|
420
|
+
parse_marker_cmd.add_argument(
|
|
421
|
+
"--comments-file",
|
|
422
|
+
required=True,
|
|
423
|
+
help='Path to a JSON array of {"author": {"login": ...}, "body": ...} '
|
|
424
|
+
"objects (gh issue view --json comments shape).",
|
|
425
|
+
)
|
|
426
|
+
parse_marker_cmd.add_argument(
|
|
427
|
+
"--invoking-login",
|
|
428
|
+
required=True,
|
|
429
|
+
help="The currently-authenticated actor's login (gh api user --jq .login).",
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
return parser
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
def _read_file_or_stdin(path: str) -> str:
|
|
436
|
+
if path == "-":
|
|
437
|
+
return sys.stdin.read()
|
|
438
|
+
with open(path, encoding="utf-8") as fh:
|
|
439
|
+
return fh.read()
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
def _read_json_file(path: str) -> Any:
|
|
443
|
+
try:
|
|
444
|
+
with open(path, encoding="utf-8") as fh:
|
|
445
|
+
raw = fh.read()
|
|
446
|
+
except OSError as exc:
|
|
447
|
+
raise ProposalsError(f"{path!r} could not be read: {exc}") from exc
|
|
448
|
+
try:
|
|
449
|
+
return json.loads(raw)
|
|
450
|
+
except json.JSONDecodeError as exc:
|
|
451
|
+
raise ProposalsError(f"{path!r} is not valid JSON: {exc}") from exc
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
def _run_validate_proposals(args: argparse.Namespace) -> dict[str, Any]:
|
|
455
|
+
raw = _read_file_or_stdin(args.agent_response_file)
|
|
456
|
+
proposals = _load_agent_response(raw)
|
|
457
|
+
ungrouped = _load_ungrouped(_read_json_file(args.ungrouped_file))
|
|
458
|
+
return validate_proposals(proposals, ungrouped, args.max_batch_size)
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
def _run_remove_blocked(args: argparse.Namespace) -> dict[str, Any]:
|
|
462
|
+
ungrouped = _load_ungrouped(_read_json_file(args.ungrouped_file))
|
|
463
|
+
batches = _load_batches(_read_json_file(args.batches_file))
|
|
464
|
+
return partition_and_filter_blocked(ungrouped, batches)
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
def _run_parse_marker(args: argparse.Namespace) -> dict[str, Any]:
|
|
468
|
+
comments = _load_comments(_read_json_file(args.comments_file))
|
|
469
|
+
return {"confirmed_batch_members": parse_marker(comments, args.invoking_login)}
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
_HANDLERS = {
|
|
473
|
+
"validate-proposals": _run_validate_proposals,
|
|
474
|
+
"remove-blocked": _run_remove_blocked,
|
|
475
|
+
"parse-marker": _run_parse_marker,
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
def main(argv: list[str] | None = None) -> int:
|
|
480
|
+
parser = build_parser()
|
|
481
|
+
args = parser.parse_args(argv)
|
|
482
|
+
|
|
483
|
+
try:
|
|
484
|
+
result = _HANDLERS[args.command](args)
|
|
485
|
+
except ProposalsError as exc:
|
|
486
|
+
print(f"autoship_proposals: {exc}", file=sys.stderr)
|
|
487
|
+
return 1
|
|
488
|
+
|
|
489
|
+
print(json.dumps(result))
|
|
490
|
+
return 0
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
if __name__ == "__main__": # pragma: no cover
|
|
494
|
+
raise SystemExit(main())
|