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,537 @@
1
+ """pre_commit_detect — shared `git commit` detection for PreToolUse:Bash hooks.
2
+
3
+ Python port of hooks/lib/pre-commit-detect.sh (#576 / #572 Cluster B).
4
+ Extended under #709 to recognize bare `-n` as a bypass flag identically to
5
+ `--no-verify` (parity fix — `hooks/telemetry.py`'s bypass detection already
6
+ matched bare `-n`; this detector did not).
7
+
8
+ Extended again (#1801, independent security-review finding surfaced during
9
+ #1761/#1762/#1763's Slice 3 build, then through THREE rounds of
10
+ correctness-review/security-review re-review before this version shipped):
11
+ the original detector only matched `git commit` at the very start of the
12
+ command string, so a handful of behaviorally-identical invocations skipped
13
+ the gate with no bypass-audit trail at all. Round 1 widened the match with
14
+ segment-split-then-regex-match; round 2 replaced that with per-segment
15
+ shlex tokenization; each round's attempt FAILED its own re-review and was
16
+ replaced rather than patched — regex-over-raw-text couldn't see through
17
+ shell quoting, per-segment tokenization still split on raw-string
18
+ separator characters BEFORE tokenizing (letting a quoted separator inside
19
+ a git-option value bisect the invocation), and neither modeled a
20
+ clustered shell flag (`bash -lc '...'`), a wrapper's own options
21
+ (`sudo -u <user>`), a path-qualified interpreter (`/bin/bash -c '...'`),
22
+ nested `<shell> -c` wrapping more than one level deep, or a bare newline
23
+ as a real statement separator without also breaking a multi-line quoted
24
+ value. This version:
25
+
26
+ - masks every BARE (non-quoted) newline to `;` before tokenizing
27
+ (`_mask_bare_newlines`, a small quote-tracking character scan — not a
28
+ full shell parser, just enough to know "am I inside a quote right
29
+ now") so a bare newline acts as a real statement separator while one
30
+ embedded in a quoted value (a multi-line commit message) stays part
31
+ of that value's own token instead of splitting it;
32
+ - tokenizes the WHOLE (masked) command in ONE quote-aware
33
+ `shlex.shlex(..., punctuation_chars=True)` pass with `commenters`
34
+ explicitly cleared (`shlex.split`'s convenience wrapper clears this by
35
+ default; constructing `shlex.shlex` directly does not, so an
36
+ un-cleared `#` mid-line silently discarded the rest of that line and
37
+ everything after it — a real regression the second round introduced
38
+ and this version closes);
39
+ - splits the resulting token list on separator TOKENS
40
+ (`_split_on_separators`) rather than raw-string characters — a
41
+ separator inside a quoted value is never a boundary — and further
42
+ decomposes any token shlex glued into a run of adjacent control
43
+ characters (`;(`, `)&&(`, `|&`) back into its constituent one/two-
44
+ character operators (`_split_control_token`) so a separator directly
45
+ adjacent to unrelated punctuation still creates a boundary;
46
+ - recognizes a shell name (matched on basename, so `/bin/bash` and
47
+ `bash` are treated alike) followed by a bare `-c` or a clustered
48
+ short-flag group ending in `c` (`-lc`, `-ec`, `-ic`) and recurses
49
+ GENUINELY into that argument's own segments — including any FURTHER
50
+ nested `<shell> -c` wrapping inside it, up to a small depth bound
51
+ (`_MAX_NEST_DEPTH`) as a defensive backstop, not a realistic ceiling;
52
+ - walks git's OWN global-option grammar token-by-token
53
+ (`_match_commit_tokens`) rather than enumerating every option's exact
54
+ spelling in a regex — an unrecognized boolean option is still safely
55
+ skipped (the "invert the allowlist" choice), and `git`/wrapper-word
56
+ matching is basename-aware the same way shell-name matching is
57
+ (`/usr/bin/git commit`, `/usr/bin/sudo git commit` both match);
58
+ - skips a wrapper word's OWN options using a table KEYED BY WRAPPER
59
+ (`_WRAPPER_VALUE_TAKING_OPTS`), not one flat set shared across all
60
+ wrappers — `-n` takes a value for `nice` but is boolean for `sudo`,
61
+ and a shared set would have misparsed `sudo -n git commit` by
62
+ swallowing `git` as `-n`'s value;
63
+ - resolved EVERY matching segment's `-C` chain independently (not just
64
+ the first) via `resolve_commit_targets` (deleted #1904 — see "Exposes"
65
+ above — once its sole caller, `pre_commit_review.py`'s per-target
66
+ commit-gating, was retired to a no-op by #1886; this paragraph
67
+ documents the #1801 hardening history, not current exposed surface),
68
+ each segment falling back to
69
+ the caller's own `payload_cwd` when it has no usable `-C` — this is
70
+ what closes the decoy-redirection bypass without over-blocking the
71
+ everyday single-segment case: a prepended `git -C <decoy> commit ...;
72
+ git commit -m real` has a SECOND matching segment with no `-C` of its
73
+ own, which resolves to `payload_cwd` on its own merits, so the payload
74
+ repo's own review can no longer be skipped by a decoy elsewhere in the
75
+ same command — while a lone `git -C <dir> commit` run from a
76
+ `payload_cwd` that isn't a git repository at all (ordinary, legitimate
77
+ `-C` usage) still resolves to `<dir>` alone, not a forced, failing
78
+ check of an unrelated non-repo directory.
79
+
80
+ This is still a best-effort heuristic, not a real shell parser — see the
81
+ "KNOWN RESIDUAL GAPS" list in `hooks/pre_commit_review.py` for what remains
82
+ uncovered (a `git`/shell alias, a genuinely PATH-shadowed non-standard
83
+ binary named `git`/`bash`/etc — as opposed to the absolute-path spelling
84
+ of the REAL one, which this module now recognizes — `eval`, `xargs`,
85
+ compound-command keywords this module doesn't enumerate, `cd`/`pushd`
86
+ changing a LATER segment's effective target, a wrapper option taking a
87
+ separate-token value before `-c` this module doesn't model
88
+ (`bash -o pipefail -c '...'`), and a wrapper or git global option needing
89
+ a separate-token value and not enumerated here at all). Widening the match
90
+ can only make DETECTION more eager, never less — a segment that looks like
91
+ `git ... commit` inside an unrecognized wrapper's argument can
92
+ false-POSITIVE into "this is a commit", which is the safe direction for a
93
+ fail-closed gate; it can't false-negative a real commit a narrower matcher
94
+ would have caught. Target RESOLUTION was different: `resolve_commit_targets`
95
+ (deleted #1904) could only ADD targets to check per matching segment, never
96
+ remove a segment's own real target from the set that gets evaluated, including
97
+ the one disclosed exception (a `-C`
98
+ chain that can't be safely resolved falls back to `payload_cwd`, which can
99
+ under-cover a commit genuinely aimed elsewhere).
100
+
101
+ Imported by the Python sibling of its one remaining live caller:
102
+ - hooks/pre_commit_knowledge_index.py (via `is_git_commit_invocation`)
103
+
104
+ `resolve_commit_targets()` (the multi-target `-C`/`--git-dir`/`--work-tree`
105
+ resolution this module used to expose) was deleted in #1904: its sole
106
+ caller, `hooks/pre_commit_review.py`'s per-target commit-gating, was
107
+ already retired to a no-op by #1886's PR-time gate migration (`gh pr
108
+ create` has no `-C`-shaped multi-repository ambiguity for
109
+ `hooks/pre_pr_review.py`, the successor hook, to resolve — see that
110
+ module's own docstring). Confirmed orphaned by repo-wide grep before
111
+ deletion, not merely unused by one caller.
112
+
113
+ Exposes:
114
+
115
+ is_git_commit_command(cmd: str) -> bool
116
+ True when `cmd` is a `git commit` invocation, regardless of any
117
+ bypass flag. Callers that need to distinguish "gate-worthy commit"
118
+ from "bypassed commit" should also consult `has_bypass_flag`.
119
+
120
+ has_bypass_flag(cmd: str) -> bool
121
+ True when `cmd` carries `--no-verify` or a bare `-n` argument — git's
122
+ two spellings of "skip hooks". Substring/word-bounded match; does not
123
+ require `cmd` to be a `git commit` invocation.
124
+
125
+ bypass_flag_name(cmd: str) -> Optional[str]
126
+ "--no-verify" or "-n" (whichever matched; `--no-verify` preferred when
127
+ both are present), or None when `cmd` carries no bypass flag.
128
+
129
+ is_git_commit_invocation(cmd: str) -> bool
130
+ True when `cmd` is a `git commit` we should gate on (no bypass flag).
131
+ Kept for backward compatibility with existing callers/tests.
132
+
133
+ Stdlib-only. See docs/python-hook-contract.md.
134
+ """
135
+
136
+ from __future__ import annotations
137
+
138
+ import re
139
+ import shlex
140
+
141
+ # Recognized shell interpreters whose own `-c`/clustered-`-c` flag takes a
142
+ # nested command as its argument (`bash -c '...'`, `bash -lc '...'`).
143
+ # Matched on basename (see `_word`) so `/bin/bash` is recognized too.
144
+ _SHELL_NAMES = frozenset({"bash", "sh", "zsh", "dash", "ksh"})
145
+
146
+ # Token forms that separate one command from the next within a single
147
+ # already-tokenized command. `_tokenize_command` (via `punctuation_chars=
148
+ # True`) emits `&&`/`||` as single two-character tokens and `;`/`|`/`&` as
149
+ # single characters — never split out of a quoted value. A bare (non-
150
+ # quoted) newline is masked to `;` before tokenizing (`_mask_bare_
151
+ # newlines`) rather than relying on shlex's own newline handling, which
152
+ # treats every newline as plain whitespace regardless of quoting.
153
+ _SEPARATOR_TOKENS = frozenset({";", "&&", "||", "|", "&"})
154
+
155
+ # Characters shlex's `punctuation_chars` mode can glue into ONE token when
156
+ # they appear adjacent with no separating whitespace (`;(`, `)&&(`, `|&`).
157
+ # `_split_control_token` decomposes such a token back into its constituent
158
+ # one/two-character operators so a separator adjacent to unrelated
159
+ # punctuation still creates a segment boundary.
160
+ _CONTROL_CHARS = frozenset(";&|()<>")
161
+
162
+ # Leading shell "noise" tokens that can precede `git` without changing what
163
+ # it targets: command wrappers that just re-exec their remaining argv
164
+ # (`env`, `exec`, `command`, `nohup`, `time`, `nice`, `sudo`, `setsid`,
165
+ # `doas`), and compound-command keywords that can immediately precede a
166
+ # command word
167
+ # (`then`, `do`, `else`, `elif`) plus grouping/negation tokens (`!`, `(`,
168
+ # `{`) that tokenize as standalone tokens when space-separated.
169
+ _WRAPPER_WORDS = frozenset(
170
+ {"env", "exec", "command", "nohup", "time", "nice", "sudo", "setsid", "doas"}
171
+ )
172
+ _LEADING_NOISE_TOKENS = frozenset({"then", "do", "else", "elif", "!", "(", "{"})
173
+
174
+ # Wrapper options that take a separate-token value, KEYED BY WRAPPER WORD
175
+ # rather than one flat set shared across all of them (#1801 third-round
176
+ # re-review): `-n` takes a value for `nice` but is boolean for `sudo`, and
177
+ # a shared set misparsed `sudo -n git commit` by swallowing `git` itself
178
+ # as `-n`'s value. A wrapper/option pair not listed here is safely
179
+ # boolean-skipped (same "invert the allowlist" choice as git's own
180
+ # options) — it only misparses if it ALSO takes a separate value this
181
+ # table doesn't know about.
182
+ _WRAPPER_VALUE_TAKING_OPTS: dict[str, frozenset[str]] = {
183
+ "sudo": frozenset({"-u", "-g", "-p", "-h", "-C"}),
184
+ "doas": frozenset({"-u", "-C", "-a"}),
185
+ "nice": frozenset({"-n"}),
186
+ "env": frozenset({"-u", "-C", "-S"}),
187
+ "exec": frozenset({"-a"}),
188
+ "time": frozenset({"-o", "-f", "--output", "--format"}),
189
+ }
190
+
191
+ # A bare `NAME=value` shell-assignment token — no `env` keyword required
192
+ # (an earlier version required it, missing the far more common bare
193
+ # `X=1 git commit` spelling — correctness/security re-review finding).
194
+ _ASSIGNMENT_RE = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*=")
195
+
196
+ # git global options that consume exactly one following token as their
197
+ # argument when not already attached via `=` in the same token (`-c` always
198
+ # consumes its next token even when valueless — `-c core.pager` sets a
199
+ # boolean true — matching git's own arg parser, not just the `name=value`
200
+ # case a fixed regex atom previously required).
201
+ _VALUE_TAKING_OPTS = frozenset(
202
+ {"-c", "--namespace", "--super-prefix", "--exec-path", "--attr-source", "--config-env"}
203
+ )
204
+
205
+ # Defensive backstop for `<shell> -c`-wrapping nesting depth
206
+ # (`_all_segments`) — genuinely recursive, not a realistic ceiling on how
207
+ # deep real commands nest; just insurance against a pathological input.
208
+ _MAX_NEST_DEPTH = 4
209
+
210
+ # The documented bypass. Substring match (no word boundary) — mirrors the
211
+ # .sh's `grep -qE -- '--no-verify'` byte-for-byte: `--no-verifying`, though
212
+ # not a real git flag, also short-circuits under the .sh, so the port does
213
+ # the same. Byte-parity is the migration contract.
214
+ _NO_VERIFY_RE = re.compile(r"--no-verify")
215
+
216
+ # git's short-form bypass flag. Word-bounded (whitespace or string edges) so
217
+ # it doesn't false-positive inside `-nx` or `--number`. Mirrors
218
+ # `hooks/telemetry.py`'s `_NO_VERIFY_RE` pattern.
219
+ _BARE_N_RE = re.compile(r"(?:^|\s)-n(?:\s|$)")
220
+
221
+
222
+ def _mask_bare_newlines(cmd: str) -> str:
223
+ """Replace every newline OUTSIDE a single/double-quoted region with
224
+ `;` — a real statement separator, the same as what a shell itself
225
+ treats a bare newline as — while a newline INSIDE a quoted region
226
+ (a multi-line commit message) is left untouched so it stays part of
227
+ that value's own token instead of being cut in half. A POSIX
228
+ backslash-newline pair (a line continuation — `git add -A && \\`
229
+ followed by a newline then `git commit -m x`) is DELETED entirely,
230
+ matching what a real shell does with it, rather than preserved: an
231
+ earlier version of this function treated `\\`+newline the same as any
232
+ other escaped character (kept both, verbatim), which fed
233
+ `_tokenize_command`'s shlex pass a literal embedded newline instead of
234
+ nothing — silently gluing the following word onto the newline and
235
+ hiding `git`/`commit` from every downstream check (#1801 fifth-round
236
+ re-review).
237
+
238
+ A small character-by-character quote-tracking scan, not a full shell
239
+ parser: both backslash branches are gated on being OUTSIDE a quote
240
+ (`quote is None`) — it performs no in-quote escape handling at all,
241
+ while POSIX double-quote escaping is actually BROADER than this scan
242
+ (`\\"`, `\\$`, `` \\` `` are all recognized escapes there this scan
243
+ doesn't treat as such). That's exactly why a double-quoted string
244
+ containing an escaped copy of its OWN quote character can end this
245
+ scan's quote-tracking early — a known, disclosed limitation (see
246
+ KNOWN RESIDUAL GAPS in hooks/pre_commit_review.py) rather than
247
+ something this function claims to handle."""
248
+ out = []
249
+ quote: str | None = None
250
+ i, n = 0, len(cmd)
251
+ while i < n:
252
+ ch = cmd[i]
253
+ if quote is None and ch == "\\" and i + 1 < n and cmd[i + 1] == "\n":
254
+ i += 2 # line continuation: delete the pair, emit nothing
255
+ continue
256
+ if quote is None and ch == "\\" and i + 1 < n:
257
+ out.append(ch)
258
+ out.append(cmd[i + 1])
259
+ i += 2
260
+ continue
261
+ if quote is not None and ch == quote:
262
+ quote = None
263
+ out.append(ch)
264
+ elif quote is None and ch in ("'", '"'):
265
+ quote = ch
266
+ out.append(ch)
267
+ elif quote is None and ch == "\n":
268
+ out.append(";")
269
+ else:
270
+ out.append(ch)
271
+ i += 1
272
+ return "".join(out)
273
+
274
+
275
+ def _tokenize_command(cmd: str) -> list[str]:
276
+ """POSIX-shell-tokenize the WHOLE (newline-masked) `cmd` in one pass,
277
+ resolving quotes/escapes the same way a real shell would — this is
278
+ what closes the quoting-evasion class (`git "commit"`, `'git' commit`,
279
+ `\\git commit`) a plain string search cannot, keeps a quoted value
280
+ containing whitespace or a separator character (`git -C "/a b"
281
+ commit`, `git -c user.name="A; B" commit`) as ONE token instead of
282
+ splitting it, and — via `commenters = \"\"` — never discards the rest
283
+ of a line at an unquoted `#` the way `shlex.shlex`'s default
284
+ `commenters` would (`shlex.split`'s convenience wrapper clears this;
285
+ constructing `shlex.shlex` directly does not, and an earlier version
286
+ of this module didn't either — a real regression this version
287
+ closes). Falls back to a naive whitespace split on unbalanced quotes
288
+ — an edge case a real shell would itself reject as malformed, so
289
+ treating it as "can't tokenize, don't try to guess" is the safe
290
+ posture."""
291
+ masked = _mask_bare_newlines(cmd)
292
+ try:
293
+ lex = shlex.shlex(masked, posix=True, punctuation_chars=True)
294
+ lex.whitespace_split = True
295
+ lex.commenters = ""
296
+ return list(lex)
297
+ except ValueError:
298
+ return masked.split()
299
+
300
+
301
+ def _split_control_token(tok: str) -> list[str]:
302
+ """Split a token shlex glued from adjacent control characters (`;(`,
303
+ `)&&(`, `|&`) back into its constituent one- or two-character shell
304
+ operators, greedily preferring the two-character forms (`&&`, `||`)
305
+ — the operators a real shell lexer would recognize, just not glued in
306
+ this token's raw form."""
307
+ pieces = []
308
+ i, n = 0, len(tok)
309
+ while i < n:
310
+ two = tok[i : i + 2]
311
+ if two in ("&&", "||"):
312
+ pieces.append(two)
313
+ i += 2
314
+ else:
315
+ pieces.append(tok[i])
316
+ i += 1
317
+ return pieces
318
+
319
+
320
+ def _split_on_separators(tokens: list[str]) -> list[list[str]]:
321
+ """Split an already-tokenized command into segments at
322
+ `_SEPARATOR_TOKENS` boundaries, first decomposing any token composed
323
+ entirely of `_CONTROL_CHARS` via `_split_control_token` so a
324
+ separator glued to adjacent, unrelated punctuation (`;(`, `|&`) still
325
+ creates a boundary. Empty segments (a leading/trailing/doubled
326
+ separator) are dropped."""
327
+ segments: list[list[str]] = [[]]
328
+ for tok in tokens:
329
+ if tok and all(c in _CONTROL_CHARS for c in tok):
330
+ pieces = _split_control_token(tok)
331
+ else:
332
+ pieces = [tok]
333
+ for piece in pieces:
334
+ if piece in _SEPARATOR_TOKENS:
335
+ segments.append([])
336
+ else:
337
+ segments[-1].append(piece)
338
+ return [segment for segment in segments if segment]
339
+
340
+
341
+ def _word(tok: str) -> str:
342
+ """The basename of `tok` when it looks path-qualified, else `tok`
343
+ itself — so `/bin/bash`, `/usr/bin/git`, and `/usr/bin/sudo` are
344
+ recognized the same as their bare spellings (#1801 third-round
345
+ re-review: exact-token comparisons elsewhere in this module used to
346
+ miss every absolute-path spelling of the same binary)."""
347
+ return tok.rsplit("/", 1)[-1]
348
+
349
+
350
+ def _extract_shell_dash_c_bodies(tokens: list[str]) -> list[str]:
351
+ """Scan an already-tokenized segment for a recognized shell name
352
+ (matched via `_word`, so path-qualified spellings count too) followed
353
+ by a bare `-c` or a clustered short-flag group ENDING in `c`
354
+ (`bash -lc '...'`, `sh -ec "..."`, `zsh -ic '...'`) and return each
355
+ such argument string found — the nested command a real shell would
356
+ separately execute. Best-effort: a wrapper option that itself takes a
357
+ separate-token value before `-c` (`bash -o pipefail -c '...'`) is not
358
+ modeled and remains a disclosed residual gap (see
359
+ `pre_commit_review.py`'s KNOWN RESIDUAL GAPS) — modeling every shell's
360
+ exact getopt grammar is out of scope for this heuristic."""
361
+ bodies = []
362
+ for i, tok in enumerate(tokens):
363
+ if _word(tok) not in _SHELL_NAMES:
364
+ continue
365
+ j = i + 1
366
+ while j < len(tokens) and tokens[j].startswith("-"):
367
+ flag = tokens[j]
368
+ if flag == "-c" or (len(flag) > 2 and flag[-1] == "c" and flag[1:-1].isalpha()):
369
+ if j + 1 < len(tokens):
370
+ bodies.append(tokens[j + 1])
371
+ break
372
+ j += 1
373
+ return bodies
374
+
375
+
376
+ def _all_segments(cmd: str, _depth: int = 0) -> list[list[str]]:
377
+ """Every already-tokenized segment worth checking for a `git ...
378
+ commit` match: `cmd` tokenized and split on separator tokens, plus the
379
+ same treatment GENUINELY recursively applied to every `<shell> -c`/
380
+ clustered-`-c` argument `_extract_shell_dash_c_bodies` finds within
381
+ those segments — including further nesting inside THOSE bodies too,
382
+ up to `_MAX_NEST_DEPTH` (a defensive backstop, not a realistic
383
+ ceiling; an earlier version of this function only extracted one level
384
+ despite its own docstring claiming otherwise — #1801 third-round
385
+ re-review)."""
386
+ if _depth > _MAX_NEST_DEPTH:
387
+ return []
388
+ segments = _split_on_separators(_tokenize_command(cmd))
389
+ all_found = list(segments)
390
+ for segment in segments:
391
+ for body in _extract_shell_dash_c_bodies(segment):
392
+ all_found.extend(_all_segments(body, _depth + 1))
393
+ return all_found
394
+
395
+
396
+ def _advance_past_value(tokens: list[str], i: int, has_attached_value: bool) -> int:
397
+ """Advance past the option token at `tokens[i]` and, unless its value
398
+ was `=`-attached to the same token, past its separate-token value too
399
+ (when one remains). Shared by the `--git-dir`/`--work-tree` and
400
+ `_VALUE_TAKING_OPTS` branches of `_match_commit_tokens`, which
401
+ otherwise repeat this exact sequence (structure-review + complexity-
402
+ review both independently flagged the duplication, #1801 re-review).
403
+
404
+ `has_attached_value` must reflect whether `=` was PRESENT in the
405
+ token, not the truthiness of the value after it (#1801 sixth-round
406
+ re-review: `tok.partition("=")`'s value is `""` for BOTH "no `=` at
407
+ all" and "`=` present with an empty value", e.g. `--namespace=`; the
408
+ caller must pass the separator's own truthiness, not the value's, or
409
+ an option with a present-but-empty attached value gets treated as
410
+ needing a separate-token value and wrongly consumes the next token —
411
+ which, for the LAST option before `commit`, silently swallows
412
+ `commit` itself)."""
413
+ i += 1
414
+ if not has_attached_value and i < len(tokens):
415
+ i += 1
416
+ return i
417
+
418
+
419
+ def _match_commit_tokens(tokens: list[str]) -> tuple[bool, list[str], bool]:
420
+ """Return `(is_commit, dash_c_chain, has_repo_override)` for an
421
+ already-tokenized command. `dash_c_chain` is every `-C` argument found,
422
+ IN ORDER (git's own left-to-right `-C` chaining — NOT "last wins").
423
+ `has_repo_override` is True when `--git-dir`/`--work-tree` also
424
+ appeared. Both were consumed by the now-deleted `resolve_commit_targets()`
425
+ (#1904, orphaned once `pre_commit_review.py`'s per-target commit-gating
426
+ was retired) — `is_git_commit_command()` below only needs the boolean
427
+ `is_commit` element, but the tuple shape is left unchanged rather than
428
+ narrowed, since narrowing it is an unrelated refactor with no behavioral
429
+ payoff for this module's one remaining consumer."""
430
+ i, n = 0, len(tokens)
431
+ while i < n:
432
+ if _ASSIGNMENT_RE.match(tokens[i]) or tokens[i] in _LEADING_NOISE_TOKENS:
433
+ i += 1
434
+ continue
435
+ wrapper = _word(tokens[i])
436
+ if wrapper in _WRAPPER_WORDS:
437
+ i += 1
438
+ # Skip the wrapper's OWN options too (#1801 third-round
439
+ # re-review) — `sudo -u dev`, `nice -n 10`, `env -i` used to
440
+ # stop this loop one token early, leaving `git` unreachable.
441
+ # The value-taking set is keyed by THIS wrapper specifically
442
+ # (`-n` is nice's value-taking option, sudo's boolean one).
443
+ value_opts = _WRAPPER_VALUE_TAKING_OPTS.get(wrapper, frozenset())
444
+ while i < n and tokens[i].startswith("-"):
445
+ if tokens[i] in value_opts and i + 1 < n:
446
+ i += 2
447
+ else:
448
+ i += 1
449
+ continue
450
+ break
451
+ if i >= n or _word(tokens[i]) != "git":
452
+ return False, [], False
453
+ i += 1
454
+ dash_c_chain: list[str] = []
455
+ has_repo_override = False
456
+ while i < n:
457
+ tok = tokens[i]
458
+ if tok == "commit":
459
+ return True, dash_c_chain, has_repo_override
460
+ if not tok.startswith("-"):
461
+ return False, [], False
462
+ opt, sep, value = tok.partition("=")
463
+ if opt == "-C":
464
+ i += 1
465
+ if sep:
466
+ dash_c_chain.append(value)
467
+ elif i < n:
468
+ dash_c_chain.append(tokens[i])
469
+ i += 1
470
+ continue
471
+ if opt in ("--git-dir", "--work-tree"):
472
+ has_repo_override = True
473
+ i = _advance_past_value(tokens, i, bool(sep))
474
+ continue
475
+ if opt in _VALUE_TAKING_OPTS:
476
+ i = _advance_past_value(tokens, i, bool(sep))
477
+ continue
478
+ # Unknown or known-boolean `-`-prefixed token: skip it alone.
479
+ # "Invert the allowlist" (#1801 re-review): an unrecognized FUTURE
480
+ # git global option that takes no value is still safely skipped;
481
+ # one that takes a separate-token value and isn't enumerated above
482
+ # remains a disclosed residual gap.
483
+ i += 1
484
+ return False, [], False
485
+
486
+
487
+ def _all_commit_matches(cmd: str) -> list[tuple[list[str], bool]]:
488
+ """Every matching segment's `(dash_c_chain, has_repo_override)` — ALL
489
+ of them, not just the first (#1801 re-review: returning only the first
490
+ match let a prepended decoy `-C` segment become the sole thing
491
+ resolved — a concern for the now-deleted `resolve_commit_targets()`,
492
+ #1904; `is_git_commit_command()` below only needs the length of this
493
+ list, not which segment's `-C` chain "won")."""
494
+ if not cmd:
495
+ return []
496
+ matches = []
497
+ for segment in _all_segments(cmd):
498
+ matched, dash_c_chain, has_repo_override = _match_commit_tokens(segment)
499
+ if matched:
500
+ matches.append((dash_c_chain, has_repo_override))
501
+ return matches
502
+
503
+
504
+ def is_git_commit_command(cmd: str) -> bool:
505
+ """Return True iff `cmd` is a `git commit` invocation (bypass or not)."""
506
+ return bool(_all_commit_matches(cmd))
507
+
508
+
509
+ def has_bypass_flag(cmd: str) -> bool:
510
+ """Return True iff `cmd` carries `--no-verify` or a bare `-n` flag."""
511
+ return bypass_flag_name(cmd) is not None
512
+
513
+
514
+ def bypass_flag_name(cmd: str) -> str | None:
515
+ """Return which bypass flag matched (`--no-verify` preferred), or None."""
516
+ if not cmd:
517
+ return None
518
+ if _NO_VERIFY_RE.search(cmd):
519
+ return "--no-verify"
520
+ if _BARE_N_RE.search(cmd):
521
+ return "-n"
522
+ return None
523
+
524
+
525
+ def is_git_commit_invocation(cmd: str) -> bool:
526
+ """Return True iff `cmd` is a gate-worthy `git commit` invocation."""
527
+ if not is_git_commit_command(cmd):
528
+ return False
529
+ return not has_bypass_flag(cmd)
530
+
531
+
532
+ __all__ = (
533
+ "bypass_flag_name",
534
+ "has_bypass_flag",
535
+ "is_git_commit_command",
536
+ "is_git_commit_invocation",
537
+ )
@@ -0,0 +1,126 @@
1
+ """hooks/lib/pre_commit_doc_classifier.py — the `.review-passed` gate's
2
+ doc-only exemption predicate (#1461, extracted from `pre_commit_review.py`
3
+ under #1477).
4
+
5
+ Moved out of `pre_commit_review.py` (which had grown to ~759 lines, mixing
6
+ the hook stdin/exit-code contract, git querying, plugin-version resolution,
7
+ bypass-audit recording, boundary-event emission, doc-only classification,
8
+ and the gate-verdict decision engine all in one file) so that module can
9
+ stay to hook-contract plumbing and wiring, with this predicate as its own
10
+ independently testable, independently reviewable unit.
11
+
12
+ Re-derives the doc-only exemption's OWN predicate (#1461 security review)
13
+ rather than trusting the claim in the ledger event: `--event doc-only`
14
+ (`boundary_events.py`) is written by the SAME untrusted party this gate
15
+ exists to constrain, so an unconditional "the event exists, therefore trust
16
+ it" check is the classic trust-the-client pattern — nothing previously
17
+ verified the exempted diff was actually documentation.
18
+
19
+ Deliberately a TIGHTER re-implementation of `code-review/SKILL.md`'s
20
+ doc-only short-circuit and `skills/code-review/scripts/change_shape.py`'s
21
+ `_is_documentation` (built on `hooks/lib/doc_classification.py`'s SHARED
22
+ literal tables, but not a lockstep copy of `change_shape.py`'s matching
23
+ logic — #1461 second security re-review found the original copy
24
+ exploitable): those two only ever ADD a review lens or skip everything on
25
+ already-honest input; this function is the sole gate deciding whether a
26
+ "record zero dispatch evidence" exemption is honored at all, so it must be
27
+ a STRICT SUBSET of what SKILL.md/change_shape.py would call documentation,
28
+ never a superset. Concretely: (1) a root-doc EXACT NAME (README, LICENSE,
29
+ ...) only counts at the repository root (`len(parts) == 1`) AND only when
30
+ the stem carries NO extension at all — `license_manager.py` staged at the
31
+ repo root must never match merely because its basename starts with
32
+ "license", and (#1461 FOURTH security re-review) `license-check` or
33
+ `readme-lint` must never match either, despite also being extensionless: an
34
+ earlier fix used `stem.startswith(prefix)`, which still admitted any
35
+ extensionless name merely beginning with a root-doc prefix. Exact
36
+ membership in the doc-root word set is the only form that matches this
37
+ comment's own stated intent ("the genuinely extensionless case: LICENSE,
38
+ NOTICE, AUTHORS") — a `README.txt`-shaped file is already covered by the
39
+ `DOC_EXTENSIONS` branch above, so this branch exists ONLY for those exact
40
+ extensionless root docs, nothing glob-shaped; (2) a `docs/` directory
41
+ membership alone is NOT sufficient — a doc extension is still required,
42
+ since `docs/conf.py` or a doc-site build script is executable code that
43
+ happens to live under `docs/`. Path segments are lower-cased once, matching
44
+ the stem, so a case-insensitive checkout (`Agents/foo.md`, `.Claude/x.md`)
45
+ can't escape the functional-config exclusion below by case alone.
46
+ `CORE_FUNCTIONAL_CONFIG_SEGMENTS`'s bare `"agents"` entry already matches
47
+ `templates/agents/`, and any other `.../agents/...` path, exactly per
48
+ `code-review/SKILL.md`'s literal stated rule — no separate
49
+ templates-specific helper is needed. If this rule ever needs to change,
50
+ change it here first and only loosen the lens-narrowing siblings to
51
+ match — never the reverse.
52
+
53
+ Stdlib only.
54
+ """
55
+
56
+ from __future__ import annotations
57
+
58
+ import sys
59
+ from pathlib import Path
60
+
61
+ _LIB_DIR = Path(__file__).resolve().parent
62
+ if str(_LIB_DIR) not in sys.path:
63
+ sys.path.insert(0, str(_LIB_DIR))
64
+
65
+ from doc_classification import (
66
+ CORE_FUNCTIONAL_CONFIG_SEGMENTS,
67
+ DOC_EXTENSIONS,
68
+ DOC_ROOT_WORDS,
69
+ FUNCTIONAL_CONFIG_NAMES,
70
+ )
71
+
72
+ _DOC_ROOT_NAMES = frozenset(DOC_ROOT_WORDS)
73
+
74
+ # `.txt` is in `DOC_EXTENSIONS` for real plain-text docs (README.txt), but a
75
+ # `.txt`/`.md`-shaped dependency manifest or build file is executable/
76
+ # supply-chain surface, not documentation (#1461 fourth security re-review) —
77
+ # denylisted by exact name regardless of matching a doc extension above.
78
+ _NON_DOC_NAMES_DESPITE_EXTENSION = {
79
+ "requirements.txt", "requirements-dev.txt", "constraints.txt",
80
+ "cmakelists.txt",
81
+ }
82
+ # Same denylist, by directory instead of exact basename (#1461 fifth
83
+ # security re-review): the common multi-file pip layout
84
+ # (`requirements/base.txt`, `constraints/pins.txt`) escapes the exact-name
85
+ # check above while still matching `DOC_EXTENSIONS`.
86
+ _NON_DOC_DIR_SEGMENTS = {"requirements", "constraints"}
87
+
88
+
89
+ def is_doc_only_changeset(files: list[str]) -> bool:
90
+ """True only when EVERY given path is provably documentation and none is
91
+ functional Claude-config markdown. An empty list — or a list whose every
92
+ entry is blank/unusable — is not doc-only: there is nothing to exempt,
93
+ so this must never vacuously pass."""
94
+ saw_any = False
95
+ for raw in files:
96
+ name = raw.strip()
97
+ if not name:
98
+ continue
99
+ parts = [p.lower() for p in name.replace("\\", "/").split("/") if p]
100
+ if not parts:
101
+ continue
102
+ saw_any = True
103
+ stem = parts[-1]
104
+ suffix = "." + stem.rsplit(".", 1)[-1] if "." in stem else ""
105
+ in_non_doc_dir = suffix in DOC_EXTENSIONS and any(
106
+ seg in _NON_DOC_DIR_SEGMENTS for seg in parts[:-1]
107
+ )
108
+ if (
109
+ stem in FUNCTIONAL_CONFIG_NAMES
110
+ or stem in _NON_DOC_NAMES_DESPITE_EXTENSION
111
+ or in_non_doc_dir
112
+ or any(seg in CORE_FUNCTIONAL_CONFIG_SEGMENTS for seg in parts)
113
+ ):
114
+ return False
115
+ if suffix in DOC_EXTENSIONS:
116
+ continue
117
+ # A root-doc EXACT NAME (README, LICENSE, ...) only counts at the
118
+ # repo root — never at any depth, never with an extension, and
119
+ # never merely as a name PREFIX (`license-check` is not "license").
120
+ if len(parts) == 1 and stem in _DOC_ROOT_NAMES:
121
+ continue
122
+ return False
123
+ return saw_any
124
+
125
+
126
+ __all__ = ("is_doc_only_changeset",)