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,193 @@
1
+ #!/usr/bin/env python3
2
+ """mutation_gate.py — PostToolUse hook (Python port of mutation-gate.sh).
3
+
4
+ After each RED-to-GREEN test transition, runs mutation testing scoped to
5
+ the affected test file and blocks tests that kill zero mutants.
6
+
7
+ Output protocol (PostToolUse):
8
+ Blocking : `emit_block` JSON on stdout, exit 0.
9
+ Advisory : `emit_advisory` JSON on stdout, exit 0.
10
+ Silent : no stdout, exit 0.
11
+
12
+ Delegates to `hooks.mutation_adapters` for detection, dispatch, and per-
13
+ adapter execution — the same Python library shipped in #572.D0.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import json
19
+ import os
20
+ import shutil
21
+ import sys
22
+ from pathlib import Path
23
+
24
+ _HOOK_DIR = Path(__file__).resolve().parent
25
+ # Add the plugin hooks dir to sys.path so the mutation_adapters package resolves.
26
+ sys.path.insert(0, str(_HOOK_DIR))
27
+ sys.path.insert(0, str(_HOOK_DIR / "lib"))
28
+
29
+ from boundary_events import emit_boundary_event as _emit_boundary_event
30
+ from mutation_adapters import lib as adapter_lib
31
+ from mutation_adapters import mutmut, pitest, stryker, stryker_net
32
+
33
+
34
+ def emit_boundary_event(*args, **kwargs) -> None:
35
+ """Local safety net (#859): even a misbehaving helper must never affect
36
+ this hook's exit code, stdout, or stderr."""
37
+ try:
38
+ _emit_boundary_event(*args, **kwargs)
39
+ except Exception: # noqa: BLE001, S110 - fail-open by design
40
+ pass
41
+
42
+
43
+ _JQ_MISSING_MESSAGE = (
44
+ "MUTATION GATE ADVISORY: jq is required but not installed. Run "
45
+ "/setup to install it, or: brew install jq (macOS) / apt install jq "
46
+ "(Linux) / winget install jqlang.jq (Windows)."
47
+ )
48
+
49
+
50
+ def _emit_advisory_pretty(message: str) -> None:
51
+ """Emit an advisory in bash `jq -n`'s pretty format (2-space indent + \\n).
52
+
53
+ `mutation-gate.sh` prints its advisories with `jq -n` so downstream Claude
54
+ Code output stays visually indented. This matches that shape byte-for-byte
55
+ for the paths the mutation-gate hook itself dispatches; the adapters still
56
+ print compact JSON (their internal `emit_advisory` returns compact),
57
+ tracked for the next release cycle when the settings-toggle flips
58
+ default to `.py`.
59
+ """
60
+ print(
61
+ json.dumps(
62
+ {
63
+ "hookSpecificOutput": {
64
+ "hookEventName": "PostToolUse",
65
+ "additionalContext": message,
66
+ }
67
+ },
68
+ indent=2,
69
+ )
70
+ )
71
+
72
+
73
+ def _emit_block_pretty(reason: str) -> None:
74
+ print(json.dumps({"decision": "block", "reason": reason}, indent=2))
75
+
76
+
77
+ def main() -> int:
78
+ # Hard dependency guards — mirror the bash order.
79
+ if shutil.which("jq") is None:
80
+ _emit_advisory_pretty(_JQ_MISSING_MESSAGE)
81
+ return 0
82
+ # python3 is by definition available here (we are python3), but if the
83
+ # bash sibling migrates a caller through the settings-toggle env var, the
84
+ # advisory would already have fired. Keep the branch for parity of the
85
+ # shape, harmlessly no-op.
86
+
87
+ if os.environ.get("MUTATION_GATE_SKIP") == "1":
88
+ return 0
89
+
90
+ raw = sys.stdin.read()
91
+ try:
92
+ payload = json.loads(raw)
93
+ except (TypeError, ValueError):
94
+ return 0
95
+ if not isinstance(payload, dict):
96
+ return 0
97
+
98
+ command = ""
99
+ tool_input = payload.get("tool_input") or {}
100
+ if isinstance(tool_input, dict):
101
+ candidate = tool_input.get("command")
102
+ if isinstance(candidate, str):
103
+ command = candidate
104
+ if not command:
105
+ return 0
106
+
107
+ if not adapter_lib.is_test_command(command):
108
+ return 0
109
+
110
+ event_json = raw
111
+ current_result = adapter_lib.detect_result(event_json)
112
+
113
+ prev_state = adapter_lib.read_state()
114
+ prev_result = "none"
115
+ if prev_state:
116
+ try:
117
+ prev_result = json.loads(prev_state).get("result") or "none"
118
+ except (TypeError, ValueError):
119
+ prev_result = "none"
120
+
121
+ adapter_lib.write_state(current_result, event_json)
122
+
123
+ if not adapter_lib.is_red_to_green(prev_result, current_result):
124
+ return 0
125
+
126
+ adapter = adapter_lib.detect_adapter(command)
127
+ if adapter == "none":
128
+ _emit_advisory_pretty(
129
+ "MUTATION GATE ADVISORY: no mutation testing adapter for this "
130
+ "language. Run /setup to install one (supports JS/TS via "
131
+ "Stryker, Java via pitest, C# via Stryker.NET)."
132
+ )
133
+ return 0
134
+
135
+ zero_kills_dir = Path(os.environ.get("TMPDIR", "/tmp")) / "mutation-gate"
136
+ zero_kills_file = zero_kills_dir / "zero-kills.json"
137
+ zero_kills_dir.mkdir(parents=True, exist_ok=True)
138
+
139
+ os.environ["ADAPTER_TIMEOUT"] = os.environ.get("MUTATION_GATE_TIMEOUT", "60")
140
+ os.environ["ADAPTER_COMMAND"] = command
141
+
142
+ runner_stdout = ""
143
+ if prev_state:
144
+ try:
145
+ runner_stdout = json.loads(prev_state).get("runner_stdout") or ""
146
+ except (TypeError, ValueError):
147
+ runner_stdout = ""
148
+ os.environ["ADAPTER_RUNNER_STDOUT"] = runner_stdout
149
+
150
+ if adapter == "stryker":
151
+ if not stryker.stryker_detect():
152
+ return 0
153
+ # bash derives ADAPTER_SOURCE_FILE from the last word of the command.
154
+ last_arg = command.rsplit(" ", 1)[-1] if command else ""
155
+ source_file = stryker.derive_source_file(last_arg) if last_arg else ""
156
+ os.environ["ADAPTER_SOURCE_FILE"] = source_file
157
+ stryker.stryker_run(zero_kills_file)
158
+ elif adapter == "pitest":
159
+ if not pitest.pitest_detect():
160
+ return 0
161
+ pitest.pitest_run(zero_kills_file)
162
+ elif adapter == "stryker-net":
163
+ if not stryker_net.stryker_net_detect():
164
+ return 0
165
+ stryker_net.stryker_net_run(zero_kills_file)
166
+ elif adapter == "mutmut":
167
+ if not mutmut.mutmut_detect():
168
+ return 0
169
+ mutmut.mutmut_run(zero_kills_file)
170
+
171
+ # Emit block if zero-kill tests found.
172
+ if zero_kills_file.is_file():
173
+ try:
174
+ data = json.loads(zero_kills_file.read_text())
175
+ except (OSError, ValueError):
176
+ data = []
177
+ if isinstance(data, list) and data:
178
+ reason = adapter_lib.format_blocking_reason(zero_kills_file, command)
179
+ _emit_block_pretty(reason)
180
+ emit_boundary_event(
181
+ payload.get("cwd") or ".",
182
+ "mutation_gate",
183
+ "Bash",
184
+ "block",
185
+ "mutation-gate-zero-kills",
186
+ payload.get("session_id"),
187
+ )
188
+
189
+ return 0
190
+
191
+
192
+ if __name__ == "__main__": # pragma: no cover
193
+ sys.exit(main())
@@ -0,0 +1,371 @@
1
+ #!/usr/bin/env python3
2
+ """Mutation-testing smoke gate — PreToolUse hook (#565; python port per #574 / #572).
3
+
4
+ Byte-compatible port of the Claude Code PreToolUse hook that enforces the
5
+ SKILL.md § Step 1c smoke gate. Blocks whole-scope Stryker.NET invocations
6
+ until a single-file smoke probe has landed a mutation-report.json under
7
+ StrykerOutput/smoke/reports/ with at least one Killed mutant.
8
+
9
+ Contract (docs/python-hook-contract.md):
10
+ Input : PreToolUse JSON on stdin
11
+ Output: exit 2 + message on stdout to BLOCK
12
+ exit 0 + no stdout for SILENT-PASS
13
+ exit 0 + ADVISORY-prefixed stdout for missing-dep / malformed / drift
14
+ Env : MUTATION_SMOKE_GATE_SKIP=1 → silent bypass + audit-log line
15
+
16
+ Stdlib-only. See docs/python-hook-contract.md.
17
+
18
+ Refs: #565 (the .sh predecessor), #554, #557 (the failure modes it guards).
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import hashlib
24
+ import json
25
+ import os
26
+ import re
27
+ import shlex
28
+ import shutil
29
+ import sys
30
+ from datetime import datetime, timezone
31
+ from pathlib import Path
32
+
33
+ _HOOK_DIR = Path(__file__).resolve().parent
34
+ _LIB_DIR = _HOOK_DIR / "lib"
35
+
36
+ sys.path.insert(0, str(_LIB_DIR))
37
+ import artifact_paths # type: ignore[import-not-found]
38
+
39
+ try:
40
+ from atomic_state import ( # type: ignore[import-not-found]
41
+ append_line_locked,
42
+ )
43
+ from boundary_events import ( # type: ignore[import-not-found]
44
+ emit_boundary_event as _emit_boundary_event,
45
+ )
46
+ from stdin_json import read_stdin_json # type: ignore[import-not-found]
47
+ except ImportError: # pragma: no cover
48
+
49
+ def read_stdin_json() -> dict | None: # type: ignore[misc]
50
+ return None
51
+
52
+ def _emit_boundary_event(*_args, **_kwargs) -> None: # type: ignore[misc]
53
+ return None
54
+
55
+ def append_line_locked( # type: ignore[misc]
56
+ path: Path, line: str, *, delay_env_var=None, fail_open: bool = True
57
+ ) -> None:
58
+ # Degraded-import fallback: atomic_state itself couldn't be
59
+ # imported, so no hardened (locked, O_NOFOLLOW) append is available.
60
+ # #1904 item 5: this used to fall back to a plain unlocked
61
+ # `open(path, "a")` — the exact O_NOFOLLOW-hardening gap that
62
+ # issue disclosed for this and `pre_commit_review.py`'s equivalent
63
+ # shim. A failed audit write is already fail-open by design (the
64
+ # bypass this line records proceeds either way), so degrading
65
+ # further to "don't write at all" costs nothing beyond the audit
66
+ # trail entry itself, and avoids reintroducing the symlink-redirect
67
+ # gap the shared helper exists to close.
68
+ if not fail_open:
69
+ raise OSError("atomic_state unavailable (degraded import)")
70
+
71
+
72
+ def emit_boundary_event(*args, **kwargs) -> None:
73
+ """Local safety net (#859): even a misbehaving helper must never affect
74
+ this hook's exit code, stdout, or stderr."""
75
+ try:
76
+ _emit_boundary_event(*args, **kwargs)
77
+ except Exception: # noqa: BLE001, S110 - fail-open by design
78
+ pass
79
+
80
+
81
+ # ---------------------------------------------------------------------------
82
+ # Trigger detection
83
+ # ---------------------------------------------------------------------------
84
+
85
+ try:
86
+ from stryker_invocation import ( # type: ignore[import-not-found]
87
+ is_stryker_invocation as _is_stryker_invocation,
88
+ )
89
+ except ImportError: # pragma: no cover - degraded fallback, hooks/lib unreachable
90
+ _STRYKER_TRIGGER_FALLBACK = re.compile(
91
+ r"(?:^|[^a-zA-Z0-9])dotnet[ \t]+stryker(?:\b|$)|csharp-stryker-net-wrapper\.sh"
92
+ )
93
+
94
+ def _is_stryker_invocation(cmd: str) -> bool: # type: ignore[misc]
95
+ return bool(cmd) and bool(_STRYKER_TRIGGER_FALLBACK.search(cmd))
96
+
97
+
98
+ def is_stryker_command(cmd: str) -> bool:
99
+ """True when `cmd` invokes dotnet stryker OR the wrapper script.
100
+
101
+ Delegates to the shared `hooks/lib/stryker_invocation` predicate (#2185):
102
+ parsed via `shlex` in program position, not scanned with a bare regex —
103
+ so a mention of the tool name in a --body/grep/echo/comment argument is
104
+ never mistaken for a real invocation.
105
+ """
106
+ if not cmd:
107
+ return False
108
+ return _is_stryker_invocation(cmd)
109
+
110
+
111
+ def extract_mutate_value(cmd: str) -> str:
112
+ """Return the --mutate value (handles --mutate=X, --mutate X, -m X).
113
+
114
+ Respects shell quoting via shlex so `--mutate 'src/Foo.cs'` and
115
+ `--mutate "src/Foo.cs"` both yield the unquoted path. Malformed shell
116
+ input yields "" (silent, matching the .sh's behavior).
117
+ """
118
+ try:
119
+ tokens = shlex.split(cmd)
120
+ except ValueError:
121
+ return ""
122
+ for i, tok in enumerate(tokens):
123
+ if tok.startswith("--mutate="):
124
+ return tok.split("=", 1)[1]
125
+ if tok in ("--mutate", "-m"):
126
+ if i + 1 < len(tokens):
127
+ return tokens[i + 1]
128
+ return ""
129
+ return ""
130
+
131
+
132
+ def is_single_file_mutate(value: str) -> bool:
133
+ """A --mutate value is single-file only when it has no glob metacharacters
134
+ (*, ?, [) AND no semicolon (Stryker.NET's multi-file separator)."""
135
+ if not value:
136
+ return False
137
+ return not any(c in value for c in ("*", "?", "[", ";"))
138
+
139
+
140
+ # ---------------------------------------------------------------------------
141
+ # Audit-log helpers
142
+ # ---------------------------------------------------------------------------
143
+
144
+
145
+ def sha256_first_16(text: str) -> str:
146
+ """First 16 hex chars of sha256(text). Matches the .sh's cross-platform
147
+ shasum/sha256sum fallback chain output."""
148
+ return hashlib.sha256(text.encode("utf-8")).hexdigest()[:16]
149
+
150
+
151
+ def iso_utc_timestamp() -> str:
152
+ """ISO-8601 UTC timestamp with 'Z' suffix. Matches the .sh helper."""
153
+ return datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
154
+
155
+
156
+ def log_bypass_audit(raw_command: str, payload_cwd: str) -> None:
157
+ """Append one JSONL line to <payload_cwd>/.claude/metrics/gate-bypass.jsonl.
158
+
159
+ Writes timestamp + hook name + command_hash (sha256 first 16) + cwd.
160
+ The raw command is NEVER written — only its hash — matching the .sh's
161
+ privacy boundary. Filesystem errors write to stderr and return
162
+ silently so the bypass still succeeds.
163
+ """
164
+ audit_file = artifact_paths.resolve_file(
165
+ "metrics", "gate-bypass.jsonl", payload_cwd
166
+ )
167
+ audit_dir = audit_file.parent
168
+ try:
169
+ audit_dir.mkdir(parents=True, exist_ok=True)
170
+ except OSError:
171
+ print(
172
+ f"mutation-testing-smoke-gate: cannot create {audit_dir} "
173
+ "(bypass still succeeds)",
174
+ file=sys.stderr,
175
+ )
176
+ return
177
+ record = {
178
+ "timestamp": iso_utc_timestamp(),
179
+ "hook": "mutation-testing-smoke-gate",
180
+ "command_hash": sha256_first_16(raw_command),
181
+ "cwd": payload_cwd,
182
+ }
183
+ try:
184
+ # Match jq -c compact output: no spaces after ',' or ':'.
185
+ append_line_locked(
186
+ audit_file, json.dumps(record, separators=(",", ":")) + "\n", fail_open=False
187
+ )
188
+ except OSError:
189
+ print(
190
+ f"mutation-testing-smoke-gate: cannot write to {audit_file} "
191
+ "(bypass still succeeds)",
192
+ file=sys.stderr,
193
+ )
194
+
195
+
196
+ # ---------------------------------------------------------------------------
197
+ # Block message
198
+ # ---------------------------------------------------------------------------
199
+
200
+
201
+ _BLOCK_TEMPLATE = """[BLOCK] mutation-testing-smoke-gate: whole-scope Stryker.NET run detected
202
+
203
+ {diagnostic}
204
+
205
+ The Step 1c smoke gate (see SKILL.md § Step 1c) requires a single-file
206
+ mutation probe with Killed > 0 before authorizing a full run. This
207
+ prevents the silent 0.00 % failure mode (see #554, #557).
208
+
209
+ To run the smoke probe:
210
+
211
+ dotnet stryker --config-file stryker-config.json \\
212
+ --mutate 'path/to/one/covered/file.cs' \\
213
+ -O StrykerOutput/smoke
214
+
215
+ Then re-run this command. To bypass this gate for a legitimate exception,
216
+ set MUTATION_SMOKE_GATE_SKIP=1 in the environment (audit-logged)."""
217
+
218
+
219
+ def print_block_message(diagnostic: str) -> None:
220
+ """Write the shared block-message body with the caller's diagnostic."""
221
+ print(_BLOCK_TEMPLATE.format(diagnostic=diagnostic))
222
+
223
+
224
+ # ---------------------------------------------------------------------------
225
+ # Report parsing
226
+ # ---------------------------------------------------------------------------
227
+
228
+
229
+ def count_mutants_by_status(report: dict, status: str) -> int:
230
+ """Count entries in report['mutants'] with the given status field."""
231
+ mutants = report.get("mutants") or []
232
+ return sum(1 for m in mutants if isinstance(m, dict) and m.get("status") == status)
233
+
234
+
235
+ # ---------------------------------------------------------------------------
236
+ # main()
237
+ # ---------------------------------------------------------------------------
238
+
239
+
240
+ def main() -> int:
241
+ # -------------------------------------------------------------------
242
+ # Dependency guards — a missing dep must NOT become a de facto gate.
243
+ # -------------------------------------------------------------------
244
+ if shutil.which("jq") is None:
245
+ # Preserve parity with the .sh, which uses jq for JSON parsing.
246
+ # The Python port does not itself use jq, but flags the missing
247
+ # dep to keep the failure mode identical across ports.
248
+ print(
249
+ "ADVISORY: mutation-testing-smoke-gate: jq is required but not installed; gate not enforced"
250
+ )
251
+ return 0
252
+ # python3 is always present by construction in a .py hook; the .sh's
253
+ # python3 dep check is a no-op here.
254
+
255
+ # -------------------------------------------------------------------
256
+ # Parse PreToolUse payload
257
+ # -------------------------------------------------------------------
258
+ payload = read_stdin_json()
259
+ if payload is None:
260
+ # Empty or malformed stdin — nothing to check, silent-pass.
261
+ return 0
262
+
263
+ command = str(payload.get("tool_input", {}).get("command", "") or "")
264
+ if not command:
265
+ return 0
266
+
267
+ # cwd from payload, fall back to $PWD (matches .sh's `${PAYLOAD_CWD:=$PWD}`).
268
+ # Prefer the shell-provided $PWD over os.getcwd() so macOS's /var → /private/var
269
+ # symlink resolution does not diverge from the .sh.
270
+ payload_cwd = str(payload.get("cwd") or os.environ.get("PWD") or os.getcwd())
271
+
272
+ # -------------------------------------------------------------------
273
+ # Trigger detection
274
+ # -------------------------------------------------------------------
275
+ if not is_stryker_command(command):
276
+ return 0
277
+
278
+ mutate_value = extract_mutate_value(command)
279
+ if is_single_file_mutate(mutate_value):
280
+ # This IS the smoke probe; do not block it.
281
+ return 0
282
+
283
+ # -------------------------------------------------------------------
284
+ # Escape hatch — must run BEFORE report check so bypass works even
285
+ # without a report. Matches .sh ordering.
286
+ # -------------------------------------------------------------------
287
+ if os.environ.get("MUTATION_SMOKE_GATE_SKIP", "0") == "1":
288
+ log_bypass_audit(command, payload_cwd)
289
+ return 0
290
+
291
+ # -------------------------------------------------------------------
292
+ # Whole-scope run detected — check the smoke report.
293
+ # -------------------------------------------------------------------
294
+ report_path = (
295
+ Path(payload_cwd)
296
+ / "StrykerOutput"
297
+ / "smoke"
298
+ / "reports"
299
+ / "mutation-report.json"
300
+ )
301
+
302
+ session_id = payload.get("session_id")
303
+
304
+ if not report_path.is_file():
305
+ print_block_message(f"no smoke report at {report_path}")
306
+ emit_boundary_event(
307
+ payload_cwd, "mutation_testing_smoke_gate", "Bash", "block",
308
+ "mutation-smoke-report-missing", session_id,
309
+ )
310
+ return 2
311
+
312
+ try:
313
+ report_text = report_path.read_text(encoding="utf-8")
314
+ except OSError:
315
+ print_block_message(f"no smoke report at {report_path}")
316
+ emit_boundary_event(
317
+ payload_cwd, "mutation_testing_smoke_gate", "Bash", "block",
318
+ "mutation-smoke-report-missing", session_id,
319
+ )
320
+ return 2
321
+
322
+ try:
323
+ report = json.loads(report_text)
324
+ except json.JSONDecodeError:
325
+ # Malformed JSON — advisory (not block, not silent-pass). Matches .sh.
326
+ print(
327
+ f"ADVISORY: mutation-testing-smoke-gate: report at {report_path} is not valid JSON — cannot enforce gate; command not blocked"
328
+ )
329
+ return 0
330
+
331
+ # Schema drift — valid JSON without mutants[]. Advisory. ORDERING NOTE
332
+ # (from .sh): schema-drift advisory MUST run before counting logic;
333
+ # otherwise a schema-drift report incorrectly reports "no scored mutants".
334
+ if not isinstance(report, dict) or "mutants" not in report:
335
+ print(
336
+ f"ADVISORY: mutation-testing-smoke-gate: report at {report_path} lacks the mutants[] key — not the mutation-testing-elements shape; cannot enforce gate"
337
+ )
338
+ return 0
339
+
340
+ killed = count_mutants_by_status(report, "Killed")
341
+ survived = count_mutants_by_status(report, "Survived")
342
+
343
+ # At least one Killed → gate passes silently.
344
+ if killed > 0:
345
+ return 0
346
+
347
+ # Killed==0 && Survived>0 → mutation-switch not observing mutations.
348
+ if survived > 0:
349
+ print_block_message(
350
+ f"killed=0 survived={survived} — mutation-switch not observing mutations at runtime "
351
+ "(see #554, #557 and SKILL.md Step 1c diagnostic checklist)"
352
+ )
353
+ emit_boundary_event(
354
+ payload_cwd, "mutation_testing_smoke_gate", "Bash", "block",
355
+ "mutation-smoke-switch-not-observed", session_id,
356
+ )
357
+ return 2
358
+
359
+ # Killed==0 && Survived==0 → empty mutants[] or only NoCoverage/CompileError.
360
+ print_block_message(
361
+ "no scored mutants in smoke report — pick a different probe file with real test coverage"
362
+ )
363
+ emit_boundary_event(
364
+ payload_cwd, "mutation_testing_smoke_gate", "Bash", "block",
365
+ "mutation-smoke-no-scored-mutants", session_id,
366
+ )
367
+ return 2
368
+
369
+
370
+ if __name__ == "__main__":
371
+ sys.exit(main())
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env python3
2
+ """SessionStart hook: notify when the pending-review queue has entries.
3
+
4
+ Emits a one-line notification when .claude/metrics/pending-review.jsonl has
5
+ unreviewed entries. Split off (#1284/#1288) from the retired
6
+ session_model_banner.py, whose other two responsibilities (persisting the
7
+ session model to `.claude/session-model` and announcing the effort-band
8
+ routing table) belonged to the band-to-model resolver system ADR 0026
9
+ retired — the harness now resolves `model:`/`effort:` natively, with no
10
+ plugin-side banner to keep in sync.
11
+
12
+ Env seams (TEST-ONLY):
13
+ PENDING_REVIEW_FILE defaults to <cwd>/.claude/metrics/pending-review.jsonl
14
+
15
+ Contract (docs/python-hook-contract.md):
16
+ Input : SessionStart JSON on stdin (hook_event_name, cwd, model, ...).
17
+ Output: notification text on stdout. Exit 0 always.
18
+ Posture: fail-open — a buggy notifier must never block a session.
19
+
20
+ Stdlib-only (json/os/pathlib/sys).
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import json
26
+ import os
27
+ import sys
28
+ from pathlib import Path
29
+
30
+ _HOOK_DIR = Path(__file__).resolve().parent
31
+ _LIB_DIR = _HOOK_DIR / "lib"
32
+ if str(_LIB_DIR) not in sys.path:
33
+ sys.path.insert(0, str(_LIB_DIR))
34
+
35
+ import artifact_paths
36
+ from stdin_json import read_stdin_json, resolve_cwd # type: ignore[import-not-found]
37
+
38
+
39
+ def _notify_pending_findings(cwd: str) -> str | None:
40
+ """Count still-pending entries in the pending-review queue, rotating out
41
+ disposed ones so the file stays bounded (#732).
42
+
43
+ A finding gains exactly one disposition (`reviewed_at` on approval,
44
+ `rejected_at` on rejection — see feedback-learning/SKILL.md); once either
45
+ is present, its audit trail lives in .claude/metrics/config-changelog.jsonl
46
+ (on approval) and the entry itself has no further use here. Rewriting the
47
+ queue to drop disposed entries every SessionStart keeps it bounded to the
48
+ outstanding backlog instead of growing without limit across the life of
49
+ a project. Lines that fail to parse can't be classified either way, so
50
+ they are left untouched — /session-review handles malformed-line
51
+ reporting on its own.
52
+ """
53
+ queue_env = os.environ.get("PENDING_REVIEW_FILE")
54
+ queue = (
55
+ Path(queue_env)
56
+ if queue_env
57
+ else artifact_paths.resolve_file("metrics", "pending-review.jsonl", cwd)
58
+ )
59
+ if not queue.is_file():
60
+ return None
61
+ try:
62
+ with queue.open("r", encoding="utf-8", errors="replace") as fh:
63
+ lines = fh.readlines()
64
+ except OSError:
65
+ return None
66
+
67
+ kept_lines: list[str] = []
68
+ dropped_any = False
69
+ count = 0
70
+ for raw_line in lines:
71
+ line = raw_line.strip()
72
+ if not line:
73
+ dropped_any = True
74
+ continue
75
+ try:
76
+ entry = json.loads(line)
77
+ except (json.JSONDecodeError, ValueError):
78
+ # Can't classify — keep it as-is rather than silently losing it.
79
+ kept_lines.append(line)
80
+ continue
81
+ if isinstance(entry, dict) and (
82
+ "reviewed_at" in entry or "rejected_at" in entry
83
+ ):
84
+ # Disposed — rotate it out of the queue.
85
+ dropped_any = True
86
+ continue
87
+ if isinstance(entry, dict):
88
+ count += 1
89
+ kept_lines.append(line)
90
+
91
+ if dropped_any:
92
+ try:
93
+ queue.write_text(
94
+ "".join(f"{line}\n" for line in kept_lines), encoding="utf-8"
95
+ )
96
+ except OSError:
97
+ pass
98
+
99
+ if count <= 0:
100
+ return None
101
+ return (
102
+ f"📋 {count} queued finding(s) from background analysis — "
103
+ "run /session-review to review\n"
104
+ )
105
+
106
+
107
+ def main() -> int:
108
+ payload = read_stdin_json()
109
+ if payload is None:
110
+ return 0
111
+ cwd = resolve_cwd(payload)
112
+
113
+ notice = _notify_pending_findings(cwd)
114
+ if notice is not None:
115
+ sys.stdout.write(notice)
116
+
117
+ return 0
118
+
119
+
120
+ if __name__ == "__main__": # pragma: no cover
121
+ sys.exit(main())