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,640 @@
1
+ #!/usr/bin/env python3
2
+ """Resolve which review lenses apply to a set of changed files (#1516).
3
+
4
+ Given changed file paths, return the review-agent lenses whose ``Scope:``
5
+ declaration matches, ordered cheap-first (non-opus before opus). ``/build``'s
6
+ inline review checkpoints call this to avoid dispatching lenses with no
7
+ matching surface in the diff (a backend-only diff should not spend tokens on
8
+ frontend/UI lenses). ``/code-review`` Step 3 also adopted this resolver
9
+ (#1533) — both live call sites now share every rule below, not just the
10
+ ones present at #1523.
11
+ A ``Scope: always`` lens named in ``NON_EXECUTABLE_SKIP_ELIGIBLE`` is
12
+ additionally excluded when every changed file is non-executable
13
+ (docs/config/assets/lockfiles, never functional Claude-config markdown —
14
+ see ``NON_EXECUTABLE_EXTENSIONS`` and ``doc_classification.is_functional_config``), since
15
+ that lens's own Skip clause would otherwise just self-report
16
+ ``{"status": "skip"}`` at opus, high-effort cost.
17
+
18
+ Roster source: the **Review Agents** table in ``knowledge/agent-registry.md``
19
+ (the curated lens list), minus the shared ``NON_REVIEW_AGENTS`` boundary and
20
+ the manifest-governed framework-reactivity agents — see ``MANIFEST_GOVERNED``.
21
+
22
+ Design: ``parse_scope`` and ``applicable_lenses`` are pure (unit-testable with
23
+ a synthetic roster). ``build_review_roster`` and ``_read_lines_from`` are the
24
+ I/O boundaries; both fail open (a read error never raises) and both report
25
+ the failure in ``warnings`` rather than silently narrowing the result —
26
+ ``unreadable-registry:<file>`` / ``unreadable-files-from:<path>`` /
27
+ ``unreadable-added-from:<path>``. An affected *agent* additionally stays
28
+ include-biased (``build_review_roster``'s unreadable-agent-file case); an
29
+ affected *file list* does not fabricate paths, so its warning is the only
30
+ signal that the returned list is short.
31
+
32
+ Stdlib-only. See docs/python-hook-contract.md.
33
+ """
34
+
35
+ from __future__ import annotations
36
+
37
+ import argparse
38
+ import json
39
+ import re
40
+ import sys
41
+ from pathlib import Path
42
+
43
+ _HERE = Path(__file__).resolve().parent
44
+ sys.path.insert(0, str(_HERE / "lib"))
45
+
46
+ import review_roster
47
+
48
+ # skills/code-review/scripts/change_shape.py's runtime-surface gate already
49
+ # solves "is this path functional Claude-config, never skippable regardless
50
+ # of extension" — reuse its shared predicate (#1477, extended #1923) rather
51
+ # than adding a fourth, independently-drifting copy of the same
52
+ # classification (a real defect a prior draft of this filter had: `.md`
53
+ # alone made `plugins/dev-team/agents/*.md` — this very repo's shipped
54
+ # agent behavior — read as "non-executable"). Same cross-boundary import
55
+ # pattern that module already uses.
56
+ _HOOKS_LIB_DIR = _HERE.parent / "hooks" / "lib"
57
+ if str(_HOOKS_LIB_DIR) not in sys.path:
58
+ sys.path.insert(0, str(_HOOKS_LIB_DIR))
59
+
60
+ # No `except ImportError` fallback (#1968). The fallback this replaced was a
61
+ # hand-written second copy of `is_functional_config`, and nothing could catch
62
+ # it drifting: the guard that claimed to (`test_select_lenses.py`'s
63
+ # `test_is_functional_config_matches_doc_classification_module`) compared the
64
+ # canonical implementation against itself whenever the import succeeded — which
65
+ # is always, here — so sabotaging the fallback to `return False` left the whole
66
+ # suite green. `hooks/lib/` ships inside this same plugin; an unreachable one is
67
+ # a broken install, not a supported degraded mode.
68
+ try:
69
+ from doc_classification import (
70
+ is_functional_config, # type: ignore[import-not-found]
71
+ )
72
+ except ImportError as exc: # pragma: no cover - broken install, not a supported mode
73
+ raise ImportError(
74
+ f"{__name__} requires the shared classifier 'doc_classification' from "
75
+ f"the dev-team plugin's hooks/lib, which could not be imported.\n"
76
+ f" searched: {_HOOKS_LIB_DIR}\n"
77
+ f" exists: {_HOOKS_LIB_DIR.is_dir()}\n"
78
+ "This module deliberately has no fallback copy of the classifier "
79
+ "(#1968) — a divergent stand-in silently mis-classifies files. Fix the "
80
+ "install or the path rather than re-adding a local implementation."
81
+ ) from exc
82
+
83
+ # `knowledge/test-file-indicators.md`'s single encoding, shared with the
84
+ # refactor test-freeze guards and `change_shape.py` (#1978). Same no-fallback
85
+ # rule as above: a hand-written second copy of "is this a test file?" is
86
+ # exactly the drift #1968 removed.
87
+ try:
88
+ # `_read_probe` is imported rather than re-implemented for the same reason
89
+ # `is_test_file` is: it owns the read cap and the decode-error policy the
90
+ # classifier's content branches expect, and a local copy is a second
91
+ # implementation free to drift (#1968).
92
+ from test_file_classify import ( # type: ignore[import-not-found]
93
+ _read_probe,
94
+ is_test_file,
95
+ )
96
+ except ImportError as exc: # pragma: no cover - broken install, not a supported mode
97
+ raise ImportError(
98
+ f"{__name__} requires the shared classifier 'test_file_classify' from "
99
+ f"the dev-team plugin's hooks/lib, which could not be imported.\n"
100
+ f" searched: {_HOOKS_LIB_DIR}\n"
101
+ f" exists: {_HOOKS_LIB_DIR.is_dir()}\n"
102
+ "This module deliberately has no fallback copy of the classifier "
103
+ "(#1968) — a divergent stand-in silently mis-classifies files. Fix the "
104
+ "install or the path rather than re-adding a local implementation."
105
+ ) from exc
106
+
107
+ # Framework-reactivity lenses declare bare ``**/*.ts`` / ``**/*.js`` globs, but
108
+ # their real trigger is a dependency-manifest match (``/code-review`` Step 3's
109
+ # separate rule), not a file-path match. Keep them OUT of this resolver's remit
110
+ # so a plain Node/TS backend with no React/Vue/Angular does not get reactivity
111
+ # lenses. MAINTENANCE: any new manifest-governed framework-reactivity agent
112
+ # with bare ``**/*.ts|js`` globs must be added here.
113
+ MANIFEST_GOVERNED = {
114
+ "react-reactivity-review",
115
+ "vue-reactivity-review",
116
+ "angular-reactivity-review",
117
+ }
118
+
119
+ _SCOPE_RE = review_roster.SCOPE_LINE_RE
120
+ _MODEL_RE = re.compile(r"^\s*model\s*:\s*(.*)$")
121
+ _BULLET_RE = re.compile(r"^\s*-\s*(\S+)")
122
+ _EXT_TOKEN_RE = re.compile(r"`?(\.\w[\w.]*)`?")
123
+ # Review Agents table rows look like: | <name> | `agents/<name>.md` | ... |
124
+ # The name must start with a letter so the markdown separator row
125
+ # (| ------- | ------ | ... |) is not captured as a bogus "-------" lens.
126
+ _TABLE_ROW_RE = re.compile(r"^\|\s*([a-z][a-z0-9-]*)\s*\|")
127
+
128
+ # The sentinel an agent uses to declare it applies to every diff (`Scope: always`).
129
+ SCOPE_ALWAYS = "always"
130
+ # The sentinel an agent uses to declare it should only fire when a matching
131
+ # file is newly *added*, not merely modified (#1733's dual-placement rule for
132
+ # `component-architecture-review`: unconditional whole-inventory pass in
133
+ # `/repo-review`, narrowed to added-only in `/code-review`'s per-diff panel).
134
+ # Parsed the same way as the empty-inline-value case (bullet block of globs)
135
+ # and encoded as `(SCOPE_ADDED_ONLY, globs)` so callers can tell it apart from
136
+ # a plain glob-list scope.
137
+ SCOPE_ADDED_ONLY = "added-only"
138
+ # The sentinel an agent uses to declare it is a genuine review agent whose
139
+ # findings are properties of the whole repository, not any single diff, and
140
+ # so must never be dispatched by the per-diff resolver — only by name (e.g.
141
+ # `/claude-setup-review`) or by the whole-tree `/repo-review` skill (#1735).
142
+ # A bare declaration, no bullet block: unlike `added-only`, there is no glob
143
+ # data to carry, so the resolver just excludes the lens outright. Replaces a
144
+ # prior, competing mechanism (listing the agent in `NON_REVIEW_AGENTS`) that
145
+ # also incorrectly exempted it from the `Scope:` declaration requirement it
146
+ # actually satisfies — see `scripts/lib/review_roster.py`'s docstring.
147
+ SCOPE_ON_DEMAND = "on-demand"
148
+ # The sentinel an agent uses to declare it applies only when the changeset
149
+ # touches a test file (#1978). A bare declaration with no bullet block, like
150
+ # `on-demand` — deliberately NOT a glob list, because the glob vocabulary
151
+ # `_matches` supports (a literal suffix) cannot express three of the five
152
+ # families in `knowledge/test-file-indicators.md`: Python's `test_*.py`
153
+ # prefix, JS/TS's `__tests__/` directory, and C#/Java's annotation-based
154
+ # indicators. A hand-maintained glob list would therefore be both incomplete
155
+ # and a second copy of that knowledge file, free to drift from it. This
156
+ # sentinel instead delegates to `test_file_classify.is_test_file` — the same
157
+ # single encoding the refactor test-freeze guards and `change_shape.py` use —
158
+ # so the answer cannot diverge from the canonical one.
159
+ SCOPE_TEST_FILES = "test-files"
160
+ # Heading substring that marks the Review Agents section of agent-registry.md.
161
+ # Named so a heading rename over there is greppable from here (the coupling).
162
+ _REVIEW_AGENTS_HEADING_MARKER = "review agent"
163
+
164
+ # Lenses whose own Skip clause covers "static assets, configuration,
165
+ # markup, or documentation with no executable logic" / "generated code,
166
+ # vendored dependencies, or lockfiles" verbatim, checked directly against
167
+ # each candidate's own agent-body text before being added here (#1923
168
+ # review round): each would only ever self-report `{"status": "skip"}` on
169
+ # an all-non-executable diff, so dispatching an opus, high-effort model
170
+ # just to hear "skip" is pure waste.
171
+ #
172
+ # Deliberately ONE member today, not "every opus-tier always lens" —
173
+ # `security-review`, `arch-review`, and `domain-review` were considered and
174
+ # REJECTED: their own Skip clauses do not authorize this. security-review's
175
+ # clause covers only "static assets, images, or documentation", not
176
+ # config/lockfiles (`NON_EXECUTABLE_EXTENSIONS` includes both), and its own
177
+ # "## Scope — files always in scope" section mandates scanning some of the
178
+ # very file classes this filter would suppress (infra manifests, configs)
179
+ # for hardcoded credentials — a real, exploitable coverage gap this filter
180
+ # would otherwise create for A08.review-manipulation/A05 detection.
181
+ # arch-review's clause is about ADR/module-boundary *absence*, not a
182
+ # docs-only diff — a pure-markdown ADR update is exactly the case its own
183
+ # `## Detect` section (ADR compliance) exists to catch, so filtering it on
184
+ # `.md` would drop the one check aimed at that content. domain-review's
185
+ # clause is "infra-only code" / "no business logic present", which is a
186
+ # file-content judgment, not a file-type one this filter can safely proxy.
187
+ #
188
+ # An explicit allowlist (matching this file's own MANIFEST_GOVERNED
189
+ # precedent above) rather than an implicit `is_opus` check: a future opus
190
+ # `Scope: always` lens defaults to NOT being filtered until it is added
191
+ # here deliberately, after the same verification against its own Skip
192
+ # clause — so a Skip-clause change on `correctness-review` (or a new
193
+ # candidate with different semantics) can't silently start/stop being
194
+ # filtered with nothing forcing that decision. MAINTENANCE: re-verify
195
+ # against the named agent's own Skip clause before adding or keeping a name
196
+ # here; remove it the moment that clause no longer matches.
197
+ #
198
+ # Relationship to `skills/code-review/scripts/change_shape.py`'s
199
+ # `LOW_YIELD_LENSES` (`["performance-review", "correctness-review"]`):
200
+ # that gate is `/code-review`-Step-3-specific and already drops
201
+ # correctness-review on a no-runtime-surface changeset (with this same
202
+ # functional-config carve-out). This allowlist is NOT redundant with it —
203
+ # `/build`'s inline review checkpoints call `applicable_lenses` directly
204
+ # and never consult `change_shape.py`, so without this, correctness-review
205
+ # still paid full opus cost on every doc-only `/build` step. The two lists
206
+ # legitimately overlap on `correctness-review` rather than duplicating by
207
+ # accident; `performance-review` is haiku-tier and not this filter's cost
208
+ # concern, so it is intentionally absent here.
209
+ # frozenset (not a plain set), matching `doc_classification.py`'s own
210
+ # convention for these shared-literal-shaped tables: this allowlist governs
211
+ # which review lenses may be dropped, so it must not be mutable by any
212
+ # importer after module load.
213
+ NON_EXECUTABLE_SKIP_ELIGIBLE = frozenset({
214
+ "correctness-review",
215
+ })
216
+
217
+ # Extensions/basenames the NON_EXECUTABLE_SKIP_ELIGIBLE lens(es) above would
218
+ # only ever self-report `{"status": "skip"}` against. Deliberately
219
+ # conservative: `.yaml`/`.yml` are excluded because CI workflow files
220
+ # routinely embed real conditionals/shell logic correctness-review
221
+ # legitimately checks (see its category 5); a lockfile written in YAML is
222
+ # instead named explicitly in NON_EXECUTABLE_BASENAMES. Safe to keep `.json`
223
+ # here even though it is a real security/execution surface elsewhere in this
224
+ # repo (`settings.json` hook registrations, `package.json` scripts) —
225
+ # `security-review` is not on the allowlist above, and correctness-review's
226
+ # "does this code do what it evidently intends" lens has no bearing on that
227
+ # concern. Deliberately DIFFERENT from `change_shape.py`'s own runtime-surface
228
+ # classifier, not merely a copy of it: the binary/vector asset extensions
229
+ # below (`.svg`/`.png`/etc.) appear in neither that module's `_DOC_EXTENSIONS`
230
+ # nor its `_CONFIG_EXTENSIONS`, so an asset-only diff is "runtime surface,
231
+ # keep every lens" there but "non-executable, skip correctness-review" here.
232
+ # That asymmetry is safe today (it can only make this module drop a lens
233
+ # `change_shape.py` would have kept, never the reverse, and only for
234
+ # correctness-review — no other lens reads this constant), but re-check it
235
+ # against `change_shape.py` before adding a second name to the allowlist
236
+ # above, per that constant's own MAINTENANCE note.
237
+ NON_EXECUTABLE_EXTENSIONS = frozenset({
238
+ ".md", ".mdx", ".rst", ".txt",
239
+ ".json", ".toml", ".ini", ".cfg",
240
+ ".svg", ".png", ".jpg", ".jpeg", ".gif", ".ico", ".webp", ".pdf",
241
+ ".lock",
242
+ })
243
+ NON_EXECUTABLE_BASENAMES = frozenset({
244
+ "LICENSE", "LICENSE.txt", ".gitignore", ".editorconfig", ".gitattributes",
245
+ "pnpm-lock.yaml",
246
+ })
247
+
248
+ def _is_non_executable_file(file_path: str) -> bool:
249
+ """True if ``file_path`` is a static asset, inert config/data,
250
+ documentation, or a lockfile — see NON_EXECUTABLE_EXTENSIONS above.
251
+ Never true for functional Claude-config markdown/paths (checked
252
+ first, via the shared `is_functional_config` — same predicate
253
+ `change_shape.py` uses), regardless of extension."""
254
+ if is_functional_config(file_path):
255
+ return False
256
+ name = Path(file_path).name
257
+ if name in NON_EXECUTABLE_BASENAMES:
258
+ return True
259
+ return Path(file_path).suffix.lower() in NON_EXECUTABLE_EXTENSIONS
260
+
261
+
262
+ def _is_all_non_executable(changed_files) -> bool:
263
+ """True iff every file in ``changed_files`` is non-executable. Callers
264
+ already special-case an empty list before reaching this."""
265
+ return bool(changed_files) and all(
266
+ _is_non_executable_file(f) for f in changed_files
267
+ )
268
+
269
+
270
+ def _should_skip_non_executable(name: str, changed_files) -> bool:
271
+ """True if ``name`` is on the skip allowlist and every changed file is
272
+ non-executable — mirrors ``_added_only_eligible``'s role below for the
273
+ added-only branch, hoisting a compound condition out of the
274
+ ``applicable_lenses`` dispatcher's own branch body."""
275
+ return name in NON_EXECUTABLE_SKIP_ELIGIBLE and _is_all_non_executable(changed_files)
276
+
277
+
278
+ def _consume_bullet_block(lines, start_index):
279
+ """Collect a contiguous ``- <glob>`` bullet block starting after
280
+ ``start_index``; stop at the first non-bullet line. Returns the globs."""
281
+ globs = []
282
+ for nxt in lines[start_index + 1:]:
283
+ b = _BULLET_RE.match(nxt)
284
+ if not b:
285
+ break
286
+ globs.append(b.group(1).strip("`"))
287
+ return globs
288
+
289
+
290
+ def parse_scope(text: str):
291
+ """Return ``"always"`` | ``"on-demand"`` | ``"test-files"`` | ``list[str]``
292
+ | ``(SCOPE_ADDED_ONLY, list[str])`` | ``None`` from agent markdown.
293
+
294
+ The **first** ``Scope:`` line is authoritative. An empty inline value
295
+ followed by a ``- **/*.ext`` bullet block yields that structured,
296
+ fnmatch-ready list (preferred over the free-text second ``Scope:`` line some
297
+ agents also carry). ``Scope: always`` -> ``"always"``. ``Scope: on-demand``
298
+ -> ``SCOPE_ON_DEMAND`` (a bare declaration — no bullet block, unlike
299
+ ``added-only``). ``Scope: added-only`` followed by the same bullet-block
300
+ shape -> ``(SCOPE_ADDED_ONLY, globs)`` (no bullet block -> ``None``, same
301
+ fail-open rule as a missing declaration). Other inline prose -> ``.ext``
302
+ tokens extracted as a fallback (``None`` if it names no extension). No
303
+ ``Scope:`` line -> ``None``.
304
+ """
305
+ lines = text.splitlines()
306
+ for i, line in enumerate(lines):
307
+ m = _SCOPE_RE.match(line)
308
+ if not m:
309
+ continue
310
+ value = m.group(1).strip()
311
+ if value.lower() == SCOPE_ALWAYS:
312
+ return SCOPE_ALWAYS
313
+ if value.lower() == SCOPE_ON_DEMAND:
314
+ return SCOPE_ON_DEMAND
315
+ if value.lower() == SCOPE_TEST_FILES:
316
+ return SCOPE_TEST_FILES
317
+ if value.lower() == SCOPE_ADDED_ONLY:
318
+ globs = _consume_bullet_block(lines, i)
319
+ return (SCOPE_ADDED_ONLY, globs) if globs else None
320
+ if value:
321
+ tokens = _EXT_TOKEN_RE.findall(value)
322
+ return [f"**/*{t}" for t in tokens] or None
323
+ # Empty inline value: consume the following bullet block (authoritative).
324
+ return _consume_bullet_block(lines, i) or None
325
+ return None
326
+
327
+
328
+ def parse_model_is_opus(text: str) -> bool:
329
+ """True if the agent's ``model:`` frontmatter resolves to an opus tier."""
330
+ for line in text.splitlines():
331
+ m = _MODEL_RE.match(line)
332
+ if m:
333
+ return "opus" in m.group(1).strip().lower()
334
+ return False
335
+
336
+
337
+ def _matches(file_path: str, pattern: str) -> bool:
338
+ """Extension-aware glob match, robust to directory depth.
339
+
340
+ ``**/*.tsx`` -> match any path ending ``.tsx``; ``**/*.component.ts`` ->
341
+ ending ``.component.ts``. Directory-insensitive on purpose (fnmatch's ``*``
342
+ would otherwise require a ``/`` for a ``**/`` prefix and miss top-level
343
+ files). A non-glob pattern matches by exact path or basename.
344
+ """
345
+ if "*" in pattern:
346
+ suffix = pattern.rsplit("*", 1)[-1]
347
+ return bool(suffix) and file_path.endswith(suffix)
348
+ return file_path == pattern or Path(file_path).name == pattern
349
+
350
+
351
+ def _scope_matches(scope, changed_files) -> bool:
352
+ """True if a glob-list ``scope`` matches any changed file (``"always"`` is
353
+ handled by the caller, not here)."""
354
+ return any(_matches(f, g) for f in changed_files for g in scope)
355
+
356
+
357
+ def _is_added_only_scope(scope) -> bool:
358
+ """True if ``scope`` is the ``(SCOPE_ADDED_ONLY, globs)`` shape."""
359
+ return isinstance(scope, tuple) and scope[0] == SCOPE_ADDED_ONLY
360
+
361
+
362
+ def _added_only_eligible(globs, changed_files, added_files) -> bool:
363
+ """True if an added-only scope's ``globs`` match within the eligible set.
364
+
365
+ ``added_files=None`` (no change-type data supplied) falls back to
366
+ matching any changed file — the fail-safe direction every other
367
+ ambiguity in this module already resolves toward. A supplied set (even
368
+ empty) narrows eligibility to only files present in it.
369
+ """
370
+ eligible = changed_files if added_files is None else [
371
+ f for f in changed_files if f in added_files
372
+ ]
373
+ return bool(eligible) and _scope_matches(globs, eligible)
374
+
375
+
376
+ #: Extensions whose test-ness `test_file_classify` decides from file CONTENT
377
+ #: (C# `[Fact]`, Java `@Test`) rather than from the name, by reading the file.
378
+ #: When such a file is not on disk — a deleted path, or a caller running
379
+ #: outside the checkout — that read yields "" and the classifier answers "not
380
+ #: a test", which would silently drop a lens. `test_file_subset` treats those
381
+ #: as possible tests instead: the same include-biased direction every other
382
+ #: ambiguity in this module already resolves toward.
383
+ _CONTENT_PROBED_SUFFIXES = (".cs", ".java")
384
+
385
+
386
+ def test_file_subset(changed_files, root=None):
387
+ """I/O boundary: which of ``changed_files`` are test files.
388
+
389
+ Reads from disk (via the shared classifier) for the content-probed
390
+ languages; every other family resolves by name alone. Returns a set
391
+ suitable for ``applicable_lenses(..., test_files=...)``. Never raises —
392
+ an unreadable content-probed file counts as a possible test, per
393
+ ``_CONTENT_PROBED_SUFFIXES``.
394
+ """
395
+ base = Path(root) if root else Path.cwd()
396
+ found = set()
397
+ for path in changed_files:
398
+ # ALWAYS classify the repo-relative path, never the absolute one: the
399
+ # classifier's `__tests__/` rule matches any path segment, so a
400
+ # checkout living under a directory named `__tests__` (a CI workspace
401
+ # at /build/__tests__/repo, say) would otherwise classify every file
402
+ # in the repo as a test. Content is supplied separately below so the
403
+ # on-disk read still happens against the real file.
404
+ if not path.lower().endswith(_CONTENT_PROBED_SUFFIXES):
405
+ if is_test_file(path):
406
+ found.add(path)
407
+ continue
408
+ full = base / path
409
+ # An empty probe means "could not read it", not "read it and found no
410
+ # test marker": `_read_probe` returns "" both for a file that is not
411
+ # there and for one that exists but raises (permissions, or a file
412
+ # replaced between this check and the open). Both are unprovable, so
413
+ # both include-bias — anything else silently drops the lens, which is
414
+ # the failure mode `_CONTENT_PROBED_SUFFIXES` exists to prevent.
415
+ probe = _read_probe(full) if full.is_file() else ""
416
+ if not probe or is_test_file(path, content=probe):
417
+ found.add(path)
418
+ return found
419
+
420
+
421
+ def applicable_lenses(changed_files, roster, added_files=None, test_files=None):
422
+ """Pure resolver. ``roster`` = ``[(name, scope, is_opus)]``. Returns
423
+ ``(lenses, warnings)`` with lenses ordered cheap-first (non-opus, then opus).
424
+
425
+ An empty ``changed_files`` yields ``([], [])`` — nothing to review, so no
426
+ lens (not even ``Scope: always``) is selected. ``scope is None`` ->
427
+ include-biased + warn (never non-executable-filtered, regardless of
428
+ ``name`` or ``is_opus`` — that filter applies only inside this
429
+ ``SCOPE_ALWAYS`` branch); ``"always"`` -> include, UNLESS ``name`` is on
430
+ the ``NON_EXECUTABLE_SKIP_ELIGIBLE`` allowlist and every changed file is
431
+ non-executable (see ``_should_skip_non_executable``) — that combination
432
+ is excluded and warned as ``skipped-non-executable:<name>`` rather than
433
+ paying an opus round trip for a self-reported skip; glob list -> include
434
+ iff any changed file matches; ``SCOPE_ON_DEMAND`` -> never include, no
435
+ warning (a deliberate, self-declared exclusion, not a defect to
436
+ surface); ``SCOPE_TEST_FILES`` -> include iff a changed file is in
437
+ ``test_files``.
438
+
439
+ ``test_files`` (#1978) is the ``SCOPE_TEST_FILES`` counterpart of
440
+ ``added_files`` below, and follows the same fail-safe rule: ``None`` (a
441
+ caller with no test-file classification to offer) includes the lens and
442
+ records ``unnarrowed-test-files:<name>`` in ``warnings`` rather than
443
+ silently dropping a lens the caller never asked to narrow. A supplied
444
+ set — even an empty one — narrows. Callers that can reach the
445
+ filesystem get the set from ``test_file_subset``.
446
+
447
+ ``added_files`` (#1733) narrows a ``(SCOPE_ADDED_ONLY, globs)`` scope to
448
+ only the changed files that are also newly *added* — but **only when the
449
+ caller actually supplies it**. ``added_files=None`` (the default — a
450
+ caller, e.g. ``/build``'s inline checkpoints, that has no change-type data
451
+ to offer) makes an added-only scope behave exactly like a plain glob list,
452
+ matching any changed file. This is deliberately fail-safe in the same
453
+ direction every other gate in this module already leans: ambiguity always
454
+ resolves toward *keeping* a lens, never toward silently dropping one a
455
+ caller never asked to narrow. When that fallback fires (a lens selected
456
+ via an added-only scope with no ``added_files`` supplied), it is recorded
457
+ in ``warnings`` as ``unnarrowed-added-only:<name>`` — the same "never
458
+ silently dropped" transparency the missing-``Scope:`` case already gets,
459
+ applied to a silent *widening* instead.
460
+ """
461
+ if not changed_files:
462
+ return [], []
463
+ selected: list[tuple[str, bool]] = []
464
+ warnings: list[str] = []
465
+ for name, scope, is_opus in roster:
466
+ if scope is None:
467
+ warnings.append(name)
468
+ selected.append((name, is_opus))
469
+ elif scope == SCOPE_ALWAYS:
470
+ if _should_skip_non_executable(name, changed_files):
471
+ warnings.append(f"skipped-non-executable:{name}")
472
+ continue
473
+ selected.append((name, is_opus))
474
+ elif scope == SCOPE_ON_DEMAND:
475
+ continue # never dispatched by the per-diff resolver, by design
476
+ elif scope == SCOPE_TEST_FILES:
477
+ if test_files is None:
478
+ selected.append((name, is_opus))
479
+ warnings.append(f"unnarrowed-test-files:{name}")
480
+ elif any(f in test_files for f in changed_files):
481
+ selected.append((name, is_opus))
482
+ elif _is_added_only_scope(scope):
483
+ if not _added_only_eligible(scope[1], changed_files, added_files):
484
+ continue
485
+ selected.append((name, is_opus))
486
+ if added_files is None:
487
+ warnings.append(f"unnarrowed-added-only:{name}")
488
+ elif _scope_matches(scope, changed_files):
489
+ selected.append((name, is_opus))
490
+ # Stable cheap-first: False (non-opus) sorts before True (opus).
491
+ selected.sort(key=lambda pair: pair[1])
492
+ return [name for name, _ in selected], warnings
493
+
494
+
495
+ def _registry_lens_names(registry_text: str) -> list[str]:
496
+ """Names in the Review Agents table section of agent-registry.md."""
497
+ names: list[str] = []
498
+ in_section = False
499
+ for line in registry_text.splitlines():
500
+ if line.startswith("## "):
501
+ in_section = _REVIEW_AGENTS_HEADING_MARKER in line.lower()
502
+ continue
503
+ if in_section:
504
+ m = _TABLE_ROW_RE.match(line)
505
+ if m:
506
+ names.append(m.group(1))
507
+ return names
508
+
509
+
510
+ def build_review_roster(agents_dir: Path, registry_path: Path):
511
+ """I/O boundary: build ``roster = [(name, scope, is_opus)]`` from disk.
512
+
513
+ Fails open: an unreadable registry yields ``([], [warning])``; an unreadable
514
+ agent file is include-biased (``scope=None`` -> included + warned) rather
515
+ than raising.
516
+ """
517
+ warnings: list[str] = []
518
+ try:
519
+ registry_text = registry_path.read_text(encoding="utf-8")
520
+ except OSError:
521
+ return [], [f"unreadable-registry:{registry_path.name}"]
522
+ roster = []
523
+ for name in _registry_lens_names(registry_text):
524
+ if name in review_roster.NON_REVIEW_AGENTS or name in MANIFEST_GOVERNED:
525
+ continue
526
+ try:
527
+ text = (agents_dir / f"{name}.md").read_text(encoding="utf-8")
528
+ except OSError:
529
+ roster.append((name, None, False)) # include-biased fail-open
530
+ continue
531
+ roster.append((name, parse_scope(text), parse_model_is_opus(text)))
532
+ return roster, warnings
533
+
534
+
535
+ def _read_lines_from(path_or_dash: str):
536
+ """Read newline-separated, non-blank lines from a file or stdin (``-``).
537
+
538
+ Returns ``(lines, error)``. Never raises — a missing or unreadable file
539
+ contributes no lines, matching `changed_file_list.py`'s identical helper
540
+ — but unlike that helper, the failure is reported back via ``error``
541
+ (``None`` on success, including a genuinely empty readable source) so
542
+ the caller can tell "nothing was there" apart from "couldn't read it"
543
+ and warn on the latter. Silently treating the two the same would make an
544
+ unreadable ``--files-from`` indistinguishable from a legitimate
545
+ "nothing changed" result.
546
+ """
547
+ try:
548
+ if path_or_dash == "-":
549
+ text = sys.stdin.read()
550
+ else:
551
+ with open(path_or_dash, encoding="utf-8") as handle:
552
+ text = handle.read()
553
+ except (OSError, ValueError) as exc:
554
+ return [], type(exc).__name__
555
+ return [line for line in text.splitlines() if line.strip()], None
556
+
557
+
558
+ def main(argv=None) -> int:
559
+ parser = argparse.ArgumentParser(description="Resolve applicable review lenses.")
560
+ parser.add_argument("--files", nargs="*", default=[], help="Changed file paths")
561
+ parser.add_argument(
562
+ "--files-from", default=None,
563
+ help=(
564
+ "Read newline-separated changed-file paths from this file "
565
+ "('-' for stdin), combined with --files. Prefer this for a "
566
+ "machine-generated or caller-uncontrolled list: it avoids "
567
+ "argparse's own argv-parsing hazards (a path starting with '-' "
568
+ "reinterpreted as a flag, word-splitting on an unquoted space) "
569
+ "— it does NOT by itself protect against a caller that "
570
+ "builds the file this reads from by shell-interpolating "
571
+ "untrusted path text; that boundary is the caller's to hold "
572
+ "(mirrors changed_file_list.py's --name-status-from)."
573
+ ),
574
+ )
575
+ parser.add_argument(
576
+ "--added", nargs="*", default=None,
577
+ help=(
578
+ "Paths that are newly added (git change-type A) in this "
579
+ "changeset, e.g. from changed_file_list.py's 'added' list. "
580
+ "Narrows any 'Scope: added-only' lens to only these paths; "
581
+ "omit both this and --added-from when the caller has no "
582
+ "change-type data (fail-safe: added-only scopes then match "
583
+ "like a plain glob list)."
584
+ ),
585
+ )
586
+ parser.add_argument(
587
+ "--added-from", default=None,
588
+ help=(
589
+ "Read newline-separated added-file paths from this file "
590
+ "('-' for stdin), combined with --added. Same caveat as "
591
+ "--files-from."
592
+ ),
593
+ )
594
+ parser.add_argument("--agents-dir", type=Path, default=_HERE.parent / "agents")
595
+ parser.add_argument(
596
+ "--registry",
597
+ type=Path,
598
+ default=_HERE.parent / "knowledge" / "agent-registry.md",
599
+ )
600
+ args = parser.parse_args(argv)
601
+ if args.files_from == "-" and args.added_from == "-":
602
+ parser.error(
603
+ "--files-from and --added-from cannot both read stdin ('-') — "
604
+ "the second read gets nothing, silently. Use a file path or "
605
+ "process substitution for at least one."
606
+ )
607
+ roster, roster_warnings = build_review_roster(args.agents_dir, args.registry)
608
+
609
+ resolver_warnings: list[str] = []
610
+
611
+ files = list(args.files)
612
+ if args.files_from:
613
+ extra, error = _read_lines_from(args.files_from)
614
+ files.extend(extra)
615
+ if error:
616
+ resolver_warnings.append(f"unreadable-files-from:{args.files_from}")
617
+
618
+ added_files = None
619
+ if args.added is not None or args.added_from:
620
+ added_files = set(args.added or [])
621
+ if args.added_from:
622
+ extra, error = _read_lines_from(args.added_from)
623
+ added_files.update(extra)
624
+ if error:
625
+ resolver_warnings.append(f"unreadable-added-from:{args.added_from}")
626
+
627
+ # Computed here, never asked of the caller: unlike `added_files` (a git
628
+ # change-type only the caller's diff knows), test-ness is derivable from
629
+ # the checkout this process can already see, so requiring a flag for it
630
+ # would add a way for a caller to get it wrong for no information gain.
631
+ lenses, warnings = applicable_lenses(
632
+ files, roster, added_files=added_files, test_files=test_file_subset(files)
633
+ )
634
+ all_warnings = roster_warnings + resolver_warnings + warnings
635
+ print(json.dumps({"lenses": lenses, "warnings": all_warnings}))
636
+ return 0
637
+
638
+
639
+ if __name__ == "__main__":
640
+ raise SystemExit(main())