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.
Files changed (780) hide show
  1. package/LICENSE +21 -0
  2. package/PORTING.md +134 -0
  3. package/README.md +207 -0
  4. package/UPSTREAM.json +64 -0
  5. package/agents/Explore.md +15 -0
  6. package/agents/a11y-review.md +118 -0
  7. package/agents/adr-author.md +70 -0
  8. package/agents/ai-provenance-review.md +120 -0
  9. package/agents/angular-reactivity-review.md +95 -0
  10. package/agents/arch-review.md +135 -0
  11. package/agents/architect.md +78 -0
  12. package/agents/autoship-batch-proposer.md +69 -0
  13. package/agents/claude-setup-review.md +136 -0
  14. package/agents/codebase-recon.md +184 -0
  15. package/agents/component-architecture-review.md +119 -0
  16. package/agents/concurrency-review.md +109 -0
  17. package/agents/correctness-review.md +290 -0
  18. package/agents/data-flow-tracer.md +120 -0
  19. package/agents/doc-review.md +165 -0
  20. package/agents/domain-review.md +136 -0
  21. package/agents/general-purpose.md +10 -0
  22. package/agents/gherkin-quality-critic.md +113 -0
  23. package/agents/js-fp-review.md +114 -0
  24. package/agents/mutation-kill.md +684 -0
  25. package/agents/naming-review.md +142 -0
  26. package/agents/orchestrator.md +339 -0
  27. package/agents/performance-review.md +105 -0
  28. package/agents/plan-review-acceptance.md +115 -0
  29. package/agents/plan-review-design.md +90 -0
  30. package/agents/plan-review-parallelization.md +84 -0
  31. package/agents/plan-review-strategic.md +96 -0
  32. package/agents/plan-review-ux.md +110 -0
  33. package/agents/platform-engineer.md +64 -0
  34. package/agents/product-manager.md +68 -0
  35. package/agents/progress-guardian.md +79 -0
  36. package/agents/qa-engineer.md +289 -0
  37. package/agents/quality-reviewer.md +132 -0
  38. package/agents/react-reactivity-review.md +102 -0
  39. package/agents/refactor-opportunity-review.md +128 -0
  40. package/agents/security-engineer.md +60 -0
  41. package/agents/security-review.md +218 -0
  42. package/agents/session-analysis.md +95 -0
  43. package/agents/software-engineer.md +105 -0
  44. package/agents/spec-compliance-review.md +100 -0
  45. package/agents/spec-reviewer.md +114 -0
  46. package/agents/structure-review.md +146 -0
  47. package/agents/tech-writer.md +84 -0
  48. package/agents/test-review.md +246 -0
  49. package/agents/test-smell-review.md +188 -0
  50. package/agents/token-efficiency-review.md +139 -0
  51. package/agents/ui-ux-designer.md +54 -0
  52. package/agents/vue-reactivity-review.md +95 -0
  53. package/bin/__pycache__/claudecpython-314.pyc +0 -0
  54. package/bin/claude +258 -0
  55. package/docs/upstream/.pages +1 -0
  56. package/docs/upstream/CHANGELOG.md +2586 -0
  57. package/docs/upstream/README.md +155 -0
  58. package/docs/upstream/agent-architecture.md +214 -0
  59. package/docs/upstream/agent_info.md +187 -0
  60. package/docs/upstream/artifact-migration.md +124 -0
  61. package/docs/upstream/code-intelligence-nudge.md +149 -0
  62. package/docs/upstream/code-review-process.md +294 -0
  63. package/docs/upstream/concurrent-use.md +73 -0
  64. package/docs/upstream/context-management.md +111 -0
  65. package/docs/upstream/developer-notes.md +280 -0
  66. package/docs/upstream/diagrams/architecture-overview.svg +101 -0
  67. package/docs/upstream/diagrams/review-dispatch.svg +139 -0
  68. package/docs/upstream/diagrams/team-agents.svg +128 -0
  69. package/docs/upstream/diagrams/test-improve-flow.svg +166 -0
  70. package/docs/upstream/diagrams/workflow-linear.svg +66 -0
  71. package/docs/upstream/diagrams/workflow-three-phase.svg +200 -0
  72. package/docs/upstream/eval-maintenance.md +95 -0
  73. package/docs/upstream/eval-running-guide.md +147 -0
  74. package/docs/upstream/eval-system.md +291 -0
  75. package/docs/upstream/session-review-oss-complements.md +75 -0
  76. package/docs/upstream/session-review.md +212 -0
  77. package/docs/upstream/skills.md +188 -0
  78. package/docs/upstream/team-structure.md +21 -0
  79. package/docs/upstream/telemetry-ci-access.md +129 -0
  80. package/docs/upstream/telemetry-repo-security.md +120 -0
  81. package/docs/upstream/test-evaluation.md +277 -0
  82. package/docs/upstream/test-improve.md +154 -0
  83. package/docs/upstream/triage-workflow.md +282 -0
  84. package/docs/upstream/workflows.md +289 -0
  85. package/extensions/dev-team/index.ts +539 -0
  86. package/extensions/dev-team/lib/agents.ts +272 -0
  87. package/extensions/dev-team/lib/ai-credits.ts +92 -0
  88. package/extensions/dev-team/lib/autocompact.ts +81 -0
  89. package/extensions/dev-team/lib/child-run.ts +102 -0
  90. package/extensions/dev-team/lib/config.ts +236 -0
  91. package/extensions/dev-team/lib/gh-command.ts +103 -0
  92. package/extensions/dev-team/lib/github-style.ts +307 -0
  93. package/extensions/dev-team/lib/hooks.ts +350 -0
  94. package/extensions/dev-team/lib/metrics.ts +115 -0
  95. package/extensions/dev-team/lib/safe-read.ts +49 -0
  96. package/extensions/dev-team/lib/session-files.ts +57 -0
  97. package/extensions/dev-team/lib/session-spend.ts +123 -0
  98. package/extensions/dev-team/lib/shell-scan.ts +205 -0
  99. package/extensions/dev-team/lib/skills.ts +213 -0
  100. package/extensions/dev-team/lib/subagent-render.ts +245 -0
  101. package/extensions/dev-team/lib/subagent-types.ts +164 -0
  102. package/extensions/dev-team/lib/subagent.ts +596 -0
  103. package/extensions/dev-team/lib/terminal-text.ts +54 -0
  104. package/extensions/dev-team/lib/tools-misc.ts +152 -0
  105. package/extensions/dev-team/lib/transcript.ts +110 -0
  106. package/extensions/dev-team/lib/trust.ts +52 -0
  107. package/extensions/dev-team/lib/usage-breakdown.ts +176 -0
  108. package/extensions/dev-team/lib/usage-chart.ts +153 -0
  109. package/extensions/dev-team/lib/usage-command.ts +107 -0
  110. package/extensions/dev-team/lib/usage-history.ts +203 -0
  111. package/extensions/dev-team/lib/usage-render.ts +225 -0
  112. package/extensions/dev-team/lib/usage-split-bar.ts +127 -0
  113. package/extensions/dev-team/lib/usage-state.ts +116 -0
  114. package/extensions/dev-team/lib/usage-text.ts +159 -0
  115. package/extensions/dev-team/lib/usage-view.ts +109 -0
  116. package/hooks/__pycache__/refactor_test_freeze_guard.cpython-314.pyc +0 -0
  117. package/hooks/agent_dispatch_ledger.py +190 -0
  118. package/hooks/autocompact_setup_nudge.py +99 -0
  119. package/hooks/bash_retry_guard.py +228 -0
  120. package/hooks/boundary_events_write_guard.py +352 -0
  121. package/hooks/code_intelligence_nudge.py +293 -0
  122. package/hooks/code_intelligence_turn_mark.py +317 -0
  123. package/hooks/codegraph_bootstrap.py +139 -0
  124. package/hooks/contract_version_guard.py +362 -0
  125. package/hooks/cost_meter.py +106 -0
  126. package/hooks/destructive-commands.json +62 -0
  127. package/hooks/destructive_guard.py +477 -0
  128. package/hooks/eval_compliance_check.py +440 -0
  129. package/hooks/guards.json +17 -0
  130. package/hooks/hooks.json +323 -0
  131. package/hooks/internal_double_gate.py +296 -0
  132. package/hooks/js_fp_review.py +212 -0
  133. package/hooks/knowledge_index.py +119 -0
  134. package/hooks/lib/__pycache__/artifact_paths.cpython-314.pyc +0 -0
  135. package/hooks/lib/__pycache__/atomic_state.cpython-314.pyc +0 -0
  136. package/hooks/lib/__pycache__/autocompact_config.cpython-314.pyc +0 -0
  137. package/hooks/lib/__pycache__/boundary_events.cpython-314.pyc +0 -0
  138. package/hooks/lib/__pycache__/doc_classification.cpython-314.pyc +0 -0
  139. package/hooks/lib/__pycache__/gh_pr_create_detect.cpython-314.pyc +0 -0
  140. package/hooks/lib/__pycache__/git_safe_diff.cpython-314.pyc +0 -0
  141. package/hooks/lib/__pycache__/instrument_log.cpython-314.pyc +0 -0
  142. package/hooks/lib/__pycache__/metrics_query.cpython-314.pyc +0 -0
  143. package/hooks/lib/__pycache__/plugin_version.cpython-314.pyc +0 -0
  144. package/hooks/lib/__pycache__/pre_commit_doc_classifier.cpython-314.pyc +0 -0
  145. package/hooks/lib/__pycache__/review_agent_registry.cpython-314.pyc +0 -0
  146. package/hooks/lib/__pycache__/review_gate_corroboration.cpython-314.pyc +0 -0
  147. package/hooks/lib/__pycache__/review_gate_hash.cpython-314.pyc +0 -0
  148. package/hooks/lib/__pycache__/review_verdicts.cpython-314.pyc +0 -0
  149. package/hooks/lib/__pycache__/stdin_json.cpython-314.pyc +0 -0
  150. package/hooks/lib/__pycache__/stryker_invocation.cpython-314.pyc +0 -0
  151. package/hooks/lib/__pycache__/telemetry_consent.cpython-314.pyc +0 -0
  152. package/hooks/lib/__pycache__/test_file_classify.cpython-314.pyc +0 -0
  153. package/hooks/lib/__pycache__/token_efficiency_limits.cpython-314.pyc +0 -0
  154. package/hooks/lib/__pycache__/verify_guard_state.cpython-314.pyc +0 -0
  155. package/hooks/lib/__pycache__/xunit_v3_operator_gate.cpython-314.pyc +0 -0
  156. package/hooks/lib/agent_skill_hints.py +74 -0
  157. package/hooks/lib/artifact_paths.py +263 -0
  158. package/hooks/lib/atomic_state.py +557 -0
  159. package/hooks/lib/autocompact_config.py +103 -0
  160. package/hooks/lib/autoship_log.py +106 -0
  161. package/hooks/lib/banned_scripts_policy.py +51 -0
  162. package/hooks/lib/boundary_events.py +436 -0
  163. package/hooks/lib/build_knowledge_index.py +504 -0
  164. package/hooks/lib/build_skills_index.py +361 -0
  165. package/hooks/lib/build_state.py +116 -0
  166. package/hooks/lib/classify_ship_outcome.py +126 -0
  167. package/hooks/lib/config_changelog_schema.py +115 -0
  168. package/hooks/lib/cost_meter.py +955 -0
  169. package/hooks/lib/doc_classification.py +116 -0
  170. package/hooks/lib/gh_pr_create_detect.py +136 -0
  171. package/hooks/lib/git_safe_diff.py +123 -0
  172. package/hooks/lib/instrument_log.py +66 -0
  173. package/hooks/lib/iteration_journal_gate.py +197 -0
  174. package/hooks/lib/knowledge_index_paths.py +88 -0
  175. package/hooks/lib/mcp_json_repowise.py +177 -0
  176. package/hooks/lib/metrics_query.py +202 -0
  177. package/hooks/lib/minimal_yaml.py +434 -0
  178. package/hooks/lib/plugin_version.py +142 -0
  179. package/hooks/lib/pre_commit_detect.py +537 -0
  180. package/hooks/lib/pre_commit_doc_classifier.py +126 -0
  181. package/hooks/lib/pricing.py +118 -0
  182. package/hooks/lib/report_pdf.py +371 -0
  183. package/hooks/lib/review_agent_registry.py +142 -0
  184. package/hooks/lib/review_dispatch_ledger.py +101 -0
  185. package/hooks/lib/review_gate_corroboration.py +521 -0
  186. package/hooks/lib/review_gate_hash.py +252 -0
  187. package/hooks/lib/review_gate_normalized_hash.py +1115 -0
  188. package/hooks/lib/review_verdicts.py +301 -0
  189. package/hooks/lib/run_report.py +160 -0
  190. package/hooks/lib/skill_categories.yaml +125 -0
  191. package/hooks/lib/stdin_json.py +57 -0
  192. package/hooks/lib/stryker_invocation.py +102 -0
  193. package/hooks/lib/telemetry_consent.py +41 -0
  194. package/hooks/lib/telemetry_report.py +108 -0
  195. package/hooks/lib/test_file_classify.py +160 -0
  196. package/hooks/lib/token_efficiency_limits.py +51 -0
  197. package/hooks/lib/turn_identity.py +77 -0
  198. package/hooks/lib/verify_guard_state.py +110 -0
  199. package/hooks/lib/workflow_state.py +206 -0
  200. package/hooks/lib/xunit_v3_operator_gate.py +596 -0
  201. package/hooks/mcp_json_repowise_nudge.py +74 -0
  202. package/hooks/mutation_adapters/__init__.py +7 -0
  203. package/hooks/mutation_adapters/__pycache__/__init__.cpython-314.pyc +0 -0
  204. package/hooks/mutation_adapters/__pycache__/lib.cpython-314.pyc +0 -0
  205. package/hooks/mutation_adapters/__pycache__/mutmut.cpython-314.pyc +0 -0
  206. package/hooks/mutation_adapters/__pycache__/pitest.cpython-314.pyc +0 -0
  207. package/hooks/mutation_adapters/__pycache__/stryker.cpython-314.pyc +0 -0
  208. package/hooks/mutation_adapters/__pycache__/stryker_net.cpython-314.pyc +0 -0
  209. package/hooks/mutation_adapters/lib.py +478 -0
  210. package/hooks/mutation_adapters/mutmut.py +188 -0
  211. package/hooks/mutation_adapters/pitest.py +266 -0
  212. package/hooks/mutation_adapters/stryker.py +157 -0
  213. package/hooks/mutation_adapters/stryker_net.py +264 -0
  214. package/hooks/mutation_gate.py +193 -0
  215. package/hooks/mutation_testing_smoke_gate.py +371 -0
  216. package/hooks/pending_review_notify.py +121 -0
  217. package/hooks/phase_marker.py +138 -0
  218. package/hooks/post_compact_state_reinject.py +180 -0
  219. package/hooks/post_format.py +115 -0
  220. package/hooks/pre_commit_knowledge_index.py +128 -0
  221. package/hooks/pre_commit_review.py +66 -0
  222. package/hooks/pre_pr_review.py +694 -0
  223. package/hooks/pre_tool_guard.py +405 -0
  224. package/hooks/py.sh +73 -0
  225. package/hooks/refactor-bash-write-patterns.json +29 -0
  226. package/hooks/refactor_test_bash_guard.py +253 -0
  227. package/hooks/refactor_test_freeze_guard.py +139 -0
  228. package/hooks/refactor_test_revert_guard.py +186 -0
  229. package/hooks/repo_review_nudge.py +287 -0
  230. package/hooks/review_verdict_recorder.py +464 -0
  231. package/hooks/scan_bash_command_for_banned_scripts.py +428 -0
  232. package/hooks/scan_worktree_for_banned_scripts.py +238 -0
  233. package/hooks/session_learning_trigger.py +248 -0
  234. package/hooks/skills_index.py +126 -0
  235. package/hooks/stryker_xunit_shim_guard.py +571 -0
  236. package/hooks/subagent_completion_guard.py +309 -0
  237. package/hooks/subagent_skill_context.py +139 -0
  238. package/hooks/task_completion_metrics.py +216 -0
  239. package/hooks/tdd_guard.py +229 -0
  240. package/hooks/telemetry.py +341 -0
  241. package/hooks/token_efficiency_review.py +194 -0
  242. package/hooks/verify_guard.py +183 -0
  243. package/hooks/verify_guard_edit_marker.py +73 -0
  244. package/hooks/version_check.py +173 -0
  245. package/knowledge/accepted-risks-schema.md +98 -0
  246. package/knowledge/adr-decision-criteria.md +64 -0
  247. package/knowledge/adversarial-review-protocol.md +139 -0
  248. package/knowledge/agent-registry.md +228 -0
  249. package/knowledge/agent-review-methodology.md +80 -0
  250. package/knowledge/ai-friendly-repo-guidelines.md +67 -0
  251. package/knowledge/architecture-assessment.md +96 -0
  252. package/knowledge/artifact-lifecycle.md +57 -0
  253. package/knowledge/cd-maturity-model.md +82 -0
  254. package/knowledge/cd-test-architecture.md +190 -0
  255. package/knowledge/ci-cd-file-scope.md +24 -0
  256. package/knowledge/codegraph-vs-graphify.md +192 -0
  257. package/knowledge/component-test-patterns.md +139 -0
  258. package/knowledge/database-change-management.md +80 -0
  259. package/knowledge/database-test-patterns.md +79 -0
  260. package/knowledge/decision-defaults.md +88 -0
  261. package/knowledge/dependency-breaking-techniques.md +116 -0
  262. package/knowledge/deployment-pipeline.md +86 -0
  263. package/knowledge/design-smells.md +122 -0
  264. package/knowledge/directory-enumeration.md +38 -0
  265. package/knowledge/domain-modeling.md +123 -0
  266. package/knowledge/evidence-bundle.md +90 -0
  267. package/knowledge/exploratory-testing-field-guide.md +122 -0
  268. package/knowledge/failure-routing.md +28 -0
  269. package/knowledge/fixture-construction.md +56 -0
  270. package/knowledge/frontend-component-architecture.md +139 -0
  271. package/knowledge/gherkin-quality-review-dispatch.md +135 -0
  272. package/knowledge/index.json +6766 -0
  273. package/knowledge/internal-collaborator-doubling.md +101 -0
  274. package/knowledge/legacy-test-strategy.md +71 -0
  275. package/knowledge/long-run-waiting.md +66 -0
  276. package/knowledge/microservice-testing.md +71 -0
  277. package/knowledge/model-pricing.json +23 -0
  278. package/knowledge/mutation-score-formulas.md +60 -0
  279. package/knowledge/object-calisthenics.md +147 -0
  280. package/knowledge/oracle-provenance.md +94 -0
  281. package/knowledge/orchestrator-script-implementation.md +185 -0
  282. package/knowledge/owasp-detection.md +148 -0
  283. package/knowledge/plan-review-rubric.md +56 -0
  284. package/knowledge/proxy-connectivity.md +62 -0
  285. package/knowledge/reactive-effect-patterns.md +73 -0
  286. package/knowledge/recon-inventory-excludes.txt +32 -0
  287. package/knowledge/references/bdd-value-guide.md +61 -0
  288. package/knowledge/references/csharp-http-client-testing.md +264 -0
  289. package/knowledge/release-strategies.md +74 -0
  290. package/knowledge/report-output-location.md +117 -0
  291. package/knowledge/report-pdf-integration.md +63 -0
  292. package/knowledge/report-print.css +129 -0
  293. package/knowledge/report-template.md +114 -0
  294. package/knowledge/report-to-pdf.md +69 -0
  295. package/knowledge/request-processing-flow.md +63 -0
  296. package/knowledge/result-verification.md +52 -0
  297. package/knowledge/review-agent-output-contract.md +121 -0
  298. package/knowledge/review-lens-classification.md +113 -0
  299. package/knowledge/review-rubric.md +62 -0
  300. package/knowledge/review-template.md +104 -0
  301. package/knowledge/rule-fixtures/A02.insecure-random-js/negative.js +1 -0
  302. package/knowledge/rule-fixtures/A02.insecure-random-js/positive.js +1 -0
  303. package/knowledge/rule-fixtures/A02.weak-hashing-md5/negative.py +1 -0
  304. package/knowledge/rule-fixtures/A02.weak-hashing-md5/positive.py +1 -0
  305. package/knowledge/rule-fixtures/A03.command-injection/negative.js +1 -0
  306. package/knowledge/rule-fixtures/A03.command-injection/positive.js +1 -0
  307. package/knowledge/rule-fixtures/A03.sql-injection/negative.js +1 -0
  308. package/knowledge/rule-fixtures/A03.sql-injection/positive.js +1 -0
  309. package/knowledge/rule-fixtures/A03.xss-innerhtml/negative.js +1 -0
  310. package/knowledge/rule-fixtures/A03.xss-innerhtml/positive.js +1 -0
  311. package/knowledge/rule-fixtures/A05.cors-wildcard/negative.js +1 -0
  312. package/knowledge/rule-fixtures/A05.cors-wildcard/positive.js +1 -0
  313. package/knowledge/rule-fixtures/A05.default-credentials/negative.js +1 -0
  314. package/knowledge/rule-fixtures/A05.default-credentials/positive.js +1 -0
  315. package/knowledge/rule-fixtures/A07.jwt-alg-none/negative.js +1 -0
  316. package/knowledge/rule-fixtures/A07.jwt-alg-none/positive.js +1 -0
  317. package/knowledge/rule-fixtures/A08.binary-formatter/negative.cs +1 -0
  318. package/knowledge/rule-fixtures/A08.binary-formatter/positive.cs +1 -0
  319. package/knowledge/rule-fixtures/A08.js-eval/negative.js +1 -0
  320. package/knowledge/rule-fixtures/A08.js-eval/positive.js +1 -0
  321. package/knowledge/rule-fixtures/A08.object-input-stream/negative.java +1 -0
  322. package/knowledge/rule-fixtures/A08.object-input-stream/positive.java +1 -0
  323. package/knowledge/schemas/disposition-register-v1.json +65 -0
  324. package/knowledge/schemas/recon-envelope-v1.json +198 -0
  325. package/knowledge/schemas/unified-finding-v1.json +72 -0
  326. package/knowledge/security-primitives-contract.md +301 -0
  327. package/knowledge/security-review-rule-map.yaml +107 -0
  328. package/knowledge/skills-registry.md +72 -0
  329. package/knowledge/task-size-classifier.md +103 -0
  330. package/knowledge/telemetry-schema.md +881 -0
  331. package/knowledge/test-automation-maturity.md +56 -0
  332. package/knowledge/test-automation-principles.md +71 -0
  333. package/knowledge/test-cadence-tradeoffs.md +68 -0
  334. package/knowledge/test-doubles.md +105 -0
  335. package/knowledge/test-file-indicators.md +22 -0
  336. package/knowledge/test-layer-gates.md +35 -0
  337. package/knowledge/test-matrix-examples/django-batch.md +24 -0
  338. package/knowledge/test-matrix-examples/dotnet-grpc-fronting-api.md +90 -0
  339. package/knowledge/test-matrix-examples/dotnet-http-consumer.md +131 -0
  340. package/knowledge/test-matrix-examples/react-node-spa.md +24 -0
  341. package/knowledge/test-matrix-examples/spring-boot-service.md +25 -0
  342. package/knowledge/test-matrix-examples/ssr-htmx.md +24 -0
  343. package/knowledge/test-organization.md +70 -0
  344. package/knowledge/test-pyramid.md +84 -0
  345. package/knowledge/test-refactoring.md +67 -0
  346. package/knowledge/test-review-division-of-labor.md +85 -0
  347. package/knowledge/test-smells.md +80 -0
  348. package/knowledge/test-stack-profiles/bdd-frameworks.md +235 -0
  349. package/knowledge/test-stack-profiles/django.md +13 -0
  350. package/knowledge/test-stack-profiles/dotnet.md +18 -0
  351. package/knowledge/test-stack-profiles/go.md +16 -0
  352. package/knowledge/test-stack-profiles/node.md +16 -0
  353. package/knowledge/test-stack-profiles/react.md +12 -0
  354. package/knowledge/test-stack-profiles/spring-boot.md +16 -0
  355. package/knowledge/test-stack-profiles/ssr-htmx.md +14 -0
  356. package/knowledge/test-stack-profiles/vue.md +12 -0
  357. package/knowledge/test-strategy.md +70 -0
  358. package/knowledge/testability-patterns.md +240 -0
  359. package/knowledge/testing-quadrants.md +44 -0
  360. package/knowledge/testing-techniques/approval.md +15 -0
  361. package/knowledge/testing-techniques/chaos.md +17 -0
  362. package/knowledge/testing-techniques/fuzz.md +15 -0
  363. package/knowledge/testing-techniques/property-based.md +15 -0
  364. package/knowledge/testing-techniques/schema-validation.md +15 -0
  365. package/knowledge/testing-techniques/screenshot.md +15 -0
  366. package/knowledge/three-phase-workflow.md +198 -0
  367. package/knowledge/value-patterns.md +55 -0
  368. package/knowledge/verification-mode.md +116 -0
  369. package/knowledge/virtual-service-libraries.md +75 -0
  370. package/knowledge/wave-consolidation-guidance.md +21 -0
  371. package/overrides/agents/Explore.md +15 -0
  372. package/overrides/agents/general-purpose.md +10 -0
  373. package/overrides/notes/autoship.md +6 -0
  374. package/overrides/notes/issues-from-assessment.md +3 -0
  375. package/overrides/notes/issues-from-plan.md +3 -0
  376. package/overrides/notes/mutation-night-watch.md +3 -0
  377. package/overrides/notes/mutation-testing.md +3 -0
  378. package/overrides/notes/pr.md +7 -0
  379. package/overrides/notes/project-init.md +6 -0
  380. package/overrides/notes/setup.md +13 -0
  381. package/overrides/notes/specs.md +3 -0
  382. package/overrides/skills/headless-run/SKILL.md +45 -0
  383. package/overrides/skills/upgrade/SKILL.md +30 -0
  384. package/overrides/skills/version/SKILL.md +25 -0
  385. package/package.json +36 -0
  386. package/scripts/authoring_digest.py +93 -0
  387. package/scripts/autoship_discover.py +121 -0
  388. package/scripts/autoship_group.py +409 -0
  389. package/scripts/autoship_proposals.py +494 -0
  390. package/scripts/autoship_queue.py +291 -0
  391. package/scripts/autoship_reclaim.py +495 -0
  392. package/scripts/build_jobs.py +108 -0
  393. package/scripts/build_rollback_point.py +240 -0
  394. package/scripts/build_slice_scope.py +157 -0
  395. package/scripts/build_wave.py +109 -0
  396. package/scripts/build_wave_reconcile.py +252 -0
  397. package/scripts/build_worktree_baseref.py +113 -0
  398. package/scripts/check_agent_scope.py +117 -0
  399. package/scripts/check_agent_tool_mapping.py +213 -0
  400. package/scripts/check_review_agent_mcp_tools.py +317 -0
  401. package/scripts/check_security_assessment_mcp_tools.py +165 -0
  402. package/scripts/checkpoint_abort.py +502 -0
  403. package/scripts/claude_setup_review.py +438 -0
  404. package/scripts/codebase_recon.py +556 -0
  405. package/scripts/coverage_config.py +623 -0
  406. package/scripts/coverage_delta_steering.py +330 -0
  407. package/scripts/coverage_discovery_dotnet.py +315 -0
  408. package/scripts/coverage_discovery_java.py +742 -0
  409. package/scripts/coverage_discovery_js.py +546 -0
  410. package/scripts/coverage_gap_ranking.py +556 -0
  411. package/scripts/coverage_readiness.py +455 -0
  412. package/scripts/coverage_report_parse.py +521 -0
  413. package/scripts/detect_bdd_convention.py +252 -0
  414. package/scripts/eval_ablation.py +376 -0
  415. package/scripts/gherkin_analysis_coverage_gate.py +306 -0
  416. package/scripts/gherkin_cross_feature_duplicate_titles_gate.py +173 -0
  417. package/scripts/gherkin_effectiveness_rollup.py +238 -0
  418. package/scripts/gherkin_failure_path_gate.py +206 -0
  419. package/scripts/gherkin_feature_merge.py +720 -0
  420. package/scripts/gherkin_stub_gate.py +163 -0
  421. package/scripts/gherkin_stub_merge.py +479 -0
  422. package/scripts/git_origin_host.py +88 -0
  423. package/scripts/install-java-static-analysis.py +110 -0
  424. package/scripts/issue_deps.py +74 -0
  425. package/scripts/lib/_bdd_markers.py +28 -0
  426. package/scripts/lib/_gherkin_text.py +93 -0
  427. package/scripts/lib/_vendored_tree.py +70 -0
  428. package/scripts/lib/autoship_state.py +397 -0
  429. package/scripts/lib/claude_md_guard.py +226 -0
  430. package/scripts/lib/deterministic_recon.py +446 -0
  431. package/scripts/lib/mcp_tool_grants.py +211 -0
  432. package/scripts/lib/plan_parse.py +386 -0
  433. package/scripts/lib/review_result.py +84 -0
  434. package/scripts/lib/review_roster.py +86 -0
  435. package/scripts/lib/session_log/__init__.py +34 -0
  436. package/scripts/lib/session_log/__pycache__/__init__.cpython-314.pyc +0 -0
  437. package/scripts/lib/session_log/__pycache__/records.cpython-314.pyc +0 -0
  438. package/scripts/lib/session_log/classify.py +231 -0
  439. package/scripts/lib/session_log/corrections.py +194 -0
  440. package/scripts/lib/session_log/discovery.py +108 -0
  441. package/scripts/lib/session_log/records.py +218 -0
  442. package/scripts/lib/session_log/redact.py +76 -0
  443. package/scripts/lib/session_log/signals.py +373 -0
  444. package/scripts/lib/session_report_downstream.py +614 -0
  445. package/scripts/lib/session_report_maintainer.py +1273 -0
  446. package/scripts/lib/session_report_shared.py +262 -0
  447. package/scripts/lib/settings_hook_guard.py +157 -0
  448. package/scripts/lib/slug.py +33 -0
  449. package/scripts/lib/stub_extractors/__init__.py +82 -0
  450. package/scripts/lib/stub_extractors/_common.py +328 -0
  451. package/scripts/lib/stub_extractors/csharp.py +19 -0
  452. package/scripts/lib/stub_extractors/go.py +173 -0
  453. package/scripts/lib/stub_extractors/java.py +18 -0
  454. package/scripts/lib/stub_extractors/jsts.py +126 -0
  455. package/scripts/mutation_stack_sections.py +149 -0
  456. package/scripts/mutation_yield_steering.py +345 -0
  457. package/scripts/orchestrator.py +895 -0
  458. package/scripts/plan_gherkin_export.py +227 -0
  459. package/scripts/plan_waves.py +208 -0
  460. package/scripts/pr_close_keyword_lint.py +108 -0
  461. package/scripts/progress_guardian.py +888 -0
  462. package/scripts/recon_inventory.py +273 -0
  463. package/scripts/review_findings_log.py +93 -0
  464. package/scripts/run_invariants.py +124 -0
  465. package/scripts/select_lenses.py +640 -0
  466. package/scripts/session_report.py +486 -0
  467. package/scripts/set_autocompact_env.py +221 -0
  468. package/scripts/ship_resume_guard.py +135 -0
  469. package/scripts/ship_review_gate.py +63 -0
  470. package/scripts/specs_convention_marker.py +103 -0
  471. package/scripts/test_improve_resume.py +277 -0
  472. package/scripts/test_review_mechanics.py +958 -0
  473. package/scripts/token_efficiency_review.py +322 -0
  474. package/scripts/verdict_scope.py +285 -0
  475. package/scripts/verify_gherkin_quality_critic_isolation.py +296 -0
  476. package/scripts/verify_tier.py +157 -0
  477. package/skills/adr-tools/SKILL.md +118 -0
  478. package/skills/agent-readiness/SKILL.md +105 -0
  479. package/skills/agent-readiness/ai_friendly_analyzers.py +326 -0
  480. package/skills/agent-readiness/scanner.py +441 -0
  481. package/skills/agent-readiness/scorecard.yaml +88 -0
  482. package/skills/api-design/SKILL.md +115 -0
  483. package/skills/apply-fixes/SKILL.md +171 -0
  484. package/skills/apply-test-doubles/SKILL.md +321 -0
  485. package/skills/artifact-lifecycle/SKILL.md +127 -0
  486. package/skills/autoship/SKILL.md +1124 -0
  487. package/skills/benchmark/SKILL.md +105 -0
  488. package/skills/branch-workflow/SKILL.md +89 -0
  489. package/skills/browse/SKILL.md +184 -0
  490. package/skills/browser-testing/SKILL.md +62 -0
  491. package/skills/browser-testing/references/playwright-patterns.md +216 -0
  492. package/skills/build/SKILL.md +422 -0
  493. package/skills/build/references/static-self-heal.md +245 -0
  494. package/skills/careful/SKILL.md +72 -0
  495. package/skills/cd-test-architecture/SKILL.md +371 -0
  496. package/skills/ci-debugging/SKILL.md +105 -0
  497. package/skills/co-evolution-audit/SKILL.md +269 -0
  498. package/skills/code-review/SKILL.md +1015 -0
  499. package/skills/code-review/examples/aggregated-sample.json +56 -0
  500. package/skills/code-review/examples/sample-report.md +41 -0
  501. package/skills/code-review/output-format.md +478 -0
  502. package/skills/code-review/scripts/activation.py +86 -0
  503. package/skills/code-review/scripts/change_impact.py +357 -0
  504. package/skills/code-review/scripts/change_shape.py +372 -0
  505. package/skills/code-review/scripts/change_size.py +212 -0
  506. package/skills/code-review/scripts/changed_file_list.py +141 -0
  507. package/skills/code-review/scripts/closing_pass.py +187 -0
  508. package/skills/code-review/scripts/consolidate.py +277 -0
  509. package/skills/code-review/scripts/contract_failure_report.py +185 -0
  510. package/skills/code-review/scripts/dispatch_reconcile.py +66 -0
  511. package/skills/code-review/scripts/dispatch_waves.py +164 -0
  512. package/skills/code-review/scripts/finding_signature.py +446 -0
  513. package/skills/code-review/scripts/ledger.py +283 -0
  514. package/skills/code-review/scripts/partition.py +169 -0
  515. package/skills/code-review/scripts/render_tiered_findings.py +274 -0
  516. package/skills/code-review/scripts/repo_invariants.py +1066 -0
  517. package/skills/code-review/scripts/review_context_pack.py +306 -0
  518. package/skills/code-review/scripts/review_round_log.py +345 -0
  519. package/skills/code-review/scripts/review_value_coverage.py +297 -0
  520. package/skills/code-review/scripts/validate_review_output.py +467 -0
  521. package/skills/code-review/sliced-mode.md +205 -0
  522. package/skills/competitive-analysis/SKILL.md +191 -0
  523. package/skills/context-loading-protocol/SKILL.md +157 -0
  524. package/skills/continue/SKILL.md +90 -0
  525. package/skills/cost-report/SKILL.md +178 -0
  526. package/skills/coverage-baseline/SKILL.md +335 -0
  527. package/skills/coverage-baseline/references/multi-project-discovery.md +202 -0
  528. package/skills/coverage-delta/SKILL.md +181 -0
  529. package/skills/coverage-delta/references/mutation-gate.md +70 -0
  530. package/skills/design-doc/SKILL.md +95 -0
  531. package/skills/design-interrogation/SKILL.md +89 -0
  532. package/skills/design-it-twice/SKILL.md +91 -0
  533. package/skills/docker-image-audit/SKILL.md +108 -0
  534. package/skills/docker-image-audit/references/install-guide.md +64 -0
  535. package/skills/docker-image-audit/references/report-template.md +73 -0
  536. package/skills/docker-image-create/SKILL.md +185 -0
  537. package/skills/domain-analysis/SKILL.md +183 -0
  538. package/skills/domain-driven-design/SKILL.md +194 -0
  539. package/skills/exploratory-testing/SKILL.md +108 -0
  540. package/skills/explore/SKILL.md +51 -0
  541. package/skills/farley-score/SKILL.md +165 -0
  542. package/skills/feature-file-validation/SKILL.md +78 -0
  543. package/skills/feature-file-validation/references/validation-rules.md +115 -0
  544. package/skills/feedback-learning/SKILL.md +414 -0
  545. package/skills/fix/SKILL.md +450 -0
  546. package/skills/freeze/SKILL.md +68 -0
  547. package/skills/frontend-architecture/SKILL.md +113 -0
  548. package/skills/gherkin-derive/SKILL.md +630 -0
  549. package/skills/gherkin-public/SKILL.md +266 -0
  550. package/skills/governance-compliance/SKILL.md +150 -0
  551. package/skills/guard/SKILL.md +75 -0
  552. package/skills/handoff/SKILL.md +139 -0
  553. package/skills/handoff/references/summary-templates.md +242 -0
  554. package/skills/harness-audit/SKILL.md +751 -0
  555. package/skills/harness-audit/scripts/lesson_validate.py +386 -0
  556. package/skills/harness-audit/scripts/redundancy_criterion.py +188 -0
  557. package/skills/headless-run/SKILL.md +45 -0
  558. package/skills/headless-run/scripts/isolated_dispatch.py +381 -0
  559. package/skills/help/SKILL.md +72 -0
  560. package/skills/hexagonal-architecture/SKILL.md +85 -0
  561. package/skills/human-oversight-protocol/SKILL.md +224 -0
  562. package/skills/issues-from-assessment/SKILL.md +223 -0
  563. package/skills/issues-from-plan/SKILL.md +133 -0
  564. package/skills/legacy-code/SKILL.md +132 -0
  565. package/skills/mermaid-diagramming/SKILL.md +120 -0
  566. package/skills/mutation-night-watch/SKILL.md +154 -0
  567. package/skills/mutation-night-watch/references/scheduling.md +135 -0
  568. package/skills/mutation-testing/SKILL.md +396 -0
  569. package/skills/mutation-testing/references/languages/csharp-stryker-net.md +676 -0
  570. package/skills/mutation-testing/references/languages/go-go-mutesting.md +95 -0
  571. package/skills/mutation-testing/references/languages/java-pitest.md +77 -0
  572. package/skills/mutation-testing/references/languages/javascript-stryker.md +188 -0
  573. package/skills/mutation-testing/references/languages/python-mutmut.md +97 -0
  574. package/skills/mutation-testing/references/time-estimation.md +34 -0
  575. package/skills/mutation-testing/references/tool-detection.md +15 -0
  576. package/skills/mutation-testing/references/workflow-callers.md +23 -0
  577. package/skills/mutation-testing/scripts/__pycache__/xunit_v3_feature_detector.cpython-314.pyc +0 -0
  578. package/skills/mutation-testing/scripts/csharp_stryker_net_slice_runner.py +635 -0
  579. package/skills/mutation-testing/scripts/csharp_stryker_net_status_loop.py +525 -0
  580. package/skills/mutation-testing/scripts/csharp_stryker_net_wrapper.py +681 -0
  581. package/skills/mutation-testing/scripts/mutation_baseline_reuse.py +292 -0
  582. package/skills/mutation-testing/scripts/mutation_exclude_policy.py +268 -0
  583. package/skills/mutation-testing/scripts/mutation_feasibility_gate.py +463 -0
  584. package/skills/mutation-testing/scripts/mutation_kill_headless.py +331 -0
  585. package/skills/mutation-testing/scripts/mutation_kill_insert.py +199 -0
  586. package/skills/mutation-testing/scripts/mutation_kill_insert_python.py +150 -0
  587. package/skills/mutation-testing/scripts/mutation_kill_loop.py +869 -0
  588. package/skills/mutation-testing/scripts/mutation_kill_loop_python.py +949 -0
  589. package/skills/mutation-testing/scripts/mutation_kill_retry.py +592 -0
  590. package/skills/mutation-testing/scripts/mutation_kill_shared.py +620 -0
  591. package/skills/mutation-testing/scripts/mutation_nightwatch.py +462 -0
  592. package/skills/mutation-testing/scripts/mutation_nightwatch_stacks.py +425 -0
  593. package/skills/mutation-testing/scripts/mutation_report.py +743 -0
  594. package/skills/mutation-testing/scripts/mutation_report_cli.py +175 -0
  595. package/skills/mutation-testing/scripts/mutation_safety_gate.py +69 -0
  596. package/skills/mutation-testing/scripts/stryker_shard_pipeline.py +847 -0
  597. package/skills/mutation-testing/scripts/stryker_shard_setup.py +440 -0
  598. package/skills/mutation-testing/scripts/stryker_timeout_retry.py +142 -0
  599. package/skills/mutation-testing/scripts/xunit_v3_feature_detector.py +341 -0
  600. package/skills/performance-benchmark/SKILL.md +174 -0
  601. package/skills/performance-benchmark/examples/report-format.md +43 -0
  602. package/skills/performance-benchmark/references/benchmark-script.md +169 -0
  603. package/skills/performance-metrics/SKILL.md +265 -0
  604. package/skills/plan/SKILL.md +199 -0
  605. package/skills/plan/references/gherkin-persistence.md +43 -0
  606. package/skills/plan/references/plan-template.md +182 -0
  607. package/skills/pr/SKILL.md +289 -0
  608. package/skills/pr/scripts/gate_retry_state.py +368 -0
  609. package/skills/project-init/README.md +141 -0
  610. package/skills/project-init/SKILL.md +1197 -0
  611. package/skills/project-init/evals/evals.json +200 -0
  612. package/skills/project-init/references/capability-tools.md +55 -0
  613. package/skills/project-init/references/configs.md +221 -0
  614. package/skills/property-based-testing/SKILL.md +121 -0
  615. package/skills/property-based-testing/fixtures/invariant_fixture.py +15 -0
  616. package/skills/property-based-testing/fixtures/js-roundtrip/README.md +42 -0
  617. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/LICENSE +21 -0
  618. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/README.md +263 -0
  619. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/cjs/fast-check.d.ts +5165 -0
  620. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/cjs/fast-check.js +12147 -0
  621. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/cjs/package.json +3 -0
  622. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/cjs/types57/fast-check.d.ts +5165 -0
  623. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/fast-check.d.ts +5165 -0
  624. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/fast-check.js +12011 -0
  625. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/rolldown-runtime-D7D4PA-g.js +13 -0
  626. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/lib/types57/fast-check.d.ts +5165 -0
  627. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/fast-check/package.json +94 -0
  628. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/LICENSE +21 -0
  629. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/README.md +168 -0
  630. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/RandomGenerator-DcXj09Ch.d.ts +14 -0
  631. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformBigInt.d.ts +15 -0
  632. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformBigInt.js +38 -0
  633. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformFloat32.d.ts +15 -0
  634. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformFloat32.js +18 -0
  635. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformFloat64.d.ts +15 -0
  636. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformFloat64.js +22 -0
  637. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformInt.d.ts +15 -0
  638. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/distribution/uniformInt.js +134 -0
  639. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/RandomGenerator-DcXj09Ch.d.ts +14 -0
  640. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformBigInt.d.ts +15 -0
  641. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformBigInt.js +37 -0
  642. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformFloat32.d.ts +15 -0
  643. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformFloat32.js +17 -0
  644. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformFloat64.d.ts +15 -0
  645. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformFloat64.js +21 -0
  646. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformInt.d.ts +15 -0
  647. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/distribution/uniformInt.js +133 -0
  648. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/congruential32.d.ts +7 -0
  649. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/congruential32.js +44 -0
  650. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/mersenne.d.ts +7 -0
  651. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/mersenne.js +90 -0
  652. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/xoroshiro128plus.d.ts +7 -0
  653. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/xoroshiro128plus.js +80 -0
  654. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/xorshift128plus.d.ts +7 -0
  655. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/generator/xorshift128plus.js +78 -0
  656. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/package.json +3 -0
  657. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/types/JumpableRandomGenerator.d.ts +16 -0
  658. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/types/JumpableRandomGenerator.js +0 -0
  659. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/types/RandomGenerator.d.ts +2 -0
  660. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/types/RandomGenerator.js +0 -0
  661. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/generateN.d.ts +6 -0
  662. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/generateN.js +8 -0
  663. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/purify.d.ts +12 -0
  664. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/purify.js +9 -0
  665. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/skipN.d.ts +6 -0
  666. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/esm/utils/skipN.js +6 -0
  667. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/congruential32.d.ts +7 -0
  668. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/congruential32.js +46 -0
  669. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/mersenne.d.ts +7 -0
  670. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/mersenne.js +92 -0
  671. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/xoroshiro128plus.d.ts +7 -0
  672. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/xoroshiro128plus.js +82 -0
  673. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/xorshift128plus.d.ts +7 -0
  674. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/generator/xorshift128plus.js +80 -0
  675. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/types/JumpableRandomGenerator.d.ts +16 -0
  676. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/types/JumpableRandomGenerator.js +0 -0
  677. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/types/RandomGenerator.d.ts +2 -0
  678. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/types/RandomGenerator.js +0 -0
  679. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/generateN.d.ts +6 -0
  680. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/generateN.js +9 -0
  681. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/purify.d.ts +12 -0
  682. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/purify.js +10 -0
  683. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/skipN.d.ts +6 -0
  684. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/lib/utils/skipN.js +7 -0
  685. package/skills/property-based-testing/fixtures/js-roundtrip/node_modules/pure-rand/package.json +133 -0
  686. package/skills/property-based-testing/fixtures/js-roundtrip/package-lock.json +1179 -0
  687. package/skills/property-based-testing/fixtures/js-roundtrip/package.json +14 -0
  688. package/skills/property-based-testing/fixtures/js-roundtrip/roundtrip.js +29 -0
  689. package/skills/property-based-testing/fixtures/js-roundtrip/roundtrip.properties.test.js +16 -0
  690. package/skills/property-based-testing/fixtures/no_property_fixture.py +10 -0
  691. package/skills/property-based-testing/fixtures/roundtrip_fixture.py +16 -0
  692. package/skills/property-based-testing/references/languages/javascript.md +54 -0
  693. package/skills/property-based-testing/scripts/detect_and_dispatch.py +80 -0
  694. package/skills/property-based-testing/scripts/hypothesis_scaffold.py +276 -0
  695. package/skills/proxy-resilience/SKILL.md +84 -0
  696. package/skills/quality-gate-pipeline/SKILL.md +184 -0
  697. package/skills/quality-targets-converge/SKILL.md +254 -0
  698. package/skills/repo-review/SKILL.md +159 -0
  699. package/skills/report-pdf/SKILL.md +66 -0
  700. package/skills/review/SKILL.md +47 -0
  701. package/skills/review-agent/SKILL.md +152 -0
  702. package/skills/review-summary/SKILL.md +73 -0
  703. package/skills/run-report/SKILL.md +70 -0
  704. package/skills/semantic-duplication-scan/SKILL.md +337 -0
  705. package/skills/semantic-scan/SKILL.md +53 -0
  706. package/skills/semgrep-analyze/SKILL.md +139 -0
  707. package/skills/setup/SKILL.md +1122 -0
  708. package/skills/ship/SKILL.md +240 -0
  709. package/skills/source-verification/SKILL.md +210 -0
  710. package/skills/source-verification/scripts/claim_extractor.py +155 -0
  711. package/skills/specs/.size-baseline.json +4 -0
  712. package/skills/specs/SKILL.md +243 -0
  713. package/skills/specs/references/completeness-checklist.md +83 -0
  714. package/skills/specs/references/extraction.md +58 -0
  715. package/skills/specs/references/glossary.md +59 -0
  716. package/skills/specs/references/persistence.md +115 -0
  717. package/skills/specs/references/predictability-check.md +77 -0
  718. package/skills/static-analysis-integration/SKILL.md +235 -0
  719. package/skills/static-analysis-integration/adapters/_envelope.py +26 -0
  720. package/skills/static-analysis-integration/adapters/jscpd-adapter.py +66 -0
  721. package/skills/static-analysis-integration/adapters/lizard-adapter.py +81 -0
  722. package/skills/static-analysis-integration/adapters/mypy-adapter.py +50 -0
  723. package/skills/static-analysis-integration/adapters/mypy-src-layout.py +93 -0
  724. package/skills/static-analysis-integration/adapters/security-review-adapter.py +212 -0
  725. package/skills/static-analysis-integration/maintenance.md +23 -0
  726. package/skills/static-analysis-integration/references/language-setup.md +228 -0
  727. package/skills/static-analysis-integration/references/sarif-parser.md +124 -0
  728. package/skills/static-analysis-integration/references/security-review-adapter.md +118 -0
  729. package/skills/static-analysis-integration/references/tool-configs.md +617 -0
  730. package/skills/static-analysis-integration/rulesets/pmd-quickstart.xml +24 -0
  731. package/skills/stryker-xunit-v2-shim/SKILL.md +274 -0
  732. package/skills/stryker-xunit-v2-shim/references/shim-howto.md +256 -0
  733. package/skills/stryker-xunit-v2-shim/scripts/generate_shim.py +143 -0
  734. package/skills/systematic-debugging/SKILL.md +130 -0
  735. package/skills/telemetry/SKILL.md +75 -0
  736. package/skills/test-audit-disable/SKILL.md +129 -0
  737. package/skills/test-design/SKILL.md +177 -0
  738. package/skills/test-design/scripts/__pycache__/internal_double_detector.cpython-314.pyc +0 -0
  739. package/skills/test-design/scripts/internal_double_detector.py +631 -0
  740. package/skills/test-design-advisor/SKILL.md +166 -0
  741. package/skills/test-driven-development/SKILL.md +169 -0
  742. package/skills/test-health/SKILL.md +262 -0
  743. package/skills/test-improve/SKILL.md +239 -0
  744. package/skills/test-improve/references/phase-0-approach-contract.md +228 -0
  745. package/skills/test-improve/references/phase-1-analyze.md +131 -0
  746. package/skills/test-improve/references/phase-2-baseline.md +121 -0
  747. package/skills/test-improve/references/phase-3-derive-gherkin.md +53 -0
  748. package/skills/test-improve/references/phase-4-plan-fixes.md +34 -0
  749. package/skills/test-improve/references/phase-5-improve.md +215 -0
  750. package/skills/test-improve/references/phase-6-refactor-decision.md +45 -0
  751. package/skills/test-improve/references/phase-7-refactor.md +44 -0
  752. package/skills/test-improve/references/phase-8-validate.md +66 -0
  753. package/skills/test-improve/references/phase-9-close-out-prompt.md +11 -0
  754. package/skills/test-improve/references/phase-9-report.md +62 -0
  755. package/skills/test-improve/references/review-loop.md +92 -0
  756. package/skills/test-improve/templates/executive-summary.md +123 -0
  757. package/skills/threat-modeling/SKILL.md +108 -0
  758. package/skills/triage/SKILL.md +211 -0
  759. package/skills/ubiquitous-language/SKILL.md +192 -0
  760. package/skills/ubiquitous-language/scripts/collect_domain_signals.py +300 -0
  761. package/skills/unfreeze/SKILL.md +37 -0
  762. package/skills/upgrade/SKILL.md +31 -0
  763. package/skills/upgrade/scripts/check_version_drift.py +113 -0
  764. package/skills/upgrade/scripts/enable_autoupdate.py +149 -0
  765. package/skills/version/SKILL.md +25 -0
  766. package/sync/__pycache__/sync_upstream.cpython-314.pyc +0 -0
  767. package/sync/sync_upstream.py +293 -0
  768. package/templates/ACCEPTED-RISKS.md.tmpl +46 -0
  769. package/templates/agents/agent-template.md +151 -0
  770. package/templates/agents/angular-testing.md +66 -0
  771. package/templates/agents/csharp-quality.md +63 -0
  772. package/templates/agents/esm-enforcer.md +52 -0
  773. package/templates/agents/front-end-testing.md +65 -0
  774. package/templates/agents/go-quality.md +65 -0
  775. package/templates/agents/python-quality.md +62 -0
  776. package/templates/agents/react-testing.md +61 -0
  777. package/templates/agents/ts-enforcer.md +60 -0
  778. package/templates/agents/twelve-factor-audit.md +49 -0
  779. package/tools/entropy-check.py +250 -0
  780. package/tools/model-hash-verify.py +213 -0
