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,141 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Compute a changed-file list with git change-type (#1734).
|
|
3
|
+
|
|
4
|
+
`arch-review` (and every other `Context needs: project-structure` lens —
|
|
5
|
+
`doc-review`, `domain-review`) has no Bash grant, yet its dispatch payload
|
|
6
|
+
today is only "full files + directory tree". Nothing stops the agent from
|
|
7
|
+
reasoning that it should "see what changed" and attempting `git diff` itself
|
|
8
|
+
— a call it does not have, denied, and surfaced as a spurious error in its
|
|
9
|
+
report. The fix is not a new tool grant (that would be a first-of-its-kind
|
|
10
|
+
precedent for a review agent); it is completing the payload the orchestrator
|
|
11
|
+
already has the data for: a changed/added/removed file list alongside the
|
|
12
|
+
full files and tree.
|
|
13
|
+
|
|
14
|
+
This module is that data, computed once from `git diff --name-status` output
|
|
15
|
+
so `/code-review` never invents it twice: `SKILL.md` step 4 feeds it into the
|
|
16
|
+
`project-structure` context payload, and step 3 feeds its `added` list into
|
|
17
|
+
`select_lenses.py`'s `--added-from` flag for `component-architecture-review`'s
|
|
18
|
+
added-only `Scope:` gate (#1733) — one changed-file computation, two
|
|
19
|
+
consumers, not two ways to derive the same fact.
|
|
20
|
+
|
|
21
|
+
**A skipped line narrows, it does not widen.** A line this module cannot
|
|
22
|
+
parse (wrong field count, empty path) is skipped rather than guessed, never
|
|
23
|
+
fabricated — but for the added-only `Scope:` gate that consumes this
|
|
24
|
+
module's `added` list, dropping a genuinely-added path *removes* it from
|
|
25
|
+
`added` while it still reaches `select_lenses.py` independently via
|
|
26
|
+
`--files`, so the gate's `f in added_files` membership test then excludes
|
|
27
|
+
that lens rather than including it. A parse skip is a missed narrowing
|
|
28
|
+
*result* (the lens is lost, not kept) — do not read it as fail-open the way
|
|
29
|
+
this module's caller (`select_lenses.py`) is fail-open for a missing
|
|
30
|
+
`Scope:` declaration; the two failure directions are opposite.
|
|
31
|
+
|
|
32
|
+
**Only `status == "A"` counts as added — renames and copies do not.** A
|
|
33
|
+
rename (`R`) or copy (`C`) produces a path that did not previously exist,
|
|
34
|
+
but it carries no new content to assess (a rename) or duplicates content
|
|
35
|
+
already reviewed elsewhere (a copy, and only reachable at all when a caller
|
|
36
|
+
passes `-C`/`--find-copies`, which none of this module's callers do today).
|
|
37
|
+
This is a deliberate, narrow choice, not an oversight — widen it (e.g.
|
|
38
|
+
`status in ("A", "C")`) only with a test pinning the new behavior.
|
|
39
|
+
|
|
40
|
+
**Known limitation: a path git C-quotes is stored quoted, not unquoted.**
|
|
41
|
+
Git always quotes a control character (including an embedded newline) or a
|
|
42
|
+
literal backslash/double-quote in a path — regardless of `core.quotePath` —
|
|
43
|
+
by wrapping it in `"..."` with C-style escapes (verified empirically: a file
|
|
44
|
+
literally named with an embedded newline round-trips through `git diff
|
|
45
|
+
--name-status` as the single line `"a\nb.txt"`, quotes included). This
|
|
46
|
+
module does not strip that quoting, so such a path reaches `select_lenses.py`
|
|
47
|
+
still wrapped in `"..."`, and its `_matches()` suffix check (`.endswith(...)`)
|
|
48
|
+
then fails against every glob — the file is invisible to every non-`always`
|
|
49
|
+
lens. Narrow in practice (control characters in filenames are rare) and not
|
|
50
|
+
a regression this module introduces (the pre-existing `--name-only` listing
|
|
51
|
+
step 1 uses has the identical exposure); fixing it needs a C-quote-aware
|
|
52
|
+
unquote step here, not attempted in this pass.
|
|
53
|
+
|
|
54
|
+
Pure policy except for the one I/O boundary in `main()` (reading
|
|
55
|
+
`--name-status-from <file>`, guarded against a missing/unreadable path).
|
|
56
|
+
Stdlib-only. See docs/python-hook-contract.md.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
from __future__ import annotations
|
|
60
|
+
|
|
61
|
+
import argparse
|
|
62
|
+
import json
|
|
63
|
+
import sys
|
|
64
|
+
from collections.abc import Iterable
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def parse_name_status(lines: Iterable[str]) -> list[dict]:
|
|
68
|
+
"""Parse `git diff --name-status` lines into `[{"path", "status"}, ...]`.
|
|
69
|
+
|
|
70
|
+
Each line is `<status>\\t<path>`, or for a rename/copy
|
|
71
|
+
`<status>\\t<old-path>\\t<new-path>` — the last field is always the
|
|
72
|
+
current path, which is what every consumer here cares about. `status` is
|
|
73
|
+
normalized to its leading letter (`R100` -> `R`) so callers compare
|
|
74
|
+
against `A`/`M`/`D`/`R`/`C` without parsing similarity percentages.
|
|
75
|
+
Unparseable lines are skipped, never raised on and never guessed.
|
|
76
|
+
"""
|
|
77
|
+
files: list[dict] = []
|
|
78
|
+
for raw in lines:
|
|
79
|
+
line = raw.rstrip("\n")
|
|
80
|
+
if not line.strip():
|
|
81
|
+
continue
|
|
82
|
+
parts = line.split("\t")
|
|
83
|
+
if len(parts) < 2:
|
|
84
|
+
continue
|
|
85
|
+
status_field = parts[0].strip()
|
|
86
|
+
path = parts[-1].strip()
|
|
87
|
+
if not status_field or not path:
|
|
88
|
+
continue
|
|
89
|
+
files.append({"path": path, "status": status_field[0]})
|
|
90
|
+
return files
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def evaluate(lines: Iterable[str]) -> dict:
|
|
94
|
+
"""Evaluate `git diff --name-status` lines into the full result dict."""
|
|
95
|
+
files = parse_name_status(lines)
|
|
96
|
+
return {
|
|
97
|
+
"files": files,
|
|
98
|
+
"added": [f["path"] for f in files if f["status"] == "A"],
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def main(argv=None) -> int:
|
|
103
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
104
|
+
parser.add_argument(
|
|
105
|
+
"--name-status", nargs="*", default=[],
|
|
106
|
+
help="git diff --name-status lines, one per arg (space-separated)",
|
|
107
|
+
)
|
|
108
|
+
parser.add_argument(
|
|
109
|
+
"--name-status-from", default=None,
|
|
110
|
+
help="read newline-separated name-status lines from this file ('-' for stdin)",
|
|
111
|
+
)
|
|
112
|
+
args = parser.parse_args(argv)
|
|
113
|
+
|
|
114
|
+
lines = list(args.name_status)
|
|
115
|
+
if args.name_status_from:
|
|
116
|
+
try:
|
|
117
|
+
if args.name_status_from == "-":
|
|
118
|
+
text = sys.stdin.read()
|
|
119
|
+
else:
|
|
120
|
+
with open(args.name_status_from) as handle:
|
|
121
|
+
text = handle.read()
|
|
122
|
+
except (OSError, ValueError):
|
|
123
|
+
# Missing/unreadable path, closed stdin, or undecodable bytes:
|
|
124
|
+
# contribute no lines rather than crash the whole invocation —
|
|
125
|
+
# consistent with every other unparseable-input case in this
|
|
126
|
+
# module. `ValueError` also covers `UnicodeDecodeError` (a
|
|
127
|
+
# subclass), reachable here because SKILL.md's caller mandates
|
|
128
|
+
# `-c core.quotePath=false`, which makes git emit raw path bytes
|
|
129
|
+
# instead of escaped octal for a non-ASCII path.
|
|
130
|
+
text = ""
|
|
131
|
+
lines.extend(line for line in text.splitlines() if line.strip())
|
|
132
|
+
|
|
133
|
+
print(json.dumps(evaluate(lines), sort_keys=True))
|
|
134
|
+
return 0
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
if __name__ == "__main__":
|
|
138
|
+
raise SystemExit(main(sys.argv[1:]))
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
__all__ = ("evaluate", "parse_name_status")
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Closing-pass composition for `/code-review`'s fix loop (#1626).
|
|
3
|
+
|
|
4
|
+
`/code-review` step 6a used to mandate: after ANY fix-loop iteration ran,
|
|
5
|
+
re-dispatch the **full** original agent panel once more against the final
|
|
6
|
+
staged content. The reason was structural, not editorial — the pre-commit
|
|
7
|
+
gate (#1461) needed `>= 2` distinct dispatches whose `subject_hash` equals the
|
|
8
|
+
FINAL staged hash, and the loop's targeted re-dispatches only cover the
|
|
9
|
+
agents that happened to have findings. So a one-line fix re-triggered an
|
|
10
|
+
18-agent panel. That is the single biggest cost multiplier in the loop, and
|
|
11
|
+
#1619 paid it repeatedly.
|
|
12
|
+
|
|
13
|
+
This module computes the **closing pass** instead: the minimal dispatch set
|
|
14
|
+
that preserves both properties the full re-panel was defending.
|
|
15
|
+
|
|
16
|
+
## The two properties, and how each is preserved
|
|
17
|
+
|
|
18
|
+
1. **The gate's corroboration floor, satisfied by construction.**
|
|
19
|
+
`hooks/pre_pr_review.py`'s `_MIN_DISTINCT_DISPATCHES` is 1 (#2147; lowered
|
|
20
|
+
from 2 — a single `/code-review` dispatch already runs a full panel
|
|
21
|
+
internally, so a second top-level dispatch was never additional
|
|
22
|
+
corroboration). The composition rule below tops up from the resolver's
|
|
23
|
+
eligible roster until at least that many distinct registered agents
|
|
24
|
+
dispatch at the final hash. No hook change, no exemption event, no ledger
|
|
25
|
+
change — the floor is met the same way it is met today, just with 1-2
|
|
26
|
+
dispatches instead of 18 (previously 2-3, under the old floor of 2).
|
|
27
|
+
|
|
28
|
+
2. **Not a rubber stamp.** Closing-pass agents keep full review authority:
|
|
29
|
+
any actionable finding re-enters the fix loop exactly as before (subject
|
|
30
|
+
to #1625's round cap). What changes is *how many* agents re-read *how
|
|
31
|
+
much* content — never whether their findings count. A pass whose findings
|
|
32
|
+
carried no consequence would be exactly the "dispatch trivial calls purely
|
|
33
|
+
to clear the gate" abuse `pre_commit_review.py`'s own docstring names.
|
|
34
|
+
|
|
35
|
+
## Scope: the fix delta, not the whole changeset
|
|
36
|
+
|
|
37
|
+
The round-1 panel already reviewed the full changeset. Only the *fix delta*
|
|
38
|
+
— what changed between what the panel reviewed and the final staged content
|
|
39
|
+
— is unreviewed. The closing pass reviews that delta.
|
|
40
|
+
|
|
41
|
+
**Escape hatch.** If the fix delta touches files the original panel never
|
|
42
|
+
targeted, scope grew mid-loop and the delta-only argument no longer holds:
|
|
43
|
+
fall back to the full re-dispatch over the whole changeset. That condition is
|
|
44
|
+
a deterministic set-comparison of two file lists, checked here rather than
|
|
45
|
+
judged in prose.
|
|
46
|
+
|
|
47
|
+
Stdlib-only. See docs/python-hook-contract.md.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
from __future__ import annotations
|
|
51
|
+
|
|
52
|
+
import argparse
|
|
53
|
+
import json
|
|
54
|
+
import sys
|
|
55
|
+
from pathlib import Path
|
|
56
|
+
|
|
57
|
+
#: Mirrors `hooks/pre_pr_review.py`'s `_MIN_DISTINCT_DISPATCHES`. Kept as
|
|
58
|
+
#: a named constant here (rather than imported) because this script must not
|
|
59
|
+
#: depend on the hook package to compute a dispatch plan; the drift test in
|
|
60
|
+
#: `plugins/dev-team/tests/scripts/test_closing_pass.py` asserts the two stay
|
|
61
|
+
#: equal, so a future change to the gate's floor fails a test rather than
|
|
62
|
+
#: silently under-composing the closing pass.
|
|
63
|
+
MIN_DISTINCT_DISPATCHES = 1
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _normalize(path) -> str:
|
|
67
|
+
text = str(path or "").replace("\\", "/")
|
|
68
|
+
while text.startswith("./"):
|
|
69
|
+
text = text[2:]
|
|
70
|
+
return text
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def scope_grew(panel_files, fix_delta_files) -> bool:
|
|
74
|
+
"""True when the fix delta touches a file the original panel never
|
|
75
|
+
targeted — the escape-hatch condition. A pure set comparison."""
|
|
76
|
+
panel = {_normalize(p) for p in panel_files if str(p or "").strip()}
|
|
77
|
+
delta = {_normalize(p) for p in fix_delta_files if str(p or "").strip()}
|
|
78
|
+
return not delta.issubset(panel)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def compose(
|
|
82
|
+
fixed_by_agents,
|
|
83
|
+
eligible_roster,
|
|
84
|
+
panel_agents,
|
|
85
|
+
panel_files=(),
|
|
86
|
+
fix_delta_files=(),
|
|
87
|
+
minimum: int = MIN_DISTINCT_DISPATCHES,
|
|
88
|
+
) -> dict:
|
|
89
|
+
"""Compute the closing-pass dispatch plan.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
fixed_by_agents: agents whose findings were fixed during the loop.
|
|
93
|
+
Each verifies its own fixes at the final hash.
|
|
94
|
+
eligible_roster: the resolver's eligible lenses in `select_lenses.py`
|
|
95
|
+
order — cheap-first (non-opus before opus). Top-ups are taken
|
|
96
|
+
from the front, so a top-up never reaches for an opus lens while
|
|
97
|
+
a cheaper eligible one is available.
|
|
98
|
+
panel_agents: the full round-1 panel, used only by the escape hatch.
|
|
99
|
+
panel_files / fix_delta_files: drive `scope_grew`.
|
|
100
|
+
minimum: the gate's distinct-dispatch floor.
|
|
101
|
+
|
|
102
|
+
Returns `{"agents", "scope", "escape_hatch", "reason", "topped_up"}`.
|
|
103
|
+
`scope` is `fix-delta` normally, `full-changeset` under the escape hatch.
|
|
104
|
+
"""
|
|
105
|
+
fixed = _dedupe(fixed_by_agents)
|
|
106
|
+
roster = _dedupe(eligible_roster)
|
|
107
|
+
panel = _dedupe(panel_agents)
|
|
108
|
+
|
|
109
|
+
if scope_grew(panel_files, fix_delta_files):
|
|
110
|
+
return {
|
|
111
|
+
"agents": panel or roster,
|
|
112
|
+
"scope": "full-changeset",
|
|
113
|
+
"escape_hatch": True,
|
|
114
|
+
"reason": "fix-delta-touched-files-outside-the-panel-target-set",
|
|
115
|
+
"topped_up": [],
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
agents = list(fixed)
|
|
119
|
+
topped_up = []
|
|
120
|
+
for candidate in roster:
|
|
121
|
+
if len(agents) >= minimum:
|
|
122
|
+
break
|
|
123
|
+
if candidate not in agents:
|
|
124
|
+
agents.append(candidate)
|
|
125
|
+
topped_up.append(candidate)
|
|
126
|
+
|
|
127
|
+
reason = None
|
|
128
|
+
if len(agents) < minimum:
|
|
129
|
+
# The eligible roster itself cannot supply the floor (a tiny or
|
|
130
|
+
# heavily-filtered roster). Say so explicitly rather than emitting a
|
|
131
|
+
# plan that will fail the gate for reasons the operator can't see.
|
|
132
|
+
reason = "eligible-roster-smaller-than-gate-floor"
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
"agents": agents,
|
|
136
|
+
"scope": "fix-delta",
|
|
137
|
+
"escape_hatch": False,
|
|
138
|
+
"reason": reason,
|
|
139
|
+
"topped_up": topped_up,
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _dedupe(values) -> list:
|
|
144
|
+
seen, out = set(), []
|
|
145
|
+
for value in values or ():
|
|
146
|
+
name = str(value or "").strip()
|
|
147
|
+
if name and name not in seen:
|
|
148
|
+
seen.add(name)
|
|
149
|
+
out.append(name)
|
|
150
|
+
return out
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def _load_list(value: str | None) -> list:
|
|
154
|
+
"""Accept either a comma-separated inline list or `@path` to a JSON file
|
|
155
|
+
holding a list (or `{"lenses": [...]}`, matching `select_lenses.py`)."""
|
|
156
|
+
if not value:
|
|
157
|
+
return []
|
|
158
|
+
if value.startswith("@"):
|
|
159
|
+
data = json.loads(Path(value[1:]).read_text(encoding="utf-8"))
|
|
160
|
+
if isinstance(data, dict):
|
|
161
|
+
data = data.get("lenses", data.get("agents", []))
|
|
162
|
+
return list(data) if isinstance(data, list) else []
|
|
163
|
+
return [v.strip() for v in value.split(",") if v.strip()]
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def main(argv=None) -> int:
|
|
167
|
+
parser = argparse.ArgumentParser(description="Compose the /code-review closing pass.")
|
|
168
|
+
parser.add_argument("--fixed-by", default="", help="Agents whose findings were fixed")
|
|
169
|
+
parser.add_argument("--roster", default="", help="Eligible roster, cheap-first (or @file.json)")
|
|
170
|
+
parser.add_argument("--panel", default="", help="The full round-1 panel (or @file.json)")
|
|
171
|
+
parser.add_argument("--panel-files", default="", help="Files the round-1 panel targeted")
|
|
172
|
+
parser.add_argument("--fix-delta-files", default="", help="Files the cumulative fix touched")
|
|
173
|
+
args = parser.parse_args(argv)
|
|
174
|
+
|
|
175
|
+
plan = compose(
|
|
176
|
+
_load_list(args.fixed_by),
|
|
177
|
+
_load_list(args.roster),
|
|
178
|
+
_load_list(args.panel),
|
|
179
|
+
_load_list(args.panel_files),
|
|
180
|
+
_load_list(args.fix_delta_files),
|
|
181
|
+
)
|
|
182
|
+
print(json.dumps(plan, sort_keys=True))
|
|
183
|
+
return 0
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
if __name__ == "__main__":
|
|
187
|
+
raise SystemExit(main(sys.argv[1:]))
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Consolidate per-slice section artifacts into one deduplicated report.
|
|
3
|
+
|
|
4
|
+
Split into a **pure** ``consolidate(sections)`` (takes a list of section dicts,
|
|
5
|
+
returns the aggregated object) and a thin ``main()`` that reads
|
|
6
|
+
``.dev-team-reports/code-review/raw/section-*.json`` and calls it — the same
|
|
7
|
+
main-wraps-pure convention as ``check_version_drift.py``/``lesson_validate.py``,
|
|
8
|
+
so the aggregation logic is unit-tested with plain dicts and no filesystem.
|
|
9
|
+
|
|
10
|
+
Consolidation:
|
|
11
|
+
- Dedupe findings by ``file:line`` — one entry, reporting agents merged into an
|
|
12
|
+
``agents[]`` array, severity = the single highest enum (per SKILL.md step 5c).
|
|
13
|
+
- Recurring-theme rollup — a review dimension (agent) whose findings recur across
|
|
14
|
+
two or more slices, so a systemic pattern surfaces above per-slice noise.
|
|
15
|
+
- Disclose which slices ran the reduced (declarative) panel.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import argparse
|
|
21
|
+
import glob
|
|
22
|
+
import json
|
|
23
|
+
import sys
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
|
|
26
|
+
# Reach the sibling ledger.py regardless of cwd or sys.path mode (matches the
|
|
27
|
+
# house pattern in change_shape.py/codebase_recon.py for reaching a sibling
|
|
28
|
+
# module rather than relying on the implicit sys.path[0] a direct script
|
|
29
|
+
# invocation provides).
|
|
30
|
+
_HERE = Path(__file__).resolve().parent
|
|
31
|
+
if str(_HERE) not in sys.path:
|
|
32
|
+
sys.path.insert(0, str(_HERE))
|
|
33
|
+
|
|
34
|
+
from ledger import raw_dir
|
|
35
|
+
|
|
36
|
+
# Single source of truth for the severity vocabulary (step 5c's ranking lived
|
|
37
|
+
# only in prose before): each severity's rank (for highest-wins merge and
|
|
38
|
+
# sorting) and its totals bucket key.
|
|
39
|
+
_SEVERITY = {
|
|
40
|
+
"suggestion": (1, "suggestions"),
|
|
41
|
+
"warning": (2, "warnings"),
|
|
42
|
+
"error": (3, "errors"),
|
|
43
|
+
}
|
|
44
|
+
_DEFAULT_SEVERITY = "suggestion"
|
|
45
|
+
|
|
46
|
+
# A review dimension recurring across at least this many slices is a theme.
|
|
47
|
+
_THEME_MIN_SLICES = 2
|
|
48
|
+
|
|
49
|
+
# Real-world review-agent output drifts from the documented schema (#1261): some
|
|
50
|
+
# agents return their findings list under `issues` (the per-agent key in
|
|
51
|
+
# output-format.md) instead of `findings` (the section-artifact key). Accept
|
|
52
|
+
# either so a mis-keyed list is aggregated, never silently counted as zero. The
|
|
53
|
+
# canonical key is tried first; the alias is a fallback.
|
|
54
|
+
_FINDINGS_KEYS = ("findings", "issues")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _rank(severity: str) -> int:
|
|
58
|
+
return _SEVERITY.get(severity, (0, ""))[0]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _bucket(severity: str) -> str:
|
|
62
|
+
return _SEVERITY.get(severity, _SEVERITY[_DEFAULT_SEVERITY])[1]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _findings_of(container: dict) -> list:
|
|
66
|
+
"""Return the findings list from ``container`` tolerating key drift (#1261).
|
|
67
|
+
|
|
68
|
+
Prefers ``findings`` (section-artifact key), falls back to ``issues``
|
|
69
|
+
(per-agent key). A value that is present but not a list is treated as no
|
|
70
|
+
findings rather than crashing the aggregation.
|
|
71
|
+
"""
|
|
72
|
+
for key in _FINDINGS_KEYS:
|
|
73
|
+
value = container.get(key)
|
|
74
|
+
if isinstance(value, list):
|
|
75
|
+
return value
|
|
76
|
+
return []
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def normalize_agent_result(raw: dict, agent_name: str | None = None) -> list:
|
|
80
|
+
"""Coerce one review agent's result into a flat, ``agent``-tagged findings list.
|
|
81
|
+
|
|
82
|
+
Absorbs the schema drift observed in real runs (#1261): the native per-agent
|
|
83
|
+
``{status, issues, summary}`` shape, findings keyed as ``issues`` **or**
|
|
84
|
+
``findings``, and any extra top-level keys (e.g. ``summary``) — all of which
|
|
85
|
+
are ignored except the findings list. Each returned finding is tagged with
|
|
86
|
+
its reporting ``agent`` (from ``raw["agentName"]``, else ``agent_name``) so
|
|
87
|
+
``consolidate()`` can merge reporters per ``file:line`` and roll up themes.
|
|
88
|
+
|
|
89
|
+
Non-dict input, or a findings entry that is not a dict, yields an empty list
|
|
90
|
+
/ is skipped — this never raises, so a malformed agent result degrades to
|
|
91
|
+
"reported nothing" rather than aborting the whole aggregation.
|
|
92
|
+
"""
|
|
93
|
+
if not isinstance(raw, dict):
|
|
94
|
+
return []
|
|
95
|
+
agent = raw.get("agentName") or agent_name
|
|
96
|
+
out = []
|
|
97
|
+
for finding in _findings_of(raw):
|
|
98
|
+
if not isinstance(finding, dict):
|
|
99
|
+
continue
|
|
100
|
+
tagged = dict(finding)
|
|
101
|
+
tagged.setdefault("agent", agent)
|
|
102
|
+
out.append(tagged)
|
|
103
|
+
return out
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _dedupe_key(finding: dict):
|
|
107
|
+
return (finding.get("file"), finding.get("line"))
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _sorted_ids(ids) -> list:
|
|
111
|
+
"""Return the non-None ids, sorted — the shared 'sorted, None-filtered' idiom."""
|
|
112
|
+
return sorted(s for s in ids if s is not None)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _merge_finding(merged: dict, order: list, finding: dict) -> None:
|
|
116
|
+
"""Insert ``finding`` into the ``file:line`` dedup map, or merge it into the
|
|
117
|
+
existing entry: highest severity wins and keeps its message; reporting agents
|
|
118
|
+
accumulate into ``agents[]`` without duplicates.
|
|
119
|
+
"""
|
|
120
|
+
key = _dedupe_key(finding)
|
|
121
|
+
agent = finding.get("agent")
|
|
122
|
+
severity = finding.get("severity", _DEFAULT_SEVERITY)
|
|
123
|
+
entry = merged.get(key)
|
|
124
|
+
if entry is None:
|
|
125
|
+
order.append(key)
|
|
126
|
+
merged[key] = {
|
|
127
|
+
"severity": severity,
|
|
128
|
+
"agents": [agent] if agent else [],
|
|
129
|
+
"file": finding.get("file"),
|
|
130
|
+
"line": finding.get("line"),
|
|
131
|
+
"message": finding.get("message"),
|
|
132
|
+
}
|
|
133
|
+
return
|
|
134
|
+
if _rank(severity) > _rank(entry["severity"]):
|
|
135
|
+
entry["severity"] = severity
|
|
136
|
+
entry["message"] = finding.get("message")
|
|
137
|
+
if agent and agent not in entry["agents"]:
|
|
138
|
+
entry["agents"].append(agent)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def _tally_severity(totals: dict, severity: str) -> None:
|
|
142
|
+
totals[_bucket(severity)] += 1
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def _tally_theme(theme_slices: dict, theme_counts: dict, agent: str | None, slice_id) -> None:
|
|
146
|
+
"""Record one finding's contribution to the recurring-theme rollup for ``agent``."""
|
|
147
|
+
if agent is None:
|
|
148
|
+
return
|
|
149
|
+
theme_slices.setdefault(agent, set()).add(slice_id)
|
|
150
|
+
theme_counts[agent] = theme_counts.get(agent, 0) + 1
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def consolidate(sections: list[dict]) -> dict:
|
|
154
|
+
"""Aggregate ``sections`` into the consolidated report object.
|
|
155
|
+
|
|
156
|
+
``sections`` is a list of per-slice artifacts (``id``/``files``/
|
|
157
|
+
``is_declarative``/``panel``/``findings``). Findings carry the usual
|
|
158
|
+
``severity``/``file``/``line``/``message`` and an optional ``agent`` naming
|
|
159
|
+
the reporting review dimension. Returns the aggregated object; an empty input
|
|
160
|
+
yields an empty (but well-formed) aggregate.
|
|
161
|
+
"""
|
|
162
|
+
merged: dict = {} # (file, line) -> consolidated finding
|
|
163
|
+
order: list = [] # first-seen order of keys, for stable output
|
|
164
|
+
theme_slices: dict = {} # agent -> set of slice ids
|
|
165
|
+
theme_counts: dict = {} # agent -> total findings
|
|
166
|
+
reduced_panel_slices: list = []
|
|
167
|
+
dispatch_failures: list = []
|
|
168
|
+
totals = {"errors": 0, "warnings": 0, "suggestions": 0}
|
|
169
|
+
|
|
170
|
+
for section in sections:
|
|
171
|
+
slice_id = section.get("id")
|
|
172
|
+
if section.get("is_declarative"):
|
|
173
|
+
reduced_panel_slices.append(slice_id)
|
|
174
|
+
section_dispatch_failures = section.get("dispatchFailures")
|
|
175
|
+
if isinstance(section_dispatch_failures, list):
|
|
176
|
+
dispatch_failures.extend(section_dispatch_failures)
|
|
177
|
+
for finding in _findings_of(section):
|
|
178
|
+
severity = finding.get("severity", _DEFAULT_SEVERITY)
|
|
179
|
+
_tally_severity(totals, severity)
|
|
180
|
+
_tally_theme(theme_slices, theme_counts, finding.get("agent"), slice_id)
|
|
181
|
+
_merge_finding(merged, order, finding)
|
|
182
|
+
|
|
183
|
+
top_findings = [merged[k] for k in order]
|
|
184
|
+
top_findings.sort(key=lambda f: (-_rank(f["severity"]), str(f["file"]), f["line"] or 0))
|
|
185
|
+
|
|
186
|
+
recurring_themes = [
|
|
187
|
+
{"agent": agent, "slices": _sorted_ids(slices), "occurrences": theme_counts[agent]}
|
|
188
|
+
for agent, slices in theme_slices.items()
|
|
189
|
+
if len(slices) >= _THEME_MIN_SLICES
|
|
190
|
+
]
|
|
191
|
+
recurring_themes.sort(key=lambda t: (-t["occurrences"], t["agent"]))
|
|
192
|
+
|
|
193
|
+
overall = "fail" if totals["errors"] else "warn" if totals["warnings"] else "pass"
|
|
194
|
+
# A non-empty dispatchFailures forces overall: fail, unconditionally — applied
|
|
195
|
+
# after the totals-based computation above so it always wins, mirroring the
|
|
196
|
+
# legacy (non-sliced) path's own unconditional-override rule.
|
|
197
|
+
if dispatch_failures:
|
|
198
|
+
overall = "fail"
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
"sliced": True,
|
|
202
|
+
"sliceCount": len(sections),
|
|
203
|
+
"overall": overall,
|
|
204
|
+
"totals": totals,
|
|
205
|
+
"topFindings": top_findings,
|
|
206
|
+
"recurringThemes": recurring_themes,
|
|
207
|
+
"reducedPanelSlices": _sorted_ids(reduced_panel_slices),
|
|
208
|
+
"dispatchFailures": dispatch_failures,
|
|
209
|
+
"summary": (
|
|
210
|
+
f"{overall.upper()} across {len(sections)} slices — "
|
|
211
|
+
f"{totals['errors']} errors, {totals['warnings']} warnings, "
|
|
212
|
+
f"{totals['suggestions']} suggestions; "
|
|
213
|
+
f"{len(recurring_themes)} recurring theme(s)."
|
|
214
|
+
),
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _read_sections(root: str) -> tuple[list, list]:
|
|
219
|
+
"""Read every ``raw/section-*.json`` under ``root``.
|
|
220
|
+
|
|
221
|
+
Returns ``(sections, malformed_paths)``. A malformed artifact is collected
|
|
222
|
+
into ``malformed_paths`` (reported by the caller), never silently dropped.
|
|
223
|
+
"""
|
|
224
|
+
sections, malformed = [], []
|
|
225
|
+
for path in sorted(glob.glob(str(raw_dir(root) / "section-*.json"))):
|
|
226
|
+
try:
|
|
227
|
+
obj = json.loads(Path(path).read_text())
|
|
228
|
+
except (json.JSONDecodeError, OSError):
|
|
229
|
+
malformed.append(path)
|
|
230
|
+
continue
|
|
231
|
+
# Valid JSON of the wrong shape (list, string, ...) is malformed too —
|
|
232
|
+
# otherwise it would crash consolidate() at section.get(...).
|
|
233
|
+
if not isinstance(obj, dict):
|
|
234
|
+
malformed.append(path)
|
|
235
|
+
continue
|
|
236
|
+
sections.append(obj)
|
|
237
|
+
return sections, malformed
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def main(argv: list[str] | None = None) -> int:
|
|
241
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
242
|
+
parser.add_argument("--root", default=".")
|
|
243
|
+
args = parser.parse_args(argv)
|
|
244
|
+
|
|
245
|
+
sections, malformed = _read_sections(args.root)
|
|
246
|
+
for path in malformed:
|
|
247
|
+
print(f"WARNING: malformed section artifact skipped: {path}", file=sys.stderr)
|
|
248
|
+
|
|
249
|
+
result = consolidate(sections)
|
|
250
|
+
if malformed:
|
|
251
|
+
result["malformedArtifacts"] = malformed
|
|
252
|
+
# A malformed artifact means that slice's findings were never read —
|
|
253
|
+
# the identical coverage gap `dispatchFailures` forces `overall`
|
|
254
|
+
# to "fail" for a few lines up in consolidate(), and for the same
|
|
255
|
+
# reason: an unexamined slice must never ride out as "pass" just
|
|
256
|
+
# because the READABLE sections happened to look clean (#1763
|
|
257
|
+
# security review — /pr --json checks only overall/status). The
|
|
258
|
+
# `summary` string is rebuilt too (#1865) — it must not interpolate
|
|
259
|
+
# the PRE-override `result['summary']` (built from `overall` INSIDE
|
|
260
|
+
# consolidate(), before this override runs): doing so would print a
|
|
261
|
+
# "FAIL ... ; WARN ..." self-contradicting summary. Rebuild it
|
|
262
|
+
# entirely from the already-available totals/recurringThemes instead.
|
|
263
|
+
result["overall"] = "fail"
|
|
264
|
+
totals = result["totals"]
|
|
265
|
+
result["summary"] = (
|
|
266
|
+
f"FAIL across {len(sections)} slices — {len(malformed)} malformed "
|
|
267
|
+
f"artifact(s) unreadable; {totals['errors']} errors, {totals['warnings']} warnings, "
|
|
268
|
+
f"{totals['suggestions']} suggestions from readable slices; "
|
|
269
|
+
f"{len(result['recurringThemes'])} recurring theme(s)."
|
|
270
|
+
)
|
|
271
|
+
print(json.dumps(result, indent=2, sort_keys=True))
|
|
272
|
+
# Non-zero exit if any artifact was unreadable, so a caller notices.
|
|
273
|
+
return 2 if malformed else 0
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
if __name__ == "__main__":
|
|
277
|
+
raise SystemExit(main(sys.argv[1:]))
|