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,525 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""csharp_stryker_net_status_loop.py — status + red-flag inspection loop for
|
|
3
|
+
long-running Stryker.NET invocations.
|
|
4
|
+
|
|
5
|
+
Called by csharp_stryker_net_wrapper.py (or usable standalone via the CLI).
|
|
6
|
+
Public API (importable):
|
|
7
|
+
|
|
8
|
+
parse_dots_count(logfile: Path) -> int
|
|
9
|
+
parse_summary_count(logfile: Path, key: str) -> Optional[int]
|
|
10
|
+
log_has_completion_marker(logfile: Path) -> bool
|
|
11
|
+
log_has_coverage_capture_failure(logfile: Path) -> bool
|
|
12
|
+
emit_status_line(logfile: Path) -> str
|
|
13
|
+
check_red_flags(logfile, threshold, stryker_pid, expected_target=None, state_dir=None, drift_threshold=3) -> list[str]
|
|
14
|
+
status_loop_start(logfile, interval, threshold, stryker_pid, expected_target=None, state_dir=None, drift_threshold=3) -> None
|
|
15
|
+
|
|
16
|
+
Refs: #558 (original bash), #571 (setup() fork hang on MSYS — closed by
|
|
17
|
+
this Python port at the source), #572 (bash → Python migration epic).
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import argparse
|
|
23
|
+
import os
|
|
24
|
+
import re
|
|
25
|
+
import signal
|
|
26
|
+
import sys
|
|
27
|
+
import time
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
|
|
30
|
+
# =============================================================================
|
|
31
|
+
# Log parsers — pure functions
|
|
32
|
+
# =============================================================================
|
|
33
|
+
_DOTS_HEADER_RE = re.compile(r"^Testing mutants:\s*$")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def parse_dots_count(logfile: Path) -> int:
|
|
37
|
+
"""Count '.' characters on the first non-empty line following
|
|
38
|
+
'Testing mutants:'. Dots reporter uses one dot per completed mutant;
|
|
39
|
+
survives log redirection. Returns 0 when the marker is absent OR the
|
|
40
|
+
first following non-empty line isn't a dots line.
|
|
41
|
+
|
|
42
|
+
Missing / unreadable file → 0 (silent — the loop tolerates a not-yet-
|
|
43
|
+
written log).
|
|
44
|
+
"""
|
|
45
|
+
try:
|
|
46
|
+
with logfile.open() as f:
|
|
47
|
+
collecting = False
|
|
48
|
+
for line in f:
|
|
49
|
+
if _DOTS_HEADER_RE.match(line):
|
|
50
|
+
collecting = True
|
|
51
|
+
continue
|
|
52
|
+
if not collecting:
|
|
53
|
+
continue
|
|
54
|
+
stripped = line.strip()
|
|
55
|
+
if not stripped:
|
|
56
|
+
continue
|
|
57
|
+
if line.startswith("."):
|
|
58
|
+
return line.count(".")
|
|
59
|
+
# First non-empty line after the header wasn't dots.
|
|
60
|
+
return 0
|
|
61
|
+
return 0
|
|
62
|
+
except (OSError, FileNotFoundError):
|
|
63
|
+
return 0
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
_SUMMARY_RES: dict[str, re.Pattern[str]] = {}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _summary_re(key: str) -> re.Pattern[str]:
|
|
70
|
+
if key not in _SUMMARY_RES:
|
|
71
|
+
_SUMMARY_RES[key] = re.compile(rf"^{re.escape(key)}:\s+(\d+)")
|
|
72
|
+
return _SUMMARY_RES[key]
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def parse_summary_count(logfile: Path, key: str) -> int | None:
|
|
76
|
+
"""Extract ``<key>: <n>`` from the last matching line in the log.
|
|
77
|
+
|
|
78
|
+
Returns the count as int, or None if no line matches. Missing file
|
|
79
|
+
also returns None.
|
|
80
|
+
"""
|
|
81
|
+
pattern = _summary_re(key)
|
|
82
|
+
last: int | None = None
|
|
83
|
+
try:
|
|
84
|
+
with logfile.open() as f:
|
|
85
|
+
for line in f:
|
|
86
|
+
m = pattern.match(line)
|
|
87
|
+
if m:
|
|
88
|
+
last = int(m.group(1))
|
|
89
|
+
return last
|
|
90
|
+
except (OSError, FileNotFoundError):
|
|
91
|
+
return None
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
_COMPLETION_RE = re.compile(r"The final mutation score|Stryker execution finished")
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def log_has_completion_marker(logfile: Path) -> bool:
|
|
98
|
+
"""True when Stryker's end-of-run marker is present in the log."""
|
|
99
|
+
try:
|
|
100
|
+
with logfile.open() as f:
|
|
101
|
+
for line in f:
|
|
102
|
+
if _COMPLETION_RE.search(line):
|
|
103
|
+
return True
|
|
104
|
+
return False
|
|
105
|
+
except (OSError, FileNotFoundError):
|
|
106
|
+
return False
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
# Canonical coverage-capture-failure signal (see #1156). Verbatim from
|
|
110
|
+
# Stryker.NET's own log: src/Stryker.Core/Stryker.Core/CoverageAnalysis/
|
|
111
|
+
# CoverageAnalyser.cs emits "It looks like the test coverage capture failed.
|
|
112
|
+
# Disable coverage based optimisation." when the initial per-test coverage pass
|
|
113
|
+
# yields zero covered mutations, then falls back to whole-suite-per-mutant. The
|
|
114
|
+
# British "optimisation" spelling matches the source. Kept byte-identical with
|
|
115
|
+
# the copy in hooks/mutation_adapters/lib.py; the two live in different import
|
|
116
|
+
# roots (skills/ vs hooks/) so they cannot share a constant — the equivalence
|
|
117
|
+
# is armored by test_coverage_capture_regex_matches_status_loop.
|
|
118
|
+
_COVERAGE_CAPTURE_FAILURE_RE = re.compile(
|
|
119
|
+
r"test coverage capture failed|disable coverage based optimisation",
|
|
120
|
+
re.IGNORECASE,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def log_has_coverage_capture_failure(logfile: Path) -> bool:
|
|
125
|
+
"""True when the log shows Stryker disabled per-test coverage optimisation
|
|
126
|
+
and fell back to whole-suite-per-mutant (see #1156). Matches either half of
|
|
127
|
+
'It looks like the test coverage capture failed. Disable coverage based
|
|
128
|
+
optimisation.' — resilient to timestamp/log prefixes (search, not match).
|
|
129
|
+
"""
|
|
130
|
+
try:
|
|
131
|
+
with logfile.open() as f:
|
|
132
|
+
for line in f:
|
|
133
|
+
if _COVERAGE_CAPTURE_FAILURE_RE.search(line):
|
|
134
|
+
return True
|
|
135
|
+
return False
|
|
136
|
+
except (OSError, FileNotFoundError):
|
|
137
|
+
return False
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
_COMPILE_ERROR_RE = re.compile(r"CompileError")
|
|
141
|
+
_TARGET_PATH_RE = re.compile(r"^Property TargetPath=(.+)$", re.MULTILINE)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def count_compile_errors(logfile: Path) -> int:
|
|
145
|
+
try:
|
|
146
|
+
return sum(1 for line in logfile.open() if _COMPILE_ERROR_RE.search(line))
|
|
147
|
+
except (OSError, FileNotFoundError):
|
|
148
|
+
return 0
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def unexpected_target_path(logfile: Path, expected_fragment: str) -> str | None:
|
|
152
|
+
"""Return the first ``Property TargetPath=<path>`` line whose path does
|
|
153
|
+
NOT contain expected_fragment, or None if all match / none present.
|
|
154
|
+
"""
|
|
155
|
+
try:
|
|
156
|
+
for line in logfile.open():
|
|
157
|
+
m = _TARGET_PATH_RE.match(line.rstrip("\n"))
|
|
158
|
+
if m:
|
|
159
|
+
path = m.group(1)
|
|
160
|
+
if expected_fragment not in path:
|
|
161
|
+
return path
|
|
162
|
+
return None
|
|
163
|
+
except (OSError, FileNotFoundError):
|
|
164
|
+
return None
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
# =============================================================================
|
|
168
|
+
# emit_status_line — one status record per tick
|
|
169
|
+
# =============================================================================
|
|
170
|
+
def emit_status_line(logfile: Path) -> str:
|
|
171
|
+
"""Return one status record string:
|
|
172
|
+
|
|
173
|
+
tested=<n> killed=<n> survived=<n> timeout=<n> elapsed=<HH:MM|?>
|
|
174
|
+
|
|
175
|
+
Callers write this to stdout (or wherever they route it).
|
|
176
|
+
"""
|
|
177
|
+
tested = parse_dots_count(logfile)
|
|
178
|
+
killed = parse_summary_count(logfile, "Killed")
|
|
179
|
+
survived = parse_summary_count(logfile, "Survived")
|
|
180
|
+
timeout = parse_summary_count(logfile, "Timeout")
|
|
181
|
+
# Elapsed derived from the log's first-line INF timestamp when present.
|
|
182
|
+
elapsed = "?"
|
|
183
|
+
return (
|
|
184
|
+
f"tested={tested} "
|
|
185
|
+
f"killed={killed if killed is not None else 0} "
|
|
186
|
+
f"survived={survived if survived is not None else 0} "
|
|
187
|
+
f"timeout={timeout if timeout is not None else 0} "
|
|
188
|
+
f"elapsed={elapsed}"
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
# =============================================================================
|
|
193
|
+
# check_red_flags — the five detectors + parser-drift catch-all
|
|
194
|
+
# =============================================================================
|
|
195
|
+
def _drift_counter_path(state_dir: Path, stryker_pid: int | None) -> Path:
|
|
196
|
+
"""Per-PID counter file. Falls back to 'noop' when PID is missing so the
|
|
197
|
+
counter still gets a stable location (tests that omit PID share one).
|
|
198
|
+
"""
|
|
199
|
+
pid_component = str(stryker_pid) if stryker_pid else "noop"
|
|
200
|
+
return state_dir / f"drift-counter-{pid_component}"
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def _pid_is_alive(pid: int) -> bool:
|
|
204
|
+
"""Cross-platform PID-liveness check.
|
|
205
|
+
|
|
206
|
+
- POSIX: ``os.kill(pid, 0)`` — raises ``ProcessLookupError`` for dead
|
|
207
|
+
PIDs, ``PermissionError`` for existing-but-not-ours.
|
|
208
|
+
- Windows: ``os.kill(pid, 0)`` has undefined semantics (it can send
|
|
209
|
+
``CTRL_C_EVENT`` to console-attached processes on some Python builds,
|
|
210
|
+
which interrupts the *current* process). Use ``ctypes.OpenProcess``
|
|
211
|
+
directly instead — no signal delivery, deterministic on any Windows
|
|
212
|
+
Python.
|
|
213
|
+
"""
|
|
214
|
+
if pid <= 0:
|
|
215
|
+
return False
|
|
216
|
+
|
|
217
|
+
if os.name == "nt":
|
|
218
|
+
# Windows: query the kernel for the process handle. If OpenProcess
|
|
219
|
+
# succeeds we have an existing PID (living or a zombie kept alive
|
|
220
|
+
# by an open handle elsewhere — either way, "alive enough" for the
|
|
221
|
+
# loop's died-mid-run red-flag test). If it fails we treat the PID
|
|
222
|
+
# as dead. Uses PROCESS_QUERY_LIMITED_INFORMATION (0x1000) — the
|
|
223
|
+
# minimum access right needed to open any process.
|
|
224
|
+
try:
|
|
225
|
+
import ctypes
|
|
226
|
+
|
|
227
|
+
PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
|
|
228
|
+
handle = ctypes.windll.kernel32.OpenProcess(
|
|
229
|
+
PROCESS_QUERY_LIMITED_INFORMATION, False, int(pid)
|
|
230
|
+
)
|
|
231
|
+
if not handle:
|
|
232
|
+
return False
|
|
233
|
+
# If the process is a zombie, GetExitCodeProcess returns
|
|
234
|
+
# STILL_ACTIVE (259) while alive and something else after exit.
|
|
235
|
+
# Distinguishing is nice but not required for this check; the
|
|
236
|
+
# OpenProcess handle being non-null already answers "does a PID
|
|
237
|
+
# slot with this number exist right now."
|
|
238
|
+
ctypes.windll.kernel32.CloseHandle(handle)
|
|
239
|
+
return True
|
|
240
|
+
except Exception: # noqa: BLE001 - deliberate fail-open on any ctypes/Windows quirk
|
|
241
|
+
# Any Windows-specific quirk — fall back to "alive" to avoid
|
|
242
|
+
# false died-mid-run red flags. That matches the POSIX
|
|
243
|
+
# "unknown-error" branch below.
|
|
244
|
+
return True
|
|
245
|
+
|
|
246
|
+
# POSIX path — signal 0 delivery is a no-op existence check.
|
|
247
|
+
try:
|
|
248
|
+
os.kill(pid, 0)
|
|
249
|
+
return True
|
|
250
|
+
except ProcessLookupError:
|
|
251
|
+
return False
|
|
252
|
+
except PermissionError:
|
|
253
|
+
# PID exists but is owned by another user — from the loop's
|
|
254
|
+
# perspective, it's alive.
|
|
255
|
+
return True
|
|
256
|
+
except OSError:
|
|
257
|
+
# Unknown error — err on the side of "alive" to avoid false
|
|
258
|
+
# died-mid-run red flags.
|
|
259
|
+
return True
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def check_red_flags(
|
|
263
|
+
logfile: Path,
|
|
264
|
+
threshold: int,
|
|
265
|
+
stryker_pid: int | None,
|
|
266
|
+
expected_target: str | None = None,
|
|
267
|
+
state_dir: Path | None = None,
|
|
268
|
+
drift_threshold: int = 3,
|
|
269
|
+
) -> list[str]:
|
|
270
|
+
"""Grep the log for known-broken signatures, check PID liveness, and
|
|
271
|
+
return zero or more ``[RED-FLAG] …`` lines. Consecutive-unrecognized-tick
|
|
272
|
+
counter is kept in a file under ``state_dir`` (default $TMPDIR), so a
|
|
273
|
+
reporter-format drift is self-detecting.
|
|
274
|
+
"""
|
|
275
|
+
if state_dir is None:
|
|
276
|
+
state_dir = Path(os.environ.get("TMPDIR", "/tmp"))
|
|
277
|
+
state_dir.mkdir(parents=True, exist_ok=True)
|
|
278
|
+
|
|
279
|
+
lines: list[str] = []
|
|
280
|
+
recognized = False
|
|
281
|
+
|
|
282
|
+
killed = parse_summary_count(logfile, "Killed")
|
|
283
|
+
survived = parse_summary_count(logfile, "Survived")
|
|
284
|
+
compile_errors = count_compile_errors(logfile)
|
|
285
|
+
|
|
286
|
+
# --- Red flag 1: Killed==0 && Survived>0 (mutation-switch not observing)
|
|
287
|
+
if killed is not None and survived is not None:
|
|
288
|
+
recognized = True
|
|
289
|
+
if killed == 0 and survived > 0:
|
|
290
|
+
lines.append(
|
|
291
|
+
f"[RED-FLAG] mutation-switch not observing mutations at "
|
|
292
|
+
f"runtime (Killed=0, Survived={survived}) — see #554"
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
# --- Red flag 2: CompileError count strictly > threshold
|
|
296
|
+
if compile_errors > 0:
|
|
297
|
+
recognized = True
|
|
298
|
+
if compile_errors > threshold:
|
|
299
|
+
lines.append(
|
|
300
|
+
f"[RED-FLAG] CompileError count {compile_errors} over "
|
|
301
|
+
f"threshold {threshold} — probe file / mutate glob likely "
|
|
302
|
+
f"misconfigured"
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
# --- Red flag 3: SolutionPath naming an unexpected TargetPath
|
|
306
|
+
if expected_target:
|
|
307
|
+
unexpected = unexpected_target_path(logfile, expected_target)
|
|
308
|
+
if unexpected:
|
|
309
|
+
recognized = True
|
|
310
|
+
lines.append(
|
|
311
|
+
f"[RED-FLAG] SolutionPath trap — {unexpected} does not "
|
|
312
|
+
f"contain expected {expected_target} — see #557"
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
# --- Red flag 4: Stryker PID dead AND no completion marker
|
|
316
|
+
if (
|
|
317
|
+
stryker_pid is not None
|
|
318
|
+
and not _pid_is_alive(stryker_pid)
|
|
319
|
+
and not log_has_completion_marker(logfile)
|
|
320
|
+
):
|
|
321
|
+
recognized = True
|
|
322
|
+
lines.append(
|
|
323
|
+
f"[RED-FLAG] Stryker process died mid-run (PID {stryker_pid} "
|
|
324
|
+
f"no longer running, no completion marker in log) — see #558"
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
# --- Red flag 6: coverage capture failed → whole-suite-per-mutant fallback
|
|
328
|
+
if log_has_coverage_capture_failure(logfile):
|
|
329
|
+
recognized = True
|
|
330
|
+
lines.append(
|
|
331
|
+
"[RED-FLAG] coverage capture failed — Stryker disabled per-test "
|
|
332
|
+
"coverage optimisation and fell back to whole-suite-per-mutant; the "
|
|
333
|
+
"mutant-kill loop is infeasible on this suite (xunit.v3) — see #1156"
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
# A log with dots or a completion marker is "recognized" even if no
|
|
337
|
+
# summary parser fired — this stops false drift-alerts during a healthy
|
|
338
|
+
# mid-run tick.
|
|
339
|
+
if parse_dots_count(logfile) > 0 or log_has_completion_marker(logfile):
|
|
340
|
+
recognized = True
|
|
341
|
+
|
|
342
|
+
# --- Red flag 5: parser drift — N consecutive unrecognized ticks
|
|
343
|
+
counter_file = _drift_counter_path(state_dir, stryker_pid)
|
|
344
|
+
drift = 0
|
|
345
|
+
if counter_file.exists():
|
|
346
|
+
try:
|
|
347
|
+
drift = int(counter_file.read_text().strip() or "0")
|
|
348
|
+
except (OSError, ValueError):
|
|
349
|
+
drift = 0
|
|
350
|
+
drift = 0 if recognized else drift + 1
|
|
351
|
+
try:
|
|
352
|
+
counter_file.write_text(f"{drift}\n")
|
|
353
|
+
except OSError:
|
|
354
|
+
# If we can't write the counter, the drift check degrades to
|
|
355
|
+
# per-tick — better than crashing the loop.
|
|
356
|
+
pass
|
|
357
|
+
|
|
358
|
+
if drift >= drift_threshold:
|
|
359
|
+
lines.append(
|
|
360
|
+
f"[RED-FLAG] parser drift — {drift} consecutive ticks with no "
|
|
361
|
+
f"recognizable Stryker output pattern; reporter format may have "
|
|
362
|
+
f"changed — see #558"
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
return lines
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
# =============================================================================
|
|
369
|
+
# status_loop_start — the tick loop
|
|
370
|
+
# =============================================================================
|
|
371
|
+
_STOP = {"requested": False}
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
def _stop_handler(signum: int, _frame) -> None:
|
|
375
|
+
_STOP["requested"] = True
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def status_loop_start(
|
|
379
|
+
logfile: Path,
|
|
380
|
+
interval: float,
|
|
381
|
+
threshold: int,
|
|
382
|
+
stryker_pid: int | None,
|
|
383
|
+
*,
|
|
384
|
+
expected_target: str | None = None,
|
|
385
|
+
state_dir: Path | None = None,
|
|
386
|
+
drift_threshold: int = 3,
|
|
387
|
+
output=sys.stdout,
|
|
388
|
+
) -> None:
|
|
389
|
+
"""Tick loop. Prints one status line + zero-or-more red-flag lines per
|
|
390
|
+
tick. Exits cleanly when Stryker has completed (PID dead AND completion
|
|
391
|
+
marker present) or when SIGTERM/SIGINT is received.
|
|
392
|
+
|
|
393
|
+
``output`` defaults to ``sys.stdout`` but can be overridden for tests.
|
|
394
|
+
"""
|
|
395
|
+
# Install signal handlers so the loop reaps on Ctrl-C / kill. Save the
|
|
396
|
+
# previous handlers so we restore them when the loop exits — critical
|
|
397
|
+
# when this function is called from another Python program (pytest,
|
|
398
|
+
# or wrapper.main() itself) so we don't leave the process's SIGINT/
|
|
399
|
+
# SIGTERM handling in a mutated state after the loop returns.
|
|
400
|
+
previous_handlers: list[tuple[int, object]] = []
|
|
401
|
+
for sig in (signal.SIGINT, signal.SIGTERM):
|
|
402
|
+
try:
|
|
403
|
+
previous_handlers.append((sig, signal.getsignal(sig)))
|
|
404
|
+
signal.signal(sig, _stop_handler)
|
|
405
|
+
except (ValueError, OSError):
|
|
406
|
+
# Called from a thread on some platforms — non-main-thread
|
|
407
|
+
# signal.signal raises ValueError. That's OK; the loop still
|
|
408
|
+
# terminates via the completion-marker check.
|
|
409
|
+
pass
|
|
410
|
+
|
|
411
|
+
try:
|
|
412
|
+
while not _STOP["requested"]:
|
|
413
|
+
print(emit_status_line(logfile), file=output, flush=True)
|
|
414
|
+
for line in check_red_flags(
|
|
415
|
+
logfile,
|
|
416
|
+
threshold,
|
|
417
|
+
stryker_pid,
|
|
418
|
+
expected_target=expected_target,
|
|
419
|
+
state_dir=state_dir,
|
|
420
|
+
drift_threshold=drift_threshold,
|
|
421
|
+
):
|
|
422
|
+
print(line, file=output, flush=True)
|
|
423
|
+
|
|
424
|
+
# Exit condition — Stryker done and log carries a completion marker.
|
|
425
|
+
if (
|
|
426
|
+
stryker_pid is not None
|
|
427
|
+
and not _pid_is_alive(stryker_pid)
|
|
428
|
+
and log_has_completion_marker(logfile)
|
|
429
|
+
):
|
|
430
|
+
break
|
|
431
|
+
|
|
432
|
+
# Sleep in small slices so signal handlers wake up promptly.
|
|
433
|
+
remaining = float(interval)
|
|
434
|
+
slice_s = 0.1
|
|
435
|
+
while remaining > 0 and not _STOP["requested"]:
|
|
436
|
+
time.sleep(min(slice_s, remaining))
|
|
437
|
+
remaining -= slice_s
|
|
438
|
+
finally:
|
|
439
|
+
# Restore prior signal handlers so callers aren't left with our
|
|
440
|
+
# _stop_handler installed process-wide.
|
|
441
|
+
for sig, handler in previous_handlers:
|
|
442
|
+
try:
|
|
443
|
+
signal.signal(sig, handler)
|
|
444
|
+
except (ValueError, OSError, TypeError):
|
|
445
|
+
pass
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
# =============================================================================
|
|
449
|
+
# CLI entry point — for standalone use
|
|
450
|
+
# =============================================================================
|
|
451
|
+
def main(argv: list[str] | None = None) -> int:
|
|
452
|
+
argv = list(sys.argv[1:] if argv is None else argv)
|
|
453
|
+
p = argparse.ArgumentParser(
|
|
454
|
+
prog="csharp_stryker_net_status_loop.py",
|
|
455
|
+
description=(
|
|
456
|
+
"Status + red-flag inspection loop for long-running Stryker.NET "
|
|
457
|
+
"invocations. Usable standalone; typically called by "
|
|
458
|
+
"csharp_stryker_net_wrapper.py."
|
|
459
|
+
),
|
|
460
|
+
)
|
|
461
|
+
p.add_argument(
|
|
462
|
+
"logfile", type=Path, help="Path to the Stryker log file being tailed"
|
|
463
|
+
)
|
|
464
|
+
p.add_argument(
|
|
465
|
+
"interval",
|
|
466
|
+
type=float,
|
|
467
|
+
help="Seconds between status ticks (0 = one tick and exit)",
|
|
468
|
+
)
|
|
469
|
+
p.add_argument(
|
|
470
|
+
"threshold", type=int, help="CompileError count above which the red-flag fires"
|
|
471
|
+
)
|
|
472
|
+
p.add_argument(
|
|
473
|
+
"stryker_pid",
|
|
474
|
+
type=int,
|
|
475
|
+
nargs="?",
|
|
476
|
+
default=None,
|
|
477
|
+
help="PID of the Stryker subprocess to monitor (optional)",
|
|
478
|
+
)
|
|
479
|
+
p.add_argument(
|
|
480
|
+
"--expected-target",
|
|
481
|
+
default=None,
|
|
482
|
+
help="Fragment expected in Property TargetPath=... lines",
|
|
483
|
+
)
|
|
484
|
+
p.add_argument(
|
|
485
|
+
"--state-dir",
|
|
486
|
+
type=Path,
|
|
487
|
+
default=None,
|
|
488
|
+
help="Directory for drift-counter state (default: $TMPDIR)",
|
|
489
|
+
)
|
|
490
|
+
p.add_argument(
|
|
491
|
+
"--drift-threshold",
|
|
492
|
+
type=int,
|
|
493
|
+
default=3,
|
|
494
|
+
help="Consecutive unrecognized ticks before drift red-flag",
|
|
495
|
+
)
|
|
496
|
+
args = p.parse_args(argv)
|
|
497
|
+
|
|
498
|
+
if args.interval <= 0:
|
|
499
|
+
# One-shot mode — emit one status + red-flag pass and exit.
|
|
500
|
+
print(emit_status_line(args.logfile), flush=True)
|
|
501
|
+
for line in check_red_flags(
|
|
502
|
+
args.logfile,
|
|
503
|
+
args.threshold,
|
|
504
|
+
args.stryker_pid,
|
|
505
|
+
expected_target=args.expected_target,
|
|
506
|
+
state_dir=args.state_dir,
|
|
507
|
+
drift_threshold=args.drift_threshold,
|
|
508
|
+
):
|
|
509
|
+
print(line, flush=True)
|
|
510
|
+
return 0
|
|
511
|
+
|
|
512
|
+
status_loop_start(
|
|
513
|
+
args.logfile,
|
|
514
|
+
args.interval,
|
|
515
|
+
args.threshold,
|
|
516
|
+
args.stryker_pid,
|
|
517
|
+
expected_target=args.expected_target,
|
|
518
|
+
state_dir=args.state_dir,
|
|
519
|
+
drift_threshold=args.drift_threshold,
|
|
520
|
+
)
|
|
521
|
+
return 0
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
if __name__ == "__main__":
|
|
525
|
+
sys.exit(main())
|