@@ -0,0 +1,266 @@
1
+ """pitest (Java/Kotlin) mutation-testing adapter — Python port of pitest.sh.
2
+
3
+ Key features (mirroring bash):
4
+ - ADAPTER_TIMEOUT default 300s (Maven startup alone can eat 20-30s).
5
+ - Source class derived from the changed file → `-DtargetClasses`.
6
+ - `-DwithHistory` for incremental runs.
7
+ - `-DtimeoutConst` / `-DtimeoutFactor` cap per-mutant wall-clock time.
8
+ - Multi-module Maven: detect the module containing the changed file → `-pl`.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import json
14
+ import os
15
+ import re
16
+ import shutil
17
+ import subprocess
18
+ import sys
19
+ from pathlib import Path
20
+
21
+ from . import lib
22
+
23
+ DEFAULT_REPORT = "target/pit-reports/mutations.xml"
24
+
25
+
26
+ def _report_path() -> Path:
27
+ return Path(os.environ.get("PITEST_REPORT", DEFAULT_REPORT))
28
+
29
+
30
+ def pitest_detect() -> bool:
31
+ """Return True when pitest is configured in this project."""
32
+ for name, needle in (
33
+ ("pom.xml", "pitest"),
34
+ ("build.gradle", "pitest"),
35
+ ("build.gradle.kts", "pitest"),
36
+ ):
37
+ p = Path(name)
38
+ if not p.is_file():
39
+ continue
40
+ try:
41
+ if needle in p.read_text():
42
+ return True
43
+ except OSError:
44
+ continue
45
+ print(
46
+ lib.emit_advisory(
47
+ "MUTATION GATE ADVISORY: pitest not found. Run /setup to "
48
+ "configure it, or add the pitest-maven plugin to pom.xml / pitest "
49
+ "plugin to build.gradle manually."
50
+ )
51
+ )
52
+ return False
53
+
54
+
55
+ _SOURCE_ROOT_RE = re.compile(
56
+ r"^.*(?:src/main/java/|src/main/kotlin/|src/main/groovy/|src/)"
57
+ )
58
+
59
+
60
+ def _java_class_from_file(file: str) -> str:
61
+ """Convert a Java/Kotlin source path to a dotted class name.
62
+
63
+ src/main/java/com/example/Calculator.java → com.example.Calculator
64
+ """
65
+ if not file:
66
+ return ""
67
+ rel = _SOURCE_ROOT_RE.sub("", file, count=1)
68
+ rel = re.sub(r"\.(java|kt|groovy|scala)$", "", rel)
69
+ return rel.replace("/", ".")
70
+
71
+
72
+ def _find_maven_module(file: str) -> str:
73
+ """Return the nearest sub-module dir containing `file`, or '' for root."""
74
+ if not file:
75
+ return ""
76
+ dir_ = os.path.dirname(file)
77
+ while dir_ and dir_ != ".":
78
+ if Path(dir_, "pom.xml").is_file() and Path("pom.xml").is_file():
79
+ return dir_
80
+ dir_ = os.path.dirname(dir_)
81
+ return ""
82
+
83
+
84
+ def _is_gradle() -> bool:
85
+ return any(
86
+ Path(name).is_file()
87
+ for name in (
88
+ "build.gradle",
89
+ "build.gradle.kts",
90
+ "settings.gradle",
91
+ "settings.gradle.kts",
92
+ )
93
+ )
94
+
95
+
96
+ def _is_pitest_source(line: str) -> bool:
97
+ """True for a non-test Java/Kotlin/Groovy/Scala source path."""
98
+ if not re.search(r"\.(java|kt|groovy|scala)$", line):
99
+ return False
100
+ return not ("Test" in line or "Spec" in line)
101
+
102
+
103
+ def _changed_source_file() -> str:
104
+ """Return the first non-test Java/Kotlin/Groovy/Scala file from git diff."""
105
+ return lib.first_changed_file(_is_pitest_source)
106
+
107
+
108
+ def _extract_test_class(command: str) -> str:
109
+ """Return the value of `-Dtest=<x>` in `command`, or ''."""
110
+ m = re.search(r"-Dtest=(\S+)", command)
111
+ return m.group(1) if m else ""
112
+
113
+
114
+ _KILLING_TEST_RE = re.compile(r"<killingTest>([^<]+)</killingTest>")
115
+ _FQ_METHOD_RE = re.compile(r"^[\w.]+\.\w+$")
116
+ _SUREFIRE_RE = re.compile(r"^(\w+)\s+(Time elapsed|PASS|FAIL)")
117
+
118
+
119
+ def pitest_parse(xml_file: Path, output_file: Path) -> None:
120
+ """Parse pitest XML + captured runner stdout; write zero-kills."""
121
+ xml_file = Path(xml_file)
122
+ output_file = Path(output_file)
123
+ runner_stdout = os.environ.get("ADAPTER_RUNNER_STDOUT", "")
124
+
125
+ if not xml_file.is_file():
126
+ print(
127
+ lib.emit_advisory(
128
+ f"MUTATION GATE ADVISORY: pitest report not found at {xml_file}. "
129
+ "Skipping mutation gate."
130
+ )
131
+ )
132
+ try:
133
+ output_file.write_text("[]")
134
+ except OSError:
135
+ pass
136
+ return
137
+
138
+ if not runner_stdout:
139
+ try:
140
+ content = xml_file.read_text()
141
+ except OSError:
142
+ content = ""
143
+ killed = content.count('status="KILLED"')
144
+ survived = content.count('status="SURVIVED"')
145
+ total = killed + survived
146
+ print(
147
+ lib.emit_advisory(
148
+ f"MUTATION GATE ADVISORY: pitest completed ({killed}/{total} "
149
+ "mutants killed) but per-test data unavailable — runner stdout "
150
+ "was not captured. Manual review recommended."
151
+ )
152
+ )
153
+ try:
154
+ output_file.write_text("[]")
155
+ except OSError:
156
+ pass
157
+ return
158
+
159
+ content = xml_file.read_text()
160
+ killing_set = {m.group(1).strip() for m in _KILLING_TEST_RE.finditer(content)}
161
+
162
+ test_methods = set()
163
+ for raw in runner_stdout.splitlines():
164
+ line = raw.strip()
165
+ if _FQ_METHOD_RE.match(line) and "." in line:
166
+ test_methods.add(line)
167
+ m = _SUREFIRE_RE.match(line)
168
+ if m:
169
+ test_methods.add(m.group(1))
170
+
171
+ zero_kills = []
172
+ for test in sorted(test_methods - killing_set):
173
+ zero_kills.append({"name": test, "file": None, "line": None, "covered": 0})
174
+ output_file.write_text(json.dumps(zero_kills))
175
+
176
+
177
+ def pitest_run(output_file: Path) -> int:
178
+ """Run pitest via Maven or Gradle and write zero-kills."""
179
+ output_file = Path(output_file)
180
+ timeout_seconds = int(os.environ.get("ADAPTER_TIMEOUT", "300"))
181
+ command = os.environ.get("ADAPTER_COMMAND", "")
182
+
183
+ changed_file = _changed_source_file()
184
+ target_class = _java_class_from_file(changed_file) if changed_file else ""
185
+ target_tests = _extract_test_class(command)
186
+
187
+ pitest_args: list[str] = [
188
+ "-DtimeoutConst=60",
189
+ "-DtimeoutFactor=2.5",
190
+ "-DoutputFormats=XML",
191
+ "-DtimestampedReports=false",
192
+ "-DwithHistory",
193
+ ]
194
+ if target_class:
195
+ pitest_args.append(f"-DtargetClasses={target_class}*")
196
+ if target_tests:
197
+ pitest_args.append(f"-DtargetTests={target_tests}")
198
+
199
+ module_flag: list[str] = []
200
+ if changed_file:
201
+ module_dir = _find_maven_module(changed_file)
202
+ if module_dir:
203
+ module_flag = ["-pl", module_dir, "--also-make-dependents"]
204
+
205
+ report_path = _report_path()
206
+
207
+ if _is_gradle():
208
+ gradle_cmd = "./gradlew" if shutil.which("./gradlew") else "gradle"
209
+ gradle_args = ["pitest"]
210
+ if target_class:
211
+ gradle_args.append(f"-PtargetClasses={target_class}*")
212
+ argv = [gradle_cmd, *gradle_args]
213
+ report_path = Path(
214
+ os.environ.get("PITEST_REPORT", "build/reports/pitest/mutations.xml")
215
+ )
216
+ else:
217
+ mvn_cmd = "./mvnw" if Path("./mvnw").is_file() else "mvn"
218
+ argv = [mvn_cmd, "pitest:mutationCoverage", *module_flag, *pitest_args]
219
+
220
+ completed = lib.run_with_timeout(
221
+ timeout_seconds,
222
+ argv,
223
+ stdout=subprocess.DEVNULL,
224
+ stderr=subprocess.DEVNULL,
225
+ )
226
+ exit_code = completed.returncode
227
+
228
+ if exit_code == 124:
229
+ hint = (
230
+ " No source file detected for scoping — scope manually with git diff."
231
+ if not target_class
232
+ else ""
233
+ )
234
+ print(
235
+ lib.emit_advisory(
236
+ f"MUTATION GATE SKIPPED: pitest timed out after {timeout_seconds}s.{hint}"
237
+ " Or: MUTATION_GATE_TIMEOUT=<seconds> to extend the limit."
238
+ )
239
+ )
240
+ output_file.write_text("[]")
241
+ return 0
242
+
243
+ if exit_code != 0 and not report_path.is_file():
244
+ print(
245
+ lib.emit_advisory(
246
+ f"MUTATION GATE ADVISORY: pitest exited with code {exit_code} and "
247
+ "produced no report. Skipping mutation gate."
248
+ )
249
+ )
250
+ output_file.write_text("[]")
251
+ return 0
252
+
253
+ pitest_parse(report_path, output_file)
254
+ return 0
255
+
256
+
257
+ def main(argv: list[str] | None = None) -> int:
258
+ args = list(sys.argv[1:] if argv is None else argv)
259
+ if not args:
260
+ print("pitest.py: OUTPUT_FILE argument required", file=sys.stderr)
261
+ return 2
262
+ return pitest_run(Path(args[0]))
263
+
264
+
265
+ if __name__ == "__main__": # pragma: no cover
266
+ sys.exit(main())
@@ -0,0 +1,157 @@
1
+ """Stryker (JS/TS) mutation-testing adapter — Python port of stryker.sh.
2
+
3
+ Contract mirrors the bash adapter:
4
+ ADAPTER_SOURCE_FILE — source file to mutate (scopes `--mutate`)
5
+ ADAPTER_TIMEOUT — outer wall-clock cap, seconds (default 300)
6
+ Output: writes zero-kill JSON to the caller-supplied output path.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import json
12
+ import os
13
+ import re
14
+ import subprocess
15
+ import sys
16
+ from pathlib import Path
17
+
18
+ from . import lib
19
+
20
+ DEFAULT_REPORT = "reports/mutation/mutation.json"
21
+
22
+
23
+ def _report_path() -> Path:
24
+ return Path(os.environ.get("STRYKER_REPORT", DEFAULT_REPORT))
25
+
26
+
27
+ def stryker_detect() -> bool:
28
+ """Return True when Stryker is available in the current project."""
29
+ if Path("node_modules/.bin/stryker").is_file():
30
+ return True
31
+ pkg = Path("package.json")
32
+ if pkg.is_file():
33
+ try:
34
+ if "@stryker-mutator/core" in pkg.read_text():
35
+ return True
36
+ except OSError:
37
+ pass
38
+ print(
39
+ lib.emit_advisory(
40
+ "MUTATION GATE ADVISORY: Stryker not installed. Run /setup to "
41
+ "install it, or add @stryker-mutator/core manually."
42
+ )
43
+ )
44
+ return False
45
+
46
+
47
+ def derive_source_file(test_file: str) -> str:
48
+ """Strip .test./.spec. from a test filename to yield the source filename.
49
+
50
+ e.g. calc.test.ts → calc.ts, calc.spec.js → calc.js.
51
+ """
52
+ return re.sub(r"\.(test|spec)\.(ts|tsx|js|jsx|mjs)$", r".\2", test_file)
53
+
54
+
55
+ def _read_configured_timeout_ms() -> int | None:
56
+ """Return the project's `timeoutMS` from Stryker config, or None.
57
+
58
+ Checks `.strykerrc.json` first (pure JSON), then greps `stryker.config.*`.
59
+ """
60
+ rc = Path(".strykerrc.json")
61
+ if rc.is_file():
62
+ try:
63
+ cfg = json.loads(rc.read_text())
64
+ val = cfg.get("timeoutMS") or cfg.get("timeout")
65
+ if val:
66
+ return int(val)
67
+ except (OSError, ValueError):
68
+ pass
69
+ return None
70
+ for name in (
71
+ "stryker.config.js",
72
+ "stryker.config.mjs",
73
+ "stryker.config.cjs",
74
+ "stryker.config.ts",
75
+ ):
76
+ p = Path(name)
77
+ if not p.is_file():
78
+ continue
79
+ try:
80
+ content = p.read_text()
81
+ except OSError:
82
+ continue
83
+ m = re.search(r"timeoutMS[\s]*:[\s]*(\d+)", content)
84
+ if m:
85
+ return int(m.group(1))
86
+ return None
87
+ return None
88
+
89
+
90
+ def stryker_run(output_file: Path) -> int:
91
+ """Run Stryker; write normalized zero-kills to `output_file`.
92
+
93
+ Advisory paths write `[]` and return 0 — the orchestrator treats those as
94
+ "gate skipped."
95
+ """
96
+ output_file = Path(output_file)
97
+ timeout_seconds = int(os.environ.get("ADAPTER_TIMEOUT", "300"))
98
+ src_file = os.environ.get("ADAPTER_SOURCE_FILE", "")
99
+
100
+ report = _report_path()
101
+ report.parent.mkdir(parents=True, exist_ok=True)
102
+
103
+ stryker_args: list[str] = ["--reporters", "json", "--coverageAnalysis", "perTest"]
104
+ if src_file:
105
+ stryker_args += ["--mutate", src_file]
106
+
107
+ argv = ["npx", "stryker", "run", *stryker_args]
108
+ completed = lib.run_with_timeout(
109
+ timeout_seconds,
110
+ argv,
111
+ stdout=subprocess.DEVNULL,
112
+ stderr=subprocess.DEVNULL,
113
+ )
114
+ exit_code = completed.returncode
115
+
116
+ if exit_code == 124:
117
+ configured = _read_configured_timeout_ms()
118
+ hint = (
119
+ ""
120
+ if configured is not None
121
+ else " Add 'timeoutMS: <ms>' to stryker.config.js to cap per-mutant runs."
122
+ )
123
+ print(
124
+ lib.emit_advisory(
125
+ f"MUTATION GATE SKIPPED: Stryker timed out after {timeout_seconds}s.{hint}"
126
+ " Or: MUTATION_GATE_TIMEOUT=<seconds> to extend the outer limit."
127
+ )
128
+ )
129
+ output_file.write_text("[]")
130
+ return 0
131
+
132
+ if exit_code != 0 and not report.is_file():
133
+ print(
134
+ lib.emit_advisory(
135
+ f"MUTATION GATE ADVISORY: Stryker exited with code {exit_code} and "
136
+ "produced no report. Skipping mutation gate."
137
+ )
138
+ )
139
+ output_file.write_text("[]")
140
+ return 0
141
+
142
+ advisory = lib.parse_stryker_kills(report, output_file)
143
+ if advisory is not None:
144
+ print(advisory)
145
+ return 0
146
+
147
+
148
+ def main(argv: list[str] | None = None) -> int:
149
+ args = list(sys.argv[1:] if argv is None else argv)
150
+ if not args:
151
+ print("stryker.py: OUTPUT_FILE argument required", file=sys.stderr)
152
+ return 2
153
+ return stryker_run(Path(args[0]))
154
+
155
+
156
+ if __name__ == "__main__": # pragma: no cover
157
+ sys.exit(main())
@@ -0,0 +1,264 @@
1
+ """Stryker.NET (C#) mutation-testing adapter — Python port of stryker-net.sh.
2
+
3
+ Uses the same JSON schema as Stryker JS, so `lib.parse_stryker_kills` is
4
+ shared. `stryker_net_run` intentionally stays separate from `stryker_run`:
5
+ the CLI surfaces diverge, only the JSON parser is the stable contract.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import functools
11
+ import json
12
+ import os
13
+ import re
14
+ import shutil
15
+ import subprocess
16
+ import sys
17
+ from pathlib import Path
18
+
19
+ from . import lib
20
+
21
+ DEFAULT_REPORT = "StrykerOutput/mutation-report.json"
22
+
23
+ #: Manual/test override for `stryker_net_version()` — an exact "X.Y.Z" (or
24
+ #: any string containing one) value. Takes precedence over the real `dotnet
25
+ #: stryker --version` probe. Exists so `stryker_xunit_shim_guard.py` (which
26
+ #: runs in a real subprocess in its own tests, so it can't monkeypatch this
27
+ #: module's internals) can pin a version, and as a manual escape hatch when
28
+ #: the installed CLI's own `--version` output can't be trusted (#2184).
29
+ _VERSION_OVERRIDE_ENV = "DEV_TEAM_STRYKER_NET_VERSION"
30
+
31
+ _VERSION_RE = re.compile(r"(\d+)\.(\d+)\.(\d+)")
32
+
33
+
34
+ def _default_report_path() -> Path:
35
+ return Path(os.environ.get("STRYKER_NET_REPORT", DEFAULT_REPORT))
36
+
37
+
38
+ @functools.lru_cache(maxsize=1)
39
+ def _stryker_net_version_probe() -> str | None:
40
+ """Cached raw stdout of `dotnet stryker --version`, or `None` when the
41
+ CLI can't be run at all (no `dotnet` on PATH, the subprocess failed to
42
+ start, or it exited non-zero).
43
+
44
+ Extracted as the single shared probe (#2184) — `stryker_net_detect()`
45
+ and `stryker_net_version()` both read through this rather than each
46
+ shelling out to `dotnet stryker --version` independently. Cached for
47
+ the lifetime of the process: this hook's own process only ever runs one
48
+ Stryker invocation, so a second call within it (e.g. detect-then-version
49
+ in the same run) should not pay for a second subprocess.
50
+
51
+ Test-only reset: `_stryker_net_version_probe.cache_clear()` (a plain
52
+ `functools.lru_cache` method) — required before any in-process test that
53
+ monkeypatches `subprocess.run`/`shutil.which`, since this cache is
54
+ otherwise shared across the whole pytest process.
55
+ """
56
+ if shutil.which("dotnet") is None:
57
+ return None
58
+ try:
59
+ proc = subprocess.run(
60
+ ["dotnet", "stryker", "--version"],
61
+ capture_output=True,
62
+ text=True,
63
+ check=False,
64
+ timeout=30,
65
+ )
66
+ except (OSError, subprocess.SubprocessError):
67
+ return None
68
+ if proc.returncode != 0:
69
+ return None
70
+ return proc.stdout or ""
71
+
72
+
73
+ def _parse_version(text: str) -> tuple[int, int, int] | None:
74
+ """First `MAJOR.MINOR.PATCH` substring in `text`, or `None` when none is
75
+ found. Deliberately permissive about surrounding text (a `v` prefix, a
76
+ package name, a `+`-separated build/prerelease suffix like
77
+ `5.0.0-preview+abcdef`) — only the leading three dot-separated integers
78
+ are meaningful for the `>= 5.0.0` comparison this exists for."""
79
+ match = _VERSION_RE.search(text)
80
+ if match is None:
81
+ return None
82
+ return (int(match.group(1)), int(match.group(2)), int(match.group(3)))
83
+
84
+
85
+ def stryker_net_version() -> tuple[int, int, int] | None:
86
+ """Parsed `(major, minor, patch)` of the installed Stryker.NET CLI, or
87
+ `None` when it can't be determined (not installed, `dotnet` missing, or
88
+ unparseable `--version` output) — callers must fail closed on `None`,
89
+ never assume a version (#2184).
90
+
91
+ Honors `DEV_TEAM_STRYKER_NET_VERSION` first (see that constant's
92
+ docstring); otherwise reads the shared, cached `dotnet stryker
93
+ --version` probe.
94
+ """
95
+ override = os.environ.get(_VERSION_OVERRIDE_ENV)
96
+ text = override if override is not None else _stryker_net_version_probe()
97
+ if text is None:
98
+ return None
99
+ return _parse_version(text)
100
+
101
+
102
+ def stryker_net_detect() -> bool:
103
+ """Return True when Stryker.NET is available."""
104
+ tools = Path(".config/dotnet-tools.json")
105
+ if tools.is_file():
106
+ try:
107
+ if "dotnet-stryker" in tools.read_text():
108
+ return True
109
+ except OSError:
110
+ pass
111
+ if _stryker_net_version_probe() is not None:
112
+ return True
113
+ print(
114
+ lib.emit_advisory(
115
+ "MUTATION GATE ADVISORY: Stryker.NET not installed. Run /setup "
116
+ "to install it, or run: dotnet tool install dotnet-stryker"
117
+ )
118
+ )
119
+ return False
120
+
121
+
122
+ def _shard_for_file(changed_file: str) -> Path | None:
123
+ """Return the stryker-config.shard-*.json whose `mutate` pattern covers
124
+ `changed_file`, or None when no shard matches.
125
+ """
126
+ if not changed_file:
127
+ return None
128
+ for shard_cfg in sorted(Path(".").glob("stryker-config.shard-*.json")):
129
+ try:
130
+ cfg = json.loads(shard_cfg.read_text())
131
+ stryker_cfg = cfg.get("stryker-config") or {}
132
+ patterns = stryker_cfg.get("mutate") or []
133
+ if not patterns:
134
+ continue
135
+ pattern = patterns[0]
136
+ # pattern is like 'src/Foo.Bar/**/*.cs' — extract prefix before '/**'
137
+ src_prefix = pattern.split("/**")[0]
138
+ except (OSError, ValueError):
139
+ continue
140
+ if not src_prefix:
141
+ continue
142
+ if changed_file.startswith((src_prefix + "/", src_prefix)):
143
+ return shard_cfg
144
+ return None
145
+
146
+
147
+ def _is_cs_source(line: str) -> bool:
148
+ """True for a non-test C# source path."""
149
+ if not line.endswith(".cs"):
150
+ return False
151
+ return not ("Test" in line or "Spec" in line)
152
+
153
+
154
+ def _changed_cs_file() -> str:
155
+ """Return the newest non-test C# file changed in HEAD (or cached), or ''."""
156
+ return lib.first_changed_file(_is_cs_source)
157
+
158
+
159
+ def stryker_net_run(output_file: Path) -> int:
160
+ """Run dotnet-stryker; write normalized zero-kills to `output_file`."""
161
+ output_file = Path(output_file)
162
+ timeout_seconds = int(os.environ.get("ADAPTER_TIMEOUT", "600"))
163
+
164
+ report_path = _default_report_path()
165
+ report_path.parent.mkdir(parents=True, exist_ok=True)
166
+
167
+ stryker_args: list[str] = [
168
+ "--reporter",
169
+ "json",
170
+ "--coverage-analysis",
171
+ "perTest",
172
+ "--mutation-level",
173
+ "Standard",
174
+ ]
175
+
176
+ changed_file = _changed_cs_file()
177
+ config_flag: list[str] = []
178
+ if changed_file:
179
+ shard_cfg = _shard_for_file(changed_file)
180
+ if shard_cfg is not None:
181
+ config_flag = ["--config-file", str(shard_cfg)]
182
+ report_path = Path("StrykerOutput/gate-shard/reports/mutation-report.json")
183
+ report_path.parent.mkdir(parents=True, exist_ok=True)
184
+
185
+ if not config_flag and Path("stryker-config.json").is_file():
186
+ config_flag = ["--config-file", "stryker-config.json"]
187
+
188
+ if changed_file and config_flag:
189
+ stryker_args += ["--mutate", f"**/{Path(changed_file).name}"]
190
+ report_path = Path("StrykerOutput/gate-shard/reports/mutation-report.json")
191
+
192
+ stryker_args += ["--output", "StrykerOutput/gate-shard"]
193
+
194
+ if os.environ.get("CI") != "true":
195
+ since = os.environ.get("STRYKER_SINCE_TARGET", "")
196
+ if since:
197
+ # bash used `--since:<ref>`; keep the same wire form
198
+ stryker_args.append(f"--since:{since}")
199
+
200
+ argv = ["dotnet", "stryker", *config_flag, *stryker_args]
201
+
202
+ completed = lib.run_with_timeout(
203
+ timeout_seconds,
204
+ argv,
205
+ stdout=subprocess.PIPE,
206
+ stderr=subprocess.STDOUT,
207
+ )
208
+ exit_code = completed.returncode
209
+ run_output = (completed.stdout or b"").decode("utf-8", "replace")
210
+
211
+ # Surface the coverage-capture failure (#1156): Stryker disabled per-test
212
+ # optimisation and fell back to whole-suite-per-mutant. The mutant-kill loop
213
+ # is infeasible on this suite (xunit.v3); a single-pass advisory with
214
+ # coverage-analysis off is the way forward. detect_coverage_capture_failure
215
+ # is the branchable predicate later slices (#1158) consume.
216
+ if lib.detect_coverage_capture_failure(run_output):
217
+ print(
218
+ lib.emit_advisory(
219
+ "MUTATION GATE ADVISORY: Stryker.NET coverage capture failed — "
220
+ "per-test optimisation disabled, falling back to "
221
+ "whole-suite-per-mutant. The mutant-kill loop is infeasible on "
222
+ "this suite (xunit.v3); prefer a single-pass advisory run with "
223
+ "coverage-analysis off, or waive. See #1156."
224
+ )
225
+ )
226
+
227
+ if exit_code == 124:
228
+ print(
229
+ lib.emit_advisory(
230
+ f"MUTATION GATE SKIPPED: Stryker.NET timed out after {timeout_seconds}s. "
231
+ "For large repos, run stryker-setup.py to generate shard configs "
232
+ "(reduces scope to one project). Or: ADAPTER_TIMEOUT=<seconds> to "
233
+ "extend the limit."
234
+ )
235
+ )
236
+ output_file.write_text("[]")
237
+ return 0
238
+
239
+ if exit_code != 0 and not report_path.is_file():
240
+ print(
241
+ lib.emit_advisory(
242
+ f"MUTATION GATE ADVISORY: Stryker.NET exited with code {exit_code} "
243
+ "and produced no report. Skipping mutation gate."
244
+ )
245
+ )
246
+ output_file.write_text("[]")
247
+ return 0
248
+
249
+ advisory = lib.parse_stryker_kills(report_path, output_file)
250
+ if advisory is not None:
251
+ print(advisory)
252
+ return 0
253
+
254
+
255
+ def main(argv: list[str] | None = None) -> int:
256
+ args = list(sys.argv[1:] if argv is None else argv)
257
+ if not args:
258
+ print("stryker_net.py: OUTPUT_FILE argument required", file=sys.stderr)
259
+ return 2
260
+ return stryker_net_run(Path(args[0]))
261
+
262
+
263
+ if __name__ == "__main__": # pragma: no cover
264
+ sys.exit(main())