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,596 @@
1
+ #!/usr/bin/env python3
2
+ """Operator decision gate for the xunit.v3 / Stryker shim block (#1791).
3
+
4
+ Detection of the xunit.v3-blocks-Stryker problem already existed in three
5
+ places — the ``stryker_xunit_shim_guard.py`` PreToolUse hook,
6
+ ``xunit_v3_feature_detector.py``, and ``mutation_feasibility_gate.py`` — but
7
+ none of it guaranteed the **operator** saw a clear explanation and a set of
8
+ choices. The guard printed what it scaffolded and blocked; the detector
9
+ classified constructs for a gate that was never wired end-to-end; the
10
+ feasibility gate recorded a fixed waiver string. All three are informative
11
+ for a report, not a decision point: the operator could discover after a
12
+ multi-hour run that the shim was silently built, silently declined, or
13
+ silently degraded, and never learn what their options had been.
14
+
15
+ This module is that decision point. It has two halves, both pure/stdlib:
16
+
17
+ 1. **The question.** :func:`build_question` turns the detector's per-construct
18
+ classification into an :class:`OperatorQuestion` — what is blocking (per
19
+ construct, per file, with coverage impact) plus the four remediation
20
+ options with their tradeoffs. :func:`render_question` renders it for the
21
+ guard's block body and the feasibility gate's ``ask-operator`` payload, so
22
+ both decision points speak with one voice.
23
+
24
+ 2. **The guarantee.** A rendered question is still just text an agent could
25
+ paraphrase or skip. What makes the gate enforceable is that the guard stays
26
+ blocked until the operator's choice is *recorded* — :func:`record_decision`
27
+ writes it, :func:`decision_for` reads it back, and a decision only covers
28
+ the blocker set it was made about (:attr:`OperatorQuestion.fingerprint`),
29
+ so a newly-appeared blocker re-asks instead of riding on a stale answer.
30
+
31
+ The four options mirror the issue verbatim: ``port`` the flagged files,
32
+ ``exclude`` them from the shim's compile set, ``skip`` (temporarily
33
+ deactivate) just the offending tests, or ``degrade`` to the no-shim floor.
34
+
35
+ Version scope (#2184): this whole gate is a < 5.0.0 concern.
36
+ ``stryker_xunit_shim_guard.py`` silent-passes a known >= 5.0.0 install
37
+ before ever reaching this module, since ``-t mtp`` +
38
+ ``coverage-analysis: perTest`` observes kills through xunit.v3 directly on
39
+ that version and above (stryker-net#3752) — no shim, no port/exclude/skip
40
+ tradeoff, and no degrade fallback to weigh. An undetermined version still
41
+ fails closed to this gate.
42
+
43
+ Audit trail (#1870): the decision store on its own is silent — the same
44
+ agent the gate constrains can record its own choice (most plausibly
45
+ ``exclude``, narrowing mutation coverage) with nothing else in the harness
46
+ ever seeing it happen. :func:`record_decision` and :func:`decision_for`
47
+ each emit a `boundary_events` entry (a "record"-decision `matched_rule` of
48
+ `xunit-v3-shim-decision-record-<choice>` on write, `-honor-<choice>` when a
49
+ stored decision is read back and used to drive the guard's outcome), bound
50
+ to the question's `fingerprint` as `subject_hash` — the same audit stream
51
+ `hooks/pre_commit_review.py`'s dispatch-ledger corroboration is reviewed
52
+ from. This does not stop a self-recorded `exclude` from taking effect (the
53
+ operator's call is still trusted, per this module's whole design) — it
54
+ makes the choice visible to anyone auditing the stream, closing the
55
+ "nothing else in the harness ever seeing it happen" gap #1870 raised.
56
+
57
+ Formerly, ``DEV_TEAM_XUNIT3_SHIM_DECISION_FILE`` let any caller relocate the
58
+ decision store at runtime with no audit trail on either the record or honor
59
+ path — dropped entirely (#1870): no legitimate caller needs to relocate the
60
+ store, so removing the seam closes the unaudited-relocation vector outright
61
+ rather than trying to retrofit an audit onto it. The store's location is
62
+ always ``artifact_paths.resolve_file(DECISION_CATEGORY, DECISION_FILENAME,
63
+ cwd)``.
64
+
65
+ Stdlib-only. See docs/python-hook-contract.md.
66
+ """
67
+
68
+ from __future__ import annotations
69
+
70
+ import argparse
71
+ import hashlib
72
+ import json
73
+ import sys
74
+ from collections.abc import Iterable, Sequence
75
+ from dataclasses import dataclass
76
+ from datetime import datetime, timezone
77
+ from pathlib import Path
78
+
79
+ _LIB_DIR = Path(__file__).resolve().parent
80
+ if str(_LIB_DIR) not in sys.path: # pragma: no cover - import bootstrap
81
+ sys.path.insert(0, str(_LIB_DIR))
82
+
83
+ import artifact_paths
84
+
85
+ try:
86
+ from boundary_events import emit_boundary_event as _emit_boundary_event
87
+ except ImportError: # pragma: no cover - degraded fallback, hooks/lib unreachable
88
+
89
+ def _emit_boundary_event(*_args, **_kwargs) -> None: # type: ignore[misc]
90
+ return None
91
+
92
+
93
+ #: Where a recorded choice lives, relative to `.claude/`.
94
+ DECISION_CATEGORY = "metrics"
95
+ DECISION_FILENAME = "xunit-v3-shim-decisions.json"
96
+
97
+
98
+ @dataclass(frozen=True)
99
+ class Option:
100
+ """One remediation the operator can choose, with its cost stated.
101
+
102
+ ``tradeoff`` is not decoration: the whole point of the gate is that the
103
+ operator picks with the cost in view, so an option without one is a
104
+ non-choice dressed up as a choice.
105
+ """
106
+
107
+ id: str
108
+ label: str
109
+ tradeoff: str
110
+
111
+
112
+ #: The four choices, in the issue's order — cheapest/most-faithful first,
113
+ #: the measurement floor last. `degrade` is deliberately NOT the default:
114
+ #: silently taking it on the operator's behalf is the defect this gate fixes.
115
+ REMEDIATION_OPTIONS: tuple[Option, ...] = (
116
+ Option(
117
+ id="port",
118
+ label="Port the flagged files to v2-compatible syntax",
119
+ tradeoff="Cheapest when only a couple of files/constructs are flagged, and "
120
+ "the only option that leaves mutation coverage complete. Costs test edits "
121
+ "in the real project (the shim links the same sources, so one edit serves "
122
+ "both) and each replacement must still compile under v3.",
123
+ ),
124
+ Option(
125
+ id="exclude",
126
+ label="Exclude the flagged files from the shim's compile set",
127
+ tradeoff="No test edits — generate_shim.py --compile-exclude drops them and "
128
+ "the shim measures the rest. The excluded files stay UNMEASURED by "
129
+ "mutation, so every mutant they alone would have killed shows up as a "
130
+ "survivor. Safe for coverage-neutral hits, blinding for coverage-bearing "
131
+ "ones.",
132
+ ),
133
+ Option(
134
+ id="skip",
135
+ label="Temporarily deactivate/skip just the offending tests",
136
+ tradeoff="Deactivate the tests instead of rewriting what they assert — a "
137
+ "smaller edit than a full port. It clears the gate ONLY where the "
138
+ "deactivation itself removes the offending construct, e.g. "
139
+ '[Fact(Explicit = true)] becoming [Fact(Skip = "...")]. A construct in the '
140
+ "test BODY (Assert.Skip, TestContext) or on a data attribute ([AutoData], "
141
+ "TheoryDataRow) stays in the source the shim links, so deactivating alone "
142
+ "will not make it compile — those need port or exclude. The deactivated "
143
+ "tests stop protecting their code meanwhile: scaffolding to undo at "
144
+ "teardown, not a permanent change.",
145
+ ),
146
+ Option(
147
+ id="degrade",
148
+ label="Degrade to the no-shim floor (single slow advisory pass)",
149
+ tradeoff="Drives the REAL v3 suite (dotnet-stryker -t mtp with "
150
+ "coverage-analysis off), so nothing is excluded and nothing is edited — "
151
+ "but it is whole-suite-per-mutant, so expect a single, much slower "
152
+ "advisory pass and no mutant-kill loop.",
153
+ ),
154
+ )
155
+
156
+ VALID_CHOICES: tuple[str, ...] = tuple(option.id for option in REMEDIATION_OPTIONS)
157
+
158
+
159
+ @dataclass(frozen=True)
160
+ class ConstructGroup:
161
+ """One classified construct rolled up across the files that use it."""
162
+
163
+ construct: str
164
+ compile_ability: str
165
+ coverage_impact: str
166
+ count: int
167
+ files: tuple[str, ...]
168
+ example: str
169
+
170
+
171
+ @dataclass(frozen=True)
172
+ class Blocker:
173
+ """One detector finding, normalised to this module's shape."""
174
+
175
+ file: str
176
+ line: int
177
+ construct: str
178
+ compile_ability: str
179
+ coverage_impact: str
180
+ snippet: str
181
+
182
+
183
+ @dataclass(frozen=True)
184
+ class OperatorQuestion:
185
+ """The always-fires question: what blocks, and which four ways out."""
186
+
187
+ project: str
188
+ blockers: tuple[Blocker, ...]
189
+ breakdown: tuple[ConstructGroup, ...]
190
+ files: tuple[str, ...]
191
+ unclassified_files: tuple[str, ...]
192
+ fingerprint: str
193
+ options: tuple[Option, ...] = REMEDIATION_OPTIONS
194
+
195
+ @property
196
+ def blocking(self) -> bool:
197
+ """True when there is something to ask about at all."""
198
+ return bool(self.blockers or self.unclassified_files)
199
+
200
+ @property
201
+ def bearing_count(self) -> int:
202
+ return sum(1 for b in self.blockers if b.coverage_impact == "bearing")
203
+
204
+ @property
205
+ def neutral_count(self) -> int:
206
+ return sum(1 for b in self.blockers if b.coverage_impact == "neutral")
207
+
208
+ @property
209
+ def headline(self) -> str:
210
+ """The one-sentence "what's blocking" the issue asks for by example."""
211
+ if not self.blocking:
212
+ return (
213
+ f"No shim-breaking xunit.v3 constructs in '{self.project}' — "
214
+ "the v2 shim path is viable as-is."
215
+ )
216
+ file_count = len(set(self.files) | set(self.unclassified_files))
217
+ names = ", ".join(group.construct for group in self.breakdown)
218
+ if self.unclassified_files:
219
+ names = f"{names}, unclassified" if names else "unclassified"
220
+ plural = "s" if file_count != 1 else ""
221
+ return (
222
+ f"{file_count} test file{plural} in '{self.project}' use "
223
+ f"{names}, which the xunit.v2 shim can't compile."
224
+ )
225
+
226
+ def as_dict(self) -> dict:
227
+ return {
228
+ "project": self.project,
229
+ "headline": self.headline,
230
+ "fingerprint": self.fingerprint,
231
+ "files": list(self.files),
232
+ "unclassified_files": list(self.unclassified_files),
233
+ "bearing_count": self.bearing_count,
234
+ "neutral_count": self.neutral_count,
235
+ "breakdown": [
236
+ {
237
+ "construct": g.construct,
238
+ "compile_ability": g.compile_ability,
239
+ "coverage_impact": g.coverage_impact,
240
+ "count": g.count,
241
+ "files": list(g.files),
242
+ "example": g.example,
243
+ }
244
+ for g in self.breakdown
245
+ ],
246
+ "options": [
247
+ {"id": o.id, "label": o.label, "tradeoff": o.tradeoff}
248
+ for o in self.options
249
+ ],
250
+ }
251
+
252
+
253
+ def _as_blocker(finding) -> Blocker:
254
+ """Accept either the detector's dataclass or its ``--json`` dict form."""
255
+ get = finding.get if isinstance(finding, dict) else lambda k, d=None: getattr(finding, k, d)
256
+ try:
257
+ line = int(get("line", 0) or 0)
258
+ except (TypeError, ValueError):
259
+ line = 0
260
+ return Blocker(
261
+ file=str(get("file", "") or ""),
262
+ line=line,
263
+ construct=str(get("construct", "") or ""),
264
+ compile_ability=str(get("compile_ability", "") or ""),
265
+ coverage_impact=str(get("coverage_impact", "") or ""),
266
+ snippet=str(get("snippet", "") or ""),
267
+ )
268
+
269
+
270
+ def _dedup(values: Iterable[str]) -> tuple[str, ...]:
271
+ """First-seen order, deduped — mirrors the detector's own file ordering so
272
+ the operator sees the same sequence in both tools."""
273
+ seen: list[str] = []
274
+ for value in values:
275
+ if value and value not in seen:
276
+ seen.append(value)
277
+ return tuple(seen)
278
+
279
+
280
+ def _breakdown(blockers: Sequence[Blocker]) -> tuple[ConstructGroup, ...]:
281
+ order: list[str] = []
282
+ grouped: dict[str, list[Blocker]] = {}
283
+ for blocker in blockers:
284
+ if blocker.construct not in grouped:
285
+ grouped[blocker.construct] = []
286
+ order.append(blocker.construct)
287
+ grouped[blocker.construct].append(blocker)
288
+ groups: list[ConstructGroup] = []
289
+ for construct in order:
290
+ members = grouped[construct]
291
+ groups.append(
292
+ ConstructGroup(
293
+ construct=construct,
294
+ compile_ability=members[0].compile_ability,
295
+ coverage_impact=members[0].coverage_impact,
296
+ count=len(members),
297
+ files=_dedup(m.file for m in members),
298
+ example=members[0].snippet,
299
+ )
300
+ )
301
+ return tuple(groups)
302
+
303
+
304
+ def fingerprint(
305
+ blockers: Sequence[Blocker], unclassified_files: Sequence[str] = ()
306
+ ) -> str:
307
+ """A stable digest of *which* blockers exist, not where they sit.
308
+
309
+ Deliberately excludes line numbers: an unrelated edit that shifts a
310
+ flagged line must not invalidate a decision the operator already made,
311
+ while a genuinely new blocking file or construct must.
312
+ """
313
+ keys = sorted({f"{b.file}::{b.construct}" for b in blockers})
314
+ keys += sorted(f"{f}::unclassified" for f in set(unclassified_files))
315
+ digest = hashlib.sha256("\n".join(keys).encode("utf-8")).hexdigest()
316
+ return digest[:16]
317
+
318
+
319
+ def build_question(
320
+ project: str,
321
+ findings: Iterable,
322
+ unclassified_files: Sequence[str] = (),
323
+ ) -> OperatorQuestion:
324
+ """Compose the operator question from the detector's classification."""
325
+ blockers = tuple(_as_blocker(f) for f in findings)
326
+ unclassified = _dedup(unclassified_files)
327
+ return OperatorQuestion(
328
+ project=project,
329
+ blockers=blockers,
330
+ breakdown=_breakdown(blockers),
331
+ files=_dedup(b.file for b in blockers),
332
+ unclassified_files=unclassified,
333
+ fingerprint=fingerprint(blockers, unclassified),
334
+ )
335
+
336
+
337
+ def render_question(
338
+ question: OperatorQuestion, *, record_command: str | None = None
339
+ ) -> list[str]:
340
+ """Render the question as operator-facing lines.
341
+
342
+ One renderer for both decision points (the guard's block body and the
343
+ feasibility gate's ``ask-operator`` payload) so the operator cannot get a
344
+ different story depending on which one fired.
345
+ """
346
+ if not question.blocking:
347
+ return [question.headline]
348
+
349
+ lines = [question.headline, ""]
350
+ lines.append("What's blocking:")
351
+ for group in question.breakdown:
352
+ lines.append(
353
+ f" - {group.construct} ({group.compile_ability}, "
354
+ f"coverage-{group.coverage_impact}) — {group.count} hit(s) in "
355
+ f"{len(group.files)} file(s)"
356
+ )
357
+ for blocker in question.blockers:
358
+ if blocker.construct == group.construct:
359
+ lines.append(f" {blocker.file}:{blocker.line} {blocker.snippet}")
360
+ if question.unclassified_files:
361
+ lines.append(
362
+ " - unclassified v3-only usage (needs manual triage — the detector "
363
+ "flagged the file but cannot classify the construct):"
364
+ )
365
+ lines += [f" {name}" for name in question.unclassified_files]
366
+ lines.append("")
367
+ if question.bearing_count:
368
+ lines.append(
369
+ f"{question.bearing_count} of these hit(s) are coverage-BEARING: "
370
+ "excluding them leaves their lines unmeasured, so mutants there will "
371
+ "report as survivors."
372
+ )
373
+ if question.neutral_count:
374
+ lines.append(
375
+ f"{question.neutral_count} hit(s) are coverage-NEUTRAL (skipped by "
376
+ "default), so excluding those changes no coverage."
377
+ )
378
+ lines.append("")
379
+ lines.append("Your options (pick one — this is the operator's call):")
380
+ for option in question.options:
381
+ lines.append(f" {option.id}: {option.label}")
382
+ lines.append(f" Tradeoff: {option.tradeoff}")
383
+ lines.append("")
384
+ lines.append(
385
+ "Present these four options to the operator (AskUserQuestion) and let "
386
+ "them pick. Do NOT choose on their behalf, and do not silently take the "
387
+ "degrade path — that is the failure this gate exists to prevent."
388
+ )
389
+ if record_command:
390
+ lines.append("Then record their choice so this gate can let the run through:")
391
+ lines.append(f" {record_command}")
392
+ return lines
393
+
394
+
395
+ # --- decision record --------------------------------------------------------
396
+
397
+
398
+ def decision_store_path(cwd: Path | str | None = None) -> Path:
399
+ """Where recorded choices live — always
400
+ `artifact_paths.resolve_file(DECISION_CATEGORY, DECISION_FILENAME, cwd)`.
401
+
402
+ No env-var override (#1870): a prior `DEV_TEAM_XUNIT3_SHIM_DECISION_FILE`
403
+ seam let any caller relocate the store at runtime with no audit trail on
404
+ either side — removed rather than audited, since no legitimate caller
405
+ needs it.
406
+ """
407
+ return artifact_paths.resolve_file(DECISION_CATEGORY, DECISION_FILENAME, cwd)
408
+
409
+
410
+ def _emit_decision_event(kind: str, entry: dict, cwd: Path | str | None) -> None:
411
+ """Shared boundary-event emission for the record and honor paths (#1870).
412
+
413
+ `kind` is `"record"` (a fresh write in `record_decision`) or `"honor"` (a
414
+ stored decision read back and used to drive the guard's outcome in
415
+ `decision_for`) — folded into `matched_rule` as
416
+ `xunit-v3-shim-decision-<kind>-<choice>`, a closed vocabulary derived
417
+ from `VALID_CHOICES` (never free text). Bound to the entry's own
418
+ `fingerprint` as `subject_hash`, mirroring how the dispatch-ledger
419
+ corroboration binds its own evidence to a content hash — so an audit of
420
+ the stream can tell which blocker set a given decision covered.
421
+
422
+ Fail-open, matching `boundary_events.emit_boundary_event`'s own
423
+ contract: a malformed `choice` (should be unreachable given both
424
+ callers' own validation) or any emission failure is swallowed, never
425
+ raised — this is telemetry, not a gate.
426
+ """
427
+ choice = entry.get("choice")
428
+ if choice not in VALID_CHOICES:
429
+ return
430
+ try:
431
+ _emit_boundary_event(
432
+ cwd,
433
+ "xunit_v3_operator_gate",
434
+ "Bash",
435
+ "record",
436
+ f"xunit-v3-shim-decision-{kind}-{choice}",
437
+ subject_hash=entry.get("fingerprint"),
438
+ )
439
+ except Exception: # noqa: BLE001, S110 - fail-open by design
440
+ pass
441
+
442
+
443
+ def _read_store(cwd: Path | str | None = None) -> dict:
444
+ path = decision_store_path(cwd)
445
+ try:
446
+ raw = path.read_text(encoding="utf-8")
447
+ except (OSError, ValueError):
448
+ return {}
449
+ try:
450
+ data = json.loads(raw)
451
+ except (json.JSONDecodeError, ValueError):
452
+ return {}
453
+ return data if isinstance(data, dict) else {}
454
+
455
+
456
+ def record_decision(
457
+ project: str,
458
+ choice: str,
459
+ cwd: Path | str | None = None,
460
+ *,
461
+ fingerprint: str,
462
+ files: Sequence[str] = (),
463
+ note: str | None = None,
464
+ ) -> dict:
465
+ """Persist the operator's choice for ``project``. Returns the entry.
466
+
467
+ Raises ``ValueError`` on a choice outside :data:`VALID_CHOICES` — an
468
+ unrecognised answer must be re-asked, never coerced into one of the four —
469
+ and on a missing ``fingerprint``, without which the entry would cover no
470
+ blocker set at all (see :func:`decision_for`). Refusing loudly at write time
471
+ beats writing a record the operator believes answered the gate while the
472
+ gate keeps asking.
473
+ """
474
+ if choice not in VALID_CHOICES:
475
+ raise ValueError(
476
+ f"invalid choice {choice!r}: expected one of {', '.join(VALID_CHOICES)}"
477
+ )
478
+ if not fingerprint:
479
+ raise ValueError(
480
+ "a fingerprint is required: it scopes the decision to the blockers "
481
+ "the operator actually saw. Use the value the guard printed."
482
+ )
483
+ entry = {
484
+ "project": project,
485
+ "choice": choice,
486
+ "fingerprint": fingerprint,
487
+ "files": list(files),
488
+ "note": note,
489
+ "recorded_at": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
490
+ }
491
+ store = _read_store(cwd)
492
+ store[project] = entry
493
+ path = decision_store_path(cwd)
494
+ path.parent.mkdir(parents=True, exist_ok=True)
495
+ path.write_text(json.dumps(store, indent=2) + "\n", encoding="utf-8")
496
+ _emit_decision_event("record", entry, cwd)
497
+ return entry
498
+
499
+
500
+ def read_decision(project: str, cwd: Path | str | None = None) -> dict | None:
501
+ """The raw recorded entry for ``project``, ignoring fingerprint staleness."""
502
+ entry = _read_store(cwd).get(project)
503
+ return entry if isinstance(entry, dict) else None
504
+
505
+
506
+ def decision_for(
507
+ question: OperatorQuestion, cwd: Path | str | None = None
508
+ ) -> dict | None:
509
+ """The decision that covers ``question``, or None when the operator must
510
+ (re-)decide.
511
+
512
+ Fails closed on every axis, because every "yes" here is a run that proceeds
513
+ without asking:
514
+
515
+ - A recorded choice covers only the blocker set it was made about. When the
516
+ fingerprint differs — or is absent, which would otherwise make the entry a
517
+ blanket answer covering every future blocker set — the operator has not
518
+ seen these blockers, and riding on the old answer would silently exclude
519
+ something they never agreed to.
520
+ - A stored ``choice`` outside :data:`VALID_CHOICES` (or missing entirely)
521
+ re-asks rather than being coerced into whichever branch happens to be
522
+ last. ``record_decision`` rejects those on the write side, so reaching
523
+ here means a hand-edited or externally-produced store — precisely why the
524
+ read side is where the guarantee has to hold.
525
+
526
+ Emits a `boundary_events` "honor" entry (#1870) whenever a decision
527
+ actually covers ``question`` and is about to drive the guard's outcome —
528
+ every caller that reaches a non-None return here is *using* the decision,
529
+ so this is the single choke point for "on every honor path" without each
530
+ call site (today: `stryker_xunit_shim_guard.py`) needing its own emission.
531
+ """
532
+ entry = read_decision(question.project, cwd)
533
+ if entry is None:
534
+ return None
535
+ if entry.get("choice") not in VALID_CHOICES:
536
+ return None
537
+ if entry.get("fingerprint") != question.fingerprint:
538
+ return None
539
+ _emit_decision_event("honor", entry, cwd)
540
+ return entry
541
+
542
+
543
+ def _cli(argv: Sequence[str]) -> int:
544
+ parser = argparse.ArgumentParser(
545
+ description="Record/inspect the operator's xunit.v3 shim remediation choice."
546
+ )
547
+ sub = parser.add_subparsers(dest="command", required=True)
548
+
549
+ rec = sub.add_parser("record", help="record the operator's choice")
550
+ rec.add_argument("--project", required=True, help="test project name (csproj stem)")
551
+ rec.add_argument("--choice", required=True, choices=list(VALID_CHOICES))
552
+ rec.add_argument(
553
+ "--fingerprint",
554
+ required=True,
555
+ help="blocker-set fingerprint, as printed by the guard's block body — "
556
+ "required, since it is what scopes the decision to the blockers the "
557
+ "operator saw",
558
+ )
559
+ rec.add_argument(
560
+ "--file", action="append", default=[], help="flagged file the choice covers"
561
+ )
562
+ rec.add_argument("--note", default=None, help="free-text rationale")
563
+
564
+ chk = sub.add_parser("check", help="print the recorded choice, if any")
565
+ chk.add_argument("--project", required=True)
566
+
567
+ sub.add_parser("options", help="print the four remediation options")
568
+
569
+ args = parser.parse_args(list(argv))
570
+
571
+ if args.command == "options":
572
+ for option in REMEDIATION_OPTIONS:
573
+ print(f"{option.id}: {option.label}")
574
+ print(f" Tradeoff: {option.tradeoff}")
575
+ return 0
576
+
577
+ if args.command == "record":
578
+ entry = record_decision(
579
+ args.project,
580
+ args.choice,
581
+ fingerprint=args.fingerprint,
582
+ files=args.file,
583
+ note=args.note,
584
+ )
585
+ print(json.dumps(entry, indent=2))
586
+ return 0
587
+
588
+ entry = read_decision(args.project)
589
+ if entry is None:
590
+ return 1
591
+ print(json.dumps(entry, indent=2))
592
+ return 0
593
+
594
+
595
+ if __name__ == "__main__": # pragma: no cover
596
+ sys.exit(_cli(sys.argv[1:]))
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env python3
2
+ """mcp_json_repowise_nudge — Claude Code SessionStart hook (#1747).
3
+
4
+ `project-init/SKILL.md`'s `.mcp.json` standing check can only relocate a
5
+ stale, git-tracked `repowise` entry when someone actually runs
6
+ `/project-init` (or `/setup`). For an already-initialized project, nobody
7
+ is prompted to do that — the entry sits untouched indefinitely. This hook
8
+ is that proactive nudge, mirroring `pending_review_notify.py`'s /
9
+ `repo_review_nudge.py`'s shape: read a small state signal, print a one-line
10
+ stdout notice, fail-open, stdlib-only.
11
+
12
+ Shares its detection predicate — `hooks/lib/mcp_json_repowise.py::detect()`
13
+ — with the standing check itself (invoked from skill markdown via that
14
+ module's own CLI), so the two can never disagree on what counts as "needs
15
+ fixing" (#1747's single-commit requirement: this hook is meaningless
16
+ without that module's `relocate()` existing, so the two ship together).
17
+
18
+ Nudges every session until the condition clears (no snooze/debounce) — same
19
+ posture as the existing pending-review-queue and repo-review nudges.
20
+
21
+ Contract (docs/python-hook-contract.md):
22
+ Input : SessionStart JSON on stdin (hook_event_name, cwd, model, ...).
23
+ Output: notification text on stdout. Exit 0 always.
24
+ Posture: fail-open — a buggy notifier must never block a session; this
25
+ hook only ever suggests, it never gates.
26
+
27
+ Stdlib-only.
28
+ """
29
+
30
+ from __future__ import annotations
31
+
32
+ import sys
33
+ from pathlib import Path
34
+
35
+ _HOOK_DIR = Path(__file__).resolve().parent
36
+ _LIB_DIR = _HOOK_DIR / "lib"
37
+ if str(_LIB_DIR) not in sys.path:
38
+ sys.path.insert(0, str(_LIB_DIR))
39
+
40
+ from stdin_json import read_stdin_json, resolve_cwd # type: ignore[import-not-found]
41
+
42
+ try:
43
+ from mcp_json_repowise import detect # type: ignore[import-not-found]
44
+ except ImportError: # pragma: no cover
45
+
46
+ def detect(cwd): # type: ignore[misc]
47
+ return None
48
+
49
+
50
+ _NUDGE_MESSAGE = (
51
+ "⚠️ .mcp.json is git-tracked and registers repowise with a "
52
+ "machine-specific path (breaks for every other clone/teammate) — run "
53
+ "/project-init (or /setup) to relocate it to local scope\n"
54
+ )
55
+
56
+
57
+ def main() -> int:
58
+ payload = read_stdin_json()
59
+ if payload is None:
60
+ return 0
61
+ cwd = resolve_cwd(payload)
62
+
63
+ if detect(Path(cwd)) is None:
64
+ return 0
65
+
66
+ sys.stdout.write(_NUDGE_MESSAGE)
67
+ return 0
68
+
69
+
70
+ if __name__ == "__main__": # pragma: no cover
71
+ try:
72
+ sys.exit(main())
73
+ except Exception: # noqa: BLE001 - fail-open: a hook bug must never block a session
74
+ sys.exit(0)
@@ -0,0 +1,7 @@
1
+ """Mutation-testing adapters — Python port of hooks/mutation-adapters/*.sh (#578).
2
+
3
+ Public surface mirrors the bash lib.sh + adapter contract so mutation-gate can
4
+ switch consumers one at a time. See `lib.py` for the shared library and
5
+ `stryker.py`, `stryker_net.py`, `pitest.py`, `mutmut.py` for the per-runner
6
+ adapters.
7
+ """