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,592 @@
1
+ #!/usr/bin/env python3
2
+ """mutation_kill_retry.py — retry-then-downgrade on repeated headless-generation
3
+ failures (#1908), extracted out of ``mutation_kill_shared.py`` (#1925).
4
+
5
+ ``mutation_kill_shared.py`` had grown into a grab-bag of five separate
6
+ concerns (git revert/commit mechanics, the stop-round predicate, headless-CLI
7
+ invocation glue, this retry/downgrade policy, and the cross-language
8
+ ``InsertOutcome``/``InsertionRefused`` shapes). A fix to git-revert semantics
9
+ and a fix to the downgrade ladder shared the same file and the same review
10
+ blast radius, with neither small enough to read in one pass and confirm it
11
+ doesn't touch the other's state. This module owns exactly the retry/downgrade
12
+ concern; ``mutation_kill_shared.py`` keeps git mechanics, ``_timeout_from_env``,
13
+ ``stop_reason``, ``resolve_model``/``resolve_fallback_model`` and the headless
14
+ ``claude --print`` invocation glue, and the ``InsertOutcome``/``InsertionRefused``
15
+ shapes.
16
+
17
+ The type precondition for the 502/gateway-class error definition is EXACT: a
18
+ :class:`mutation_kill_shared.HeadlessCallFailed` raised by
19
+ ``run_claude_headless``'s non-zero-exit shape (never its
20
+ ``TimeoutExpired``-derived shape, which raises a plain ``RuntimeError`` — a
21
+ local generation timeout, not an upstream provider signal). Within that type,
22
+ the classifier reads the full, untruncated ``stderr``, case-insensitively,
23
+ for either one of the non-numeric markers below or the anchored numeral
24
+ pattern (``_GATEWAY_STATUS_RE``) — a bare ``"502"``/``"503"``/``"504"``
25
+ substring is not enough on its own (#1938). That marker/regex match is a
26
+ best-effort heuristic, not an exhaustive one: it does not yet recognize
27
+ ``error_code: 503``-style underscore-joined tokens, status 529, or errors
28
+ that only appear on stdout — filed and deliberately deferred rather than
29
+ fixed in this slice, see #1950.
30
+
31
+ This module's dependencies on ``mutation_kill_shared`` are
32
+ ``run_claude_headless``/``resolve_fallback_model`` — both accessed via the
33
+ module object (``mutation_kill_shared.run_claude_headless(...)``), not a
34
+ ``from ... import`` binding, so a test's ``monkeypatch.setattr(mutation_kill_shared,
35
+ "run_claude_headless", fake)`` takes effect here too (mirrors the existing
36
+ same-module-globals contract ``_mutation_test_helpers.sequenced_run_claude_headless``
37
+ already documents) — plus ``HeadlessCallFailed``, referenced only as a type
38
+ (``isinstance(exc, mutation_kill_shared.HeadlessCallFailed)``), which carries
39
+ no monkeypatch sensitivity of its own since nothing here calls it.
40
+ ``run_claude_headless`` is reached on every generation attempt unless the
41
+ caller injects ``call_headless`` (#1918), in which case it is never reached —
42
+ see :meth:`_RetryCallContext.resolve_call_headless`. (This
43
+ mirrors the dependency inventory documented from the other direction in
44
+ ``mutation_kill_shared.py``'s own module docstring — keep the two in sync.)
45
+
46
+ Stdlib-only. See ADR 0014.
47
+ """
48
+
49
+ from __future__ import annotations
50
+
51
+ import re
52
+ import time
53
+ from collections.abc import Callable
54
+ from dataclasses import dataclass
55
+ from pathlib import Path
56
+
57
+ import mutation_kill_shared
58
+
59
+ _GATEWAY_CLASS_MARKERS = (
60
+ "bad gateway",
61
+ "service unavailable",
62
+ "gateway timeout",
63
+ "overloaded_error",
64
+ "upstream connect error",
65
+ "connection reset",
66
+ )
67
+
68
+ # Anchored numeral markers (#1938, widened by #1950): a bare "502"/"503"/"504"
69
+ # substring false-positives on unrelated numbers (a request id, a byte count).
70
+ # Requires a status-context word (status/http/code) close before the digits, so
71
+ # "HTTP 502", "status: 503", and "error code 504" all match but
72
+ # "request id 502391" does not.
73
+ #
74
+ # Three #1950 corrections to the original `\b(?:status|http|code)[^0-9]{0,12}50[234]\b`:
75
+ #
76
+ # 1. `\b` REJECTED UNDERSCORE-JOINED KEYS. `_` is a `\w` character, so `\b`
77
+ # requires a NON-word character immediately before status/http/code — and
78
+ # the `_c` in `error_code: 503` and the `rC` in `errorCode=504` are both
79
+ # word-to-word transitions. Underscore- and camel-joined status keys are
80
+ # routine in real provider payloads. The lookbehind is now
81
+ # `(?<![A-Za-z0-9])`, which treats `_` (and a camel boundary) as a
82
+ # separator while still refusing to match inside a longer alphanumeric run.
83
+ # 2. `HTTP/1.1 502` FAILED because the version token puts digits in the gap,
84
+ # which `[^0-9]{0,12}` forbids. An optional `/<major>[.<minor>]` is now
85
+ # consumed explicitly rather than by widening the gap to allow digits —
86
+ # widening would have re-admitted exactly the "request id 502391" class
87
+ # #1938 anchored the pattern to exclude.
88
+ # 3. STATUS 529 (Anthropic's own overload code) was absent from the numeral
89
+ # alternation. The downgrade ladder this policy drives is Anthropic-specific,
90
+ # so 529 is plausibly the most common real "retry me" signal this classifier
91
+ # will ever see. It was covered only via the `overloaded_error` marker
92
+ # string, which a rendered `API Error: 529 Overloaded` does not contain
93
+ # verbatim.
94
+ #
95
+ # The trailing `(?![0-9])` replaces `\b` for the same reason as the lookbehind,
96
+ # and still rejects "502391" (the `2` is followed by `3`).
97
+ #
98
+ # 4. A CAMEL-JOINED key (`errorCode=504`) still fails a plain lookbehind: the
99
+ # `rC` transition is letter-to-letter, and the pattern is IGNORECASE so the
100
+ # lookbehind cannot itself distinguish case. Rather than relaxing the
101
+ # lookbehind to allow any preceding letter — which would admit "barcode 502"
102
+ # and "decode 503" — camel humps are split to `_` first, reducing the camel
103
+ # case to the underscore case already handled.
104
+ # 5. `error` joins the context words so a rendered `API Error: 529 Overloaded`
105
+ # anchors at all; it carries none of status/http/code. The trailing
106
+ # `(?![0-9])` keeps this from admitting "error after 5024 ms".
107
+ _CAMEL_SPLIT_RE = re.compile(r"(?<=[a-z0-9])(?=[A-Z])")
108
+
109
+ _GATEWAY_STATUS_RE = re.compile(
110
+ r"(?<![A-Za-z0-9])(?:status|http|code|error)(?:/\d+(?:\.\d+)?)?"
111
+ r"[^0-9]{0,12}(?:50[234]|529)(?![0-9])",
112
+ re.IGNORECASE,
113
+ )
114
+
115
+
116
+ def _anchorable(text: str) -> str:
117
+ """Normalize camel humps to `_` so a camel-joined status key anchors.
118
+
119
+ Pure and deterministic: `errorCode=504` -> `error_Code=504`, which the
120
+ pattern's `(?<![A-Za-z0-9])` lookbehind then accepts.
121
+ """
122
+ return _CAMEL_SPLIT_RE.sub("_", text)
123
+
124
+ # 3 consecutive gateway-class failures on the same model earn exactly one
125
+ # same-model retry before a downgrade is considered (#1908).
126
+ _GATEWAY_FAILURE_THRESHOLD = 3
127
+
128
+ # Backoff formula for the pre-threshold retries: min(_BACKOFF_BASE **
129
+ # (streak - 1), _BACKOFF_CAP_S) seconds (#1908 review).
130
+ _BACKOFF_BASE = 2
131
+ _BACKOFF_CAP_S = 10
132
+
133
+
134
+ def is_gateway_class_error(exc: BaseException) -> bool:
135
+ """True iff ``exc`` is a :class:`mutation_kill_shared.HeadlessCallFailed`
136
+ raised by :func:`mutation_kill_shared.run_claude_headless`'s non-zero-exit
137
+ shape whose full, untruncated ``stderr``, case-insensitively, contains a
138
+ non-numeric gateway-class marker or matches the anchored numeral pattern
139
+ (#1938).
140
+
141
+ Everything else — a plain ``RuntimeError`` (the
142
+ ``subprocess.TimeoutExpired``-derived shape is a local generation
143
+ timeout, not an upstream provider signal, and never raises
144
+ ``HeadlessCallFailed``) and a ``HeadlessCallFailed`` whose stderr matches
145
+ none of the markers — is non-gateway-class.
146
+ """
147
+ if not isinstance(exc, mutation_kill_shared.HeadlessCallFailed):
148
+ return False
149
+ # #1950: classify over stderr AND stdout. The claude CLI renders some
150
+ # upstream failures to stdout while stderr carries only a generic
151
+ # non-zero-exit line; a stderr-only classifier calls those non-gateway-class
152
+ # and spends the file's whole budget on a genuinely retryable overload.
153
+ # `getattr` rather than attribute access so a HeadlessCallFailed built by
154
+ # an older two-argument call site (or a test fake) still classifies.
155
+ combined = f"{exc.stderr}\n{getattr(exc, 'stdout', '') or ''}"
156
+ lowered = combined.lower()
157
+ return any(marker in lowered for marker in _GATEWAY_CLASS_MARKERS) or bool(
158
+ _GATEWAY_STATUS_RE.search(_anchorable(combined))
159
+ )
160
+
161
+
162
+ # Shared exit code for the clean-continuable outcome class (#1908 review):
163
+ # either a fully spent retry-then-downgrade budget (GenerationExhausted) or
164
+ # any other provably-clean-of-inserted-content generation/infrastructure
165
+ # failure that isn't a failed revert. Used by both headless CLIs' main() and
166
+ # stryker_shard_pipeline.py's shard driver so the meaning of "5" lives in one
167
+ # place instead of three duplicated literals.
168
+ #
169
+ # EXIT_CLEAN_UNFIXED is the primary, outcome-shaped name (#1956): the value
170
+ # has named two distinct causes since #1939 (true GenerationExhausted, or any
171
+ # other clean RuntimeError such as a generation timeout), and the original
172
+ # name only describes one of them. EXIT_GENERATION_EXHAUSTED is kept as an
173
+ # alias — same value, zero behavior change — because every existing call
174
+ # site (stryker_shard_pipeline.py, mutation_kill_headless.py,
175
+ # mutation_kill_loop_python.py) and their tests already import it by that
176
+ # name; renaming those call sites too was judged not worth the diff for a
177
+ # purely cosmetic rename with no behavior change (#1956 explicitly frames
178
+ # this as "consider," not a mandate). New code should prefer
179
+ # EXIT_CLEAN_UNFIXED.
180
+ EXIT_CLEAN_UNFIXED = 5
181
+ EXIT_GENERATION_EXHAUSTED = EXIT_CLEAN_UNFIXED
182
+
183
+ # Shared exit code for the fatal, working-tree-possibly-mutated outcome class
184
+ # (#1930): a failed revert (or a failed-commit round-abandonment's own
185
+ # revert) leaves the tree in an unknown state. Used by both headless CLIs'
186
+ # main() functions so the meaning of "4" lives in one place instead of two
187
+ # duplicated literals. stryker_shard_pipeline.py's shard driver never
188
+ # imports this constant — it decodes exit 4 by exclusion (any non-zero,
189
+ # non-EXIT_GENERATION_EXHAUSTED exit is treated as fatal) and only names "4"
190
+ # in prose/log wording.
191
+ EXIT_REVERT_FAILED = 4
192
+
193
+
194
+ class GenerationExhausted(RuntimeError):
195
+ """Raised when the fallback tier's own generation call also exhausts its
196
+ 3-consecutive-gateway-class-failures/1-same-model-retry budget (#1908).
197
+
198
+ This file gets exactly one downgrade, ever — reaching this exception
199
+ means no second downgrade will be attempted, regardless of whether the
200
+ exhausted tier is the true ladder floor (``haiku``), a mid-ladder tier
201
+ (e.g. ``sonnet``), or an operator override. Callers (the ``--headless``
202
+ CLIs' ``main()``) catch this subclass ahead of ``RevertFailed`` and the
203
+ generic ``RuntimeError`` and report it via the existing exit-code
204
+ taxonomy — the message names the file, round, model, and error class,
205
+ plus an explicit "no further downgrade will be attempted" statement.
206
+ """
207
+
208
+
209
+ @dataclass(frozen=True)
210
+ class DowngradeEvent:
211
+ """One downgrade (or final-exhaustion) decision from the
212
+ retry-then-downgrade mechanism (#1908).
213
+
214
+ This is the seam Step 3.2b's audit-trail write hangs off of: pass an
215
+ ``on_downgrade`` callback to :func:`make_retrying_headless_call` (or
216
+ :func:`make_headless_generator`) to record this event durably. Nothing
217
+ in this module writes an audit trail itself yet.
218
+ """
219
+
220
+ source_file: str
221
+ round_num: int | None
222
+ from_model: str | None
223
+ to_model: str | None
224
+ error_class: str
225
+ #: Whether this file had ALREADY spent its one downgrade before this
226
+ #: failure. #1952: on an exhausted event this is the actual reason the
227
+ #: caller computed and then discarded, forcing
228
+ #: :func:`_format_downgrade_message` to re-infer it from a proxy (is
229
+ #: ``from_model`` a known ladder model?) that a valid non-ladder
230
+ #: ``--model``/``DEV_TEAM_MUTATION_FALLBACK_MODEL`` override defeats.
231
+ #: Defaulted so every existing construction keeps working; the one
232
+ #: internal call site sets it explicitly.
233
+ already_downgraded: bool = False
234
+
235
+ @property
236
+ def exhausted(self) -> bool:
237
+ """True iff no fallback tier was available — derived from
238
+ ``to_model`` rather than stored separately, so the two can never
239
+ disagree (#1918 Step 2.3)."""
240
+ return self.to_model is None
241
+
242
+
243
+ def _format_downgrade_message(event: DowngradeEvent) -> str:
244
+ source_file = " ".join(str(event.source_file).split())
245
+ if event.exhausted:
246
+ model_label = event.from_model if event.from_model is not None else "unspecified"
247
+ # #1952: branch on the reason the caller actually computed, not on
248
+ # whether from_model happens to be a ladder name. `fable` is a VALID
249
+ # --model / DEV_TEAM_MUTATION_FALLBACK_MODEL override that deliberately
250
+ # has no _MODEL_DOWNGRADE_LADDER entry, so a file that started on opus,
251
+ # downgraded once to fable, and then exhausted was reported as "no
252
+ # downgrade ladder position available for this model" when the true
253
+ # cause was "this file already spent its one downgrade".
254
+ if event.already_downgraded:
255
+ return (
256
+ f"generation for {source_file} (round {event.round_num}) "
257
+ f"exhausted its retry budget on model {model_label!r} after "
258
+ f"a {event.error_class} retry failure — no further downgrade "
259
+ "will be attempted"
260
+ )
261
+ return (
262
+ f"generation for {source_file} (round {event.round_num}) "
263
+ f"exhausted its retry budget on model {model_label!r} after a "
264
+ f"{event.error_class} retry failure — no downgrade ladder "
265
+ "position available for this model, surfacing to operator"
266
+ )
267
+ return (
268
+ f"downgrading generation for {source_file} (round "
269
+ f"{event.round_num}) from {event.from_model!r} to {event.to_model!r} "
270
+ f"after a {event.error_class} retry failure"
271
+ )
272
+
273
+
274
+ @dataclass
275
+ class _RetryState:
276
+ """Mutable per-file retry/downgrade state for one
277
+ :func:`make_retrying_headless_call` closure (#1908 review).
278
+
279
+ Replaces an untyped ``dict[str, object]`` that forced
280
+ ``# type: ignore[arg-type]`` at two call sites and an ``int(...)`` cast on
281
+ every streak read — a plain dataclass carries its own types, so neither
282
+ workaround is needed. Not frozen: every field is mutated in place as the
283
+ closure runs.
284
+ """
285
+
286
+ model: str | None
287
+ streak: int = 0
288
+ downgraded: bool = False
289
+
290
+ def record_gateway_failure(self) -> int:
291
+ """Increment the consecutive-gateway-failure streak and return the
292
+ new count."""
293
+ self.streak += 1
294
+ return self.streak
295
+
296
+ def reset_streak(self) -> None:
297
+ """Zero the consecutive-gateway-failure streak."""
298
+ self.streak = 0
299
+
300
+ def spend_downgrade(self, to_model: str) -> None:
301
+ """Spend this file's one-and-only downgrade, moving to ``to_model``.
302
+
303
+ Raises :class:`RuntimeError` if this state has already spent its one
304
+ downgrade — a file gets exactly one downgrade, ever (#1908).
305
+ """
306
+ if self.downgraded:
307
+ raise RuntimeError(
308
+ f"file already spent its one downgrade (current model {self.model!r})"
309
+ )
310
+ self.model = to_model
311
+ self.downgraded = True
312
+
313
+
314
+ @dataclass(frozen=True)
315
+ class _RetryCallContext:
316
+ """Call-invariant collaborators for one file's retry/downgrade closure
317
+ (#1908 review). Bundles ``cwd``/``log``/``on_downgrade`` — none of which
318
+ change between calls or rounds — so :func:`_retry_once_then_maybe_downgrade`
319
+ takes one object instead of three separate keyword parameters.
320
+
321
+ ``call_headless`` is ``None`` when the caller didn't inject a transport
322
+ (#1918 Step 2.2) — :meth:`resolve_call_headless` looks up
323
+ ``mutation_kill_shared.run_claude_headless`` fresh on every actual call,
324
+ not once here at construction time, so a test that monkeypatches the
325
+ module attribute *after* constructing the closure (but before invoking
326
+ it) still observes the patch — exactly the dynamic-lookup contract the
327
+ pre-injection code had via its direct
328
+ ``mutation_kill_shared.run_claude_headless(...)`` call sites."""
329
+
330
+ cwd: Path | None
331
+ log: Callable[[str], None]
332
+ on_downgrade: Callable[[DowngradeEvent], None] | None
333
+ call_headless: Callable[..., str] | None
334
+
335
+ def resolve_call_headless(self) -> Callable[..., str]:
336
+ """Return the injected transport, or
337
+ ``mutation_kill_shared.run_claude_headless`` looked up dynamically
338
+ via the module object when none was injected."""
339
+ return (
340
+ self.call_headless
341
+ if self.call_headless is not None
342
+ else mutation_kill_shared.run_claude_headless
343
+ )
344
+
345
+ def invoke(self, prompt: str, model: str | None) -> str:
346
+ """Call the resolved transport with this context's ``cwd`` — the one
347
+ call expression both :func:`_retry_once_then_maybe_downgrade` and
348
+ :func:`make_retrying_headless_call`'s ``call`` closure need, so it's
349
+ defined once instead of duplicated verbatim at both sites (#1938
350
+ review)."""
351
+ return self.resolve_call_headless()(prompt, model=model, cwd=self.cwd)
352
+
353
+
354
+ def _retry_once_then_maybe_downgrade(
355
+ state: _RetryState,
356
+ prompt: str,
357
+ source_file: str,
358
+ round_num: int | None,
359
+ *,
360
+ ctx: _RetryCallContext,
361
+ ) -> str | None:
362
+ """The 3rd-consecutive-failure branch: exactly one same-model retry, then
363
+ decide downgrade-or-exhausted (#1908). Extracted out of
364
+ :func:`make_retrying_headless_call`'s ``call`` closure to keep it under
365
+ size/nesting/complexity thresholds — ``ctx`` carries the same
366
+ ``on_downgrade``/``log``/``cwd`` the caller already has (passed
367
+ explicitly, not captured by closure, so this function stays testable in
368
+ isolation), and mutates ``state`` in place exactly as the inline branch
369
+ it replaces did.
370
+
371
+ Returns the retry's result string on a successful retry. Returns
372
+ ``None`` when a downgrade was applied instead — the caller's
373
+ ``while True`` loop re-enters :func:`mutation_kill_shared.run_claude_headless`
374
+ on the new model. Raises :class:`GenerationExhausted` on exhaustion (no
375
+ fallback tier available, or this file already spent its one downgrade).
376
+ """
377
+ already_downgraded = state.downgraded
378
+ try:
379
+ return ctx.invoke(prompt, state.model)
380
+ except RuntimeError as retry_exc:
381
+ error_class = (
382
+ "gateway-class" if is_gateway_class_error(retry_exc) else "non-gateway-class"
383
+ )
384
+ from_model = state.model
385
+ to_model = (
386
+ None
387
+ if already_downgraded
388
+ else mutation_kill_shared.resolve_fallback_model(from_model)
389
+ )
390
+ event = DowngradeEvent(
391
+ source_file=source_file,
392
+ round_num=round_num,
393
+ from_model=from_model,
394
+ to_model=to_model,
395
+ error_class=error_class,
396
+ already_downgraded=already_downgraded,
397
+ )
398
+ ctx.log(_format_downgrade_message(event))
399
+ if ctx.on_downgrade is not None:
400
+ ctx.on_downgrade(event)
401
+ if to_model is None:
402
+ raise GenerationExhausted(_format_downgrade_message(event)) from retry_exc
403
+ state.spend_downgrade(to_model)
404
+ return None
405
+
406
+
407
+ def make_retrying_headless_call(
408
+ *,
409
+ initial_model: str | None,
410
+ cwd: Path | None = None,
411
+ log: Callable[[str], None] = print,
412
+ on_downgrade: Callable[[DowngradeEvent], None] | None = None,
413
+ sleep: Callable[[float], None] = time.sleep,
414
+ call_headless: Callable[..., str] | None = None,
415
+ ) -> Callable[[str, str, int | None], str]:
416
+ """Return a per-file, stateful wrapper around
417
+ :func:`mutation_kill_shared.run_claude_headless` implementing the
418
+ retry-then-downgrade rule (#1908): 3 consecutive gateway-class failures
419
+ on the model in use earn exactly one same-model retry; if that retry
420
+ ALSO fails (of any error class — the retry's own outcome is a plain
421
+ pass/fail, never re-filtered by error class), this file spends its
422
+ one-and-only downgrade and continues on the next ladder tier
423
+ (:func:`mutation_kill_shared.resolve_fallback_model`). A success resets
424
+ the consecutive-failure counter to 0; a non-gateway-class failure also
425
+ resets it to 0 (it never counts toward the threshold, and it breaks an
426
+ in-progress gateway-class streak). If the fallback tier's own budget is
427
+ ALSO exhausted (or there is no fallback tier to move to), this raises
428
+ :class:`GenerationExhausted` — no second downgrade is ever attempted.
429
+
430
+ **This is all intra-call, not cross-round (#1908 review, correcting an
431
+ earlier revision of this docstring/the plan).** Every retry and the
432
+ at-most-one downgrade happen inside a single invocation of the returned
433
+ ``call`` — the same ``generate()`` call one round makes. ``state``
434
+ persists across rounds only because the closure itself does; for every
435
+ ``RuntimeError``-mediated exit path (a return, or a raise) the streak is
436
+ reset first, so no round mediated that way ever actually leaves a
437
+ non-zero streak behind. A non-``RuntimeError`` escape from
438
+ :func:`mutation_kill_shared.run_claude_headless` (e.g.
439
+ ``FileNotFoundError``/``OSError`` if the CLI binary disappears mid-run)
440
+ is NOT caught by the ``except RuntimeError`` below, so it skips the
441
+ reset — but that escape is fatal to the process, so a residual streak
442
+ from it is never observed. So while the counter is *structurally*
443
+ shared across a file's rounds, in practice a partial streak never
444
+ survives past one round's call — describing this as "carried across
445
+ rounds" overstates what's observable.
446
+
447
+ **Backoff between pre-threshold retries (#1908 review).** Silently
448
+ retrying the 1st and 2nd consecutive gateway-class failures with zero
449
+ delay let one ``generate()`` call fire up to 4 same-model attempts back
450
+ to back at an already-overloaded upstream. ``sleep`` (real
451
+ :func:`time.sleep` by default, injectable for tests) is now called with
452
+ an increasing, capped delay — ``min(2 ** (streak - 1), 10)`` seconds —
453
+ before each of those two retries (streak 1 -> ~1s, streak 2 -> ~2s). The
454
+ 3rd-failure same-model retry itself (handled by
455
+ :func:`_retry_once_then_maybe_downgrade`) is unpaced — it already earned
456
+ its attempt via the threshold, and a downgrade beyond it changes model,
457
+ not just repeats the same call.
458
+
459
+ **State ownership (Design & Architecture Critic's review, #1908).** The
460
+ consecutive-failure counter, the model currently in use, and whether
461
+ this file has already spent its one downgrade all live in THIS
462
+ closure's :class:`_RetryState` — meant to be constructed once per file,
463
+ inside each language loop's own ``make_headless_generator`` factory —
464
+ never at module scope. :func:`mutation_kill_shared.run_claude_headless`
465
+ itself stays the stateless, language-neutral single-shot call it
466
+ already is; this wrapper adds retry/downgrade semantics entirely from
467
+ the caller's side, so a new file's closure always starts fresh at the
468
+ top of the ladder and concurrent files (each with their own closure)
469
+ never leak state to one another.
470
+
471
+ The returned callable takes ``(prompt, source_file, round_num)`` and
472
+ returns the generated text — exactly what a single
473
+ :func:`mutation_kill_shared.run_claude_headless` call would return.
474
+ Every retry and downgrade happens transparently inside one call: neither
475
+ loop's round machinery (``_run_round``/``run_for_file``) needs to
476
+ change, since a call either eventually succeeds or raises (a plain
477
+ ``RuntimeError`` for a non-gateway-class failure, unchanged from today;
478
+ :class:`GenerationExhausted` only once the retry-then-downgrade budget
479
+ is fully spent).
480
+
481
+ **Injectable transport (#1918 Step 2.2).** ``call_headless`` defaults to
482
+ ``None``, resolved by :meth:`_RetryCallContext.resolve_call_headless` to
483
+ :func:`mutation_kill_shared.run_claude_headless` fresh on every actual
484
+ generation attempt rather than once here at construction time — a
485
+ signature-level default (``call_headless: Callable[..., str] =
486
+ mutation_kill_shared.run_claude_headless``) would bind that reference
487
+ once, at module-import time, and a construction-time resolution would
488
+ still be a single stale snapshot; either way, a test's
489
+ ``monkeypatch.setattr(mutation_kill_shared, "run_claude_headless", fake)``
490
+ made after this factory returns its closure (but before the closure is
491
+ invoked) would silently miss the patch (this module's own docstring
492
+ dependency-inventory note above depends on the module-attribute lookup
493
+ staying dynamic on every call, matching the pre-injection code's direct
494
+ ``mutation_kill_shared.run_claude_headless(...)`` call sites). Every
495
+ generation attempt this closure makes — the initial attempt and the
496
+ 3rd-failure same-model retry — goes through ``call_headless``, so a test
497
+ can also substitute a fake transport directly via this parameter without
498
+ monkeypatching the shared module at all. ``resolve_fallback_model`` is
499
+ unaffected — it stays a direct
500
+ :func:`mutation_kill_shared.resolve_fallback_model` reference.
501
+ """
502
+ state = _RetryState(model=initial_model)
503
+ ctx = _RetryCallContext(cwd=cwd, log=log, on_downgrade=on_downgrade, call_headless=call_headless)
504
+
505
+ def call(prompt: str, source_file: str, round_num: int | None = None) -> str:
506
+ while True:
507
+ try:
508
+ result = ctx.invoke(prompt, state.model)
509
+ except RuntimeError as exc:
510
+ if not is_gateway_class_error(exc):
511
+ # Never counts toward the threshold, and breaks an
512
+ # in-progress gateway-class streak rather than being
513
+ # skipped over.
514
+ state.reset_streak()
515
+ raise
516
+ current_streak = state.record_gateway_failure()
517
+ if current_streak < _GATEWAY_FAILURE_THRESHOLD:
518
+ sleep(min(_BACKOFF_BASE ** (current_streak - 1), _BACKOFF_CAP_S))
519
+ continue # transparently retry, same model
520
+ # 3rd consecutive gateway-class failure: exactly one
521
+ # same-model retry before considering downgrade.
522
+ state.reset_streak()
523
+ retry_result = _retry_once_then_maybe_downgrade(
524
+ state,
525
+ prompt,
526
+ source_file,
527
+ round_num,
528
+ ctx=ctx,
529
+ )
530
+ if retry_result is None:
531
+ continue # downgraded — retry the 3-then-1 sequence on the new model
532
+ return retry_result
533
+ else:
534
+ state.reset_streak()
535
+ return result
536
+
537
+ return call
538
+
539
+
540
+ def _format_downgrade_label(event: DowngradeEvent) -> str:
541
+ """Compact ``Generator:`` audit-trailer label for a downgrade event
542
+ (#1908 Step 3.2b) — the same four facts as :func:`_format_downgrade_message`
543
+ (source file, round, from-model, to-model, error class), worded for a
544
+ commit trailer rather than a live log line.
545
+ """
546
+ return (
547
+ f"headless (downgraded {event.from_model!r} -> {event.to_model!r} "
548
+ f"for {event.source_file} at round {event.round_num}, "
549
+ f"{event.error_class})"
550
+ )
551
+
552
+
553
+ def make_downgrade_audit_hook() -> (
554
+ tuple[Callable[[DowngradeEvent], None], Callable[[], str | None]]
555
+ ):
556
+ """Return an ``(on_downgrade, get_label_override)`` pair that carries a
557
+ downgrade event into the commit-message audit trail (#1908 Step 3.2b).
558
+
559
+ ``RunContext.generator_label`` is ``frozen=True`` and set once per
560
+ file's run, read unchanged by every round's commit — it cannot carry a
561
+ downgrade's per-round dynamic content (from-model, to-model, round)
562
+ without breaking that invariant. This pair is the seam instead:
563
+
564
+ - Pass ``on_downgrade`` straight through as
565
+ :func:`make_retrying_headless_call`'s ``on_downgrade`` kwarg —
566
+ construct both, once per file, inside each language loop's own
567
+ ``make_headless_generator`` factory (never at module scope, matching
568
+ that function's own per-file state-ownership contract).
569
+ - Wire ``get_label_override`` into ``RunContext.label_override_provider``
570
+ so each loop's ``_commit_message`` passes its result to
571
+ :func:`mutation_safety_gate.append_generator_trailer` as
572
+ ``label_override`` — which wins over the frozen ``generator_label``
573
+ whenever it is not ``None``.
574
+
575
+ Before any downgrade, ``get_label_override()`` returns ``None`` and the
576
+ frozen ``generator_label`` default is used, unchanged. The "exhausted, no
577
+ further downgrade" event is deliberately NOT recorded here — no round
578
+ ever completes after it (the caller raises :class:`GenerationExhausted`
579
+ before generation returns), so there is nothing left to commit that
580
+ override could ever reach.
581
+ """
582
+ state: dict[str, str | None] = {"label": None}
583
+
584
+ def on_downgrade(event: DowngradeEvent) -> None:
585
+ if event.exhausted:
586
+ return
587
+ state["label"] = _format_downgrade_label(event)
588
+
589
+ def get_label_override() -> str | None:
590
+ return state["label"]
591
+
592
+ return on_downgrade, get_label_override