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,331 @@
1
+ #!/usr/bin/env python3
2
+ """mutation_kill_headless.py — unattended generation + CLI entry point.
3
+
4
+ Split out of ``mutation_kill_loop.py`` (#1562): the ``--headless`` CLI
5
+ argument parsing and entry point for the C#/Stryker.NET loop. The
6
+ agent-driven (default, interactive) path never touches this module — the
7
+ mutation-kill agent calls :func:`mutation_kill_loop.run_for_file` directly
8
+ with its own ``generate`` hook.
9
+
10
+ The ``claude --print`` invocation glue itself (``run_claude_headless``,
11
+ ``resolve_model``, ``strip_code_fences``, ``claude_cli_available``,
12
+ ``CLAUDE_CLI``) lives in ``mutation_kill_shared.py``, not here (#1601) — it's
13
+ reused verbatim by ``mutation_kill_loop_python.py``, and none of it is
14
+ C#-specific. This module only builds the C#-flavored prompt
15
+ (``build_generation_prompt``) and imports the handful of shared names it
16
+ actually calls (``CLAUDE_CLI``, ``resolve_model``, ``claude_cli_available``,
17
+ ``run_claude_headless``); ``mutation_kill_loop_python.py`` now imports the
18
+ same names directly from ``mutation_kill_shared`` too, rather than through
19
+ this module, which previously dragged the whole C#/Stryker.NET stack
20
+ (``mutation_kill_loop`` and everything it imports) into the Python loop just
21
+ to reuse five language-neutral names.
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ import argparse
27
+ import os
28
+ import sys
29
+ import time
30
+ from collections.abc import Callable, Sequence
31
+ from pathlib import Path
32
+
33
+ from mutation_kill_loop import Generator, RunContext, load_loop_config, run_for_file
34
+ from mutation_kill_retry import (
35
+ EXIT_GENERATION_EXHAUSTED,
36
+ EXIT_REVERT_FAILED,
37
+ DowngradeEvent,
38
+ GenerationExhausted,
39
+ make_downgrade_audit_hook,
40
+ make_retrying_headless_call,
41
+ )
42
+ from mutation_kill_shared import (
43
+ CLAUDE_CLI,
44
+ RevertFailed,
45
+ claude_cli_available,
46
+ resolve_model,
47
+ run_claude_headless, # noqa: F401 — re-exported for tests (headless.run_claude_headless identity check); make_headless_generator now calls it indirectly via make_retrying_headless_call (#1908)
48
+ )
49
+
50
+ # The exact message the bare-CLI startup preflight prints. Pinned so the
51
+ # contract test can assert it verbatim.
52
+ NO_GENERATOR_MESSAGE = (
53
+ "no test generator available — invoke via the mutation-kill agent "
54
+ "or pass --headless"
55
+ )
56
+
57
+ # Printed when --headless is requested but the Claude CLI can't be reached.
58
+ # Names exactly how to install and authenticate it, and mutates no files.
59
+ MISSING_CLAUDE_MESSAGE = (
60
+ f"--headless requires the Claude CLI but '{CLAUDE_CLI}' is not available. "
61
+ "Install Claude Code (`npm install -g @anthropic-ai/claude-code`) and "
62
+ "authenticate it (run `claude` once to log in, or set ANTHROPIC_API_KEY) — "
63
+ "or set CLAUDE_BIN to the CLI's path."
64
+ )
65
+
66
+
67
+ def build_survivor_summary(survivors: list[dict], *, limit: int = 40) -> str:
68
+ """Render surviving mutants as a compact, framework-agnostic list."""
69
+ lines = []
70
+ for mutant in survivors[:limit]:
71
+ line = mutant.get("location", {}).get("start", {}).get("line", "?")
72
+ mutator = mutant.get("mutatorName", "?")
73
+ replacement = mutant.get("replacement", "")
74
+ lines.append(f"- L{line} {mutator}: {replacement}".rstrip())
75
+ if len(survivors) > limit:
76
+ lines.append(f"- … and {len(survivors) - limit} more")
77
+ return "\n".join(lines)
78
+
79
+
80
+ def build_generation_prompt(
81
+ source_file: str,
82
+ survivors: list[dict],
83
+ source_text: str,
84
+ test_text: str,
85
+ *,
86
+ source_limit: int = 8000,
87
+ ) -> str:
88
+ """Build the generation prompt.
89
+
90
+ The existing test file is the *only* pattern — assertion library, mocking
91
+ approach, fixtures, and naming conventions are all inferred from it. No
92
+ library name is hardcoded here, so the prompt is repo-agnostic (AC1).
93
+ """
94
+ return (
95
+ f"You are adding new test methods that KILL surviving mutations in "
96
+ f"{source_file}.\n\n"
97
+ "Match the existing test file exactly: its imports, assertion style, "
98
+ "mocking approach, fixtures, and naming conventions are the pattern to "
99
+ "follow. Do not introduce any library, helper, or convention that does "
100
+ "not already appear in it.\n\n"
101
+ f"## Surviving mutations ({len(survivors)})\n"
102
+ f"{build_survivor_summary(survivors)}\n\n"
103
+ f"## Source under test\n{source_text[:source_limit]}\n\n"
104
+ f"## Existing test file (the pattern to match)\n{test_text}\n\n"
105
+ "## Rules\n"
106
+ "1. Return ONLY the new test methods — no class wrapper, namespace, or "
107
+ "imports.\n"
108
+ "2. Each must compile against the helpers already in the existing test "
109
+ "file.\n"
110
+ "3. Reuse the existing file's assertion, mocking, and fixture patterns "
111
+ "exactly.\n"
112
+ "4. Match the existing naming convention.\n"
113
+ "5. Do not redeclare fields or helpers already present.\n"
114
+ "6. Do not emit closing braces for the class or namespace.\n"
115
+ )
116
+
117
+
118
+ def make_headless_generator(
119
+ model: str | None = None,
120
+ *,
121
+ cwd: Path | None = None,
122
+ log: Callable[[str], None] = print,
123
+ on_downgrade: Callable[[DowngradeEvent], None] | None = None,
124
+ sleep: Callable[[float], None] = time.sleep,
125
+ ) -> Generator:
126
+ """Return a :data:`mutation_kill_loop.Generator` that shells to
127
+ ``claude --print``.
128
+
129
+ The returned callable builds the prompt from the existing test file (the
130
+ pattern) plus the survivor summary, then delegates everything else to
131
+ :func:`mutation_kill_retry.make_retrying_headless_call` (#1908) — the
132
+ 3-consecutive-gateway-class-failures/1-same-model-retry/at-most-once-
133
+ per-file-downgrade wrapper around :func:`run_claude_headless`.
134
+
135
+ The retry/downgrade state (consecutive-failure counter, model in use,
136
+ whether this file already spent its one downgrade) lives in the
137
+ ``retrying_call`` closure below — constructed once per file, here, never
138
+ at module scope — so a new file's generator always starts fresh at the
139
+ top of the ladder regardless of a prior file's downgrade, and concurrent
140
+ files under ``--all --concurrency`` (each with their own closure) never
141
+ leak state to one another. ``round_num`` is derived from how many times
142
+ THIS closure has been invoked (the loop calls its ``generate`` once per
143
+ round), since the shared :data:`Generator` signature carries no round
144
+ number of its own.
145
+
146
+ ``on_downgrade``, when given, is passed straight through to
147
+ :func:`mutation_kill_retry.make_retrying_headless_call`. Building the
148
+ ``on_downgrade``/``get_label_override`` audit-trail pair
149
+ (:func:`mutation_kill_retry.make_downgrade_audit_hook`) is this
150
+ module's own ``main()``'s job now (#1908 review) — this function no
151
+ longer constructs one internally or attaches a
152
+ ``label_override_provider`` attribute to the returned ``generate``;
153
+ ``main()`` has ``get_label_override`` directly in scope and wires it
154
+ into :class:`RunContext` itself, so no attribute-smuggling is needed.
155
+ """
156
+ retrying_call = make_retrying_headless_call(
157
+ initial_model=model, cwd=cwd, log=log, on_downgrade=on_downgrade, sleep=sleep
158
+ )
159
+ round_counter = {"n": 0}
160
+
161
+ def generate(
162
+ source_file: str,
163
+ survivors: list[dict],
164
+ source_text: str,
165
+ test_text: str,
166
+ ) -> str:
167
+ round_counter["n"] += 1
168
+ prompt = build_generation_prompt(source_file, survivors, source_text, test_text)
169
+ return retrying_call(prompt, source_file, round_counter["n"])
170
+
171
+ return generate
172
+
173
+
174
+ def parse_args(argv: Sequence[str]) -> argparse.Namespace:
175
+ p = argparse.ArgumentParser(
176
+ prog="mutation_kill_loop.py",
177
+ description=(
178
+ "Config-driven survivor-kill loop. Agent-driven by default; "
179
+ "--headless enables unattended generation via the Claude CLI."
180
+ ),
181
+ )
182
+ p.add_argument("--config", default="stryker-config.json", help="stryker-config.json path")
183
+ p.add_argument("--file", help="Source file to target (basename or path)")
184
+ p.add_argument("--output", default="StrykerOutput/agent", help="Scoped-run output dir")
185
+ p.add_argument("--max-rounds", type=int, default=5, help="Max rounds per file")
186
+ p.add_argument(
187
+ "--stryker-bin",
188
+ default=os.environ.get("STRYKER_BIN", "dotnet"),
189
+ help="Stryker executable name, or 'dotnet' to invoke a local-tool-"
190
+ "manifest install via 'dotnet stryker' (default: %(default)s)",
191
+ )
192
+ p.add_argument(
193
+ "--headless",
194
+ action="store_true",
195
+ help="Unattended generation via `claude --print` (CI / shard pipeline).",
196
+ )
197
+ p.add_argument(
198
+ "--model",
199
+ help=(
200
+ "Generation model for --headless. Default: DEV_TEAM_MUTATION_MODEL "
201
+ "env var, else omitted so `claude --print` uses its own default."
202
+ ),
203
+ )
204
+ p.add_argument("--test-file", help="Test file to extend (required with --headless)")
205
+ p.add_argument("--source-path", help="Source file under test (required with --headless)")
206
+ p.add_argument(
207
+ "--target-honest-score",
208
+ type=float,
209
+ default=None,
210
+ help=(
211
+ "Phase-0 mutation target (percent). Stop a file once its honest "
212
+ "score reaches this, since work past the threshold cannot change "
213
+ "the Phase-8 verdict. Default off — unset reproduces pre-#2030 "
214
+ "behavior exactly."
215
+ ),
216
+ )
217
+ p.add_argument(
218
+ "--min-kills-per-round",
219
+ type=float,
220
+ default=None,
221
+ help=(
222
+ "Marginal-yield floor. >=1 is an absolute kill count; 0<v<1 is a "
223
+ "fraction of the round's starting survivors. A round below the "
224
+ "floor while still under target is surfaced to the operator "
225
+ "([c]ontinue / [r]etry / [w]aive / [q]uit), never stopped "
226
+ "silently. Default off."
227
+ ),
228
+ )
229
+ p.add_argument("--report", help="Initial mutation report to seed round 1 (--headless)")
230
+ return p.parse_args(list(argv))
231
+
232
+
233
+ def main(argv: Sequence[str] | None = None) -> int:
234
+ """CLI entry point.
235
+
236
+ The CLI has no way to inject an agent generator (that path calls
237
+ :func:`mutation_kill_loop.run_for_file` directly). So without
238
+ ``--headless`` there is no generator, and we fail fast **at startup** —
239
+ before resolving config, probing DOTNET_ROOT, running Stryker, or
240
+ touching any file.
241
+
242
+ With ``--headless`` the generator shells to ``claude --print``. The Claude
243
+ CLI is preflight-checked *before* any file argument validation, so a
244
+ missing CLI fails cleanly at startup and mutates nothing.
245
+ """
246
+ argv = list(sys.argv[1:] if argv is None else argv)
247
+ args = parse_args(argv)
248
+
249
+ if not args.headless:
250
+ sys.stderr.write(f"error: {NO_GENERATOR_MESSAGE}\n")
251
+ return 1
252
+
253
+ model = resolve_model(args.model)
254
+
255
+ # Preflight the CLI first — a missing CLI must fail before we touch any
256
+ # file or validate run arguments.
257
+ if not claude_cli_available():
258
+ sys.stderr.write(f"error: {MISSING_CLAUDE_MESSAGE}\n")
259
+ return 3
260
+
261
+ if not (args.file and args.test_file and args.source_path):
262
+ sys.stderr.write(
263
+ "error: --headless requires --file, --test-file, and --source-path\n"
264
+ )
265
+ return 2
266
+
267
+ on_downgrade, get_label_override = make_downgrade_audit_hook()
268
+ generate = make_headless_generator(model, on_downgrade=on_downgrade)
269
+ try:
270
+ run_for_file(
271
+ args.file,
272
+ RunContext(
273
+ config=load_loop_config(Path(args.config)),
274
+ test_file=Path(args.test_file),
275
+ source_path=Path(args.source_path),
276
+ output_dir=Path(args.output),
277
+ stryker_bin=args.stryker_bin,
278
+ initial_report_path=Path(args.report) if args.report else None,
279
+ generator_label=f"headless ({model or 'default'})",
280
+ label_override_provider=get_label_override,
281
+ target_honest_score=args.target_honest_score,
282
+ min_kills_per_round=args.min_kills_per_round,
283
+ ),
284
+ generate=generate,
285
+ max_rounds=args.max_rounds,
286
+ )
287
+ except GenerationExhausted as exc:
288
+ # This file's retry-then-downgrade budget is fully spent (3
289
+ # consecutive gateway-class failures + 1 same-model retry, at the
290
+ # original model AND at most one fallback tier) — distinct from
291
+ # RevertFailed below (exit 4, working tree possibly mutated) and
292
+ # from the generic RuntimeError case below it (exit 5, clean but
293
+ # not exhausted — e.g. a non-gateway-class generation timeout). A
294
+ # clean exhaustion mutates nothing: generation precedes insertion
295
+ # within a round, and a prior round's own revert failure is itself
296
+ # fatal (raised as RevertFailed, never swallowed). What isn't
297
+ # independently re-verified here is that a revert git reports as
298
+ # successful actually left the tree clean (#1955) — so callers
299
+ # (stryker_shard_pipeline.py's shard driver) can log this file as
300
+ # unfixed and continue to the next file without affecting the run's
301
+ # exit status, instead of aborting the whole shard (#1908 review).
302
+ sys.stderr.write(f"error: {exc}\n")
303
+ return EXIT_GENERATION_EXHAUSTED
304
+ except RevertFailed as exc:
305
+ # A failed revert (or a failed-commit round-abandonment's own
306
+ # revert) leaves the working tree in an unknown, possibly-mutated
307
+ # state (#1930) — narrower and more urgent than the generic
308
+ # RuntimeError case below: this is the only case that can't be
309
+ # trusted as clean.
310
+ sys.stderr.write(f"error: {exc}\n")
311
+ return EXIT_REVERT_FAILED
312
+ except RuntimeError as exc:
313
+ # Every other RuntimeError this loop raises (a generation timeout,
314
+ # a mutmut/Stryker infrastructure failure, etc.) is clean with
315
+ # respect to inserted test content — generation precedes insertion,
316
+ # and a failed insertion-revert is RevertFailed, caught above. The
317
+ # C# solution-file restore (wrapper.restore_sln) now also reports a
318
+ # bool outcome (#1955) and run_scoped_stryker raises RevertFailed on
319
+ # a False return, so a stray hidden .sln is caught by the
320
+ # RevertFailed branch above, not silently reaching here. Not a
321
+ # retry-budget exhaustion — reuses exit 5 (#1956: this is the
322
+ # OUTCOME class, not a specific cause) because the shard driver only
323
+ # distinguishes "fatal, stop" (4) from "clean, continue" (5), not
324
+ # why a file wasn't fixed.
325
+ sys.stderr.write(f"error: {exc} — generation failed cleanly, continuing\n")
326
+ return EXIT_GENERATION_EXHAUSTED
327
+ return 0
328
+
329
+
330
+ if __name__ == "__main__":
331
+ sys.exit(main())
@@ -0,0 +1,199 @@
1
+ #!/usr/bin/env python3
2
+ """mutation_kill_insert.py — C# test-method insertion mechanics.
3
+
4
+ Split out of ``mutation_kill_loop.py`` (#1562): detect-or-refuse insertion of
5
+ generated test methods before a test class's closing brace. The heuristic
6
+ supports only conventional block-namespace, 4-space-indented C# test classes
7
+ — a file-scoped namespace or non-4-space indentation is refused rather than
8
+ risk a mis-insertion.
9
+
10
+ ``InsertOutcome``/``InsertionRefused`` are imported from
11
+ ``mutation_kill_shared`` (#1583, relocated from ``mutation_safety_gate`` in
12
+ #1602), not defined here — they're structurally identical to the Python
13
+ sibling's (``mutation_kill_insert_python.py``), so both modules share one
14
+ definition instead of two hand-maintained copies. See
15
+ ``mutation_kill_shared``'s module docstring for the unification rationale.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import re
21
+ from collections.abc import Sequence
22
+ from pathlib import Path
23
+
24
+ import mutation_safety_gate
25
+ from mutation_kill_shared import InsertionRefused, InsertOutcome
26
+
27
+ # Matches a public test-method declaration (async Task or void), capturing the
28
+ # method name. Framework-agnostic — no attribute or library name is assumed.
29
+ _METHOD_RE = re.compile(
30
+ r"public\s+(?:async\s+)?(?:void|Task(?:<[^>]*>)?)\s+(\w+)\s*\("
31
+ )
32
+
33
+ # A file-scoped namespace declaration ends with a semicolon and has no
34
+ # wrapping braces: ``namespace Foo.Bar;``
35
+ _FILE_SCOPED_NS_RE = re.compile(r"^\s*namespace\s+[\w.]+\s*;", re.MULTILINE)
36
+
37
+
38
+ def detect_duplicate_methods(test_text: str, new_text: str) -> list[str]:
39
+ """Return the method names in ``new_text`` that already exist in the file."""
40
+ existing = set(_METHOD_RE.findall(test_text))
41
+ incoming = _METHOD_RE.findall(new_text)
42
+ return [name for name in incoming if name in existing]
43
+
44
+
45
+ def count_methods(new_text: str) -> int:
46
+ """Count public test-method declarations in ``new_text``."""
47
+ return len(_METHOD_RE.findall(new_text))
48
+
49
+
50
+ # A deny-list of APIs a test method that merely kills mutants never
51
+ # legitimately needs. Scoped to generated *test* text only — never to the
52
+ # source-under-test — so it doesn't false-positive on production code that
53
+ # does real I/O. This is a static-pattern gate, not a sandbox: a
54
+ # sufficiently obfuscated payload (reflection-built names, string
55
+ # concatenation) could still evade it. Guards against a prompt-injection
56
+ # payload in the mutated source producing generated test code with
57
+ # network/filesystem/process side effects that would still pass build+test
58
+ # (which only check compilation and pass/fail, never behavior) and, in
59
+ # --headless mode, get committed with zero human review. Category names are
60
+ # a stable, test-pinned contract shared with mutation_kill_loop_python's
61
+ # deny-list — renaming one is a breaking change for callers matching on
62
+ # InsertOutcome.reason.
63
+ _UNSAFE_PATTERNS: dict[str, re.Pattern[str]] = {
64
+ "network": re.compile(
65
+ r"\b(HttpClient|WebRequest|WebClient|TcpClient|UdpClient|SmtpClient|Socket|Dns|"
66
+ r"System\s*\.\s*Net\s*\.)\b"
67
+ ),
68
+ "process": re.compile(r"\b(Process|StartInfo|ProcessStartInfo)\b"),
69
+ "filesystem": re.compile(
70
+ r"\b(File\s*\.\s*(WriteAllText|WriteAllBytes|WriteAllLines|AppendAllText|"
71
+ r"AppendAllLines)(Async)?|File\s*\.\s*(Create|Delete|Move|Copy|Open|OpenWrite)|"
72
+ r"Directory\s*\.\s*(Delete|CreateDirectory|Move)|StreamWriter|FileStream|"
73
+ r"FileInfo|DirectoryInfo)\b"
74
+ ),
75
+ "environment": re.compile(
76
+ r"\b(Environment\s*\.\s*GetEnvironmentVariables?|ConfigurationManager\s*\.\s*AppSettings)\b"
77
+ ),
78
+ "reflection": re.compile(
79
+ r"\b(Assembly\s*\.\s*Load(From|File|WithPartialName)?|"
80
+ r"Activator\s*\.\s*CreateInstance(From)?|System\s*\.\s*Reflection\s*\.\s*Emit)\b"
81
+ ),
82
+ "interop": re.compile(r"\b(Marshal\s*\.|DllImport)\b|(?<![\w.])unsafe\b"),
83
+ }
84
+
85
+
86
+ def scan_for_unsafe_patterns(new_methods: str) -> list[str]:
87
+ """Return the category names of any unsafe pattern found in generated text.
88
+
89
+ A non-empty result refuses insertion outright — this deny-list is
90
+ deliberately conservative for *generated test* code specifically (a
91
+ legitimate mutant-killing test never needs network/filesystem/process/env
92
+ access), so a false positive refuses-and-logs rather than silently
93
+ inserting unreviewed code. Delegates to :mod:`mutation_safety_gate`,
94
+ shared with :mod:`mutation_kill_insert_python`, so a future bypass fix or
95
+ new category lands once for both languages.
96
+ """
97
+ return mutation_safety_gate.scan_for_unsafe_patterns(new_methods, _UNSAFE_PATTERNS)
98
+
99
+
100
+ def _find_block_namespace_class_close(lines: Sequence[str]) -> int | None:
101
+ """Return the index of the class-closing brace, or None to refuse.
102
+
103
+ Walks from the end: finds the namespace-closing brace (a line whose
104
+ stripped form is ``}``), then the last line that is exactly four spaces
105
+ followed by ``}`` before it — the conventional block-namespace class
106
+ close. Any other indentation yields None (refuse).
107
+ """
108
+ ns_idx = None
109
+ for i in range(len(lines) - 1, -1, -1):
110
+ if lines[i].strip() == "}":
111
+ ns_idx = i
112
+ break
113
+ if ns_idx is None:
114
+ return None
115
+ for i in range(ns_idx - 1, -1, -1):
116
+ if lines[i].rstrip("\r\n") == " }":
117
+ return i
118
+ return None
119
+
120
+
121
+ def insert_before_class_close(test_file: Path, new_methods: str, text: str) -> None:
122
+ """Insert ``new_methods`` before the test class's closing brace.
123
+
124
+ Raises :class:`InsertionRefused` for a file-scoped namespace or any
125
+ non-4-space-indented class the heuristic can't safely locate. The file is
126
+ left untouched on refusal.
127
+
128
+ ``text`` is the current test-file content, already read by the caller
129
+ (:func:`apply_generated_methods`) — this function performs no read of its
130
+ own. A previous, optional ``test_text=`` shape let a caller pass in
131
+ content that bypassed reading the file's CURRENT state (including this
132
+ function's own refusal-guard check running against stale content rather
133
+ than what's actually on disk) — a real hazard even though no caller
134
+ exploited it. Removing the optional/None-triggered-fallback shape closes
135
+ that off: freshness is now entirely ``apply_generated_methods``'s
136
+ responsibility, which reads immediately before calling this (#1598/#1584
137
+ review, item 7).
138
+ """
139
+ if _FILE_SCOPED_NS_RE.search(text):
140
+ raise InsertionRefused(
141
+ f"refusing to insert into {test_file.name}: file-scoped namespace "
142
+ "detected — the class-close heuristic supports only block-namespace, "
143
+ "4-space-indented classes"
144
+ )
145
+
146
+ lines = text.splitlines(keepends=True)
147
+ cc_idx = _find_block_namespace_class_close(lines)
148
+ if cc_idx is None:
149
+ raise InsertionRefused(
150
+ f"refusing to insert into {test_file.name}: could not locate a "
151
+ "conventional 4-space class-closing brace (non-standard indentation?)"
152
+ )
153
+
154
+ block = (
155
+ ["\n"]
156
+ + [ln if ln.endswith("\n") else ln + "\n" for ln in new_methods.strip().splitlines()]
157
+ + ["\n"]
158
+ )
159
+ lines = lines[:cc_idx] + block + lines[cc_idx:]
160
+ test_file.write_text("".join(lines), encoding="utf-8")
161
+
162
+
163
+ def apply_generated_methods(test_file: Path, new_methods: str) -> InsertOutcome:
164
+ """Insert generated methods, guarding duplicates and unsafe structure.
165
+
166
+ Returns an :class:`InsertOutcome`; the file is only ever written on the
167
+ ``inserted=True`` path. Empty generation, an unsafe pattern, duplicate
168
+ method names, and a refused insert all leave the file untouched.
169
+
170
+ Reads ``test_file`` exactly once here — immediately before the
171
+ duplicate-name check — and reuses that single fresh read for both the
172
+ check and the write (passed through to :func:`insert_before_class_close`,
173
+ which performs no read of its own). A prior shape let the caller (e.g.
174
+ ``_run_round``) thread in its OWN already-read ``test_text`` for the
175
+ duplicate check — but that text was read *before* the possibly
176
+ multi-minute ``generate()`` call, so the check ran against a stale
177
+ snapshot: a method name added to the file during generation (by another
178
+ process, or a second concurrent round) would go undetected as a
179
+ duplicate. Reading fresh here, after ``generate()`` has already
180
+ returned, closes that gap (#1598/#1584 review, item 7).
181
+ """
182
+ if not new_methods.strip():
183
+ return InsertOutcome(False, "no methods generated")
184
+
185
+ unsafe_categories = scan_for_unsafe_patterns(new_methods)
186
+ if unsafe_categories:
187
+ return InsertOutcome(False, f"refused — unsafe pattern(s): {unsafe_categories}")
188
+
189
+ text = test_file.read_text(encoding="utf-8")
190
+
191
+ dupes = detect_duplicate_methods(text, new_methods)
192
+ if dupes:
193
+ return InsertOutcome(False, f"duplicate method names: {dupes}")
194
+
195
+ try:
196
+ insert_before_class_close(test_file, new_methods, text)
197
+ except InsertionRefused as exc:
198
+ return InsertOutcome(False, str(exc))
199
+ return InsertOutcome(True, "inserted")
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env python3
2
+ """mutation_kill_insert_python.py — Python/pytest test-function insertion
3
+ mechanics.
4
+
5
+ Split out of ``mutation_kill_loop_python.py`` (#1583), mirroring the C#
6
+ split ``mutation_kill_insert.py`` (#1562): detect-or-refuse insertion of
7
+ generated pytest test functions at the end of a test file. Unlike C#'s
8
+ "find the class-closing brace" problem, a flat pytest module has no
9
+ enclosing structure to locate — the safe insertion point is simply
10
+ end-of-file, PROVIDED the file already follows that flat, top-level
11
+ ``def test_*():`` convention. A file with no top-level ``def test_`` function
12
+ at all (e.g. tests organized as ``class Test...:`` methods) doesn't match
13
+ this convention, and the loop refuses rather than guess.
14
+
15
+ ``InsertOutcome``/``InsertionRefused`` are imported from
16
+ ``mutation_kill_shared`` (relocated from ``mutation_safety_gate`` in #1602;
17
+ not defined here) — they're structurally identical to the C# sibling's, so
18
+ both modules share one definition instead of two hand-maintained copies. See
19
+ ``mutation_kill_shared``'s module docstring for the unification rationale.
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import re
25
+ from pathlib import Path
26
+
27
+ import mutation_safety_gate
28
+ from mutation_kill_shared import InsertionRefused, InsertOutcome
29
+
30
+ # A top-level (unindented) pytest test function declaration, capturing the name.
31
+ _FUNC_RE = re.compile(r"^def\s+(test_\w+)\s*\(", re.MULTILINE)
32
+
33
+
34
+ def detect_duplicate_functions(test_text: str, new_text: str) -> list[str]:
35
+ """Return the function names in ``new_text`` that already exist in the file."""
36
+ existing = set(_FUNC_RE.findall(test_text))
37
+ incoming = _FUNC_RE.findall(new_text)
38
+ return [name for name in incoming if name in existing]
39
+
40
+
41
+ def count_tests(new_text: str) -> int:
42
+ """Count top-level ``def test_*():`` declarations in ``new_text``.
43
+
44
+ Mirrors ``mutation_kill_insert.count_methods`` — the loop uses this to
45
+ report how many new tests a round added in its commit message.
46
+ """
47
+ return len(_FUNC_RE.findall(new_text))
48
+
49
+
50
+ def append_at_end_of_file(test_file: Path, new_tests: str, text: str) -> None:
51
+ """Append ``new_tests`` to the end of the file, with one blank line of
52
+ separation, and a trailing newline.
53
+
54
+ Raises :class:`InsertionRefused` when the file has no existing top-level
55
+ ``def test_*():`` — the flat-module convention this heuristic supports.
56
+ The file is left untouched on refusal.
57
+
58
+ ``text`` is the current test-file content, already read by the caller
59
+ (:func:`apply_generated_tests`) — this function performs no read of its
60
+ own, so freshness is entirely the caller's responsibility.
61
+ """
62
+ if not _FUNC_RE.search(text):
63
+ raise InsertionRefused(
64
+ f"refusing to insert into {test_file.name}: no top-level "
65
+ "`def test_*():` found — this heuristic supports only the flat "
66
+ "module convention (a class-based test file needs a different "
67
+ "insertion point, not appended at end-of-file)"
68
+ )
69
+
70
+ body = new_tests.strip()
71
+ separator = "" if text.endswith("\n\n") else ("\n" if text.endswith("\n") else "\n\n")
72
+ test_file.write_text(text + separator + body + "\n", encoding="utf-8")
73
+
74
+
75
+ # A deny-list of APIs a test function that merely kills mutants never
76
+ # legitimately needs. Scoped to generated *test* text only — never to the
77
+ # source-under-test. Same rationale and same category names as
78
+ # ``mutation_kill_insert``'s C# counterpart (kept consistent as a stable,
79
+ # operator-facing and test-pinned contract) — this is the Python/pytest
80
+ # equivalent, guarding this loop's own ``--headless`` unattended-commit path
81
+ # against a prompt-injection payload in the mutated source producing
82
+ # generated test code with network/filesystem/process side effects that
83
+ # would still pass compile+test and get committed with zero human review.
84
+ _UNSAFE_PATTERNS: dict[str, re.Pattern[str]] = {
85
+ "network": re.compile(
86
+ r"\b(requests\s*\.|urllib\s*\.\s*request|urllib3\s*\.|httpx\s*\.|socket\s*\.|http\s*\.\s*client)\b"
87
+ ),
88
+ "process": re.compile(
89
+ r"\b(subprocess\s*\.|os\s*\.\s*system|os\s*\.\s*popen|os\s*\.\s*exec\w*|"
90
+ r"os\s*\.\s*(spawn\w*|posix_spawn|fork|forkpty)|Popen)\b"
91
+ ),
92
+ "filesystem": re.compile(
93
+ r"\b(shutil\s*\.\s*rmtree|os\s*\.\s*(remove|unlink))\b"
94
+ r"|\.\s*(write_text|write_bytes|unlink)\s*\("
95
+ r"|open\s*\([^)]*[\"'][waxA]"
96
+ ),
97
+ "environment": re.compile(r"\b(os\s*\.\s*environ|os\s*\.\s*getenv)\b"),
98
+ "reflection": re.compile(r"\b(importlib\s*\.\s*import_module|__import__)\b"),
99
+ "interop": re.compile(r"\b(eval|exec)\s*\(|\bctypes\s*\.|\bpickle\s*\.\s*loads\s*\("),
100
+ }
101
+
102
+
103
+ def scan_for_unsafe_patterns(new_tests: str) -> list[str]:
104
+ """Return the category names of any unsafe pattern found in generated text.
105
+
106
+ A non-empty result refuses insertion outright — this deny-list is
107
+ deliberately conservative for *generated test* code specifically (a
108
+ legitimate mutant-killing test never needs network/filesystem/process/env
109
+ access), so a false positive refuses-and-logs rather than silently
110
+ inserting unreviewed code. Delegates to :mod:`mutation_safety_gate`,
111
+ shared with :mod:`mutation_kill_insert`, so a future bypass fix or new
112
+ category lands once for both languages.
113
+ """
114
+ return mutation_safety_gate.scan_for_unsafe_patterns(new_tests, _UNSAFE_PATTERNS)
115
+
116
+
117
+ def apply_generated_tests(test_file: Path, new_tests: str) -> InsertOutcome:
118
+ """Insert generated tests, guarding duplicates and unsafe structure.
119
+
120
+ Returns an :class:`InsertOutcome`; the file is only ever written on the
121
+ ``inserted=True`` path. Empty generation, an unsafe pattern, duplicate
122
+ function names, and a refused insert all leave the file untouched.
123
+
124
+ Reads ``test_file`` exactly once here — immediately before the
125
+ duplicate-name check — and reuses that single fresh read for both the
126
+ check and the write (passed through to :func:`append_at_end_of_file`,
127
+ which performs no read of its own). Reading fresh here, after the
128
+ caller's (possibly multi-minute) generation call has already returned,
129
+ means a test function added to the file externally in the meantime is
130
+ still caught as a duplicate rather than silently double-inserted
131
+ (#1598/#1584 review, item 7).
132
+ """
133
+ if not new_tests.strip():
134
+ return InsertOutcome(False, "no tests generated")
135
+
136
+ unsafe_categories = scan_for_unsafe_patterns(new_tests)
137
+ if unsafe_categories:
138
+ return InsertOutcome(False, f"refused — unsafe pattern(s): {unsafe_categories}")
139
+
140
+ text = test_file.read_text(encoding="utf-8")
141
+
142
+ dupes = detect_duplicate_functions(text, new_tests)
143
+ if dupes:
144
+ return InsertOutcome(False, f"duplicate function names: {dupes}")
145
+
146
+ try:
147
+ append_at_end_of_file(test_file, new_tests, text)
148
+ except InsertionRefused as exc:
149
+ return InsertOutcome(False, str(exc))
150
+ return InsertOutcome(True, "inserted")