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,478 @@
1
+ """Shared library for mutation-gate hook and adapters — Python port of lib.sh.
2
+
3
+ Adapter contract (mirrors the bash lib.sh header):
4
+
5
+ Inputs (env vars set by mutation-gate orchestrator):
6
+ ADAPTER_COMMAND — the original test command (used for pitest class extraction)
7
+ ADAPTER_SOURCE_FILE — path to the source file under test (JS/TS adapters)
8
+ ADAPTER_TIMEOUT — seconds (from MUTATION_GATE_TIMEOUT, default 60)
9
+ ADAPTER_RUNNER_STDOUT — captured test runner stdout (for pitest test-list derivation)
10
+
11
+ Output: adapter writes normalized zero-kill list to $TMPDIR/mutation-gate/zero-kills.json
12
+ Format: [{"name":"TestName","file":"path.ts","line":12,"covered":4}]
13
+ "line" is null when unknown.
14
+
15
+ Exit codes: 0 = success or advisory (orchestrator reads zero-kills.json), 1 = internal error.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import hashlib
21
+ import json
22
+ import os
23
+ import re
24
+ import shutil
25
+ import subprocess
26
+ import sys
27
+ import time
28
+ from collections.abc import Callable, Sequence
29
+ from pathlib import Path
30
+ from typing import Any
31
+
32
+ # ---------------------------------------------------------------------------
33
+ # _timeout — portable wrapper: `timeout` > `gtimeout` > unbounded fallback
34
+ # ---------------------------------------------------------------------------
35
+
36
+
37
+ def run_with_timeout(
38
+ seconds: int,
39
+ argv: Sequence[str],
40
+ **kwargs: Any,
41
+ ) -> subprocess.CompletedProcess[bytes]:
42
+ """Run `argv` with the given `seconds` wall-clock cap, mirroring bash `_timeout`.
43
+
44
+ Prefers `timeout`/`gtimeout` on PATH (so the runner keeps its bash-native
45
+ kill semantics on hosts that have coreutils); falls back to
46
+ `subprocess.run(..., timeout=...)` when neither is available. On timeout,
47
+ return code is 124 to match `timeout(1)`'s convention.
48
+
49
+ All extra kwargs pass through to `subprocess.run`. Callers pass `check=False`
50
+ when they want to inspect the exit code themselves.
51
+ """
52
+ kwargs.setdefault("check", False)
53
+ timeout_bin = shutil.which("timeout") or shutil.which("gtimeout")
54
+ if timeout_bin is not None:
55
+ # `check` is already guaranteed present via the `setdefault` above;
56
+ # ruff can't see through `**kwargs` to confirm it statically.
57
+ return subprocess.run([timeout_bin, str(seconds), *argv], **kwargs) # noqa: PLW1510
58
+ # No coreutils timeout available — emit the same advisory as bash lib
59
+ # to stderr so the JSON stdout channel stays clean.
60
+ sys.stderr.write(
61
+ "mutation-gate: timeout unavailable (install coreutils for gtimeout); "
62
+ "run is unbounded\n"
63
+ )
64
+ try:
65
+ # `check` is already guaranteed present via the `setdefault` above;
66
+ # ruff can't see through `**kwargs` to confirm it statically.
67
+ return subprocess.run(list(argv), timeout=seconds, **kwargs) # noqa: PLW1510
68
+ except subprocess.TimeoutExpired as exc:
69
+ # Synthesize a CompletedProcess with the timeout-native exit code so
70
+ # callers keep their `exit == 124` branch.
71
+ return subprocess.CompletedProcess(
72
+ args=list(argv),
73
+ returncode=124,
74
+ stdout=exc.stdout or b"",
75
+ stderr=exc.stderr or b"",
76
+ )
77
+
78
+
79
+ # ---------------------------------------------------------------------------
80
+ # JSON output helpers
81
+ #
82
+ # The bash lib pipes through `jq -n` to build objects; here we compose with
83
+ # `json.dumps` and preserve the same key order + no trailing newline so the
84
+ # hook's JSON decision channel stays byte-parity with the bash implementation.
85
+ # ---------------------------------------------------------------------------
86
+
87
+
88
+ def emit_block(reason: str) -> str:
89
+ """Return `{"decision":"block","reason":"..."}` as compact JSON (no trailing \\n)."""
90
+ return json.dumps({"decision": "block", "reason": reason})
91
+
92
+
93
+ # Canonical coverage-capture-failure signal (see #1156). Verbatim from
94
+ # Stryker.NET's own log: src/Stryker.Core/Stryker.Core/CoverageAnalysis/
95
+ # CoverageAnalyser.cs emits "It looks like the test coverage capture failed.
96
+ # Disable coverage based optimisation." when the initial per-test coverage pass
97
+ # yields zero covered mutations, then calls AssumeAllTestsAreNeeded() —
98
+ # silently falling back to whole-suite-per-mutant. The British "optimisation"
99
+ # spelling matches the source. Kept byte-identical with the copy in the status
100
+ # loop (csharp_stryker_net_status_loop.py); the two live in different import
101
+ # roots (hooks/ vs skills/) so they cannot share a constant — the equivalence
102
+ # is armored by test_coverage_capture_regex_matches_status_loop.
103
+ _COVERAGE_CAPTURE_FAILURE_RE = re.compile(
104
+ r"test coverage capture failed|disable coverage based optimisation",
105
+ re.IGNORECASE,
106
+ )
107
+
108
+
109
+ def detect_coverage_capture_failure(text: str) -> bool:
110
+ """True when `text` (Stryker's captured stdout/stderr) shows per-test
111
+ coverage capture failed and Stryker fell back to whole-suite-per-mutant.
112
+
113
+ A pure predicate later slices (#1158's feasibility gate) branch on to
114
+ decide loop-vs-degrade. Matches either half of 'It looks like the test
115
+ coverage capture failed. Disable coverage based optimisation.'
116
+ """
117
+ if not text:
118
+ return False
119
+ return bool(_COVERAGE_CAPTURE_FAILURE_RE.search(text))
120
+
121
+
122
+ def emit_advisory(message: str) -> str:
123
+ """Return the PostToolUse additionalContext envelope for an advisory message."""
124
+ return json.dumps(
125
+ {
126
+ "hookSpecificOutput": {
127
+ "hookEventName": "PostToolUse",
128
+ "additionalContext": message,
129
+ }
130
+ }
131
+ )
132
+
133
+
134
+ # ---------------------------------------------------------------------------
135
+ # State file management — mirrors bash lib
136
+ #
137
+ # Location: $TMPDIR/mutation-gate/session-<12-char sha256 of cwd>
138
+ # TTL: 4 hours (14400 seconds)
139
+ # ---------------------------------------------------------------------------
140
+
141
+
142
+ _STATE_TTL_SECONDS = 14400
143
+
144
+
145
+ def _state_dir() -> Path:
146
+ return Path(os.environ.get("TMPDIR", "/tmp")) / "mutation-gate"
147
+
148
+
149
+ def state_file_path(cwd: Path | None = None) -> Path:
150
+ """Return the per-project state file path (`session-<hash>`)."""
151
+ base = str(cwd if cwd is not None else Path.cwd())
152
+ digest = hashlib.sha256(base.encode("utf-8")).hexdigest()[:12]
153
+ return _state_dir() / f"session-{digest}"
154
+
155
+
156
+ def _purge_stale_states(state_dir: Path) -> None:
157
+ """Delete session-* files older than TTL. Best-effort; errors ignored."""
158
+ if not state_dir.is_dir():
159
+ return
160
+ now = time.time()
161
+ for path in state_dir.glob("session-*"):
162
+ try:
163
+ if now - path.stat().st_mtime > _STATE_TTL_SECONDS:
164
+ path.unlink()
165
+ except OSError:
166
+ pass
167
+
168
+
169
+ def write_state(result: str, event_json: str, cwd: Path | None = None) -> None:
170
+ """Write the state file from a PostToolUse event body.
171
+
172
+ `result` is "pass" or "fail"; `event_json` is the raw stdin JSON string —
173
+ we extract `tool_response.output` and truncate it to 64 KiB, matching the
174
+ bash `head -c 65536` behaviour.
175
+ """
176
+ state_dir = _state_dir()
177
+ state_dir.mkdir(parents=True, exist_ok=True)
178
+ _purge_stale_states(state_dir)
179
+ try:
180
+ event = json.loads(event_json) if event_json else {}
181
+ except (TypeError, ValueError):
182
+ event = {}
183
+ tool_response = event.get("tool_response") or {}
184
+ runner_stdout = tool_response.get("output") or ""
185
+ if len(runner_stdout) > 65536:
186
+ runner_stdout = runner_stdout[:65536]
187
+ payload = {
188
+ "result": result,
189
+ "timestamp": int(time.time()),
190
+ "runner_stdout": runner_stdout,
191
+ }
192
+ target = state_file_path(cwd)
193
+ target.write_text(json.dumps(payload))
194
+
195
+
196
+ def read_state(cwd: Path | None = None) -> str:
197
+ """Return the state JSON as a string, or `""` if absent / stale.
198
+
199
+ Stale files (> TTL) are deleted lazily on read so subsequent calls don't
200
+ keep re-reading them.
201
+ """
202
+ path = state_file_path(cwd)
203
+ if not path.is_file():
204
+ return ""
205
+ try:
206
+ data = json.loads(path.read_text())
207
+ except (OSError, ValueError):
208
+ return ""
209
+ ts = data.get("timestamp") or 0
210
+ if int(time.time()) - int(ts) > _STATE_TTL_SECONDS:
211
+ try:
212
+ path.unlink()
213
+ except OSError:
214
+ pass
215
+ return ""
216
+ return path.read_text()
217
+
218
+
219
+ # ---------------------------------------------------------------------------
220
+ # Result detection
221
+ # ---------------------------------------------------------------------------
222
+
223
+
224
+ _PASS_PATTERNS = re.compile(
225
+ r"passing|tests run.*failures: 0|all tests passed|✓|ok [0-9]",
226
+ re.IGNORECASE,
227
+ )
228
+ _FAIL_PATTERNS = re.compile(
229
+ r"failing|failures: [1-9]|error:|FAILED",
230
+ re.IGNORECASE,
231
+ )
232
+
233
+
234
+ def detect_result(event_json: str) -> str:
235
+ """Return "pass" or "fail" for a PostToolUse event.
236
+
237
+ Primary signal: `tool_response.exit_code`. Secondary: stdout patterns —
238
+ used for runners that always exit 0. Default: "fail" when uncertain (the
239
+ bash lib does the same).
240
+ """
241
+ try:
242
+ event = json.loads(event_json) if event_json else {}
243
+ except (TypeError, ValueError):
244
+ event = {}
245
+ tool_response = event.get("tool_response") or {}
246
+ exit_code = tool_response.get("exit_code")
247
+ if exit_code == 0:
248
+ return "pass"
249
+ if exit_code is not None and exit_code != -1:
250
+ return "fail"
251
+ output = tool_response.get("output") or ""
252
+ if _PASS_PATTERNS.search(output):
253
+ return "pass"
254
+ if _FAIL_PATTERNS.search(output):
255
+ return "fail"
256
+ return "fail"
257
+
258
+
259
+ def is_red_to_green(prev_result: str, cur_result: str) -> bool:
260
+ """Return True if `prev_result` = fail and `cur_result` = pass."""
261
+ return prev_result == "fail" and cur_result == "pass"
262
+
263
+
264
+ # ---------------------------------------------------------------------------
265
+ # Test command detection
266
+ # ---------------------------------------------------------------------------
267
+
268
+
269
+ def _tokens(command: str) -> list[str]:
270
+ return command.strip().split()
271
+
272
+
273
+ def is_test_command(command: str) -> bool:
274
+ """Return True when `command` looks like a supported test runner invocation."""
275
+ tokens = _tokens(command)
276
+ if not tokens:
277
+ return False
278
+ head = tokens[0]
279
+ if head == "npm":
280
+ if len(tokens) >= 2 and tokens[1] == "test":
281
+ return True
282
+ return len(tokens) >= 3 and tokens[1] == "run" and tokens[2] == "test"
283
+ if head == "npx" and len(tokens) >= 2 and tokens[1] in {"vitest", "jest"}:
284
+ return True
285
+ if (
286
+ head in {"mvn", "./mvnw", "mvnw"}
287
+ and len(tokens) >= 2
288
+ and tokens[1]
289
+ in {
290
+ "test",
291
+ "verify",
292
+ }
293
+ ):
294
+ return True
295
+ if (
296
+ head in {"gradle", "./gradlew", "gradlew"}
297
+ and len(tokens) >= 2
298
+ and tokens[1] == "test"
299
+ ):
300
+ return True
301
+ if head == "dotnet" and len(tokens) >= 2 and tokens[1] == "test":
302
+ return True
303
+ if head == "pytest":
304
+ return True
305
+ if head in {"python", "python3"} and any("pytest" in t for t in tokens[1:]):
306
+ return True
307
+ if head == "go" and len(tokens) >= 2 and tokens[1] == "test":
308
+ return True
309
+ return head == "cargo" and len(tokens) >= 2 and tokens[1] == "test"
310
+
311
+
312
+ # ---------------------------------------------------------------------------
313
+ # Adapter dispatch
314
+ # ---------------------------------------------------------------------------
315
+
316
+
317
+ def detect_adapter(command: str) -> str:
318
+ """Return one of stryker | pitest | stryker-net | mutmut | none."""
319
+ tokens = _tokens(command)
320
+ if not tokens:
321
+ return "none"
322
+ head = tokens[0]
323
+ if head == "npm" and (
324
+ (len(tokens) >= 2 and tokens[1] == "test")
325
+ or (len(tokens) >= 3 and tokens[1] == "run" and tokens[2] == "test")
326
+ ):
327
+ return "stryker"
328
+ if head == "npx" and len(tokens) >= 2 and tokens[1] in {"vitest", "jest"}:
329
+ return "stryker"
330
+ if (
331
+ head in {"mvn", "./mvnw", "mvnw"}
332
+ and len(tokens) >= 2
333
+ and tokens[1]
334
+ in {
335
+ "test",
336
+ "verify",
337
+ }
338
+ ):
339
+ return "pitest"
340
+ if (
341
+ head in {"gradle", "./gradlew", "gradlew"}
342
+ and len(tokens) >= 2
343
+ and tokens[1] == "test"
344
+ ):
345
+ return "pitest"
346
+ if head == "dotnet" and len(tokens) >= 2 and tokens[1] == "test":
347
+ return "stryker-net"
348
+ if head == "pytest":
349
+ return "mutmut"
350
+ if head in {"python", "python3"}:
351
+ # python -m pytest, python3 -m pytest, python somefile-pytest, python -m unittest
352
+ for t in tokens[1:]:
353
+ if "pytest" in t or "unittest" in t:
354
+ return "mutmut"
355
+ return "none"
356
+ return "none"
357
+
358
+
359
+ # ---------------------------------------------------------------------------
360
+ # First changed source file — shared by pitest / stryker-net / mutmut adapters
361
+ #
362
+ # Each adapter needs "the first non-test source file touched by this change"
363
+ # to scope its mutation run (target class, --mutate pattern, --paths-to-mutate).
364
+ # The traversal (git diff --name-only HEAD, falling back to --cached) is
365
+ # identical across adapters; only the extension set and test-name exclusion
366
+ # differ, so those are supplied as a single predicate.
367
+ # ---------------------------------------------------------------------------
368
+
369
+
370
+ def first_changed_file(is_source_predicate: Callable[[str], bool]) -> str:
371
+ """Return the first changed file for which `is_source_predicate` is True.
372
+
373
+ Checks `git diff --name-only HEAD` first, then falls back to
374
+ `git diff --cached --name-only` (mirrors the bash adapters' behaviour of
375
+ preferring unstaged/working-tree changes over already-staged ones).
376
+ Returns "" when git is unavailable or no line satisfies the predicate.
377
+ """
378
+ for cmd in (
379
+ ["git", "diff", "--name-only", "HEAD"],
380
+ ["git", "diff", "--cached", "--name-only"],
381
+ ):
382
+ try:
383
+ proc = subprocess.run(cmd, capture_output=True, text=True, check=False)
384
+ except (FileNotFoundError, OSError):
385
+ return ""
386
+ for line in proc.stdout.splitlines():
387
+ if is_source_predicate(line):
388
+ return line
389
+ return ""
390
+
391
+
392
+ # ---------------------------------------------------------------------------
393
+ # Zero-kill parsing (Stryker JSON schema, shared by stryker + stryker-net)
394
+ # ---------------------------------------------------------------------------
395
+
396
+
397
+ def parse_stryker_kills(report_file: Path, output_file: Path) -> str | None:
398
+ """Parse Stryker JSON, write zero-kills to `output_file`.
399
+
400
+ Returns None on success; returns the advisory JSON string when the report
401
+ is missing (mirrors bash: bash emits the advisory to stdout, callers
402
+ forward it). Caller writes `[]` to `output_file` in that path already so
403
+ the return value is only consumed for the advisory.
404
+ """
405
+ report_file = Path(report_file)
406
+ output_file = Path(output_file)
407
+ if not report_file.is_file():
408
+ advisory = emit_advisory(
409
+ f"MUTATION GATE ADVISORY: Stryker report not found at {report_file}. "
410
+ "Run completed without mutation gate."
411
+ )
412
+ try:
413
+ output_file.write_text("[]")
414
+ except OSError:
415
+ pass
416
+ return advisory
417
+
418
+ data = json.loads(report_file.read_text())
419
+ mutants = data.get("mutants", [])
420
+
421
+ killing_set = set()
422
+ coverage: dict[str, int] = {}
423
+ for mutant in mutants:
424
+ for t in mutant.get("killedBy", []):
425
+ killing_set.add(t)
426
+ for t in mutant.get("coveredBy", []):
427
+ coverage[t] = coverage.get(t, 0) + 1
428
+
429
+ zero_kills: list[dict[str, Any]] = []
430
+ for test in sorted(set(coverage.keys()) - killing_set):
431
+ zero_kills.append(
432
+ {
433
+ "name": test,
434
+ "file": None,
435
+ "line": None,
436
+ "covered": coverage[test],
437
+ }
438
+ )
439
+
440
+ output_file.write_text(json.dumps(zero_kills))
441
+ return None
442
+
443
+
444
+ # ---------------------------------------------------------------------------
445
+ # Blocking-reason formatter — same output as the bash inline Python heredoc.
446
+ # ---------------------------------------------------------------------------
447
+
448
+
449
+ def format_blocking_reason(zero_kills_file: Path, command: str) -> str:
450
+ """Return the multi-line human-readable reason string for a blocked gate.
451
+
452
+ `command` is unused (kept for signature parity with bash) — the message
453
+ catalogs the zero-kill tests read from `zero_kills_file`.
454
+ """
455
+ with open(zero_kills_file) as f:
456
+ zero_kills = json.load(f)
457
+
458
+ lines = [
459
+ "MUTATION GATE BLOCKED: zero-kill tests detected after RED-GREEN transition",
460
+ "",
461
+ "These tests covered mutants but killed none — they provide no regression safety.",
462
+ "A useful assertion changes the expected value when the implementation changes",
463
+ "(e.g., assert result === 5, not assert result !== undefined).",
464
+ "Rewrite each to assert the precise return value or side effect, or remove it:",
465
+ "",
466
+ ]
467
+ for zk in zero_kills:
468
+ name = zk.get("name", "<unknown>")
469
+ file_ = zk.get("file") or "<unknown>"
470
+ line = zk.get("line")
471
+ loc = f"({file_}:{line})" if line else f"({file_}:<unknown>)"
472
+ covered = zk.get("covered", 0)
473
+ lines.append(f" - {name} {loc}")
474
+ lines.append(f" Covered {covered} mutants, killed 0")
475
+ lines.append("")
476
+
477
+ lines.append("Fix these tests before continuing.")
478
+ return "\n".join(lines)
@@ -0,0 +1,188 @@
1
+ """mutmut (Python) mutation-testing adapter — Python port of mutmut.sh.
2
+
3
+ mutmut scopes to a single file via `--paths-to-mutate` and completes in
4
+ seconds-to-minutes for typical Python unit test suites. mutmut has no
5
+ `--json` results output; survivors are read from `mutmut junitxml`.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ import os
12
+ import shutil
13
+ import subprocess
14
+ import sys
15
+ import xml.etree.ElementTree as ET
16
+ from pathlib import Path
17
+
18
+ from . import lib
19
+
20
+
21
+ def mutmut_detect() -> bool:
22
+ """Return True when mutmut is available in this project."""
23
+ if shutil.which("mutmut") is not None:
24
+ return True
25
+ try:
26
+ # `mutmut` is a `version` subcommand, not a `--version` flag — the
27
+ # flag form exits nonzero on the real CLI and always reads as absent.
28
+ proc = subprocess.run(
29
+ ["python3", "-m", "mutmut", "version"],
30
+ stdout=subprocess.DEVNULL,
31
+ stderr=subprocess.DEVNULL,
32
+ check=False,
33
+ )
34
+ if proc.returncode == 0:
35
+ return True
36
+ except (FileNotFoundError, OSError):
37
+ pass
38
+ print(
39
+ lib.emit_advisory(
40
+ "MUTATION GATE ADVISORY: mutmut not installed. Run /setup to "
41
+ "install it, or: pip install mutmut"
42
+ )
43
+ )
44
+ return False
45
+
46
+
47
+ def _derive_python_source(test_file: str) -> str:
48
+ """Strip test_ prefix / _test suffix from `test_file` to find the source."""
49
+ base = Path(test_file).stem
50
+ base = base.removeprefix("test_")
51
+ base = base.removesuffix("_test")
52
+ for dir_ in ("src", "", "lib"):
53
+ candidate = f"{dir_}/{base}.py" if dir_ else f"{base}.py"
54
+ if Path(candidate).is_file():
55
+ return candidate
56
+ return test_file
57
+
58
+
59
+ def _is_python_source(line: str) -> bool:
60
+ """True for a non-test Python source path."""
61
+ if not line.endswith(".py"):
62
+ return False
63
+ return not (line.startswith("test_") or "_test.py" in line or "/test_" in line)
64
+
65
+
66
+ def _changed_python_source() -> str:
67
+ return lib.first_changed_file(_is_python_source)
68
+
69
+
70
+ def _mutmut_argv() -> list[str]:
71
+ """Return the argv prefix for invoking mutmut — either `mutmut` or `python3 -m mutmut`."""
72
+ if shutil.which("mutmut") is not None:
73
+ return ["mutmut"]
74
+ return ["python3", "-m", "mutmut"]
75
+
76
+
77
+ def mutmut_run(output_file: Path) -> int:
78
+ """Run mutmut scoped to the changed Python file; write zero-kills."""
79
+ output_file = Path(output_file)
80
+ timeout_seconds = int(os.environ.get("ADAPTER_TIMEOUT", "120"))
81
+
82
+ src_file = _changed_python_source()
83
+
84
+ mutmut_prefix = _mutmut_argv()
85
+ mutmut_args = ["run"]
86
+ if src_file:
87
+ mutmut_args.append(f"--paths-to-mutate={src_file}")
88
+
89
+ argv = [*mutmut_prefix, *mutmut_args]
90
+ completed = lib.run_with_timeout(
91
+ timeout_seconds,
92
+ argv,
93
+ stdout=subprocess.DEVNULL,
94
+ stderr=subprocess.PIPE,
95
+ text=True,
96
+ )
97
+ exit_code = completed.returncode
98
+
99
+ if exit_code == 124:
100
+ hint = (
101
+ ""
102
+ if src_file
103
+ else " No source file detected — scope with --paths-to-mutate."
104
+ )
105
+ print(
106
+ lib.emit_advisory(
107
+ f"MUTATION GATE SKIPPED: mutmut timed out after {timeout_seconds}s.{hint}"
108
+ " Or: MUTATION_GATE_TIMEOUT=<seconds> to extend the limit."
109
+ )
110
+ )
111
+ output_file.write_text("[]")
112
+ return 0
113
+
114
+ # mutmut's exit code is a bitmask: 1=fatal error, 2=survived, 4=timeout,
115
+ # 8=slow (any combination ORs together; 0 means every mutant was
116
+ # killed). Bit 1 (fatal error — e.g. the baseline test run itself
117
+ # failed) is the only outcome that invalidates the run; survivors
118
+ # (bit 2) are the expected, common case and must still be parsed.
119
+ if exit_code & 1:
120
+ stderr = completed.stderr or ""
121
+ if "cannot pickle" in stderr and "itertools.count" in stderr:
122
+ hint = (
123
+ " Known cause: mutmut<3 crashes on Python 3.13+ "
124
+ "('TypeError: cannot pickle itertools.count object', a "
125
+ "parso/pony-ORM deepcopy incompatibility) — install mutmut "
126
+ "into a venv running Python <=3.12; the --runner test "
127
+ "command can stay on the project's real interpreter."
128
+ )
129
+ else:
130
+ hint = ""
131
+ print(
132
+ lib.emit_advisory(
133
+ f"MUTATION GATE ADVISORY: mutmut exited with code {exit_code}. "
134
+ f"Skipping mutation gate.{hint}"
135
+ )
136
+ )
137
+ output_file.write_text("[]")
138
+ return 0
139
+
140
+ # Read survivors from `mutmut junitxml` — mutmut's `results` subcommand
141
+ # has no `--json` output; junitxml is the only structured report it
142
+ # ships. A <testcase> with a <failure> child is a survived mutant under
143
+ # the default suspicious/untested policies (both "ignore").
144
+ try:
145
+ junit = subprocess.run(
146
+ [*mutmut_prefix, "junitxml"],
147
+ capture_output=True,
148
+ text=True,
149
+ check=False,
150
+ )
151
+ raw = junit.stdout or ""
152
+ except (FileNotFoundError, OSError):
153
+ raw = ""
154
+
155
+ try:
156
+ root = ET.fromstring(raw) if raw.strip() else None
157
+ except ET.ParseError:
158
+ root = None
159
+
160
+ zero_kills = []
161
+ if root is not None:
162
+ for testcase in root.iter("testcase"):
163
+ if testcase.find("failure") is None:
164
+ continue
165
+ line = testcase.get("line")
166
+ zero_kills.append(
167
+ {
168
+ "name": f"mutant_{testcase.get('name', '?')}",
169
+ "file": testcase.get("file"),
170
+ "line": int(line) if line and line.isdigit() else None,
171
+ "covered": 0,
172
+ }
173
+ )
174
+
175
+ output_file.write_text(json.dumps(zero_kills))
176
+ return 0
177
+
178
+
179
+ def main(argv: list[str] | None = None) -> int:
180
+ args = list(sys.argv[1:] if argv is None else argv)
181
+ if not args:
182
+ print("mutmut.py: OUTPUT_FILE argument required", file=sys.stderr)
183
+ return 2
184
+ return mutmut_run(Path(args[0]))
185
+
186
+
187
+ if __name__ == "__main__": # pragma: no cover
188
+ sys.exit(main())