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,467 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Deterministic contract validation for review-agent output (#1998).
|
|
3
|
+
|
|
4
|
+
Session-report analysis over 3,213 review runs found 585 (18.2%) returning
|
|
5
|
+
output that does not match the shared review-agent JSON contract
|
|
6
|
+
(`knowledge/review-agent-output-contract.md`). Those findings were discarded
|
|
7
|
+
without a diagnostic — the orchestrator eyeballs each agent's raw text
|
|
8
|
+
against the contract and, when it doesn't obviously fit, the loss is silent:
|
|
9
|
+
no agent name, no raw output, no reason is ever recorded, so the failure
|
|
10
|
+
shapes are unknown. #1980/#1982's per-lens `$/finding` figures divide by
|
|
11
|
+
that same lossy denominator, and the loss rate varies ~8x by agent
|
|
12
|
+
(`concurrency-review` 49%, `spec-compliance-review` 30%, `doc-review` 19%).
|
|
13
|
+
|
|
14
|
+
This module is the deterministic half of the fix: given an agent's raw text
|
|
15
|
+
output, decide whether it satisfies the contract and, when it doesn't,
|
|
16
|
+
classify *why* and log a diagnostic — agent name, a redacted prefix of the
|
|
17
|
+
raw output, and the specific validation error — to
|
|
18
|
+
`.claude/metrics/contract-failures.jsonl`. Per this repo's CLAUDE.md:
|
|
19
|
+
"instrument before fixing... the failure shapes are currently unknown, so a
|
|
20
|
+
fix written first would be a guess." Fixing by shape (a tolerant extractor
|
|
21
|
+
for the recoverable cases, a schema fix, a hard error for the unusable ones)
|
|
22
|
+
and recomputing `$/finding` on the repaired denominator are follow-on work
|
|
23
|
+
once this log has real data in it.
|
|
24
|
+
|
|
25
|
+
Two independent dimensions are tracked, not one:
|
|
26
|
+
|
|
27
|
+
- ``extraction`` — how the JSON was framed: ``clean`` (no wrapper), ``fenced``
|
|
28
|
+
(a ` ```json ` block), or ``prose-preamble`` (a leading/trailing prose
|
|
29
|
+
sentence around a balanced object). ``None`` when no JSON-like structure
|
|
30
|
+
was ever recovered at all.
|
|
31
|
+
- ``shape`` — the outcome. On success it equals ``extraction``. On failure it
|
|
32
|
+
is one of the loggable failure shapes (see ``FAILURE_SHAPES``) — including
|
|
33
|
+
``schema-drift`` and ``malformed-json``, both of which can co-occur with any
|
|
34
|
+
extraction (``clean``/``fenced``/``prose-preamble``), so ``extraction``
|
|
35
|
+
survives even when the object was recovered from a fenced block or a prose
|
|
36
|
+
preamble and only then found to violate the contract or fail to parse.
|
|
37
|
+
``empty``/``truncated``/``not-json`` never carry an ``extraction`` — no
|
|
38
|
+
JSON-shaped candidate was ever recovered for those. Collapsing these into
|
|
39
|
+
one field was the original design and it silently discarded the extraction
|
|
40
|
+
dimension on exactly the failures a tolerant extractor would need it for.
|
|
41
|
+
|
|
42
|
+
Stdlib-only. See docs/python-hook-contract.md.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
from __future__ import annotations
|
|
46
|
+
|
|
47
|
+
import argparse
|
|
48
|
+
import json
|
|
49
|
+
import re
|
|
50
|
+
import sys
|
|
51
|
+
from datetime import datetime, timezone
|
|
52
|
+
from pathlib import Path
|
|
53
|
+
|
|
54
|
+
# skills/code-review/scripts -> skills/code-review -> skills -> plugin root
|
|
55
|
+
_PLUGIN_ROOT = Path(__file__).resolve().parents[3]
|
|
56
|
+
_HOOKS_LIB_DIR = _PLUGIN_ROOT / "hooks" / "lib"
|
|
57
|
+
if str(_HOOKS_LIB_DIR) not in sys.path:
|
|
58
|
+
sys.path.insert(0, str(_HOOKS_LIB_DIR))
|
|
59
|
+
|
|
60
|
+
try:
|
|
61
|
+
import artifact_paths # type: ignore[import-not-found]
|
|
62
|
+
import atomic_state # type: ignore[import-not-found]
|
|
63
|
+
import review_agent_registry # type: ignore[import-not-found]
|
|
64
|
+
except ImportError: # pragma: no cover - degraded fallback, hooks/lib unreachable
|
|
65
|
+
# Same guarded-import shape as `review_round_log.py`'s sibling pattern:
|
|
66
|
+
# the `sys.path` setup above must run before this import, which is why
|
|
67
|
+
# it isn't at the top of the file (`ruff.toml` suppresses E402 for this
|
|
68
|
+
# whole directory for exactly that reason).
|
|
69
|
+
artifact_paths = None
|
|
70
|
+
atomic_state = None
|
|
71
|
+
review_agent_registry = None
|
|
72
|
+
|
|
73
|
+
_STREAM_NAME = "contract-failures.jsonl"
|
|
74
|
+
|
|
75
|
+
#: How much of the (redacted) raw output a failure diagnostic carries — enough
|
|
76
|
+
#: to recognize the shape (a preamble sentence, a fence opener, truncation) at
|
|
77
|
+
#: a glance, without inflating the log with full agent output on every
|
|
78
|
+
#: failure.
|
|
79
|
+
_RAW_PREFIX_LEN = 200
|
|
80
|
+
|
|
81
|
+
#: Cap on the persisted/printed `error` string. `_validate_schema` interpolates
|
|
82
|
+
#: agent-controlled values (`status`, `severity`) with `!r` — unlike
|
|
83
|
+
#: `raw_prefix`, nothing bounded this field's length or redacted it before
|
|
84
|
+
#: #1998 wave-2-follow-up, so a drifting agent could write an arbitrarily
|
|
85
|
+
#: long, secret-bearing `error` straight into `contract-failures.jsonl` and
|
|
86
|
+
#: into every downstream `dispatchFailures[].error` consumer.
|
|
87
|
+
_ERROR_MAX_LEN = 256
|
|
88
|
+
|
|
89
|
+
_VALID_STATUSES = frozenset({"pass", "warn", "fail", "skip"})
|
|
90
|
+
_VALID_SEVERITIES = frozenset({"error", "warning", "suggestion"})
|
|
91
|
+
|
|
92
|
+
_FENCE_RE = re.compile(r"```(?:json)?\s*\n(.*?)```", re.DOTALL)
|
|
93
|
+
|
|
94
|
+
#: Secret-shaped substrings to scrub before any raw agent text is persisted.
|
|
95
|
+
#: Review-agent output is not independent of the reviewed repository — a
|
|
96
|
+
#: lens quoting a hardcoded-key finding verbatim reproduces the secret it
|
|
97
|
+
#: found — so `raw_prefix` is a transitive channel for repo content, not
|
|
98
|
+
#: "AI-authored text" in the sense of being free of user/repo material.
|
|
99
|
+
#: First pattern is this repo's own canonical hardcoded-key detector
|
|
100
|
+
#: (`knowledge/owasp-detection.md`'s "Hardcoded-key pattern"); the rest are
|
|
101
|
+
#: high-signal vendor token prefixes cheap enough to check unconditionally.
|
|
102
|
+
_SECRET_PATTERNS = (
|
|
103
|
+
# No required closing quote (unlike the canonical pattern in
|
|
104
|
+
# `knowledge/owasp-detection.md`): this module's own most common failure
|
|
105
|
+
# shape, `truncated`, cuts output mid-string, and requiring a closing
|
|
106
|
+
# quote before redacting would let exactly that secret through unredacted.
|
|
107
|
+
re.compile(r"(?i)(api[_-]?key|secret|password|token)\s*[:=]\s*['\"][^'\"]{8,}"),
|
|
108
|
+
# `[A-Za-z0-9_-]`, not just alphanumeric: segmented vendor-key formats
|
|
109
|
+
# (`sk-ant-...`, `sk-proj-...`) use `-`/`_` inside the token body and
|
|
110
|
+
# would otherwise stop matching at the first separator.
|
|
111
|
+
re.compile(r"sk-[A-Za-z0-9_-]{16,}"),
|
|
112
|
+
re.compile(r"AKIA[0-9A-Z]{16}"),
|
|
113
|
+
re.compile(r"gh[pousr]_[A-Za-z0-9]{20,}"),
|
|
114
|
+
re.compile(r"xox[baprs]-[A-Za-z0-9-]{10,}"),
|
|
115
|
+
re.compile(r"eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}"),
|
|
116
|
+
# Complete PEM block, bounded by its own END marker.
|
|
117
|
+
re.compile(r"-----BEGIN [A-Z ]*PRIVATE KEY-----.*?-----END [A-Z ]*PRIVATE KEY-----", re.DOTALL),
|
|
118
|
+
# A BEGIN marker with no matching END left in the text — the truncated
|
|
119
|
+
# shape again: redact from BEGIN to EOF rather than leave the key body
|
|
120
|
+
# unredacted because the block never closed.
|
|
121
|
+
re.compile(r"-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*$"),
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
#: Extraction shapes — how a successfully-recovered JSON object was framed.
|
|
125
|
+
#: These label *successful* extraction only; they never appear as a `shape`
|
|
126
|
+
#: value in a failure row (see ``FAILURE_SHAPES``) except indirectly via the
|
|
127
|
+
#: `extraction` field on a `schema-drift` failure.
|
|
128
|
+
SHAPE_CLEAN = "clean"
|
|
129
|
+
SHAPE_FENCED = "fenced"
|
|
130
|
+
SHAPE_PROSE_PREAMBLE = "prose-preamble"
|
|
131
|
+
|
|
132
|
+
#: Failure shapes this module distinguishes — the taxonomy #1998 asks for.
|
|
133
|
+
SHAPE_EMPTY = "empty"
|
|
134
|
+
SHAPE_TRUNCATED = "truncated"
|
|
135
|
+
SHAPE_MALFORMED_JSON = "malformed-json"
|
|
136
|
+
SHAPE_SCHEMA_DRIFT = "schema-drift"
|
|
137
|
+
SHAPE_NOT_JSON = "not-json"
|
|
138
|
+
|
|
139
|
+
#: The closed set of `shape` values `contract-failures.jsonl` can ever carry.
|
|
140
|
+
#: Kept here, not re-enumerated in prose, so `SKILL.md` and
|
|
141
|
+
#: `telemetry-schema.md` can be checked against one source of truth
|
|
142
|
+
#: (`repo_invariants.py::check_contract_failure_shapes_documented`).
|
|
143
|
+
FAILURE_SHAPES = frozenset(
|
|
144
|
+
{SHAPE_EMPTY, SHAPE_TRUNCATED, SHAPE_MALFORMED_JSON, SHAPE_SCHEMA_DRIFT, SHAPE_NOT_JSON}
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
#: The closed set of `extraction` values a *successful* validation can carry.
|
|
148
|
+
SUCCESS_SHAPES = frozenset({SHAPE_CLEAN, SHAPE_FENCED, SHAPE_PROSE_PREAMBLE})
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _now_iso() -> str:
|
|
152
|
+
return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _redact(text: str) -> str:
|
|
156
|
+
"""Scrub secret-shaped substrings from ``text`` before any further
|
|
157
|
+
processing (including truncation) sees it — a secret straddling the
|
|
158
|
+
``_RAW_PREFIX_LEN`` cut must still be caught, so redaction runs on the
|
|
159
|
+
full text first, never on the already-truncated slice."""
|
|
160
|
+
for pattern in _SECRET_PATTERNS:
|
|
161
|
+
text = pattern.sub("[REDACTED]", text)
|
|
162
|
+
return text
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _extract_fenced_json(text: str) -> str | None:
|
|
166
|
+
match = _FENCE_RE.search(text)
|
|
167
|
+
return match.group(1).strip() if match else None
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def _advance_in_string(ch: str, escape: bool) -> tuple[bool, bool]:
|
|
171
|
+
"""One character step of the in-string/escape state machine, given the
|
|
172
|
+
current character and whether the previous one was an unconsumed
|
|
173
|
+
backslash. Returns ``(still_in_string, escape)`` for the next character."""
|
|
174
|
+
if escape:
|
|
175
|
+
return True, False
|
|
176
|
+
if ch == "\\":
|
|
177
|
+
return True, True
|
|
178
|
+
if ch == '"':
|
|
179
|
+
return False, False
|
|
180
|
+
return True, False
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def _scan_balanced(text: str, start: int) -> str | None:
|
|
184
|
+
"""Scan forward from ``start`` (must index a ``{``), tracking string/escape
|
|
185
|
+
state so a brace inside a quoted string value doesn't corrupt depth
|
|
186
|
+
counting. Returns the balanced ``{...}`` substring, or ``None`` if depth
|
|
187
|
+
never returns to zero before EOF."""
|
|
188
|
+
depth = 0
|
|
189
|
+
in_string = False
|
|
190
|
+
escape = False
|
|
191
|
+
for i in range(start, len(text)):
|
|
192
|
+
ch = text[i]
|
|
193
|
+
if in_string:
|
|
194
|
+
in_string, escape = _advance_in_string(ch, escape)
|
|
195
|
+
continue
|
|
196
|
+
if ch == '"':
|
|
197
|
+
in_string = True
|
|
198
|
+
elif ch == "{":
|
|
199
|
+
depth += 1
|
|
200
|
+
elif ch == "}":
|
|
201
|
+
depth -= 1
|
|
202
|
+
if depth == 0:
|
|
203
|
+
return text[start : i + 1]
|
|
204
|
+
return None
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def _find_first_json_object(text: str) -> tuple[str | None, bool]:
|
|
208
|
+
"""Return ``(candidate, truncated)``: ``candidate`` is the first balanced
|
|
209
|
+
``{...}`` substring in ``text``, tolerating leading/trailing prose, or
|
|
210
|
+
``None`` if no starting ``{`` ever balances. Every ``{`` in ``text`` is
|
|
211
|
+
tried as a candidate start, not just the first — a ``{`` inside leading
|
|
212
|
+
prose (e.g. quoted code in a review lens's preamble sentence) that never
|
|
213
|
+
balances must not prevent recovery of a real, later JSON object; only
|
|
214
|
+
when *no* starting position balances does this report failure.
|
|
215
|
+
``truncated`` is True only when at least one ``{`` was found but none of
|
|
216
|
+
them ever balanced back to depth zero before EOF — the
|
|
217
|
+
token-limit-truncation shape, distinguished here (by the same
|
|
218
|
+
string-aware scanner, not a separate naive brace count) rather than left
|
|
219
|
+
for a caller to re-derive."""
|
|
220
|
+
start = text.find("{")
|
|
221
|
+
saw_unbalanced = False
|
|
222
|
+
while start != -1:
|
|
223
|
+
candidate = _scan_balanced(text, start)
|
|
224
|
+
if candidate is not None:
|
|
225
|
+
return candidate, False
|
|
226
|
+
saw_unbalanced = True
|
|
227
|
+
start = text.find("{", start + 1)
|
|
228
|
+
return None, saw_unbalanced
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def _validate_schema(parsed) -> str | None:
|
|
232
|
+
"""Check a successfully-`json.loads`-ed value against the contract's
|
|
233
|
+
required shape. Deliberately permissive on optional fields (`category`
|
|
234
|
+
is documented optional; `confidence`/`file`/`line`/`suggestedFix` are not
|
|
235
|
+
re-validated here) — this function's job is to catch schema *drift*
|
|
236
|
+
(wrong status enum, missing issues array, unrecognized severity), not to
|
|
237
|
+
re-implement the full contract as a strict schema.
|
|
238
|
+
|
|
239
|
+
Returns the drift error string, or ``None`` when ``parsed`` satisfies the
|
|
240
|
+
contract.
|
|
241
|
+
"""
|
|
242
|
+
if not isinstance(parsed, dict):
|
|
243
|
+
return f"top-level value is {type(parsed).__name__}, expected an object"
|
|
244
|
+
status = parsed.get("status")
|
|
245
|
+
if status not in _VALID_STATUSES:
|
|
246
|
+
return f"status={status!r} not one of {sorted(_VALID_STATUSES)}"
|
|
247
|
+
issues = parsed.get("issues")
|
|
248
|
+
if not isinstance(issues, list):
|
|
249
|
+
return "issues field missing or not an array"
|
|
250
|
+
for i, issue in enumerate(issues):
|
|
251
|
+
if not isinstance(issue, dict):
|
|
252
|
+
return f"issues[{i}] is not an object"
|
|
253
|
+
severity = issue.get("severity")
|
|
254
|
+
if severity not in _VALID_SEVERITIES:
|
|
255
|
+
return f"issues[{i}].severity={severity!r} not one of {sorted(_VALID_SEVERITIES)}"
|
|
256
|
+
if "summary" not in parsed:
|
|
257
|
+
return "summary field missing"
|
|
258
|
+
return None
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def _success(shape: str) -> dict:
|
|
262
|
+
return {"valid": True, "shape": shape, "extraction": shape, "error": None}
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def _schema_drift(extraction: str, error: str) -> dict:
|
|
266
|
+
return {"valid": False, "shape": SHAPE_SCHEMA_DRIFT, "extraction": extraction, "error": error}
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def _failure(shape: str, extraction: str | None, error: str) -> dict:
|
|
270
|
+
return {"valid": False, "shape": shape, "extraction": extraction, "error": error}
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def _try_parse(candidate: str, extraction: str) -> dict:
|
|
274
|
+
"""Parse and validate a recovered JSON-shaped candidate. ``candidate`` is
|
|
275
|
+
always a complete text span (a fenced code block's contents, or a
|
|
276
|
+
balanced ``{...}`` substring) — a ``json.loads`` failure here means the
|
|
277
|
+
JSON is malformed, not truncated (truncation is decided earlier, by
|
|
278
|
+
whether a balanced candidate was found at all)."""
|
|
279
|
+
try:
|
|
280
|
+
parsed = json.loads(candidate)
|
|
281
|
+
except json.JSONDecodeError as exc:
|
|
282
|
+
return _failure(SHAPE_MALFORMED_JSON, extraction, str(exc))
|
|
283
|
+
error = _validate_schema(parsed)
|
|
284
|
+
return _success(extraction) if error is None else _schema_drift(extraction, error)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def classify_and_validate(raw_text: str) -> dict:
|
|
288
|
+
"""Classify ``raw_text`` (an agent's raw final-turn text) against the
|
|
289
|
+
review-agent output contract.
|
|
290
|
+
|
|
291
|
+
Returns ``{"valid": bool, "shape": str, "extraction": str|None, "error":
|
|
292
|
+
str|None}``. Tries, in order: (1) a strict parse of the stripped text as
|
|
293
|
+
-is, (2) a fenced ```json code block, (3) the first balanced ``{...}``
|
|
294
|
+
object, tolerating a prose preamble or trailing prose. Each
|
|
295
|
+
successfully-recovered candidate is then checked against the contract's
|
|
296
|
+
required shape; a ``schema-drift`` or ``malformed-json`` failure carries
|
|
297
|
+
the ``extraction`` shape that recovered the candidate, rather than
|
|
298
|
+
discarding that information — including when the candidate came from a
|
|
299
|
+
fenced block that itself failed to parse (no further fallback is
|
|
300
|
+
attempted once a fence is found; a fence match requires a closing
|
|
301
|
+
delimiter, so its contents are a complete span, never a truncation). A
|
|
302
|
+
``{`` that never balances (in the fenceless path) is reported as
|
|
303
|
+
``truncated``; a balanced object that still fails to parse (unquoted
|
|
304
|
+
keys, a trailing comma, a Python-repr dict) is reported as
|
|
305
|
+
``malformed-json`` — distinct from ``truncated``, since the output
|
|
306
|
+
finished, it just wasn't valid JSON.
|
|
307
|
+
"""
|
|
308
|
+
stripped = raw_text.strip()
|
|
309
|
+
if not stripped:
|
|
310
|
+
return _failure(SHAPE_EMPTY, None, "output was empty or whitespace-only")
|
|
311
|
+
|
|
312
|
+
try:
|
|
313
|
+
parsed = json.loads(stripped)
|
|
314
|
+
except json.JSONDecodeError:
|
|
315
|
+
pass
|
|
316
|
+
else:
|
|
317
|
+
error = _validate_schema(parsed)
|
|
318
|
+
return _success(SHAPE_CLEAN) if error is None else _schema_drift(SHAPE_CLEAN, error)
|
|
319
|
+
|
|
320
|
+
fenced = _extract_fenced_json(stripped)
|
|
321
|
+
if fenced is not None:
|
|
322
|
+
return _try_parse(fenced, SHAPE_FENCED)
|
|
323
|
+
|
|
324
|
+
candidate, unbalanced = _find_first_json_object(stripped)
|
|
325
|
+
if candidate is not None:
|
|
326
|
+
extraction = SHAPE_CLEAN if candidate == stripped else SHAPE_PROSE_PREAMBLE
|
|
327
|
+
return _try_parse(candidate, extraction)
|
|
328
|
+
|
|
329
|
+
if unbalanced:
|
|
330
|
+
return _failure(SHAPE_TRUNCATED, None, "unbalanced braces — output likely truncated at a token limit")
|
|
331
|
+
|
|
332
|
+
return _failure(SHAPE_NOT_JSON, None, "no JSON object found in output")
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def _resolve_stream(cwd: Path, *, migrate: bool = True) -> Path:
|
|
336
|
+
if artifact_paths is not None:
|
|
337
|
+
return artifact_paths.resolve_file("metrics", _STREAM_NAME, cwd, migrate=migrate)
|
|
338
|
+
return cwd / ".claude" / "metrics" / _STREAM_NAME
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def _normalize_agent(agent: str) -> str:
|
|
342
|
+
"""Strip this plugin's own `dev-team:` dispatch qualifier so this
|
|
343
|
+
stream's `agent` field matches `boundary-events.jsonl`'s `matched_rule`
|
|
344
|
+
vocabulary — the field `contract_failure_report.py` joins against.
|
|
345
|
+
Without this, an orchestrator passing the real dispatch form
|
|
346
|
+
(`dev-team:<agent-name>`) silently produces a phantom agent with 0
|
|
347
|
+
dispatches and inflates the reported total-failure rate (same class of
|
|
348
|
+
bug #1461 found in the ledger hook itself)."""
|
|
349
|
+
if review_agent_registry is not None:
|
|
350
|
+
return review_agent_registry.strip_plugin_prefix(agent)
|
|
351
|
+
return agent
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def _safe_error(error: str) -> str:
|
|
355
|
+
"""Redact and cap a diagnostic ``error`` string before it is persisted or
|
|
356
|
+
printed. `_validate_schema` interpolates agent-controlled values (e.g.
|
|
357
|
+
``status={status!r}``) into this string, so — unlike a fixed-format
|
|
358
|
+
message — it can carry secret-shaped or unbounded content the same way
|
|
359
|
+
`raw_prefix` can; apply the same two controls here rather than leaving
|
|
360
|
+
this sibling field as the one channel that bypasses both."""
|
|
361
|
+
return _redact(str(error))[:_ERROR_MAX_LEN]
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
def build_failure_entry(agent: str, raw_text: str, diagnostic: dict, timestamp: str | None = None) -> dict:
|
|
365
|
+
"""Assemble one `contract-failures.jsonl` row. ``diagnostic`` must be a
|
|
366
|
+
non-valid result from `classify_and_validate`."""
|
|
367
|
+
if diagnostic.get("valid") or diagnostic.get("shape") not in FAILURE_SHAPES:
|
|
368
|
+
raise ValueError(
|
|
369
|
+
f"build_failure_entry requires a failing classify_and_validate() result, got {diagnostic!r}"
|
|
370
|
+
)
|
|
371
|
+
redacted = _redact(raw_text.strip())
|
|
372
|
+
return {
|
|
373
|
+
"timestamp": timestamp or _now_iso(),
|
|
374
|
+
"agent": _normalize_agent(agent),
|
|
375
|
+
"shape": diagnostic["shape"],
|
|
376
|
+
"extraction": diagnostic.get("extraction"),
|
|
377
|
+
"error": _safe_error(diagnostic["error"]),
|
|
378
|
+
"raw_prefix": redacted[:_RAW_PREFIX_LEN],
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
def log_failure(entry: dict, cwd: Path | None = None) -> Path | None:
|
|
383
|
+
"""Append one diagnostic row to `.claude/metrics/contract-failures.jsonl`.
|
|
384
|
+
|
|
385
|
+
Delegates to `atomic_state.append_line_locked` — the plugin's hardened,
|
|
386
|
+
symlink-safe, lock-serialized JSONL append (#1889) every other metrics
|
|
387
|
+
emitter in this plugin uses (`boundary_events.py`, `review_round_log.py`,
|
|
388
|
+
et al.) — rather than a bare `open(..., "a")`, which would reintroduce
|
|
389
|
+
the exact symlink-follow / unsynchronized-write gap #1889 closed
|
|
390
|
+
elsewhere. Passes `fail_open=False` so a write rejected inside the lock
|
|
391
|
+
(e.g. the O_NOFOLLOW check refusing a planted symlink) raises instead of
|
|
392
|
+
being silently swallowed there — this function's own `except Exception`
|
|
393
|
+
below is where fail-open is applied, so the swallowed case and the
|
|
394
|
+
successful case stay distinguishable and this docstring's contract
|
|
395
|
+
holds. A full disk or a read-only metrics directory must still never
|
|
396
|
+
fail a review. Returns the path written, or `None` when the write
|
|
397
|
+
failed or `hooks/lib` is unreachable.
|
|
398
|
+
"""
|
|
399
|
+
try:
|
|
400
|
+
base = cwd or Path.cwd()
|
|
401
|
+
log = _resolve_stream(base)
|
|
402
|
+
log.parent.mkdir(parents=True, exist_ok=True)
|
|
403
|
+
line = json.dumps(entry, separators=(",", ":"), sort_keys=True) + "\n"
|
|
404
|
+
if atomic_state is not None:
|
|
405
|
+
atomic_state.append_line_locked(log, line, fail_open=False)
|
|
406
|
+
else: # pragma: no cover - degraded fallback, hooks/lib unreachable
|
|
407
|
+
with open(log, "a", encoding="utf-8") as handle:
|
|
408
|
+
handle.write(line)
|
|
409
|
+
return log
|
|
410
|
+
except Exception: # noqa: BLE001 - fail-open: telemetry never blocks a review
|
|
411
|
+
return None
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
def main(argv=None) -> int:
|
|
415
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
416
|
+
parser.add_argument("--agent", required=True, help="Name of the review agent whose output is being validated")
|
|
417
|
+
parser.add_argument(
|
|
418
|
+
"--file",
|
|
419
|
+
required=True,
|
|
420
|
+
help="Path to the agent's raw final-turn text output; '-' for stdin",
|
|
421
|
+
)
|
|
422
|
+
parser.add_argument("--cwd", default=None)
|
|
423
|
+
parser.add_argument(
|
|
424
|
+
"--dry-run",
|
|
425
|
+
action="store_true",
|
|
426
|
+
help="Classify only; never write the failure diagnostic",
|
|
427
|
+
)
|
|
428
|
+
args = parser.parse_args(argv)
|
|
429
|
+
|
|
430
|
+
raw_text = sys.stdin.read() if args.file == "-" else Path(args.file).read_text(encoding="utf-8")
|
|
431
|
+
result = classify_and_validate(raw_text)
|
|
432
|
+
|
|
433
|
+
if not result["valid"] and not args.dry_run:
|
|
434
|
+
entry = build_failure_entry(args.agent, raw_text, result)
|
|
435
|
+
log_failure(entry, Path(args.cwd) if args.cwd else None)
|
|
436
|
+
|
|
437
|
+
printed = {"agent": _normalize_agent(args.agent), **result}
|
|
438
|
+
if not result["valid"]:
|
|
439
|
+
# SKILL.md step 4 carries this printed `error` forward, unmodified,
|
|
440
|
+
# into `dispatchFailures[].error` — sanitize it at the source so
|
|
441
|
+
# every downstream consumer (the report, the aggregate, the log)
|
|
442
|
+
# inherits the same redaction/cap `raw_prefix` gets, rather than
|
|
443
|
+
# relying on each consumer to re-apply it.
|
|
444
|
+
printed["error"] = _safe_error(result["error"])
|
|
445
|
+
print(json.dumps(printed, sort_keys=True))
|
|
446
|
+
return 0 if result["valid"] else 1
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
if __name__ == "__main__":
|
|
450
|
+
raise SystemExit(main(sys.argv[1:]))
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
__all__ = (
|
|
454
|
+
"FAILURE_SHAPES",
|
|
455
|
+
"SHAPE_CLEAN",
|
|
456
|
+
"SHAPE_EMPTY",
|
|
457
|
+
"SHAPE_FENCED",
|
|
458
|
+
"SHAPE_MALFORMED_JSON",
|
|
459
|
+
"SHAPE_NOT_JSON",
|
|
460
|
+
"SHAPE_PROSE_PREAMBLE",
|
|
461
|
+
"SHAPE_SCHEMA_DRIFT",
|
|
462
|
+
"SHAPE_TRUNCATED",
|
|
463
|
+
"SUCCESS_SHAPES",
|
|
464
|
+
"build_failure_entry",
|
|
465
|
+
"classify_and_validate",
|
|
466
|
+
"log_failure",
|
|
467
|
+
)
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# Sliced large-repo review
|
|
2
|
+
|
|
3
|
+
Orchestration reference for `/code-review`'s large-repo path. `SKILL.md` routes
|
|
4
|
+
here when sliced mode engages (see its Scope-validation step); the deterministic
|
|
5
|
+
work is done by `scripts/partition.py`, `scripts/activation.py`,
|
|
6
|
+
`scripts/ledger.py`, and `scripts/consolidate.py` — all unit-tested
|
|
7
|
+
(partition/activation/consolidate as pure functions; ledger against a temp root).
|
|
8
|
+
|
|
9
|
+
The design keeps orchestrator context **flat regardless of repo size**: each
|
|
10
|
+
slice is reviewed, its findings persisted to disk, and then dropped from context
|
|
11
|
+
— only a one-line tally is retained. A final consolidation pass reads the
|
|
12
|
+
persisted artifacts back and produces one deduplicated report.
|
|
13
|
+
|
|
14
|
+
## Terminology
|
|
15
|
+
|
|
16
|
+
**Slice** and **section** are the same unit. A *slice* is the in-flight review
|
|
17
|
+
unit; its persisted artifact on disk is `raw/section-<id>.json`, where `<id>` is
|
|
18
|
+
the slice id. An operator inspecting `.dev-team-reports/code-review/raw/` needs no
|
|
19
|
+
mental remapping — `section-<id>.json` is slice `<id>`.
|
|
20
|
+
|
|
21
|
+
## When sliced mode engages (activation)
|
|
22
|
+
|
|
23
|
+
Call `scripts/activation.py` → `should_slice(scope_kind, file_count, threshold,
|
|
24
|
+
slice_flag, no_slice_flag)`. It returns `(engage, cap)` with this precedence:
|
|
25
|
+
|
|
26
|
+
1. **`--no-slice`** always wins — never slice (legacy single pass).
|
|
27
|
+
2. **`--slice <N>`** always engages, cap `N` (a positive integer), at any size.
|
|
28
|
+
3. **Auto-engage** only when scope is full-repo **and** `file_count > threshold`
|
|
29
|
+
(the existing `>500` tier). Exactly at the threshold does not engage.
|
|
30
|
+
4. Otherwise do not slice.
|
|
31
|
+
|
|
32
|
+
Non-full-repo scopes (`--path`, `--since`, auto-scoped uncommitted changes)
|
|
33
|
+
never auto-engage — they run the legacy path unchanged, no matter how many files
|
|
34
|
+
match.
|
|
35
|
+
|
|
36
|
+
On engagement, report the slice count to the operator (e.g. `Sliced mode: N
|
|
37
|
+
slices`).
|
|
38
|
+
|
|
39
|
+
## Partitioning
|
|
40
|
+
|
|
41
|
+
Call `scripts/partition.py` → `partition_files(files, cap)`. Files are grouped by
|
|
42
|
+
directory (module boundary); a directory larger than `cap` splits across
|
|
43
|
+
consecutive slices; small sibling directories coalesce up to `cap`. Slice ids are
|
|
44
|
+
stable and deterministic — the same file set always partitions into the same ids
|
|
45
|
+
mapped to the same files, which is what makes `--resume` (below) safe.
|
|
46
|
+
|
|
47
|
+
After partitioning, call `activation.check_slice_ceiling(slice_count)`. When the
|
|
48
|
+
count is very high it returns an advisory warning suggesting a larger `--slice`
|
|
49
|
+
cap; report it and proceed (it never blocks).
|
|
50
|
+
|
|
51
|
+
## Per-slice review panel
|
|
52
|
+
|
|
53
|
+
Select each slice's review panel from its `is_declarative` flag (set by
|
|
54
|
+
`partition.py` → `is_declarative_slice`, a conservative name/extension
|
|
55
|
+
heuristic — any doubt yields non-declarative):
|
|
56
|
+
|
|
57
|
+
- **Declarative slice** (`is_declarative: true` — pure interface/type/DTO/
|
|
58
|
+
constant/model/schema/enum files, no behavioral tokens): run the **reduced
|
|
59
|
+
panel** — `correctness-review` and `structure-review` only. The six-lens
|
|
60
|
+
semantic panel is wasted on declaration files.
|
|
61
|
+
- **Non-declarative slice**: run the **full panel** — the standard agent
|
|
62
|
+
eligibility rules from `SKILL.md` steps 3–4 (self-declared `Scope:`,
|
|
63
|
+
framework reactivity lens, ai-provenance), scoped to the slice's files.
|
|
64
|
+
|
|
65
|
+
The exact declarative rule is owned by `partition.py`; this file does not
|
|
66
|
+
re-encode it. **Disclose the panel per slice**: record which panel ran in the
|
|
67
|
+
slice's section artifact (see the next section), and the consolidated report
|
|
68
|
+
names the slices that ran the reduced panel so a reader can tell "fewer
|
|
69
|
+
findings" from "fewer reviewers ran."
|
|
70
|
+
|
|
71
|
+
**Wave-bound the panel dispatch (issue #1762).** Before dispatching either
|
|
72
|
+
panel (reduced or full), compute its wave split via `dispatch_waves.py` —
|
|
73
|
+
the same `maxParallel` resolution the legacy path uses
|
|
74
|
+
(`DEV_TEAM_MAX_PARALLEL_REVIEW_AGENTS`, default 10; see `SKILL.md` Step 4):
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
sh "$CLAUDE_PLUGIN_ROOT/hooks/py.sh" "$CLAUDE_PLUGIN_ROOT/skills/code-review/scripts/dispatch_waves.py" --agents "<this slice's panel agent names, in order>"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Dispatch one wave at a time, waiting for each wave to fully return before
|
|
81
|
+
dispatching the next — same discipline as the legacy path. A reduced panel
|
|
82
|
+
(2 agents) never exceeds a single wave at the default cap; a full panel can,
|
|
83
|
+
on a slice with many eligible lens/framework agents.
|
|
84
|
+
|
|
85
|
+
## Persist-and-drop and the progress ledger
|
|
86
|
+
|
|
87
|
+
At the start of a sliced run, initialize the ledger from the partitioned slices:
|
|
88
|
+
`scripts/ledger.py` → `init_ledger(slices, cap, root)` writes
|
|
89
|
+
`.dev-team-reports/code-review/ledger.json` with every slice `pending` and the
|
|
90
|
+
partition cap recorded.
|
|
91
|
+
|
|
92
|
+
Review slices in **bounded parallelism — 2–3 slices at a time** (not the whole
|
|
93
|
+
repo at once). This slice-level concurrency heuristic is unchanged by the
|
|
94
|
+
panel-level wave cap above — the two bound different things: how many slices
|
|
95
|
+
are in flight at once, versus how many agents one slice's own panel dispatches
|
|
96
|
+
in a single message.
|
|
97
|
+
|
|
98
|
+
For each slice, once its panel's waves (per the section above) return:
|
|
99
|
+
|
|
100
|
+
1. **Reconcile dispatched vs. returned, per wave**: determine each agent's
|
|
101
|
+
contract-valid status the same deterministic way as the legacy path
|
|
102
|
+
(`SKILL.md` Step 4's `validate_review_output.py` call, #1998) — never by
|
|
103
|
+
eyeballing the raw output — then feed the resulting `--returned` set to
|
|
104
|
+
`dispatch_reconcile.py`, the same CLI as the legacy path, scoped to this
|
|
105
|
+
slice's dispatched agents for that wave:
|
|
106
|
+
```bash
|
|
107
|
+
sh "$CLAUDE_PLUGIN_ROOT/hooks/py.sh" "$CLAUDE_PLUGIN_ROOT/skills/code-review/scripts/dispatch_reconcile.py" --dispatched "<this wave's dispatched agent names>" --returned "<this wave's contract-valid agent names>"
|
|
108
|
+
```
|
|
109
|
+
Every name in the resulting `"missing"` array is a dispatch failure for
|
|
110
|
+
this slice's current wave.
|
|
111
|
+
2. **Retry once per agent**: retry each missing agent exactly once,
|
|
112
|
+
individually — same policy as `SKILL.md` Step 4, see there for rationale.
|
|
113
|
+
A recovered dispatch (fails once, retry succeeds) writes an empty
|
|
114
|
+
`dispatchFailures` list and emits no boundary event, mirroring the legacy
|
|
115
|
+
path's own guarantee. **Accumulate unrecovered failures across every wave
|
|
116
|
+
of this slice's panel** (a panel can span more than one wave when it's
|
|
117
|
+
larger than `maxParallel` — see the section above): a wave-1 failure is
|
|
118
|
+
never dropped just because wave 2 returned cleanly — carry the running
|
|
119
|
+
list forward and pass the union to step 3, once, after the slice's last
|
|
120
|
+
wave returns.
|
|
121
|
+
3. **Persist** its findings: `write_section`'s CLI (`ledger.py write-section`)
|
|
122
|
+
writes `raw/section-<id>.json` (findings + the panel that ran) and flips
|
|
123
|
+
the slice's ledger status to `done`. Pass `--dispatch-failures` with the
|
|
124
|
+
slice's still-unrecovered failures, accumulated across all its waves —
|
|
125
|
+
an empty list (or the flag omitted) when every agent recovered on retry.
|
|
126
|
+
Each entry has the same shape as the legacy path's `dispatchFailures`
|
|
127
|
+
entries (`output-format.md`): `{"agentName": "<name>", "attempts": 2,
|
|
128
|
+
"error": "<message>", "shape": "<shape or null>", "extraction": "<extraction
|
|
129
|
+
or null>"}` — never a different key for the agent name.
|
|
130
|
+
4. **Emit the boundary event for each unrecovered failure**: at the same
|
|
131
|
+
moment step 3 records the failure, emit the `dispatch-failure` boundary
|
|
132
|
+
event (Slice 1's shared CLI), bound to the `subject_hash` in effect for
|
|
133
|
+
that slice's dispatch (the cosmetic-delta carry-forward lens this used to
|
|
134
|
+
also bind a normalized hash for was specific to the retired commit-time
|
|
135
|
+
gate and was deleted in #1904 — sliced mode never wrote that gate file to
|
|
136
|
+
begin with, so the normalized hash never had a consumer on this path):
|
|
137
|
+
```bash
|
|
138
|
+
HASH=$(python3 "${CLAUDE_PLUGIN_ROOT}/hooks/lib/review_gate_hash.py" --branch-diff)
|
|
139
|
+
python3 "${CLAUDE_PLUGIN_ROOT}/hooks/lib/boundary_events.py" --event dispatch-failure --agent "<name>" --subject-hash "$HASH"
|
|
140
|
+
```
|
|
141
|
+
5. **Drop** the findings from orchestrator context. **Retain only a one-line tally per slice** — e.g. `section-0001: 3 findings (1 error, 2 warnings)`. This
|
|
142
|
+
is the move that keeps context flat regardless of repo size: never hold more
|
|
143
|
+
than the tallies plus the slices currently in flight.
|
|
144
|
+
6. **Report progress**: emit `slice k of N done` as each slice completes, so a
|
|
145
|
+
long monorepo run is observably advancing.
|
|
146
|
+
|
|
147
|
+
If the run is interrupted, the ledger and the already-written section artifacts
|
|
148
|
+
remain on disk and stay valid. Tell the operator the review is incomplete and
|
|
149
|
+
can be continued: **rerun with `--resume`** to review only the remaining slices.
|
|
150
|
+
|
|
151
|
+
## Resuming an interrupted run
|
|
152
|
+
|
|
153
|
+
When `--resume` is given, do **not** re-initialize the ledger. Instead:
|
|
154
|
+
|
|
155
|
+
1. **Guard the cap**: call `ledger.py` → `check_resume_cap(root, cap)`. If the
|
|
156
|
+
`--slice` cap differs from the cap the interrupted run recorded in the
|
|
157
|
+
ledger, **stop with that error** — repartitioning at a different cap would
|
|
158
|
+
desync the new slice ids from the `section-<id>.json` files already on disk.
|
|
159
|
+
Rerun with the recorded cap (or no `--slice`), or start fresh.
|
|
160
|
+
2. **Review only the pending slices**: `pending_slices(slices, root)` returns
|
|
161
|
+
the slices needing (re-)review. A slice whose `section-<id>.json` does not
|
|
162
|
+
yet exist is pending, same as before — **and, as of issue #1762, a slice
|
|
163
|
+
whose artifact already exists but carries a non-empty `dispatchFailures`
|
|
164
|
+
list is also pending**: it is **not** treated as done on `--resume`; its
|
|
165
|
+
panel is re-dispatched, same as a slice with no artifact at all, so the
|
|
166
|
+
previously-failed agent(s) get a real chance to produce a superseding
|
|
167
|
+
result, per the retry-once policy in `SKILL.md`'s "Dispatch failure
|
|
168
|
+
handling" (Step 4) — see there for the full mechanics, not restated here.
|
|
169
|
+
Every other slice keeps today's rule unchanged: an artifact
|
|
170
|
+
exists with an empty `dispatchFailures` list is skipped and reused as-is
|
|
171
|
+
— disk is the source of truth (a slice with a clean artifact is done even
|
|
172
|
+
if the ledger still says `pending`).
|
|
173
|
+
3. Consolidation (below) reads **all** section artifacts — the ones reused from
|
|
174
|
+
the prior run and the ones this resume produced.
|
|
175
|
+
|
|
176
|
+
Without `--resume`, a fresh sliced run re-initializes the ledger and reviews
|
|
177
|
+
every slice.
|
|
178
|
+
|
|
179
|
+
## Consolidation
|
|
180
|
+
|
|
181
|
+
Once every slice has a section artifact (a fresh run's full set, or a
|
|
182
|
+
`--resume` run's reused + newly-written set), consolidate:
|
|
183
|
+
|
|
184
|
+
1. Run `scripts/consolidate.py` (its `main()` reads every
|
|
185
|
+
`raw/section-*.json`) → the consolidated aggregate (schema in
|
|
186
|
+
[`output-format.md`](output-format.md#consolidated-aggregate-sliced-mode)):
|
|
187
|
+
findings **deduped by `file:line`** with reporting agents merged, a
|
|
188
|
+
**recurring-theme rollup** (dimensions recurring across ≥2 slices), and the
|
|
189
|
+
`reducedPanelSlices` disclosure. A malformed artifact is reported by name,
|
|
190
|
+
never silently dropped.
|
|
191
|
+
2. Apply `ACCEPTED-RISKS.md` at this consolidation step exactly as the
|
|
192
|
+
legacy path does (SKILL.md step 5a) — suppression happens once, over the
|
|
193
|
+
merged findings.
|
|
194
|
+
|
|
195
|
+
**Report-only.** Sliced mode does **not** run the interactive review-fix loop.
|
|
196
|
+
It is a reporting/consolidation pass:
|
|
197
|
+
|
|
198
|
+
- Write the consolidated prose report to `.dev-team-reports/code-review.md` and
|
|
199
|
+
per-issue correction prompts to `./corrections/` (for `/apply-fixes` to act
|
|
200
|
+
on later). Both paths are repo-relative to the target repo's working
|
|
201
|
+
directory.
|
|
202
|
+
- In `--json` mode, emit the single consolidated aggregate object to **stdout**
|
|
203
|
+
and write **no** file — the existing `--json` contract (SKILL.md step 7),
|
|
204
|
+
now carrying the consolidated `topFindings` / `recurringThemes` /
|
|
205
|
+
`reducedPanelSlices`.
|