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,306 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""gherkin_analysis_coverage_gate.py — flag a surface inventory whose
|
|
3
|
+
required-category section skips a required category.
|
|
4
|
+
|
|
5
|
+
Originally built for `gherkin-derive/SKILL.md` Step 2's mandatory in-depth
|
|
6
|
+
codebase analysis (issue #1450): every run must explicitly analyze
|
|
7
|
+
controllers, handlers, services, domain logic, workflows, validation rules,
|
|
8
|
+
error handling, and business processes — not just enumerate registered entry
|
|
9
|
+
points. Step 5 requires the resulting surface inventory (`gherkin.md`) to
|
|
10
|
+
record what was found (or explicitly "none found") for each of those eight
|
|
11
|
+
categories under a `## Analysis Coverage` (H2) heading, so a run that
|
|
12
|
+
silently skipped one is detectable rather than merely asserted.
|
|
13
|
+
|
|
14
|
+
Generalized (issue #1464) so the same three-way exit contract and
|
|
15
|
+
"missing vs. did-not-run" distinction serve a second caller,
|
|
16
|
+
`cd-test-architecture/SKILL.md` Step 1's own mandatory exhaustive
|
|
17
|
+
surface-type discovery, which records its search under a `### Components &
|
|
18
|
+
patterns` (H3) heading with its own eight component-pattern categories (UI,
|
|
19
|
+
API Provider, API Consumer, Event Consumer, Event Producer, Stateful
|
|
20
|
+
Service, CLI-Library, Scheduled Job). The heading level, section-header
|
|
21
|
+
string, and category list are now parameters (a small named-configuration
|
|
22
|
+
table, selected via `--config`) rather than hardcoded — the gherkin-derive
|
|
23
|
+
shape remains the default so its existing behavior is unchanged.
|
|
24
|
+
|
|
25
|
+
Expected inventory shape — an H-level heading (matching `--config`'s
|
|
26
|
+
`heading_level`) with one bullet per category, bold-labelled:
|
|
27
|
+
|
|
28
|
+
## Analysis Coverage
|
|
29
|
+
|
|
30
|
+
- **Controllers**: <findings, or "none found in this codebase">
|
|
31
|
+
- **Handlers**: ...
|
|
32
|
+
- **Services**: ...
|
|
33
|
+
- **Domain logic**: ...
|
|
34
|
+
- **Workflows**: ...
|
|
35
|
+
- **Validation rules**: ...
|
|
36
|
+
- **Error handling**: ...
|
|
37
|
+
- **Business processes**: ...
|
|
38
|
+
|
|
39
|
+
Mirrors `gherkin_failure_path_gate.py`'s shape: a deterministic, best-effort
|
|
40
|
+
heuristic over the inventory's own text — not a semantic classifier. A
|
|
41
|
+
category heading present with no non-placeholder content after the colon is
|
|
42
|
+
treated as a gap, identical to an absent heading; only literal presence of
|
|
43
|
+
real content (found items, or an explicit "none found" statement) satisfies
|
|
44
|
+
a category.
|
|
45
|
+
|
|
46
|
+
The "did not run" exit (2) covers three distinct shapes, all disjoint from
|
|
47
|
+
"nothing missing" (0) and "some categories missing" (1): the target file
|
|
48
|
+
is absent, the heading itself is absent, or the heading is present but has
|
|
49
|
+
zero recognized category rows beneath it at all (a stub section, never
|
|
50
|
+
actually filled in — a different claim than "N of the required categories
|
|
51
|
+
are genuinely missing").
|
|
52
|
+
|
|
53
|
+
Stdlib-only. (ADR 0014/0015).
|
|
54
|
+
|
|
55
|
+
Usage:
|
|
56
|
+
python3 gherkin_analysis_coverage_gate.py --file <path/to/gherkin.md> [--json]
|
|
57
|
+
python3 gherkin_analysis_coverage_gate.py --file <path/to/report.md> \\
|
|
58
|
+
--config cd-test-architecture [--json]
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
from __future__ import annotations
|
|
62
|
+
|
|
63
|
+
import argparse
|
|
64
|
+
import json
|
|
65
|
+
import re
|
|
66
|
+
import sys
|
|
67
|
+
from dataclasses import dataclass
|
|
68
|
+
from pathlib import Path
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass(frozen=True)
|
|
72
|
+
class GateConfig:
|
|
73
|
+
"""One named configuration: which heading level and section title the
|
|
74
|
+
gate looks for, and which categories are required beneath it."""
|
|
75
|
+
|
|
76
|
+
name: str
|
|
77
|
+
heading_level: int
|
|
78
|
+
section_name: str
|
|
79
|
+
categories: tuple[str, ...]
|
|
80
|
+
# Adjective inserted before "categor(y/ies)" in the CLI's human-readable
|
|
81
|
+
# FAIL/OK messages (e.g. "analysis categories", "component-pattern
|
|
82
|
+
# categories") — kept per-config so gherkin-derive's existing message
|
|
83
|
+
# wording ("analysis categor(y/ies)") stays byte-for-byte unchanged.
|
|
84
|
+
category_kind: str = "analysis"
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# Canonical eight categories named by gherkin-derive/SKILL.md Step 2 — kept
|
|
88
|
+
# here as the single source of truth so this gate's required-category list
|
|
89
|
+
# can never drift from what it enforces. Step 2/Step 5's prose names these
|
|
90
|
+
# verbatim (issue #1450); a future category addition/rename updates this
|
|
91
|
+
# tuple and the SKILL.md wording together, not independently.
|
|
92
|
+
_REQUIRED_CATEGORIES = (
|
|
93
|
+
"controllers",
|
|
94
|
+
"handlers",
|
|
95
|
+
"services",
|
|
96
|
+
"domain logic",
|
|
97
|
+
"workflows",
|
|
98
|
+
"validation rules",
|
|
99
|
+
"error handling",
|
|
100
|
+
"business processes",
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
GHERKIN_DERIVE_CONFIG = GateConfig(
|
|
104
|
+
name="gherkin-derive",
|
|
105
|
+
heading_level=2,
|
|
106
|
+
section_name="Analysis Coverage",
|
|
107
|
+
categories=_REQUIRED_CATEGORIES,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
# The eight component-pattern categories named by
|
|
111
|
+
# `cd-test-architecture/SKILL.md` Step 1 / `component-test-patterns.md`
|
|
112
|
+
# (issue #1464) — kept here as the single source of truth, same rationale
|
|
113
|
+
# as `_REQUIRED_CATEGORIES` above.
|
|
114
|
+
_CD_TEST_ARCHITECTURE_CATEGORIES = (
|
|
115
|
+
"ui",
|
|
116
|
+
"api provider",
|
|
117
|
+
"api consumer",
|
|
118
|
+
"event consumer",
|
|
119
|
+
"event producer",
|
|
120
|
+
"stateful service",
|
|
121
|
+
"cli-library",
|
|
122
|
+
"scheduled job",
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
CD_TEST_ARCHITECTURE_CONFIG = GateConfig(
|
|
126
|
+
name="cd-test-architecture",
|
|
127
|
+
heading_level=3,
|
|
128
|
+
section_name="Components & patterns",
|
|
129
|
+
categories=_CD_TEST_ARCHITECTURE_CATEGORIES,
|
|
130
|
+
category_kind="component-pattern",
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
_CONFIGS = {c.name: c for c in (GHERKIN_DERIVE_CONFIG, CD_TEST_ARCHITECTURE_CONFIG)}
|
|
134
|
+
|
|
135
|
+
# Exit codes: a three-way contract, not a boolean. 2 ("gate did not run")
|
|
136
|
+
# is distinct from 0 (all clear) — a missing file or absent section must
|
|
137
|
+
# never be silently read as "nothing missing."
|
|
138
|
+
EXIT_OK = 0
|
|
139
|
+
EXIT_MISSING_CATEGORIES = 1
|
|
140
|
+
EXIT_GATE_DID_NOT_RUN = 2
|
|
141
|
+
|
|
142
|
+
_ANY_HEADING = re.compile(r"^#{1,6}\s+")
|
|
143
|
+
# A bullet naming a category: "- **<label>**: <content>" (content optional —
|
|
144
|
+
# an empty/placeholder tail is a gap, checked separately from the match).
|
|
145
|
+
_BULLET = re.compile(r"^[-*]\s*\*\*(?P<label>[^*]+)\*\*\s*:\s*(?P<content>.*)$")
|
|
146
|
+
|
|
147
|
+
# Placeholder tails that read as "not actually filled in" even though a
|
|
148
|
+
# bullet line exists — an angle-bracket template token, or nothing at all.
|
|
149
|
+
_PLACEHOLDER = re.compile(r"^<.*>$")
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _section_heading_pattern(config: GateConfig) -> re.Pattern:
|
|
153
|
+
"""Build the heading regex for `config`. The exact heading level is a
|
|
154
|
+
real match constraint, not a hardcoded `##`: `#{level}` followed
|
|
155
|
+
immediately by required whitespace means a line with more or fewer
|
|
156
|
+
leading `#` characters never matches (e.g. `#{2}\\s+` cannot match
|
|
157
|
+
`### Foo` — the character after the second `#` is another `#`, not
|
|
158
|
+
whitespace), so an H3 config never silently matches an H2 heading or
|
|
159
|
+
vice versa."""
|
|
160
|
+
return re.compile(
|
|
161
|
+
rf"^#{{{config.heading_level}}}\s+{re.escape(config.section_name)}\s*$",
|
|
162
|
+
re.IGNORECASE,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def _heading_markup(config: GateConfig) -> str:
|
|
167
|
+
return f"{'#' * config.heading_level} {config.section_name}"
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def find_analysis_coverage_section(
|
|
171
|
+
text: str, config: GateConfig = GHERKIN_DERIVE_CONFIG
|
|
172
|
+
) -> str | None:
|
|
173
|
+
"""Return the body text of `config`'s section (between its heading and
|
|
174
|
+
the next heading of any level, or EOF), or None if no such heading
|
|
175
|
+
exists."""
|
|
176
|
+
heading_re = _section_heading_pattern(config)
|
|
177
|
+
lines = text.splitlines()
|
|
178
|
+
start = None
|
|
179
|
+
for i, line in enumerate(lines):
|
|
180
|
+
if heading_re.match(line.strip()):
|
|
181
|
+
start = i + 1
|
|
182
|
+
break
|
|
183
|
+
if start is None:
|
|
184
|
+
return None
|
|
185
|
+
end = len(lines)
|
|
186
|
+
for i in range(start, len(lines)):
|
|
187
|
+
if _ANY_HEADING.match(lines[i].strip()):
|
|
188
|
+
end = i
|
|
189
|
+
break
|
|
190
|
+
return "\n".join(lines[start:end])
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def parse_category_bullets(section_text: str) -> dict:
|
|
194
|
+
"""Return {lowercased label: content} for every `- **label**: content`
|
|
195
|
+
bullet in `section_text`. Later bullets with the same (lowercased) label
|
|
196
|
+
overwrite earlier ones — the inventory is expected to list each category
|
|
197
|
+
once; a duplicate is a content problem for the author, not this gate."""
|
|
198
|
+
entries: dict = {}
|
|
199
|
+
for line in section_text.splitlines():
|
|
200
|
+
match = _BULLET.match(line.strip())
|
|
201
|
+
if match:
|
|
202
|
+
entries[match.group("label").strip().lower()] = match.group(
|
|
203
|
+
"content"
|
|
204
|
+
).strip()
|
|
205
|
+
return entries
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def _is_empty_or_placeholder(content: str) -> bool:
|
|
209
|
+
return content == "" or bool(_PLACEHOLDER.match(content))
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def find_missing_categories(
|
|
213
|
+
entries: dict, config: GateConfig = GHERKIN_DERIVE_CONFIG
|
|
214
|
+
) -> list:
|
|
215
|
+
"""Return the required categories (in canonical order) that are absent
|
|
216
|
+
from `entries`, or present but empty/placeholder."""
|
|
217
|
+
missing = []
|
|
218
|
+
for category in config.categories:
|
|
219
|
+
content = entries.get(category)
|
|
220
|
+
if content is None or _is_empty_or_placeholder(content):
|
|
221
|
+
missing.append(category)
|
|
222
|
+
return missing
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def _gate_did_not_run(message: str, as_json: bool) -> int:
|
|
226
|
+
"""Print `message` (JSON or WARN-prefixed text) and return the shared
|
|
227
|
+
exit-2 outcome — the file-not-found and no-section-found guard clauses
|
|
228
|
+
are otherwise identical except for this string."""
|
|
229
|
+
if as_json:
|
|
230
|
+
print(json.dumps({"missing": [], "warning": message}, indent=2))
|
|
231
|
+
else:
|
|
232
|
+
print(f"WARN: {message}")
|
|
233
|
+
return EXIT_GATE_DID_NOT_RUN
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def main(argv: list | None = None) -> int:
|
|
237
|
+
parser = argparse.ArgumentParser(
|
|
238
|
+
prog="gherkin_analysis_coverage_gate.py",
|
|
239
|
+
description=(
|
|
240
|
+
"Flag a surface inventory whose required-category section "
|
|
241
|
+
"skips a required category."
|
|
242
|
+
),
|
|
243
|
+
)
|
|
244
|
+
parser.add_argument("--file", dest="file", type=Path, required=True)
|
|
245
|
+
parser.add_argument(
|
|
246
|
+
"--config",
|
|
247
|
+
dest="config",
|
|
248
|
+
choices=sorted(_CONFIGS),
|
|
249
|
+
default=GHERKIN_DERIVE_CONFIG.name,
|
|
250
|
+
help=(
|
|
251
|
+
"Named gate configuration (heading level, section header, "
|
|
252
|
+
"category list). Defaults to gherkin-derive's existing "
|
|
253
|
+
"'## Analysis Coverage' / 8-category shape."
|
|
254
|
+
),
|
|
255
|
+
)
|
|
256
|
+
parser.add_argument("--json", action="store_true")
|
|
257
|
+
args = parser.parse_args(argv)
|
|
258
|
+
|
|
259
|
+
config = _CONFIGS[args.config]
|
|
260
|
+
|
|
261
|
+
if not args.file.is_file():
|
|
262
|
+
return _gate_did_not_run(f"{args.file} not found — gate did not run", args.json)
|
|
263
|
+
|
|
264
|
+
text = args.file.read_text(encoding="utf-8", errors="replace")
|
|
265
|
+
section_text = find_analysis_coverage_section(text, config)
|
|
266
|
+
|
|
267
|
+
if section_text is None:
|
|
268
|
+
return _gate_did_not_run(
|
|
269
|
+
f"no '{_heading_markup(config)}' section found in {args.file} — gate did not run",
|
|
270
|
+
args.json,
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
entries = parse_category_bullets(section_text)
|
|
274
|
+
|
|
275
|
+
# A heading with zero recognized category rows beneath it (issue
|
|
276
|
+
# #1464) is a third "did not run" shape, distinct from "some
|
|
277
|
+
# categories missing": a section that was never filled in at all
|
|
278
|
+
# (e.g. a stub heading left over from a template) is not the same
|
|
279
|
+
# claim as "N of 8 categories genuinely absent" — the former means no
|
|
280
|
+
# search was recorded, the latter means a partial one was.
|
|
281
|
+
if not entries:
|
|
282
|
+
return _gate_did_not_run(
|
|
283
|
+
f"'{_heading_markup(config)}' section in {args.file} has no category rows — gate did not run",
|
|
284
|
+
args.json,
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
missing = find_missing_categories(entries, config)
|
|
288
|
+
|
|
289
|
+
if args.json:
|
|
290
|
+
print(json.dumps({"missing": missing}, indent=2))
|
|
291
|
+
return EXIT_MISSING_CATEGORIES if missing else EXIT_OK
|
|
292
|
+
|
|
293
|
+
if missing:
|
|
294
|
+
print(
|
|
295
|
+
f"FAIL: {len(missing)} {config.category_kind} categor{'y' if len(missing) == 1 else 'ies'} missing from the coverage record:"
|
|
296
|
+
)
|
|
297
|
+
for category in missing:
|
|
298
|
+
print(f" - {category}")
|
|
299
|
+
return EXIT_MISSING_CATEGORIES
|
|
300
|
+
|
|
301
|
+
print(f"OK: all {len(config.categories)} {config.category_kind} categories recorded.")
|
|
302
|
+
return EXIT_OK
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
if __name__ == "__main__": # pragma: no cover
|
|
306
|
+
sys.exit(main())
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""gherkin_cross_feature_duplicate_titles_gate.py — flag a scenario title that
|
|
3
|
+
appears under two or more distinct Feature: blocks (issue #1526).
|
|
4
|
+
|
|
5
|
+
Mirrors `gherkin_failure_path_gate.py`'s shape: scans `.feature` files under
|
|
6
|
+
one or more directories, parses each `Feature:` block's scenario titles (with
|
|
7
|
+
each scenario's own line number), and flags any title that recurs under more
|
|
8
|
+
than one distinct Feature title. A title repeated multiple times under the
|
|
9
|
+
*same* Feature title is out of scope here — that is
|
|
10
|
+
`gherkin_feature_merge.py`'s own within-file merge-dedup concern (issue
|
|
11
|
+
#1420), already handled there. This gate exists because a generic,
|
|
12
|
+
surface-agnostic scenario title (e.g. "returns error for invalid input") can
|
|
13
|
+
collide across two unrelated endpoints/surfaces; `gherkin_feature_merge.py`'s
|
|
14
|
+
dedup only ever compares titles *within* the Feature block it is merging
|
|
15
|
+
into, so a cross-file collision like this is otherwise invisible until a
|
|
16
|
+
human notices two features documenting "the same" scenario.
|
|
17
|
+
|
|
18
|
+
Stdlib-only. (ADR 0014/0015).
|
|
19
|
+
|
|
20
|
+
Usage:
|
|
21
|
+
python3 gherkin_cross_feature_duplicate_titles_gate.py --dir <dir> [--dir <dir> ...] [--json]
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import argparse
|
|
27
|
+
import json
|
|
28
|
+
import sys
|
|
29
|
+
from collections import defaultdict
|
|
30
|
+
from pathlib import Path
|
|
31
|
+
|
|
32
|
+
_HERE = Path(__file__).resolve().parent
|
|
33
|
+
sys.path.insert(0, str(_HERE / "lib"))
|
|
34
|
+
|
|
35
|
+
from _gherkin_text import FEATURE_PREFIX as _FEATURE_PREFIX
|
|
36
|
+
from _gherkin_text import SCENARIO_OUTLINE_PREFIX as _SCENARIO_OUTLINE_PREFIX
|
|
37
|
+
from _gherkin_text import SCENARIO_PREFIX as _SCENARIO_PREFIX
|
|
38
|
+
from _gherkin_text import safe_for_terminal as _safe_for_terminal
|
|
39
|
+
from _gherkin_text import stripped as _stripped
|
|
40
|
+
from _gherkin_text import trim_trailing_tag_run as _trim_trailing_tag_run
|
|
41
|
+
from _vendored_tree import find_files as _find_files
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def find_feature_files(directories: list) -> list:
|
|
45
|
+
"""Return every `.feature` file under `directories`, pruning vendored
|
|
46
|
+
trees, sorted for deterministic output."""
|
|
47
|
+
return _find_files(directories, lambda path: path.suffix == ".feature")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def parse_scenario_locations(text: str, path) -> list:
|
|
51
|
+
"""Return one entry per `Scenario:`/`Scenario Outline:` line across every
|
|
52
|
+
`Feature:` block in `text`: {file, feature_title, scenario_title, line}.
|
|
53
|
+
`line` is the scenario's own 1-based line number (not the enclosing
|
|
54
|
+
Feature block's), since the report needs to point at the exact
|
|
55
|
+
colliding line, not just the block it lives in."""
|
|
56
|
+
lines = text.splitlines(keepends=True)
|
|
57
|
+
header_indices = [
|
|
58
|
+
i for i, line in enumerate(lines) if _stripped(line).strip().startswith(_FEATURE_PREFIX)
|
|
59
|
+
]
|
|
60
|
+
entries = []
|
|
61
|
+
for idx, header_index in enumerate(header_indices):
|
|
62
|
+
feature_title = _stripped(lines[header_index]).strip()[len(_FEATURE_PREFIX) :].strip()
|
|
63
|
+
end_index = header_indices[idx + 1] if idx + 1 < len(header_indices) else len(lines)
|
|
64
|
+
end_index = _trim_trailing_tag_run(lines, header_index, end_index)
|
|
65
|
+
for line_index in range(header_index + 1, end_index):
|
|
66
|
+
stripped = _stripped(lines[line_index]).strip()
|
|
67
|
+
if stripped.startswith(_SCENARIO_OUTLINE_PREFIX):
|
|
68
|
+
title = stripped[len(_SCENARIO_OUTLINE_PREFIX) :].strip()
|
|
69
|
+
elif stripped.startswith(_SCENARIO_PREFIX):
|
|
70
|
+
title = stripped[len(_SCENARIO_PREFIX) :].strip()
|
|
71
|
+
else:
|
|
72
|
+
continue
|
|
73
|
+
entries.append(
|
|
74
|
+
{
|
|
75
|
+
"file": str(path),
|
|
76
|
+
"feature_title": feature_title,
|
|
77
|
+
"scenario_title": title,
|
|
78
|
+
"line": line_index + 1,
|
|
79
|
+
}
|
|
80
|
+
)
|
|
81
|
+
return entries
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def find_cross_feature_duplicates(entries: list) -> list:
|
|
85
|
+
"""Group `entries` by scenario title; return one finding per title that
|
|
86
|
+
appears under 2+ *distinct* Feature titles: {scenario_title,
|
|
87
|
+
occurrences: [{feature_title, file, line}, ...]}. A title repeated only
|
|
88
|
+
under one Feature title (any number of times) is not a finding — that is
|
|
89
|
+
gherkin_feature_merge.py's own within-file dedup concern, out of scope
|
|
90
|
+
here."""
|
|
91
|
+
by_title = defaultdict(list)
|
|
92
|
+
for entry in entries:
|
|
93
|
+
by_title[entry["scenario_title"]].append(entry)
|
|
94
|
+
|
|
95
|
+
findings = []
|
|
96
|
+
for title, occurrences in by_title.items():
|
|
97
|
+
if len({o["feature_title"] for o in occurrences}) < 2:
|
|
98
|
+
continue
|
|
99
|
+
findings.append(
|
|
100
|
+
{
|
|
101
|
+
"scenario_title": title,
|
|
102
|
+
"occurrences": [
|
|
103
|
+
{
|
|
104
|
+
"feature_title": o["feature_title"],
|
|
105
|
+
"file": o["file"],
|
|
106
|
+
"line": o["line"],
|
|
107
|
+
}
|
|
108
|
+
for o in occurrences
|
|
109
|
+
],
|
|
110
|
+
}
|
|
111
|
+
)
|
|
112
|
+
findings.sort(key=lambda f: f["scenario_title"])
|
|
113
|
+
return findings
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def main(argv: list | None = None) -> int:
|
|
117
|
+
parser = argparse.ArgumentParser(
|
|
118
|
+
prog="gherkin_cross_feature_duplicate_titles_gate.py",
|
|
119
|
+
description="Flag a scenario title duplicated across distinct Feature: blocks.",
|
|
120
|
+
)
|
|
121
|
+
parser.add_argument("--dir", dest="dirs", action="append", type=Path, required=True)
|
|
122
|
+
parser.add_argument("--json", action="store_true")
|
|
123
|
+
args = parser.parse_args(argv)
|
|
124
|
+
|
|
125
|
+
files = find_feature_files(args.dirs)
|
|
126
|
+
|
|
127
|
+
if not files:
|
|
128
|
+
# Mirrors gherkin_failure_path_gate.py's identical decision: a --dir
|
|
129
|
+
# that resolves to zero .feature files must say so distinctly, not
|
|
130
|
+
# report an affirmative all-clear for zero evidence scanned.
|
|
131
|
+
dirs_display = ", ".join(str(d) for d in args.dirs)
|
|
132
|
+
message = f"no .feature files found under {dirs_display} — gate did not run"
|
|
133
|
+
if args.json:
|
|
134
|
+
print(json.dumps({"scanned": [], "findings": [], "warning": message}, indent=2))
|
|
135
|
+
else:
|
|
136
|
+
# --dir is composed by gherkin-derive from a probe of the target
|
|
137
|
+
# repo, not always typed by a human — the same untrusted-path
|
|
138
|
+
# class as a scanned file's path, sanitized the same way.
|
|
139
|
+
print(f"WARN: no .feature files found under {_safe_for_terminal(dirs_display)} — gate did not run")
|
|
140
|
+
return 2
|
|
141
|
+
|
|
142
|
+
all_entries = []
|
|
143
|
+
for path in files:
|
|
144
|
+
text = path.read_text(encoding="utf-8", errors="replace")
|
|
145
|
+
all_entries.extend(parse_scenario_locations(text, path))
|
|
146
|
+
|
|
147
|
+
findings = find_cross_feature_duplicates(all_entries)
|
|
148
|
+
|
|
149
|
+
if args.json:
|
|
150
|
+
print(json.dumps({"scanned": [str(f) for f in files], "findings": findings}, indent=2))
|
|
151
|
+
return 1 if findings else 0
|
|
152
|
+
|
|
153
|
+
if findings:
|
|
154
|
+
print(f"FAIL: {len(findings)} scenario title(s) duplicated across distinct Feature blocks:")
|
|
155
|
+
for finding in findings:
|
|
156
|
+
title = _safe_for_terminal(finding["scenario_title"])
|
|
157
|
+
locations = " and ".join(
|
|
158
|
+
f"{_safe_for_terminal(o['feature_title'])} "
|
|
159
|
+
f"({_safe_for_terminal(o['file'])}:{o['line']})"
|
|
160
|
+
for o in finding["occurrences"]
|
|
161
|
+
)
|
|
162
|
+
print(f" - \"{title}\" appears in {locations}")
|
|
163
|
+
return 1
|
|
164
|
+
|
|
165
|
+
print(
|
|
166
|
+
f"OK: {len(all_entries)} scenario(s) scanned, "
|
|
167
|
+
"no title is duplicated across distinct Feature blocks."
|
|
168
|
+
)
|
|
169
|
+
return 0
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
if __name__ == "__main__": # pragma: no cover
|
|
173
|
+
sys.exit(main())
|