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,102 @@
1
+ #!/usr/bin/env python3
2
+ """Shared predicate: does a shell command actually RUN Stryker.NET? (#2185)
3
+
4
+ Both C# mutation PreToolUse gates (`mutation_testing_smoke_gate.py` and
5
+ `stryker_xunit_shim_guard.py`) used to decide "is this a Stryker run?" with a
6
+ bare `re.search` over the entire command string — no notion of argument
7
+ position, quoting, or comments. Any command that merely *mentioned* the tool
8
+ name in prose (a `gh issue create --body "..."`, a `grep`, an `echo`, a
9
+ Python comment) was treated as an invocation and blocked.
10
+
11
+ This module parses the command instead of scanning it: tokenize with
12
+ `shlex.shlex(..., punctuation_chars=True)` (posix quoting rules, `&&`/`||`/
13
+ `;`/`|` recognised as their own tokens), split the token stream into
14
+ per-operator segments, and match the tool only in **program position** of a
15
+ segment — `dotnet` with `stryker` as its very next token, a bare
16
+ `dotnet-stryker` token, or the wrapper script (however it's invoked: directly,
17
+ or via an interpreter like `bash <path>` — matched by exact basename, not
18
+ substring, so a quoted prose mention that happens to contain the wrapper's
19
+ name cannot collide with a real path token).
20
+
21
+ Heredoc bodies are stripped before tokenizing (`<<EOF ... EOF` /
22
+ `<<'EOF' ... EOF` / `<<-EOF ... EOF`) — a command that pipes documentation
23
+ prose through a heredoc is the same false-positive shape as a quoted
24
+ argument, just harder for `shlex` to see through structurally.
25
+
26
+ Fails closed: if `shlex` raises (unbalanced quotes it cannot tokenize), fall
27
+ back to the old permissive regex over the raw command rather than silently
28
+ returning False — a malformed command still gets caught rather than sliding
29
+ through unblocked.
30
+ """
31
+
32
+ from __future__ import annotations
33
+
34
+ import re
35
+ import shlex
36
+ from pathlib import Path
37
+
38
+ #: Matches only when shlex tokenization itself fails — the pre-#2185
39
+ #: permissive scan, kept as the fail-closed fallback for unparseable input.
40
+ _FALLBACK_TRIGGER = re.compile(
41
+ r"(?:^|[^a-zA-Z0-9])dotnet[ \t-]+stryker(?:\b|$)|csharp[_-]stryker[_-]net[_-]wrapper"
42
+ )
43
+
44
+ #: Shell operators that separate one command segment from the next. `>`/`<`
45
+ #: (redirects) deliberately excluded — they don't start a new program.
46
+ _SEGMENT_OPERATORS = {"&&", "||", ";", "|"}
47
+
48
+ #: A `<<[-]DELIM ... DELIM` heredoc body, DELIM optionally quoted.
49
+ _HEREDOC_RE = re.compile(r"<<-?\s*['\"]?(\w+)['\"]?\n.*?\n\1\b", re.DOTALL)
50
+
51
+ #: The plugin's Stryker.NET wrapper script, matched against a token's
52
+ #: basename — with or without hyphen/underscore separators, with or without
53
+ #: the `.sh` extension (mirrors the two gates' previously-divergent forms).
54
+ _WRAPPER_NAME_RE = re.compile(r"^csharp[_-]stryker[_-]net[_-]wrapper(\.sh)?$")
55
+
56
+
57
+ def _strip_heredocs(command: str) -> str:
58
+ return _HEREDOC_RE.sub("", command)
59
+
60
+
61
+ def _segments(tokens: list[str]) -> list[list[str]]:
62
+ segments: list[list[str]] = [[]]
63
+ for tok in tokens:
64
+ if tok in _SEGMENT_OPERATORS:
65
+ segments.append([])
66
+ else:
67
+ segments[-1].append(tok)
68
+ return [seg for seg in segments if seg]
69
+
70
+
71
+ def _segment_is_stryker(segment: list[str]) -> bool:
72
+ if not segment:
73
+ return False
74
+ first = segment[0]
75
+ if first == "dotnet" and len(segment) > 1 and segment[1] == "stryker":
76
+ return True
77
+ if first == "dotnet-stryker":
78
+ return True
79
+ # The wrapper, invoked directly or via an interpreter (`bash <path>`,
80
+ # `sh <path>`) — only the program and its immediate first argument can
81
+ # be the wrapper path, so later arguments are never checked.
82
+ for tok in segment[:2]:
83
+ if _WRAPPER_NAME_RE.match(Path(tok).name):
84
+ return True
85
+ return False
86
+
87
+
88
+ def is_stryker_invocation(command: str) -> bool:
89
+ """True only when `command` actually runs Stryker.NET — `dotnet stryker`,
90
+ `dotnet-stryker`, or the plugin's wrapper script, in program position of
91
+ one of the command's operator-separated segments. A mention of the tool
92
+ name in a --body/grep/echo/comment argument does not count."""
93
+ if not command:
94
+ return False
95
+ stripped = _strip_heredocs(command)
96
+ try:
97
+ lexer = shlex.shlex(stripped, posix=True, punctuation_chars=True)
98
+ lexer.whitespace_split = True
99
+ tokens = list(lexer)
100
+ except ValueError:
101
+ return bool(_FALLBACK_TRIGGER.search(command))
102
+ return any(_segment_is_stryker(seg) for seg in _segments(tokens))
@@ -0,0 +1,41 @@
1
+ """telemetry_consent.py — shared, home-scoped telemetry consent check (#1405).
2
+
3
+ Single source of truth for whether the user has opted in to the plugin's
4
+ local telemetry writers. Reads **only** `~/.claude/telemetry.json` —
5
+ deliberately no environment-variable branch and no project-scoped
6
+ (`<cwd>/.claude/telemetry.json`) fallback. Consent is a user-level decision,
7
+ not a per-project or per-invocation one.
8
+
9
+ Fail-open: a missing file, a malformed file, or any read error is treated as
10
+ "not enabled" — never raises, never blocks the calling hook.
11
+
12
+ Stdlib only. See ADR 0014 / ADR 0015.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import json
18
+ from pathlib import Path
19
+
20
+
21
+ def _consent_path() -> Path:
22
+ return Path.home() / ".claude" / "telemetry.json"
23
+
24
+
25
+ def is_enabled() -> bool:
26
+ """Return True only when `~/.claude/telemetry.json` contains
27
+ `{"enabled": true}`. Any other state — file absent, malformed JSON,
28
+ `"enabled"` false or missing, or a read error — returns False."""
29
+ config = _consent_path()
30
+ try:
31
+ if not config.is_file():
32
+ return False
33
+ data = json.loads(config.read_text(encoding="utf-8"))
34
+ except (OSError, ValueError):
35
+ return False
36
+ if not isinstance(data, dict):
37
+ return False
38
+ # Deliberate strict identity check (`is True`, not truthiness): a
39
+ # non-bool value such as `"true"` or `1` must NOT imply consent — only
40
+ # the literal JSON boolean `true` does.
41
+ return data.get("enabled") is True
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env python3
2
+ """Telemetry report (issues #106, #135).
3
+
4
+ Aggregates the opt-in, privacy-clean event log written by hooks/telemetry.py
5
+ (~/.claude/metrics/telemetry.jsonl, home-scoped per #1405/#1406 Slice 1) into:
6
+ command usage counts, skill usage counts (including agent-/auto-invoked
7
+ skills, counted distinctly from user-typed commands — #135), and the
8
+ pre-commit review gate's bypass rate (bypassed / (fired + bypassed)). With
9
+ telemetry disabled the log doesn't exist and this reports that nothing was
10
+ collected — satisfying "with it disabled, nothing leaves the machine."
11
+
12
+ Usage: telemetry_report.py [--log ~/.claude/metrics/telemetry.jsonl] [--json]
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import argparse
18
+ import json
19
+ import sys
20
+ from collections import Counter
21
+ from pathlib import Path
22
+
23
+ _DEFAULT_LOG = Path.home() / ".claude" / "metrics" / "telemetry.jsonl"
24
+
25
+
26
+ def aggregate(log: Path) -> dict:
27
+ commands: Counter = Counter()
28
+ skills: Counter = Counter()
29
+ gate_by_name: dict[str, Counter] = {}
30
+ total_events = 0
31
+ for line in log.read_text().splitlines():
32
+ line = line.strip()
33
+ if not line:
34
+ continue
35
+ try:
36
+ e = json.loads(line)
37
+ except json.JSONDecodeError:
38
+ continue
39
+ total_events += 1
40
+ if e.get("event") == "command":
41
+ commands[e.get("name", "?")] += 1
42
+ elif e.get("event") == "skill":
43
+ skills[e.get("name", "?")] += 1
44
+ elif e.get("event") == "gate":
45
+ name = e.get("name", "?")
46
+ gate_by_name.setdefault(name, Counter())[e.get("outcome", "?")] += 1
47
+
48
+ gate_summary = {}
49
+ for name, oc in gate_by_name.items():
50
+ fired = oc.get("fired", 0)
51
+ bypassed = oc.get("bypassed", 0)
52
+ denom = fired + bypassed
53
+ gate_summary[name] = {
54
+ "fired": fired,
55
+ "bypassed": bypassed,
56
+ "bypass_rate": round(bypassed / denom, 4) if denom else 0.0,
57
+ }
58
+ return {
59
+ "total_events": total_events,
60
+ "command_usage": dict(commands.most_common()),
61
+ "skill_usage": dict(skills.most_common()),
62
+ "gates": gate_summary,
63
+ }
64
+
65
+
66
+ def main(argv: list[str]) -> int:
67
+ ap = argparse.ArgumentParser(description=__doc__)
68
+ ap.add_argument("--log", default=str(_DEFAULT_LOG))
69
+ ap.add_argument("--json", action="store_true")
70
+ args = ap.parse_args(argv)
71
+
72
+ log = Path(args.log)
73
+ if not log.is_file():
74
+ print("Telemetry is off (or no events recorded): "
75
+ f"{log} does not exist. Nothing has left the machine.")
76
+ return 0
77
+
78
+ summary = aggregate(log)
79
+ if args.json:
80
+ print(json.dumps(summary, indent=2))
81
+ return 0
82
+
83
+ print(f"# Telemetry report — {summary['total_events']} event(s)\n")
84
+ print("## Command usage (user-typed slash commands)")
85
+ if summary["command_usage"]:
86
+ for name, n in summary["command_usage"].items():
87
+ print(f" /{name}: {n}")
88
+ else:
89
+ print(" (none)")
90
+ print("\n## Skill usage (incl. agent-/auto-invoked)")
91
+ if summary["skill_usage"]:
92
+ for name, n in summary["skill_usage"].items():
93
+ print(f" {name}: {n}")
94
+ else:
95
+ print(" (none)")
96
+ print("\n## Gate bypass rates")
97
+ if summary["gates"]:
98
+ for name, g in summary["gates"].items():
99
+ print(f" {name}: {g['bypassed']} bypassed / "
100
+ f"{g['fired'] + g['bypassed']} attempts "
101
+ f"({g['bypass_rate'] * 100:.1f}% bypassed)")
102
+ else:
103
+ print(" (none)")
104
+ return 0
105
+
106
+
107
+ if __name__ == "__main__":
108
+ raise SystemExit(main(sys.argv[1:]))
@@ -0,0 +1,160 @@
1
+ """test_file_classify — shared test-file classifier + build-phase reader.
2
+
3
+ Single encoding of `knowledge/test-file-indicators.md` for hooks that need to
4
+ decide "is this a test file?" (the refactor test-freeze guards), plus the
5
+ reader for the build-phase state `/build` records at each step-phase
6
+ transition (`.claude/memory/build-phase.json`).
7
+
8
+ Stdlib-only. See docs/python-hook-contract.md.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import json
14
+ import re
15
+ import sys
16
+ import time
17
+ from datetime import datetime, timezone
18
+ from pathlib import Path
19
+
20
+ _LIB_DIR = Path(__file__).resolve().parent
21
+ if str(_LIB_DIR) not in sys.path:
22
+ sys.path.insert(0, str(_LIB_DIR))
23
+
24
+ import artifact_paths
25
+
26
+ #: memory/build-phase.json older than this is treated as absent — a crashed
27
+ #: build must not freeze tests forever.
28
+ STALE_AFTER_SECONDS = 4 * 60 * 60
29
+
30
+ _JS_TS_NAME_RE = re.compile(r"\.(test|spec)\.[^./]+$", re.IGNORECASE)
31
+ _STEP_DEF_RE = re.compile(r"(\.steps\.[^./]+$|StepDefinitions\.[^./]+$|Steps\.[^./]+$)")
32
+ _CSHARP_MARKER_RE = re.compile(r"\[(Fact|Theory|Test|TestCase|TestMethod|TestClass)\]")
33
+ _JAVA_MARKER_RE = re.compile(r"@(Test|ParameterizedTest|TestFactory)\b")
34
+ _JAVA_CLASS_SUFFIXES = ("Test", "Tests", "TestCase", "Spec")
35
+ _PYTHON_NAME_RE = re.compile(r"^(test_.+|.+_test)\.py$", re.IGNORECASE)
36
+
37
+ #: How much of a file to read when a content probe is needed.
38
+ _CONTENT_PROBE_BYTES = 256 * 1024
39
+
40
+
41
+ def _read_probe(path: Path) -> str:
42
+ try:
43
+ with open(path, "r", encoding="utf-8", errors="replace") as handle:
44
+ return handle.read(_CONTENT_PROBE_BYTES)
45
+ except OSError:
46
+ return ""
47
+
48
+
49
+ def is_test_file(path: str, content: str | None = None) -> bool:
50
+ """True when `path` is a test file per knowledge/test-file-indicators.md.
51
+
52
+ `content` overrides the on-disk read for the languages whose indicator is
53
+ content-based (C#, Java) — pass it in tests or when the file is not on
54
+ disk yet (a PreToolUse Write).
55
+ """
56
+ if not path:
57
+ return False
58
+ p = Path(path)
59
+ name = p.name
60
+ posix = p.as_posix()
61
+
62
+ # BDD/Gherkin — a .feature file always counts as a test file.
63
+ if name.lower().endswith(".feature"):
64
+ return True
65
+ if _STEP_DEF_RE.search(name):
66
+ return True
67
+
68
+ # JS/TS — *.test.*, *.spec.*, or inside __tests__/
69
+ if _JS_TS_NAME_RE.search(name):
70
+ return True
71
+ if "/__tests__/" in posix or posix.startswith("__tests__/"):
72
+ return True
73
+
74
+ # Python — test_*.py or *_test.py (pytest/unittest convention).
75
+ if _PYTHON_NAME_RE.match(name):
76
+ return True
77
+
78
+ suffix = p.suffix.lower()
79
+ if suffix == ".cs":
80
+ probe = content if content is not None else _read_probe(p)
81
+ return bool(_CSHARP_MARKER_RE.search(probe))
82
+
83
+ if suffix == ".java":
84
+ if p.stem.endswith(_JAVA_CLASS_SUFFIXES):
85
+ return True
86
+ probe = content if content is not None else _read_probe(p)
87
+ return bool(_JAVA_MARKER_RE.search(probe))
88
+
89
+ return False
90
+
91
+
92
+ def _parse_written_at(value: str) -> float | None:
93
+ """ISO-8601 → epoch seconds, tolerant of a trailing 'Z'. None when unparseable."""
94
+ if not isinstance(value, str) or not value:
95
+ return None
96
+ candidate = value.strip()
97
+ if candidate.endswith("Z"):
98
+ candidate = candidate[:-1] + "+00:00"
99
+ try:
100
+ parsed = datetime.fromisoformat(candidate)
101
+ except ValueError:
102
+ return None
103
+ if parsed.tzinfo is None:
104
+ parsed = parsed.replace(tzinfo=timezone.utc)
105
+ return parsed.timestamp()
106
+
107
+
108
+ def build_phase_path(project_dir: Path) -> Path:
109
+ # Read-only: no Python writer of build-phase.json exists anywhere in
110
+ # hooks/ — it is agent-instruction-written (build/SKILL.md). migrate=False
111
+ # so this read never migrates a legacy file or creates .claude/memory/ as
112
+ # a side effect.
113
+ return artifact_paths.resolve_file(
114
+ "memory", "build-phase.json", project_dir, migrate=False
115
+ )
116
+
117
+
118
+ def read_build_phase(
119
+ project_dir: Path, now: float | None = None
120
+ ) -> tuple[dict | None, str | None]:
121
+ """Read `memory/build-phase.json`. Returns `(state, error)`.
122
+
123
+ - `(None, None)` — no state recorded, or the state is stale
124
+ (> STALE_AFTER_SECONDS old): guards treat both as "no phase".
125
+ - `(None, <why>)` — the file exists but is unreadable or malformed:
126
+ guards fail OPEN and record the reason in the audit log.
127
+ - `(state, None)` — an active, fresh phase record. `state["phase"]` is a
128
+ string; `state["test_files_staged"]` is always a list of strings.
129
+
130
+ `now` is the injectable clock (epoch seconds) for staleness tests.
131
+ """
132
+ path = build_phase_path(project_dir)
133
+ if not path.is_file():
134
+ return None, None
135
+ try:
136
+ raw = path.read_text(encoding="utf-8")
137
+ except OSError as exc:
138
+ return None, f"unreadable build-phase state: {exc}"
139
+ try:
140
+ data = json.loads(raw)
141
+ except ValueError:
142
+ return None, "malformed build-phase state: invalid JSON"
143
+ if not isinstance(data, dict):
144
+ return None, "malformed build-phase state: not an object"
145
+ phase = data.get("phase")
146
+ if not isinstance(phase, str) or not phase:
147
+ return None, "malformed build-phase state: missing phase"
148
+ written_at = _parse_written_at(data.get("written_at", ""))
149
+ if written_at is None:
150
+ return None, "malformed build-phase state: missing/unparseable written_at"
151
+ current = time.time() if now is None else now
152
+ if current - written_at > STALE_AFTER_SECONDS:
153
+ return None, None
154
+ staged = data.get("test_files_staged", [])
155
+ if not isinstance(staged, list):
156
+ return None, "malformed build-phase state: test_files_staged not a list"
157
+ files: list[str] = [f for f in staged if isinstance(f, str) and f]
158
+ state = dict(data)
159
+ state["test_files_staged"] = files
160
+ return state, None
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env python3
2
+ """token_efficiency_limits — shared thresholds for token-efficiency checks.
3
+
4
+ Single source of truth for the limits enforced by both
5
+ `hooks/token_efficiency_review.py` (the shipped PostToolUse hook) and
6
+ `plugins/dev-team/scripts/token_efficiency_review.py` (the review-agent CI runner). Both
7
+ previously hardcoded their own copy of these numbers.
8
+
9
+ It is also the single source of truth for two small pieces of *logic* that
10
+ drifted between those same two callers: which filename counts as "CLAUDE.md"
11
+ and how "character count" is measured. The hook used to match only the exact
12
+ case `CLAUDE.md` and count bytes; the CI runner matched case-insensitively
13
+ and counted decoded characters — so the same file could report two different
14
+ counts, or be checked in one caller and silently skipped in the other,
15
+ depending on nothing but its name's casing.
16
+
17
+ Stdlib-only. See docs/python-hook-contract.md.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ from pathlib import Path
23
+
24
+ # CLAUDE.md character-count limit (advisory in the hook, hard error in CI).
25
+ CLAUDE_MD_CHAR_LIMIT: int = 5000
26
+
27
+ # Any tracked source/CLAUDE.md file's line-count limit.
28
+ FILE_LINE_LIMIT: int = 500
29
+
30
+ # CLAUDE.md rule-count limit. Lives here rather than as a local literal in the
31
+ # CI runner (#1651) so this module's "single source of truth" claim above is
32
+ # true of every limit, not just the two that happened to be duplicated when it
33
+ # was written. Only the CI runner reads it today — the shipped hook does not
34
+ # count rules — but a second reader is exactly how the other two limits drifted
35
+ # into needing this module in the first place.
36
+ CLAUDE_MD_RULE_LIMIT: int = 200
37
+
38
+
39
+ def is_claude_md_file(path: Path) -> bool:
40
+ """Return True when `path`'s filename is CLAUDE.md, case-insensitively."""
41
+ return path.name.lower() == "claude.md"
42
+
43
+
44
+ def char_count(path: Path) -> int:
45
+ """Return the decoded character count of `path`.
46
+
47
+ Character count, not byte count: `CLAUDE_MD_CHAR_LIMIT` is a token-budget
48
+ proxy, and decoded characters track token count far more closely than
49
+ bytes do for any file containing multi-byte UTF-8 sequences.
50
+ """
51
+ return len(path.read_text(encoding="utf-8", errors="replace"))
@@ -0,0 +1,77 @@
1
+ """turn_identity — shared transcript/turn identity helpers.
2
+
3
+ Extracted from the tail-window logic that used to live independently in
4
+ both `codegraph_nudge.py` (read side) and `codegraph_turn_mark.py` (write
5
+ side) — the latter's own docstring already flagged this exact duplication
6
+ as intended for a "future PR." Both hooks now import from here so the
7
+ transcript_id/turn_counter computation can't drift between the two sides
8
+ of the sentinel contract.
9
+
10
+ Stdlib-only.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import os
16
+ from pathlib import Path
17
+
18
+ # Same 1 MiB tail window both hooks applied independently before this
19
+ # extraction — a monotonically growing transcript stays O(1) per read.
20
+ _TAIL_WINDOW_BYTES = 1_048_576
21
+
22
+ _USER_LINE_MARKER = b'"type":"user"'
23
+
24
+
25
+ def transcript_id(path: str) -> str:
26
+ """basename(path) with the last extension stripped.
27
+
28
+ `Path.stem` matches the shapes the harness emits (`.jsonl`, `.json`,
29
+ no extension).
30
+ """
31
+ return Path(path).stem
32
+
33
+
34
+ def count_user_lines(transcript_path: Path) -> int:
35
+ """Count `"type":"user"` occurrences in the last 1 MiB of the transcript.
36
+
37
+ Errors -> 0 (fail-open). Reads a bounded tail so growing transcripts
38
+ don't turn every call into a full-file scan.
39
+ """
40
+ try:
41
+ with transcript_path.open("rb") as fh:
42
+ fh.seek(0, os.SEEK_END)
43
+ size = fh.tell()
44
+ offset = max(0, size - _TAIL_WINDOW_BYTES)
45
+ fh.seek(offset, os.SEEK_SET)
46
+ tail = fh.read()
47
+ except OSError:
48
+ return 0
49
+ return tail.count(_USER_LINE_MARKER)
50
+
51
+
52
+ # Single source of truth for the sentinel's location relative to the
53
+ # project dir — both code_intelligence_nudge.py (read side) and
54
+ # code_intelligence_turn_mark.py (write side) used to hardcode this
55
+ # path independently.
56
+ SENTINEL_RELATIVE_PATH = Path(".claude") / "code-intelligence-turn-state.json"
57
+
58
+
59
+ def matches_current_turn(sentinel: dict, tid: str, tc: int) -> bool:
60
+ """True when `sentinel`'s identity fields match the freshly computed
61
+ transcript_id/turn_counter for the current call — i.e. the sentinel was
62
+ written earlier in the *same* turn.
63
+
64
+ Owns the type coercion once for both sides of the sentinel contract:
65
+ `transcript_id` is compared as a string (coercing a missing/`None`
66
+ value to `""`), and `turn_counter` is compared via `int()` wrapped in a
67
+ try/except — a non-numeric or otherwise uncoercible value (corrupt
68
+ sentinel) resolves to `False` rather than raising, matching this
69
+ module's fail-open posture.
70
+ """
71
+ sentinel_tid = str(sentinel.get("transcript_id") or "")
72
+ if sentinel_tid != tid:
73
+ return False
74
+ try:
75
+ return int(sentinel.get("turn_counter")) == tc
76
+ except (TypeError, ValueError):
77
+ return False
@@ -0,0 +1,110 @@
1
+ """Shared per-session state helpers for verify_guard.py and
2
+ verify_guard_edit_marker.py (#708).
3
+
4
+ verify_guard.py (PreToolUse `Bash`) needs to tell a genuinely stuck loop
5
+ (the same verify command run over and over with zero intervening code
6
+ changes) apart from ordinary TDD re-verification (RED, GREEN, REFACTOR
7
+ each legitimately re-run the same command, but each preceded by a real
8
+ edit). The two hooks communicate that signal through one JSON state file
9
+ per session, keyed identically by both hooks — so this module exists to
10
+ make sure "identically" is actually true, rather than two independently
11
+ maintained copies of the same hashing/keying logic drifting apart.
12
+
13
+ State shape (JSON object): ``{"hash": str, "count": int, "edited": bool}``.
14
+ ``hash`` and ``count`` are verify_guard.py's consecutive-identical-command
15
+ counter; ``edited`` is set true by verify_guard_edit_marker.py whenever an
16
+ Edit/Write/NotebookEdit tool call is observed, and consumed (reset to
17
+ false) by verify_guard.py on its next run.
18
+
19
+ Stdlib-only. See docs/python-hook-contract.md.
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import json
25
+ import os
26
+ import tempfile
27
+ import time
28
+ import zlib
29
+ from pathlib import Path
30
+
31
+ _STATE_DIRNAME = "dev-team-verify-guard"
32
+
33
+ # Same TTL-purge-on-write pattern as tdd_guard.py / mutation_adapters/lib.py
34
+ # (#732) — one state file is written per session with no expiry otherwise,
35
+ # so long-lived hosts accumulate a file per session forever.
36
+ _STATE_TTL_SECONDS = 14400 # 4 hours
37
+
38
+
39
+ def cksum(text: str) -> str:
40
+ """In-process, deterministic hash used for state-key/hash purposes.
41
+
42
+ The bash-parity `cksum` shell-out this used to require is gone (the
43
+ .sh implementations were removed — ADR 0015 / epic #572); only that
44
+ both hooks hash the same way matters, so the state key/hash they
45
+ compute for the same session agrees — hence the shared helper rather
46
+ than two copies. Uses zlib.crc32, matching bash_retry_guard.py's own
47
+ `_cksum` exactly so checksums stay comparable if anything ever
48
+ persists/compares both.
49
+ """
50
+ return str(zlib.crc32(text.encode("utf-8")) & 0xFFFFFFFF)
51
+
52
+
53
+ def tmpdir() -> Path:
54
+ return Path(os.environ.get("TMPDIR") or tempfile.gettempdir() or "/tmp")
55
+
56
+
57
+ def state_dir() -> Path:
58
+ return tmpdir() / _STATE_DIRNAME
59
+
60
+
61
+ def state_key(session_id: str, cwd: str) -> str:
62
+ """Prefer session_id, fall back to cksum of cwd (or $PWD when both empty)."""
63
+ if session_id:
64
+ return session_id
65
+ return cksum(cwd or os.getcwd())
66
+
67
+
68
+ def state_file(key: str) -> Path:
69
+ return state_dir() / f"{key}.json"
70
+
71
+
72
+ def read_state(path: Path) -> dict:
73
+ if not path.is_file():
74
+ return {}
75
+ try:
76
+ data = json.loads(path.read_text())
77
+ except (OSError, json.JSONDecodeError, ValueError):
78
+ return {}
79
+ return data if isinstance(data, dict) else {}
80
+
81
+
82
+ def purge_stale(directory: Path) -> None:
83
+ """Delete `*.json` state files in `directory` untouched past the TTL.
84
+
85
+ Both verify_guard.py and verify_guard_edit_marker.py write through
86
+ `write_state`, so calling this there is the single choke point that
87
+ keeps the shared state dir from accumulating one file per session
88
+ forever (#732).
89
+ """
90
+ if not directory.is_dir():
91
+ return
92
+ now = time.time()
93
+ for path in directory.glob("*.json"):
94
+ try:
95
+ if now - path.stat().st_mtime > _STATE_TTL_SECONDS:
96
+ path.unlink()
97
+ except OSError:
98
+ pass
99
+
100
+
101
+ def write_state(path: Path, data: dict) -> None:
102
+ try:
103
+ path.parent.mkdir(parents=True, exist_ok=True)
104
+ except OSError:
105
+ return
106
+ purge_stale(path.parent)
107
+ try:
108
+ path.write_text(json.dumps(data, separators=(",", ":")) + "\n")
109
+ except OSError:
110
+ pass