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,620 @@
1
+ #!/usr/bin/env python3
2
+ """mutation_kill_shared.py — cross-language loop mechanics shared verbatim
3
+ between ``mutation_kill_loop.py`` (C#/Stryker.NET) and
4
+ ``mutation_kill_loop_python.py`` (Python/mutmut) (#1583).
5
+
6
+ Pieces were hand-duplicated between the two loops with identical behavior —
7
+ not just similar, identical argv shapes, identical error messages, identical
8
+ timeout semantics — before this module existed:
9
+
10
+ - ``_timeout_from_env`` — the env-var-driven timeout parser both loops (and
11
+ the headless-generation timeouts below) rely on.
12
+ - ``git_revert`` / ``git_reset_and_revert`` / ``git_commit`` — discard,
13
+ unstage-then-discard, and stage-then-commit exactly one test file, under a
14
+ bounded timeout with the ``--literal-pathspecs``/``--`` pathspec guards
15
+ hardened in #1598/#1599.
16
+ - ``RevertFailed`` — raised when a cleanup or insertion revert itself fails,
17
+ leaving the working tree in an unknown, possibly-mutated state (#1930).
18
+ - ``stop_reason`` — the "zero survivors, or no improvement over the previous
19
+ round" predicate that ends a file's kill loop.
20
+ - ``resolve_model`` / ``strip_code_fences`` / ``claude_cli_available`` /
21
+ ``CLAUDE_CLI`` / ``run_claude_headless`` / ``HeadlessCallFailed`` (moved
22
+ here from ``mutation_kill_headless.py`` in #1601) — the ``claude --print`` invocation
23
+ glue neither loop's scoring/insertion/orchestration logic actually needs,
24
+ but that ``mutation_kill_loop_python.py`` previously reused by importing
25
+ ``mutation_kill_headless.py`` at module scope. That module is NOT a neutral
26
+ one — it imports ``mutation_kill_loop`` (the C#/Stryker.NET loop) and owns
27
+ the C#-only ``--config``/``--stryker-bin`` CLI surface — so importing it
28
+ from the Python loop transitively pulled in the entire C# stack just to
29
+ reuse five language-neutral names. Both loops now import these directly
30
+ from here instead.
31
+ - ``InsertOutcome`` / ``InsertionRefused`` (moved here from
32
+ ``mutation_safety_gate.py`` in #1602) — neither is a safety concept
33
+ (``mutation_safety_gate.py`` is scoped to the unattended-commit
34
+ prompt-injection threat model); they're the plain, framework-agnostic
35
+ result/exception shape both loops' insertion mechanics
36
+ (``mutation_kill_insert.py``, ``mutation_kill_insert_python.py``) return,
37
+ identical in shape between the two languages.
38
+ The retry-then-downgrade policy on repeated headless-generation failures
39
+ (``is_gateway_class_error``, ``make_retrying_headless_call``,
40
+ ``GenerationExhausted``, ``DowngradeEvent``, ``make_downgrade_audit_hook``,
41
+ #1908) lives in ``mutation_kill_retry.py`` instead — extracted out of this
42
+ module (#1925) once it grew into a five-concern grab-bag; that module's
43
+ dependencies on this one are ``run_claude_headless``/``resolve_fallback_model``,
44
+ plus ``HeadlessCallFailed`` referenced only as a type
45
+ (``isinstance(exc, mutation_kill_shared.HeadlessCallFailed)``), not a
46
+ monkeypatch-sensitive callable. ``run_claude_headless`` is reached on every
47
+ generation attempt unless the caller injects ``call_headless`` (#1918), in
48
+ which case it is never reached. (Keep this in sync with the
49
+ mirrored dependency inventory in ``mutation_kill_retry.py``'s own module
50
+ docstring.)
51
+
52
+ Centralizing the pieces below here means a future hardening fix lands once instead of
53
+ drifting between two copies (the exact drift risk #1598/#1599 already
54
+ demonstrated in practice). Language-specific scoring, insertion mechanics,
55
+ and round orchestration stay in each loop's own module.
56
+
57
+ Stdlib-only. See ADR 0014.
58
+ """
59
+
60
+ from __future__ import annotations
61
+
62
+ import math
63
+ import os
64
+ import re
65
+ import subprocess
66
+ import sys
67
+ from dataclasses import dataclass
68
+ from pathlib import Path
69
+
70
+
71
+ def _timeout_from_env(name: str, default: int) -> int:
72
+ """Parse a positive-integer timeout (seconds) from an env var.
73
+
74
+ Fails fast with a message naming the offending env var, rather than the
75
+ bare, unattributed ``ValueError`` a naked ``int(os.environ.get(...))``
76
+ would raise on a malformed override.
77
+ """
78
+ raw = os.environ.get(name)
79
+ if raw is None:
80
+ return default
81
+ try:
82
+ value = int(raw)
83
+ except ValueError:
84
+ raise ValueError(
85
+ f"{name} must be an integer number of seconds, got {raw!r}"
86
+ ) from None
87
+ if value <= 0:
88
+ raise ValueError(f"{name} must be a positive number of seconds, got {value}")
89
+ return value
90
+
91
+
92
+ # 30s — near-instant local git operations against a repo that's presumably
93
+ # already responsive. Overridable via env var for a legitimately slow
94
+ # repo/filesystem. Shared by both loops (#1583) — previously two separately
95
+ # maintained (but identically named and valued) constants.
96
+ GIT_TIMEOUT_S = _timeout_from_env("DEV_TEAM_MUTATION_GIT_TIMEOUT_S", 30)
97
+
98
+
99
+ def git_revert(
100
+ test_file: Path, *, cwd: Path | None = None, env: dict[str, str] | None = None
101
+ ) -> bool:
102
+ """Discard working-tree changes to one file (``git checkout -- <file>``).
103
+
104
+ Returns True on a successful revert, False on a non-zero exit or a
105
+ timeout — callers can no longer mistake a failed/timed-out revert for a
106
+ successful one (#1598); a leftover, uncommitted mutation left on disk
107
+ after a revert *claims* success is exactly the integrity gap this fixes.
108
+
109
+ ``env`` defaults to ``None`` (inherit the ambient environment); tests
110
+ pass a scrubbed env so this real git subprocess can't be redirected by
111
+ an inherited ``GIT_DIR``/``GIT_WORK_TREE`` (#1598/#1584 review, item 4
112
+ follow-up).
113
+
114
+ Tolerates a ``None`` result from ``subprocess.run`` (in addition to a
115
+ non-zero returncode) as a failure rather than raising — mirrors the old
116
+ C#-loop-only ``_run_with_timeout``-based implementation's behavior
117
+ (pre-#1583), which several existing tests' minimal test doubles
118
+ incidentally depend on (a ``lambda`` whose body is a bare
119
+ ``list.append(...)``/``dict.update(...)`` call returns ``None``, not a
120
+ ``CompletedProcess``).
121
+
122
+ Callers must inspect the return value; a failed revert is typically
123
+ treated as fatal (see :class:`RevertFailed`).
124
+ """
125
+ try:
126
+ result = subprocess.run(
127
+ ["git", "--literal-pathspecs", "checkout", "--", str(test_file)],
128
+ cwd=cwd,
129
+ check=False,
130
+ timeout=GIT_TIMEOUT_S,
131
+ env=env,
132
+ )
133
+ except subprocess.TimeoutExpired:
134
+ sys.stderr.write(
135
+ f"error: git checkout reverting {test_file} timed out after "
136
+ f"{GIT_TIMEOUT_S}s (set DEV_TEAM_MUTATION_GIT_TIMEOUT_S to "
137
+ "raise it)\n"
138
+ )
139
+ return False
140
+ if result is None:
141
+ return False
142
+ return result.returncode == 0
143
+
144
+
145
+ def git_reset_and_revert(
146
+ test_file: Path, *, cwd: Path | None = None, env: dict[str, str] | None = None
147
+ ) -> bool:
148
+ """Unstage AND restore ``test_file`` — the correct revert after a FAILED
149
+ commit specifically, distinct from :func:`git_revert`.
150
+
151
+ ``git_commit`` runs ``git add -- <test_file>`` *before* attempting the
152
+ commit. If the commit itself then fails, ``test_file`` is left staged
153
+ with the mutated content. A plain ``git checkout -- <file>`` (what
154
+ :func:`git_revert` does) restores the working tree **from the index**,
155
+ which still holds the mutation — so that revert *reports* success while
156
+ the mutated content survives on disk, staged. This is exactly the
157
+ integrity gap #1598 was meant to close. Unstaging first
158
+ (``git reset -q HEAD -- <file>``) before the checkout makes HEAD, the
159
+ index, and the working tree all agree afterward.
160
+
161
+ Returns True only if both the unstage step and the restore step succeed.
162
+
163
+ Both loops call this specifically on the after-a-failed-commit path
164
+ (``_revert_or_raise(..., after_commit=True)``); a build failure or test
165
+ failure calls plain :func:`git_revert` instead — their index already
166
+ equals HEAD in that case (nothing was ever staged), so there's no reason
167
+ to pay the extra ``git reset`` subprocess.
168
+ """
169
+ try:
170
+ reset_result = subprocess.run(
171
+ ["git", "--literal-pathspecs", "reset", "-q", "HEAD", "--", str(test_file)],
172
+ cwd=cwd,
173
+ check=False,
174
+ timeout=GIT_TIMEOUT_S,
175
+ env=env,
176
+ )
177
+ except subprocess.TimeoutExpired:
178
+ sys.stderr.write(
179
+ f"error: git reset unstaging {test_file} timed out after "
180
+ f"{GIT_TIMEOUT_S}s (set DEV_TEAM_MUTATION_GIT_TIMEOUT_S to "
181
+ "raise it)\n"
182
+ )
183
+ return False
184
+ if reset_result is None or reset_result.returncode != 0:
185
+ return False
186
+ return git_revert(test_file, cwd=cwd, env=env)
187
+
188
+
189
+ class RevertFailed(RuntimeError):
190
+ """Raised when a git revert itself fails: the working tree may be left in
191
+ an unknown/possibly-mutated state, distinct from every other
192
+ ``RuntimeError`` this codebase raises, which are clean with respect to
193
+ inserted test content — generation precedes insertion, and a failed
194
+ insertion-revert is this class, not a plain ``RuntimeError``. Also raised
195
+ by ``mutation_kill_loop.py``'s ``run_scoped_stryker`` when the C#
196
+ solution-file restore (``wrapper.restore_sln``, which now returns a bool
197
+ outcome rather than reporting nothing — #1955) fails: a stray hidden
198
+ ``.sln`` is the same "working tree left in an unknown state" shape as a
199
+ failed git revert, just for a different file.
200
+ """
201
+
202
+
203
+ def git_commit(
204
+ message: str,
205
+ test_file: Path,
206
+ *,
207
+ cwd: Path | None = None,
208
+ env: dict[str, str] | None = None,
209
+ ) -> bool:
210
+ """Stage and commit only ``test_file``. Returns True on a successful commit.
211
+
212
+ Does not inspect ``git add``'s own returncode (only its timeout) — a
213
+ non-timeout ``git add`` failure (e.g. bad pathspec) still falls through
214
+ to attempting the commit, which will then itself fail and report False.
215
+
216
+ ``--`` guards against a ``test_file`` path that happens to start with
217
+ ``-`` being parsed as a git flag instead of a path.
218
+ ``--literal-pathspecs`` (right after ``git``) forces every pathspec
219
+ argument below — including this one — to be treated as a literal path,
220
+ not a pathspec: ``--`` alone does NOT disable pathspec magic (``:/``,
221
+ ``:(exclude)``, ``:!``, etc.) for the argument that follows it, so a
222
+ ``test_file`` value containing those characters could otherwise silently
223
+ broaden what a git command actually touches (#1598/#1584 review, item 5).
224
+ """
225
+ try:
226
+ subprocess.run(
227
+ ["git", "--literal-pathspecs", "add", "--", str(test_file)],
228
+ cwd=cwd,
229
+ check=False,
230
+ timeout=GIT_TIMEOUT_S,
231
+ env=env,
232
+ )
233
+ except subprocess.TimeoutExpired:
234
+ sys.stderr.write(
235
+ f"error: git add for {test_file} timed out after "
236
+ f"{GIT_TIMEOUT_S}s (set DEV_TEAM_MUTATION_GIT_TIMEOUT_S to "
237
+ "raise it)\n"
238
+ )
239
+ return False
240
+ # Scoped with the same `-- <path>` pathspec as `git add` above: without
241
+ # it, `git commit -m message` commits the *entire* index, not just
242
+ # test_file — silently sweeping in whatever else happens to be staged
243
+ # (#1598).
244
+ try:
245
+ commit_result = subprocess.run(
246
+ ["git", "--literal-pathspecs", "commit", "-m", message, "--", str(test_file)],
247
+ capture_output=True,
248
+ text=True,
249
+ cwd=cwd,
250
+ check=False,
251
+ timeout=GIT_TIMEOUT_S,
252
+ env=env,
253
+ )
254
+ except subprocess.TimeoutExpired:
255
+ sys.stderr.write(
256
+ f"error: git commit for {test_file} timed out after "
257
+ f"{GIT_TIMEOUT_S}s (set DEV_TEAM_MUTATION_GIT_TIMEOUT_S to "
258
+ "raise it)\n"
259
+ )
260
+ return False
261
+ if commit_result is None:
262
+ return False
263
+ return commit_result.returncode == 0
264
+
265
+
266
+ @dataclass(frozen=True)
267
+ class StopDecision:
268
+ """Why a round stopped, and whether that stop is the loop's own call.
269
+
270
+ ``terminal`` is the distinction #2030 turns on. Three of the four stop
271
+ paths are **terminal**: the loop has established the file is done and
272
+ stopping needs no operator involvement. The fourth — the marginal-yield
273
+ floor — is **advisory**: the round did make progress, just less than the
274
+ floor, and the file may still be below its mutation target. Stopping
275
+ there is a judgement about whether another round is worth its price, and
276
+ per #2030 that judgement stays with the operator, routed through the
277
+ ``[c]ontinue / [r]etry / [w]aive / [q]uit`` prompt Phase 5 already
278
+ defines for residual survivors.
279
+
280
+ Collapsing the two into a bare string is exactly the conflation #1951 and
281
+ #1956 document elsewhere in this pipeline: a caller that cannot tell
282
+ "done" from "stopped early, your call" reports the wrong thing to the
283
+ operator, and an advisory stop silently becomes a terminal one.
284
+ """
285
+
286
+ reason: str
287
+ terminal: bool = True
288
+
289
+ def __str__(self) -> str: # so `f" {decision}"` logs the reason alone
290
+ return self.reason
291
+
292
+
293
+ def resolve_kill_floor(
294
+ min_kills_per_round: float | None, starting_survivors: int
295
+ ) -> int | None:
296
+ """Resolve the marginal-yield floor to an absolute kill count.
297
+
298
+ A value **>= 1** is an absolute kill count, used verbatim. A value
299
+ **strictly between 0 and 1** is a fraction of the round's starting
300
+ survivor count, rounded up so a non-zero fraction of a non-zero survivor
301
+ set never resolves to a floor of 0 (which would disable the check while
302
+ looking configured). ``None``, 0, or a negative value disables the floor.
303
+
304
+ Rounding up is the safe direction here: it can only surface a round to
305
+ the operator earlier, never suppress one that should have surfaced.
306
+ """
307
+ if min_kills_per_round is None or min_kills_per_round <= 0:
308
+ return None
309
+ if min_kills_per_round >= 1:
310
+ return int(min_kills_per_round)
311
+ if starting_survivors <= 0:
312
+ return None
313
+ return math.ceil(min_kills_per_round * starting_survivors)
314
+
315
+
316
+ def stop_reason(
317
+ survivor_count: int,
318
+ prev_survivor_count: int | None,
319
+ *,
320
+ honest_score: float | None = None,
321
+ target_honest_score: float | None = None,
322
+ min_kills_per_round: float | None = None,
323
+ ) -> StopDecision | None:
324
+ """Return the reason a round should stop, or ``None`` to continue to
325
+ generation.
326
+
327
+ Shared, byte-for-byte-identical predicate between the two loops (#1583).
328
+ The two original clauses are unchanged: a file is done when zero
329
+ survivors remain, and a round that didn't improve on the previous round's
330
+ survivor count also stops the loop (the "no improvement across rounds"
331
+ guard that prevents chasing the same survivors forever).
332
+
333
+ #2030 adds two opt-in clauses, both **default-off** — with
334
+ ``target_honest_score`` and ``min_kills_per_round`` both ``None`` this
335
+ function's verdicts are identical to the pre-#2030 behavior for every
336
+ input, which is what lets a bare ``mutation-kill`` invocation stay
337
+ unchanged while ``/test-improve`` Phase 5 threads the target through:
338
+
339
+ ``target_honest_score`` — stop once the file's honest score reaches the
340
+ number Phase 8 (``/quality-targets-converge``) actually gates on. Work
341
+ done past that threshold cannot change the gate's verdict, so this is
342
+ risk-neutral by construction: the honest score remains the only gate,
343
+ Phase 8 still measures it independently, and stopping *at* the threshold
344
+ cannot turn a pass into a fail. The score is already computed every round
345
+ by ``mutation_report.score_report_for_file`` — this reads a number that
346
+ is on hand rather than adding a measurement.
347
+
348
+ ``min_kills_per_round`` — a marginal-yield floor. A round that kills 1 of
349
+ 40 survivors costs the same as the first, most productive round (scoped
350
+ mutation run + generation + build + scoped test + commit), so without a
351
+ floor the loop chases the long tail at full price. Unlike the other
352
+ three, this returns a **non-terminal** decision: it is surfaced to the
353
+ operator, never acted on unilaterally. It is also skipped entirely once
354
+ the target is met, since the target clause has already stopped the loop
355
+ for a better reason.
356
+ """
357
+ if survivor_count == 0:
358
+ return StopDecision("no survivors — done")
359
+ if (
360
+ target_honest_score is not None
361
+ and honest_score is not None
362
+ and honest_score >= target_honest_score
363
+ ):
364
+ return StopDecision(
365
+ f"honest score {honest_score:.1f}% has reached the "
366
+ f"{target_honest_score:.1f}% mutation target — done "
367
+ f"({survivor_count} survivor(s) left deliberately unaddressed; "
368
+ "further rounds cannot change the Phase-8 verdict)"
369
+ )
370
+ if prev_survivor_count is not None and survivor_count >= prev_survivor_count:
371
+ return StopDecision("no improvement this round — stopping")
372
+ if prev_survivor_count is not None:
373
+ floor = resolve_kill_floor(min_kills_per_round, prev_survivor_count)
374
+ if floor is not None:
375
+ killed_this_round = prev_survivor_count - survivor_count
376
+ if killed_this_round < floor:
377
+ return StopDecision(
378
+ f"marginal yield: killed {killed_this_round} of "
379
+ f"{prev_survivor_count} survivor(s) this round, below the "
380
+ f"floor of {floor} — another round costs the same as the "
381
+ "first. Operator decides: [c]ontinue / [r]etry / [w]aive / "
382
+ "[q]uit",
383
+ terminal=False,
384
+ )
385
+ return None
386
+
387
+
388
+ # =============================================================================
389
+ # Headless generation glue — shelling to `claude --print`. Moved here from
390
+ # mutation_kill_headless.py (#1601): both mutation_kill_headless.py (the
391
+ # C# CLI) and mutation_kill_loop_python.py (the Python loop) reuse this
392
+ # verbatim; neither loop's own scoring/insertion/orchestration logic is
393
+ # C#- or Python-specific here.
394
+ # =============================================================================
395
+
396
+ # Timeout for the `claude --print` generation subprocess. Overridable via env
397
+ # var since a legitimately slow/large prompt may need a larger budget than
398
+ # this default — unlike the 30s used by this module's git-shelling helpers
399
+ # above, this subprocess routinely runs for tens of seconds to minutes.
400
+ CLAUDE_GENERATION_TIMEOUT_S = _timeout_from_env("DEV_TEAM_MUTATION_GENERATION_TIMEOUT_S", 300)
401
+
402
+ # Timeout for the `claude --version` availability probe — small, since it's a
403
+ # startup check, not a generation call.
404
+ CLAUDE_VERSION_TIMEOUT_S = _timeout_from_env("DEV_TEAM_MUTATION_VERSION_TIMEOUT_S", 30)
405
+
406
+ # The Claude CLI binary. Overridable via CLAUDE_BIN so a non-PATH install can
407
+ # be pointed at without editing this module.
408
+ CLAUDE_CLI = os.environ.get("CLAUDE_BIN", "claude")
409
+
410
+
411
+ def resolve_model(explicit: str | None = None) -> str | None:
412
+ """Resolve the generation model: ``--model`` > ``DEV_TEAM_MUTATION_MODEL``
413
+ > ``None``. When ``None``, ``--model`` is omitted from the ``claude --print``
414
+ invocation and the Claude CLI uses its own default — the plugin never pins a
415
+ model snapshot id in source (models are resolved dynamically, not literalized;
416
+ see ``tests/repo/test_no_pinned_snapshots.py``, the enforcing authority for
417
+ that rule)."""
418
+ if explicit:
419
+ return explicit
420
+ return os.environ.get("DEV_TEAM_MUTATION_MODEL") or None
421
+
422
+
423
+ # One-step model-downgrade ladder (#1908): opus -> sonnet -> haiku -> floor.
424
+ # No ``None`` entry: resolve_model()'s "unspecified, let the CLI pick its own
425
+ # default" result has no observable ladder position from this codebase (the
426
+ # CLI's actual default model is not knowable here), so treating it as
427
+ # equivalent to "opus" would be an unverified assumption. ``.get()`` returning
428
+ # ``None`` for an unresolved model, the floor (``haiku``), AND any
429
+ # operator-supplied model string outside {opus, sonnet, haiku} all mean the
430
+ # same thing to this ladder: no known position to step down from. Every round
431
+ # before a downgrade is otherwise unaffected: no --model flag is added, no
432
+ # snapshot id is pinned (see ``tests/repo/test_no_pinned_snapshots.py``)
433
+ # unless/until a downgrade actually happens.
434
+ _MODEL_DOWNGRADE_LADDER: dict[str, str] = {
435
+ "opus": "sonnet",
436
+ "sonnet": "haiku",
437
+ }
438
+
439
+ # Mirrors plugins/marketplace-dev/knowledge/agent-contract.json's
440
+ # ``model.enum`` minus ``inherit`` (which doesn't make sense as a fallback
441
+ # target). ``fable`` is a display-latency variant, not a capability tier, so
442
+ # it is a valid --model/DEV_TEAM_MUTATION_FALLBACK_MODEL override value but
443
+ # deliberately has no entry in _MODEL_DOWNGRADE_LADDER above — it is not part
444
+ # of the opus->sonnet->haiku capability step-down.
445
+ _VALID_FALLBACK_MODELS = frozenset({"opus", "sonnet", "haiku", "fable"})
446
+
447
+
448
+ def resolve_fallback_model(current: str | None) -> str | None:
449
+ """Resolve the next model one step down the downgrade ladder from
450
+ ``current``, or the ``DEV_TEAM_MUTATION_FALLBACK_MODEL`` override when
451
+ it names a valid tier.
452
+
453
+ ``current`` is expected to be ``resolve_model()``'s result: ``None``,
454
+ ``"opus"``, ``"sonnet"``, or ``"haiku"`` (matched case-insensitively).
455
+ ``None`` (unresolved), ``"haiku"`` (the floor), and any other value not
456
+ on the ladder (an unrecognized model string) all return ``None`` — "no
457
+ known ladder position to step down to." The three cases are
458
+ indistinguishable to ``resolve_fallback_model`` itself; a caller that
459
+ needs to tell them apart for messaging purposes (e.g.
460
+ :func:`_format_downgrade_message`) does so separately, from the
461
+ ``DowngradeEvent`` it already has in hand.
462
+
463
+ ``DEV_TEAM_MUTATION_FALLBACK_MODEL``, when set, is checked first and
464
+ wins outright — accepted at ANY ladder position, with no check that it
465
+ is actually a downgrade from ``current``: an explicit operator override
466
+ is authoritative operator intent, not validated against the ladder
467
+ position it replaces (#1908). Matched case-insensitively against
468
+ ``{opus, sonnet, haiku, fable}``. A value outside that enum is never
469
+ silently accepted or silently ignored: it's reported on stderr and this
470
+ call falls back to the one-step ladder default instead.
471
+ """
472
+ override = os.environ.get("DEV_TEAM_MUTATION_FALLBACK_MODEL")
473
+ if override:
474
+ normalized_override = override.strip().lower()
475
+ if normalized_override in _VALID_FALLBACK_MODELS:
476
+ return normalized_override
477
+ sys.stderr.write(
478
+ f"warning: DEV_TEAM_MUTATION_FALLBACK_MODEL={override!r} is not "
479
+ "one of opus/sonnet/haiku/fable — ignoring the override and "
480
+ "using the one-step ladder default instead\n"
481
+ )
482
+
483
+ normalized_current = current.strip().lower() if current else None
484
+ return _MODEL_DOWNGRADE_LADDER.get(normalized_current)
485
+
486
+
487
+ _FENCE_OPEN_RE = re.compile(r"^```[\w-]*\n?")
488
+ _FENCE_CLOSE_RE = re.compile(r"\n?```$")
489
+
490
+
491
+ def strip_code_fences(text: str) -> str:
492
+ """Strip one leading and one trailing markdown code fence, if present.
493
+
494
+ Claude may wrap generated methods in a ```` ```csharp ```` (or
495
+ ```` ```python ````) block; the loop inserts raw method/test text, so the
496
+ fence is removed on both ends.
497
+ """
498
+ text = _FENCE_OPEN_RE.sub("", text.strip())
499
+ text = _FENCE_CLOSE_RE.sub("", text.strip())
500
+ return text.strip()
501
+
502
+
503
+ class HeadlessCallFailed(RuntimeError):
504
+ """Raised by :func:`run_claude_headless` when ``claude --print`` exits
505
+ non-zero.
506
+
507
+ Carries the full, untruncated ``returncode``/``stderr`` as public
508
+ attributes for callers that need to inspect them directly; ``__str__``
509
+ truncates ``stderr`` to 500 bytes to stay byte-for-byte identical to the
510
+ plain ``RuntimeError`` message this type replaces, so any consumer that
511
+ only formats/prints the exception (``str(exc)``) sees the same message as
512
+ before.
513
+ """
514
+
515
+ def __init__(self, returncode: int, stderr: str, stdout: str = "") -> None:
516
+ self.returncode = returncode
517
+ self.stderr = stderr
518
+ # #1950: the classifier was structurally blind to stdout. The claude
519
+ # CLI renders some upstream failures to stdout (a rendered
520
+ # "API Error: 529 Overloaded" body) while stderr carries only a
521
+ # generic non-zero-exit line, so a stderr-only classifier calls a
522
+ # genuinely retryable overload non-gateway-class and burns the file's
523
+ # whole budget on it. Defaulted so every existing two-argument
524
+ # construction — including test fakes — keeps working unchanged.
525
+ self.stdout = stdout
526
+ super().__init__(str(self))
527
+
528
+ def __str__(self) -> str:
529
+ return f"claude CLI failed (exit {self.returncode}): {self.stderr[:500]}"
530
+
531
+
532
+ def claude_cli_available() -> bool:
533
+ """True if the Claude CLI responds to ``--version``."""
534
+ try:
535
+ result = subprocess.run(
536
+ [CLAUDE_CLI, "--version"],
537
+ capture_output=True,
538
+ text=True,
539
+ check=False,
540
+ timeout=CLAUDE_VERSION_TIMEOUT_S,
541
+ )
542
+ except (FileNotFoundError, OSError, subprocess.TimeoutExpired):
543
+ return False
544
+ return result.returncode == 0
545
+
546
+
547
+ def run_claude_headless(prompt: str, *, model: str | None, cwd: Path | None = None) -> str:
548
+ """Shell to ``claude --print`` with an already-built ``prompt``; return
549
+ stdout with markdown code fences stripped.
550
+
551
+ The single shared invocation glue behind both languages'
552
+ ``make_headless_generator`` factories (#1583). ``--model`` is passed only
553
+ when ``model`` is set; when ``None`` the Claude CLI uses its own default
554
+ (the plugin pins no model snapshot id — see
555
+ ``tests/repo/test_no_pinned_snapshots.py``).
556
+
557
+ ``prompt`` is passed over stdin (``input=prompt``), not as a trailing
558
+ argv element (#1607): an argv-passed prompt is both parsed for
559
+ dash-prefixed option injection by the CLI's own arg parser and visible to
560
+ any other process on the host via ``ps``/procfs for the subprocess's
561
+ lifetime — stdin avoids both.
562
+ """
563
+ cmd = [CLAUDE_CLI, "--print"]
564
+ if model:
565
+ cmd += ["--model", model]
566
+ try:
567
+ result = subprocess.run(
568
+ cmd,
569
+ input=prompt,
570
+ capture_output=True,
571
+ text=True,
572
+ cwd=cwd,
573
+ check=False,
574
+ timeout=CLAUDE_GENERATION_TIMEOUT_S,
575
+ )
576
+ except subprocess.TimeoutExpired as exc:
577
+ raise RuntimeError(
578
+ f"claude --print generation timed out after "
579
+ f"{CLAUDE_GENERATION_TIMEOUT_S}s (set "
580
+ "DEV_TEAM_MUTATION_GENERATION_TIMEOUT_S to raise it)"
581
+ ) from exc
582
+ if result.returncode != 0:
583
+ raise HeadlessCallFailed(result.returncode, result.stderr, result.stdout or "")
584
+ return strip_code_fences(result.stdout)
585
+
586
+
587
+ # =============================================================================
588
+ # Insertion result shape — shared verbatim between mutation_kill_insert.py
589
+ # (C#) and mutation_kill_insert_python.py (Python). Moved here from
590
+ # mutation_safety_gate.py (#1602): neither type is a safety concept — that
591
+ # module is scoped to the unattended-commit prompt-injection threat model,
592
+ # and InsertOutcome/InsertionRefused are returned/raised for plain structural
593
+ # refusals too (duplicate names, no methods generated, unrecognized file
594
+ # layout).
595
+ # =============================================================================
596
+ class InsertionRefused(Exception):
597
+ """Raised when a language-specific insertion heuristic can't safely
598
+ locate where to insert generated tests/methods, and refuses rather than
599
+ guess and risk a mis-insertion.
600
+
601
+ Framework-agnostic and shared verbatim between ``mutation_kill_insert.py``
602
+ (C# — refuses on a file-scoped namespace or non-4-space class indentation)
603
+ and ``mutation_kill_insert_python.py`` (Python — refuses on a test file
604
+ with no top-level ``def test_*():``) (#1583).
605
+ """
606
+
607
+
608
+ @dataclass(frozen=True)
609
+ class InsertOutcome:
610
+ """Result of attempting to apply generated tests/methods to a test file.
611
+
612
+ ``inserted`` is False when the file was left untouched; ``reason`` says
613
+ why. Framework-agnostic and shared verbatim between
614
+ ``mutation_kill_insert.py`` and ``mutation_kill_insert_python.py``
615
+ (#1583) — the two languages' insertion heuristics differ, but the result
616
+ shape each reports back to its loop is identical.
617
+ """
618
+
619
+ inserted: bool
620
+ reason: str