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,467 @@
1
+ #!/usr/bin/env python3
2
+ """Deterministic contract validation for review-agent output (#1998).
3
+
4
+ Session-report analysis over 3,213 review runs found 585 (18.2%) returning
5
+ output that does not match the shared review-agent JSON contract
6
+ (`knowledge/review-agent-output-contract.md`). Those findings were discarded
7
+ without a diagnostic — the orchestrator eyeballs each agent's raw text
8
+ against the contract and, when it doesn't obviously fit, the loss is silent:
9
+ no agent name, no raw output, no reason is ever recorded, so the failure
10
+ shapes are unknown. #1980/#1982's per-lens `$/finding` figures divide by
11
+ that same lossy denominator, and the loss rate varies ~8x by agent
12
+ (`concurrency-review` 49%, `spec-compliance-review` 30%, `doc-review` 19%).
13
+
14
+ This module is the deterministic half of the fix: given an agent's raw text
15
+ output, decide whether it satisfies the contract and, when it doesn't,
16
+ classify *why* and log a diagnostic — agent name, a redacted prefix of the
17
+ raw output, and the specific validation error — to
18
+ `.claude/metrics/contract-failures.jsonl`. Per this repo's CLAUDE.md:
19
+ "instrument before fixing... the failure shapes are currently unknown, so a
20
+ fix written first would be a guess." Fixing by shape (a tolerant extractor
21
+ for the recoverable cases, a schema fix, a hard error for the unusable ones)
22
+ and recomputing `$/finding` on the repaired denominator are follow-on work
23
+ once this log has real data in it.
24
+
25
+ Two independent dimensions are tracked, not one:
26
+
27
+ - ``extraction`` — how the JSON was framed: ``clean`` (no wrapper), ``fenced``
28
+ (a ` ```json ` block), or ``prose-preamble`` (a leading/trailing prose
29
+ sentence around a balanced object). ``None`` when no JSON-like structure
30
+ was ever recovered at all.
31
+ - ``shape`` — the outcome. On success it equals ``extraction``. On failure it
32
+ is one of the loggable failure shapes (see ``FAILURE_SHAPES``) — including
33
+ ``schema-drift`` and ``malformed-json``, both of which can co-occur with any
34
+ extraction (``clean``/``fenced``/``prose-preamble``), so ``extraction``
35
+ survives even when the object was recovered from a fenced block or a prose
36
+ preamble and only then found to violate the contract or fail to parse.
37
+ ``empty``/``truncated``/``not-json`` never carry an ``extraction`` — no
38
+ JSON-shaped candidate was ever recovered for those. Collapsing these into
39
+ one field was the original design and it silently discarded the extraction
40
+ dimension on exactly the failures a tolerant extractor would need it for.
41
+
42
+ Stdlib-only. See docs/python-hook-contract.md.
43
+ """
44
+
45
+ from __future__ import annotations
46
+
47
+ import argparse
48
+ import json
49
+ import re
50
+ import sys
51
+ from datetime import datetime, timezone
52
+ from pathlib import Path
53
+
54
+ # skills/code-review/scripts -> skills/code-review -> skills -> plugin root
55
+ _PLUGIN_ROOT = Path(__file__).resolve().parents[3]
56
+ _HOOKS_LIB_DIR = _PLUGIN_ROOT / "hooks" / "lib"
57
+ if str(_HOOKS_LIB_DIR) not in sys.path:
58
+ sys.path.insert(0, str(_HOOKS_LIB_DIR))
59
+
60
+ try:
61
+ import artifact_paths # type: ignore[import-not-found]
62
+ import atomic_state # type: ignore[import-not-found]
63
+ import review_agent_registry # type: ignore[import-not-found]
64
+ except ImportError: # pragma: no cover - degraded fallback, hooks/lib unreachable
65
+ # Same guarded-import shape as `review_round_log.py`'s sibling pattern:
66
+ # the `sys.path` setup above must run before this import, which is why
67
+ # it isn't at the top of the file (`ruff.toml` suppresses E402 for this
68
+ # whole directory for exactly that reason).
69
+ artifact_paths = None
70
+ atomic_state = None
71
+ review_agent_registry = None
72
+
73
+ _STREAM_NAME = "contract-failures.jsonl"
74
+
75
+ #: How much of the (redacted) raw output a failure diagnostic carries — enough
76
+ #: to recognize the shape (a preamble sentence, a fence opener, truncation) at
77
+ #: a glance, without inflating the log with full agent output on every
78
+ #: failure.
79
+ _RAW_PREFIX_LEN = 200
80
+
81
+ #: Cap on the persisted/printed `error` string. `_validate_schema` interpolates
82
+ #: agent-controlled values (`status`, `severity`) with `!r` — unlike
83
+ #: `raw_prefix`, nothing bounded this field's length or redacted it before
84
+ #: #1998 wave-2-follow-up, so a drifting agent could write an arbitrarily
85
+ #: long, secret-bearing `error` straight into `contract-failures.jsonl` and
86
+ #: into every downstream `dispatchFailures[].error` consumer.
87
+ _ERROR_MAX_LEN = 256
88
+
89
+ _VALID_STATUSES = frozenset({"pass", "warn", "fail", "skip"})
90
+ _VALID_SEVERITIES = frozenset({"error", "warning", "suggestion"})
91
+
92
+ _FENCE_RE = re.compile(r"```(?:json)?\s*\n(.*?)```", re.DOTALL)
93
+
94
+ #: Secret-shaped substrings to scrub before any raw agent text is persisted.
95
+ #: Review-agent output is not independent of the reviewed repository — a
96
+ #: lens quoting a hardcoded-key finding verbatim reproduces the secret it
97
+ #: found — so `raw_prefix` is a transitive channel for repo content, not
98
+ #: "AI-authored text" in the sense of being free of user/repo material.
99
+ #: First pattern is this repo's own canonical hardcoded-key detector
100
+ #: (`knowledge/owasp-detection.md`'s "Hardcoded-key pattern"); the rest are
101
+ #: high-signal vendor token prefixes cheap enough to check unconditionally.
102
+ _SECRET_PATTERNS = (
103
+ # No required closing quote (unlike the canonical pattern in
104
+ # `knowledge/owasp-detection.md`): this module's own most common failure
105
+ # shape, `truncated`, cuts output mid-string, and requiring a closing
106
+ # quote before redacting would let exactly that secret through unredacted.
107
+ re.compile(r"(?i)(api[_-]?key|secret|password|token)\s*[:=]\s*['\"][^'\"]{8,}"),
108
+ # `[A-Za-z0-9_-]`, not just alphanumeric: segmented vendor-key formats
109
+ # (`sk-ant-...`, `sk-proj-...`) use `-`/`_` inside the token body and
110
+ # would otherwise stop matching at the first separator.
111
+ re.compile(r"sk-[A-Za-z0-9_-]{16,}"),
112
+ re.compile(r"AKIA[0-9A-Z]{16}"),
113
+ re.compile(r"gh[pousr]_[A-Za-z0-9]{20,}"),
114
+ re.compile(r"xox[baprs]-[A-Za-z0-9-]{10,}"),
115
+ re.compile(r"eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}"),
116
+ # Complete PEM block, bounded by its own END marker.
117
+ re.compile(r"-----BEGIN [A-Z ]*PRIVATE KEY-----.*?-----END [A-Z ]*PRIVATE KEY-----", re.DOTALL),
118
+ # A BEGIN marker with no matching END left in the text — the truncated
119
+ # shape again: redact from BEGIN to EOF rather than leave the key body
120
+ # unredacted because the block never closed.
121
+ re.compile(r"-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*$"),
122
+ )
123
+
124
+ #: Extraction shapes — how a successfully-recovered JSON object was framed.
125
+ #: These label *successful* extraction only; they never appear as a `shape`
126
+ #: value in a failure row (see ``FAILURE_SHAPES``) except indirectly via the
127
+ #: `extraction` field on a `schema-drift` failure.
128
+ SHAPE_CLEAN = "clean"
129
+ SHAPE_FENCED = "fenced"
130
+ SHAPE_PROSE_PREAMBLE = "prose-preamble"
131
+
132
+ #: Failure shapes this module distinguishes — the taxonomy #1998 asks for.
133
+ SHAPE_EMPTY = "empty"
134
+ SHAPE_TRUNCATED = "truncated"
135
+ SHAPE_MALFORMED_JSON = "malformed-json"
136
+ SHAPE_SCHEMA_DRIFT = "schema-drift"
137
+ SHAPE_NOT_JSON = "not-json"
138
+
139
+ #: The closed set of `shape` values `contract-failures.jsonl` can ever carry.
140
+ #: Kept here, not re-enumerated in prose, so `SKILL.md` and
141
+ #: `telemetry-schema.md` can be checked against one source of truth
142
+ #: (`repo_invariants.py::check_contract_failure_shapes_documented`).
143
+ FAILURE_SHAPES = frozenset(
144
+ {SHAPE_EMPTY, SHAPE_TRUNCATED, SHAPE_MALFORMED_JSON, SHAPE_SCHEMA_DRIFT, SHAPE_NOT_JSON}
145
+ )
146
+
147
+ #: The closed set of `extraction` values a *successful* validation can carry.
148
+ SUCCESS_SHAPES = frozenset({SHAPE_CLEAN, SHAPE_FENCED, SHAPE_PROSE_PREAMBLE})
149
+
150
+
151
+ def _now_iso() -> str:
152
+ return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
153
+
154
+
155
+ def _redact(text: str) -> str:
156
+ """Scrub secret-shaped substrings from ``text`` before any further
157
+ processing (including truncation) sees it — a secret straddling the
158
+ ``_RAW_PREFIX_LEN`` cut must still be caught, so redaction runs on the
159
+ full text first, never on the already-truncated slice."""
160
+ for pattern in _SECRET_PATTERNS:
161
+ text = pattern.sub("[REDACTED]", text)
162
+ return text
163
+
164
+
165
+ def _extract_fenced_json(text: str) -> str | None:
166
+ match = _FENCE_RE.search(text)
167
+ return match.group(1).strip() if match else None
168
+
169
+
170
+ def _advance_in_string(ch: str, escape: bool) -> tuple[bool, bool]:
171
+ """One character step of the in-string/escape state machine, given the
172
+ current character and whether the previous one was an unconsumed
173
+ backslash. Returns ``(still_in_string, escape)`` for the next character."""
174
+ if escape:
175
+ return True, False
176
+ if ch == "\\":
177
+ return True, True
178
+ if ch == '"':
179
+ return False, False
180
+ return True, False
181
+
182
+
183
+ def _scan_balanced(text: str, start: int) -> str | None:
184
+ """Scan forward from ``start`` (must index a ``{``), tracking string/escape
185
+ state so a brace inside a quoted string value doesn't corrupt depth
186
+ counting. Returns the balanced ``{...}`` substring, or ``None`` if depth
187
+ never returns to zero before EOF."""
188
+ depth = 0
189
+ in_string = False
190
+ escape = False
191
+ for i in range(start, len(text)):
192
+ ch = text[i]
193
+ if in_string:
194
+ in_string, escape = _advance_in_string(ch, escape)
195
+ continue
196
+ if ch == '"':
197
+ in_string = True
198
+ elif ch == "{":
199
+ depth += 1
200
+ elif ch == "}":
201
+ depth -= 1
202
+ if depth == 0:
203
+ return text[start : i + 1]
204
+ return None
205
+
206
+
207
+ def _find_first_json_object(text: str) -> tuple[str | None, bool]:
208
+ """Return ``(candidate, truncated)``: ``candidate`` is the first balanced
209
+ ``{...}`` substring in ``text``, tolerating leading/trailing prose, or
210
+ ``None`` if no starting ``{`` ever balances. Every ``{`` in ``text`` is
211
+ tried as a candidate start, not just the first — a ``{`` inside leading
212
+ prose (e.g. quoted code in a review lens's preamble sentence) that never
213
+ balances must not prevent recovery of a real, later JSON object; only
214
+ when *no* starting position balances does this report failure.
215
+ ``truncated`` is True only when at least one ``{`` was found but none of
216
+ them ever balanced back to depth zero before EOF — the
217
+ token-limit-truncation shape, distinguished here (by the same
218
+ string-aware scanner, not a separate naive brace count) rather than left
219
+ for a caller to re-derive."""
220
+ start = text.find("{")
221
+ saw_unbalanced = False
222
+ while start != -1:
223
+ candidate = _scan_balanced(text, start)
224
+ if candidate is not None:
225
+ return candidate, False
226
+ saw_unbalanced = True
227
+ start = text.find("{", start + 1)
228
+ return None, saw_unbalanced
229
+
230
+
231
+ def _validate_schema(parsed) -> str | None:
232
+ """Check a successfully-`json.loads`-ed value against the contract's
233
+ required shape. Deliberately permissive on optional fields (`category`
234
+ is documented optional; `confidence`/`file`/`line`/`suggestedFix` are not
235
+ re-validated here) — this function's job is to catch schema *drift*
236
+ (wrong status enum, missing issues array, unrecognized severity), not to
237
+ re-implement the full contract as a strict schema.
238
+
239
+ Returns the drift error string, or ``None`` when ``parsed`` satisfies the
240
+ contract.
241
+ """
242
+ if not isinstance(parsed, dict):
243
+ return f"top-level value is {type(parsed).__name__}, expected an object"
244
+ status = parsed.get("status")
245
+ if status not in _VALID_STATUSES:
246
+ return f"status={status!r} not one of {sorted(_VALID_STATUSES)}"
247
+ issues = parsed.get("issues")
248
+ if not isinstance(issues, list):
249
+ return "issues field missing or not an array"
250
+ for i, issue in enumerate(issues):
251
+ if not isinstance(issue, dict):
252
+ return f"issues[{i}] is not an object"
253
+ severity = issue.get("severity")
254
+ if severity not in _VALID_SEVERITIES:
255
+ return f"issues[{i}].severity={severity!r} not one of {sorted(_VALID_SEVERITIES)}"
256
+ if "summary" not in parsed:
257
+ return "summary field missing"
258
+ return None
259
+
260
+
261
+ def _success(shape: str) -> dict:
262
+ return {"valid": True, "shape": shape, "extraction": shape, "error": None}
263
+
264
+
265
+ def _schema_drift(extraction: str, error: str) -> dict:
266
+ return {"valid": False, "shape": SHAPE_SCHEMA_DRIFT, "extraction": extraction, "error": error}
267
+
268
+
269
+ def _failure(shape: str, extraction: str | None, error: str) -> dict:
270
+ return {"valid": False, "shape": shape, "extraction": extraction, "error": error}
271
+
272
+
273
+ def _try_parse(candidate: str, extraction: str) -> dict:
274
+ """Parse and validate a recovered JSON-shaped candidate. ``candidate`` is
275
+ always a complete text span (a fenced code block's contents, or a
276
+ balanced ``{...}`` substring) — a ``json.loads`` failure here means the
277
+ JSON is malformed, not truncated (truncation is decided earlier, by
278
+ whether a balanced candidate was found at all)."""
279
+ try:
280
+ parsed = json.loads(candidate)
281
+ except json.JSONDecodeError as exc:
282
+ return _failure(SHAPE_MALFORMED_JSON, extraction, str(exc))
283
+ error = _validate_schema(parsed)
284
+ return _success(extraction) if error is None else _schema_drift(extraction, error)
285
+
286
+
287
+ def classify_and_validate(raw_text: str) -> dict:
288
+ """Classify ``raw_text`` (an agent's raw final-turn text) against the
289
+ review-agent output contract.
290
+
291
+ Returns ``{"valid": bool, "shape": str, "extraction": str|None, "error":
292
+ str|None}``. Tries, in order: (1) a strict parse of the stripped text as
293
+ -is, (2) a fenced ```json code block, (3) the first balanced ``{...}``
294
+ object, tolerating a prose preamble or trailing prose. Each
295
+ successfully-recovered candidate is then checked against the contract's
296
+ required shape; a ``schema-drift`` or ``malformed-json`` failure carries
297
+ the ``extraction`` shape that recovered the candidate, rather than
298
+ discarding that information — including when the candidate came from a
299
+ fenced block that itself failed to parse (no further fallback is
300
+ attempted once a fence is found; a fence match requires a closing
301
+ delimiter, so its contents are a complete span, never a truncation). A
302
+ ``{`` that never balances (in the fenceless path) is reported as
303
+ ``truncated``; a balanced object that still fails to parse (unquoted
304
+ keys, a trailing comma, a Python-repr dict) is reported as
305
+ ``malformed-json`` — distinct from ``truncated``, since the output
306
+ finished, it just wasn't valid JSON.
307
+ """
308
+ stripped = raw_text.strip()
309
+ if not stripped:
310
+ return _failure(SHAPE_EMPTY, None, "output was empty or whitespace-only")
311
+
312
+ try:
313
+ parsed = json.loads(stripped)
314
+ except json.JSONDecodeError:
315
+ pass
316
+ else:
317
+ error = _validate_schema(parsed)
318
+ return _success(SHAPE_CLEAN) if error is None else _schema_drift(SHAPE_CLEAN, error)
319
+
320
+ fenced = _extract_fenced_json(stripped)
321
+ if fenced is not None:
322
+ return _try_parse(fenced, SHAPE_FENCED)
323
+
324
+ candidate, unbalanced = _find_first_json_object(stripped)
325
+ if candidate is not None:
326
+ extraction = SHAPE_CLEAN if candidate == stripped else SHAPE_PROSE_PREAMBLE
327
+ return _try_parse(candidate, extraction)
328
+
329
+ if unbalanced:
330
+ return _failure(SHAPE_TRUNCATED, None, "unbalanced braces — output likely truncated at a token limit")
331
+
332
+ return _failure(SHAPE_NOT_JSON, None, "no JSON object found in output")
333
+
334
+
335
+ def _resolve_stream(cwd: Path, *, migrate: bool = True) -> Path:
336
+ if artifact_paths is not None:
337
+ return artifact_paths.resolve_file("metrics", _STREAM_NAME, cwd, migrate=migrate)
338
+ return cwd / ".claude" / "metrics" / _STREAM_NAME
339
+
340
+
341
+ def _normalize_agent(agent: str) -> str:
342
+ """Strip this plugin's own `dev-team:` dispatch qualifier so this
343
+ stream's `agent` field matches `boundary-events.jsonl`'s `matched_rule`
344
+ vocabulary — the field `contract_failure_report.py` joins against.
345
+ Without this, an orchestrator passing the real dispatch form
346
+ (`dev-team:<agent-name>`) silently produces a phantom agent with 0
347
+ dispatches and inflates the reported total-failure rate (same class of
348
+ bug #1461 found in the ledger hook itself)."""
349
+ if review_agent_registry is not None:
350
+ return review_agent_registry.strip_plugin_prefix(agent)
351
+ return agent
352
+
353
+
354
+ def _safe_error(error: str) -> str:
355
+ """Redact and cap a diagnostic ``error`` string before it is persisted or
356
+ printed. `_validate_schema` interpolates agent-controlled values (e.g.
357
+ ``status={status!r}``) into this string, so — unlike a fixed-format
358
+ message — it can carry secret-shaped or unbounded content the same way
359
+ `raw_prefix` can; apply the same two controls here rather than leaving
360
+ this sibling field as the one channel that bypasses both."""
361
+ return _redact(str(error))[:_ERROR_MAX_LEN]
362
+
363
+
364
+ def build_failure_entry(agent: str, raw_text: str, diagnostic: dict, timestamp: str | None = None) -> dict:
365
+ """Assemble one `contract-failures.jsonl` row. ``diagnostic`` must be a
366
+ non-valid result from `classify_and_validate`."""
367
+ if diagnostic.get("valid") or diagnostic.get("shape") not in FAILURE_SHAPES:
368
+ raise ValueError(
369
+ f"build_failure_entry requires a failing classify_and_validate() result, got {diagnostic!r}"
370
+ )
371
+ redacted = _redact(raw_text.strip())
372
+ return {
373
+ "timestamp": timestamp or _now_iso(),
374
+ "agent": _normalize_agent(agent),
375
+ "shape": diagnostic["shape"],
376
+ "extraction": diagnostic.get("extraction"),
377
+ "error": _safe_error(diagnostic["error"]),
378
+ "raw_prefix": redacted[:_RAW_PREFIX_LEN],
379
+ }
380
+
381
+
382
+ def log_failure(entry: dict, cwd: Path | None = None) -> Path | None:
383
+ """Append one diagnostic row to `.claude/metrics/contract-failures.jsonl`.
384
+
385
+ Delegates to `atomic_state.append_line_locked` — the plugin's hardened,
386
+ symlink-safe, lock-serialized JSONL append (#1889) every other metrics
387
+ emitter in this plugin uses (`boundary_events.py`, `review_round_log.py`,
388
+ et al.) — rather than a bare `open(..., "a")`, which would reintroduce
389
+ the exact symlink-follow / unsynchronized-write gap #1889 closed
390
+ elsewhere. Passes `fail_open=False` so a write rejected inside the lock
391
+ (e.g. the O_NOFOLLOW check refusing a planted symlink) raises instead of
392
+ being silently swallowed there — this function's own `except Exception`
393
+ below is where fail-open is applied, so the swallowed case and the
394
+ successful case stay distinguishable and this docstring's contract
395
+ holds. A full disk or a read-only metrics directory must still never
396
+ fail a review. Returns the path written, or `None` when the write
397
+ failed or `hooks/lib` is unreachable.
398
+ """
399
+ try:
400
+ base = cwd or Path.cwd()
401
+ log = _resolve_stream(base)
402
+ log.parent.mkdir(parents=True, exist_ok=True)
403
+ line = json.dumps(entry, separators=(",", ":"), sort_keys=True) + "\n"
404
+ if atomic_state is not None:
405
+ atomic_state.append_line_locked(log, line, fail_open=False)
406
+ else: # pragma: no cover - degraded fallback, hooks/lib unreachable
407
+ with open(log, "a", encoding="utf-8") as handle:
408
+ handle.write(line)
409
+ return log
410
+ except Exception: # noqa: BLE001 - fail-open: telemetry never blocks a review
411
+ return None
412
+
413
+
414
+ def main(argv=None) -> int:
415
+ parser = argparse.ArgumentParser(description=__doc__)
416
+ parser.add_argument("--agent", required=True, help="Name of the review agent whose output is being validated")
417
+ parser.add_argument(
418
+ "--file",
419
+ required=True,
420
+ help="Path to the agent's raw final-turn text output; '-' for stdin",
421
+ )
422
+ parser.add_argument("--cwd", default=None)
423
+ parser.add_argument(
424
+ "--dry-run",
425
+ action="store_true",
426
+ help="Classify only; never write the failure diagnostic",
427
+ )
428
+ args = parser.parse_args(argv)
429
+
430
+ raw_text = sys.stdin.read() if args.file == "-" else Path(args.file).read_text(encoding="utf-8")
431
+ result = classify_and_validate(raw_text)
432
+
433
+ if not result["valid"] and not args.dry_run:
434
+ entry = build_failure_entry(args.agent, raw_text, result)
435
+ log_failure(entry, Path(args.cwd) if args.cwd else None)
436
+
437
+ printed = {"agent": _normalize_agent(args.agent), **result}
438
+ if not result["valid"]:
439
+ # SKILL.md step 4 carries this printed `error` forward, unmodified,
440
+ # into `dispatchFailures[].error` — sanitize it at the source so
441
+ # every downstream consumer (the report, the aggregate, the log)
442
+ # inherits the same redaction/cap `raw_prefix` gets, rather than
443
+ # relying on each consumer to re-apply it.
444
+ printed["error"] = _safe_error(result["error"])
445
+ print(json.dumps(printed, sort_keys=True))
446
+ return 0 if result["valid"] else 1
447
+
448
+
449
+ if __name__ == "__main__":
450
+ raise SystemExit(main(sys.argv[1:]))
451
+
452
+
453
+ __all__ = (
454
+ "FAILURE_SHAPES",
455
+ "SHAPE_CLEAN",
456
+ "SHAPE_EMPTY",
457
+ "SHAPE_FENCED",
458
+ "SHAPE_MALFORMED_JSON",
459
+ "SHAPE_NOT_JSON",
460
+ "SHAPE_PROSE_PREAMBLE",
461
+ "SHAPE_SCHEMA_DRIFT",
462
+ "SHAPE_TRUNCATED",
463
+ "SUCCESS_SHAPES",
464
+ "build_failure_entry",
465
+ "classify_and_validate",
466
+ "log_failure",
467
+ )
@@ -0,0 +1,205 @@
1
+ # Sliced large-repo review
2
+
3
+ Orchestration reference for `/code-review`'s large-repo path. `SKILL.md` routes
4
+ here when sliced mode engages (see its Scope-validation step); the deterministic
5
+ work is done by `scripts/partition.py`, `scripts/activation.py`,
6
+ `scripts/ledger.py`, and `scripts/consolidate.py` — all unit-tested
7
+ (partition/activation/consolidate as pure functions; ledger against a temp root).
8
+
9
+ The design keeps orchestrator context **flat regardless of repo size**: each
10
+ slice is reviewed, its findings persisted to disk, and then dropped from context
11
+ — only a one-line tally is retained. A final consolidation pass reads the
12
+ persisted artifacts back and produces one deduplicated report.
13
+
14
+ ## Terminology
15
+
16
+ **Slice** and **section** are the same unit. A *slice* is the in-flight review
17
+ unit; its persisted artifact on disk is `raw/section-<id>.json`, where `<id>` is
18
+ the slice id. An operator inspecting `.dev-team-reports/code-review/raw/` needs no
19
+ mental remapping — `section-<id>.json` is slice `<id>`.
20
+
21
+ ## When sliced mode engages (activation)
22
+
23
+ Call `scripts/activation.py` → `should_slice(scope_kind, file_count, threshold,
24
+ slice_flag, no_slice_flag)`. It returns `(engage, cap)` with this precedence:
25
+
26
+ 1. **`--no-slice`** always wins — never slice (legacy single pass).
27
+ 2. **`--slice <N>`** always engages, cap `N` (a positive integer), at any size.
28
+ 3. **Auto-engage** only when scope is full-repo **and** `file_count > threshold`
29
+ (the existing `>500` tier). Exactly at the threshold does not engage.
30
+ 4. Otherwise do not slice.
31
+
32
+ Non-full-repo scopes (`--path`, `--since`, auto-scoped uncommitted changes)
33
+ never auto-engage — they run the legacy path unchanged, no matter how many files
34
+ match.
35
+
36
+ On engagement, report the slice count to the operator (e.g. `Sliced mode: N
37
+ slices`).
38
+
39
+ ## Partitioning
40
+
41
+ Call `scripts/partition.py` → `partition_files(files, cap)`. Files are grouped by
42
+ directory (module boundary); a directory larger than `cap` splits across
43
+ consecutive slices; small sibling directories coalesce up to `cap`. Slice ids are
44
+ stable and deterministic — the same file set always partitions into the same ids
45
+ mapped to the same files, which is what makes `--resume` (below) safe.
46
+
47
+ After partitioning, call `activation.check_slice_ceiling(slice_count)`. When the
48
+ count is very high it returns an advisory warning suggesting a larger `--slice`
49
+ cap; report it and proceed (it never blocks).
50
+
51
+ ## Per-slice review panel
52
+
53
+ Select each slice's review panel from its `is_declarative` flag (set by
54
+ `partition.py` → `is_declarative_slice`, a conservative name/extension
55
+ heuristic — any doubt yields non-declarative):
56
+
57
+ - **Declarative slice** (`is_declarative: true` — pure interface/type/DTO/
58
+ constant/model/schema/enum files, no behavioral tokens): run the **reduced
59
+ panel** — `correctness-review` and `structure-review` only. The six-lens
60
+ semantic panel is wasted on declaration files.
61
+ - **Non-declarative slice**: run the **full panel** — the standard agent
62
+ eligibility rules from `SKILL.md` steps 3–4 (self-declared `Scope:`,
63
+ framework reactivity lens, ai-provenance), scoped to the slice's files.
64
+
65
+ The exact declarative rule is owned by `partition.py`; this file does not
66
+ re-encode it. **Disclose the panel per slice**: record which panel ran in the
67
+ slice's section artifact (see the next section), and the consolidated report
68
+ names the slices that ran the reduced panel so a reader can tell "fewer
69
+ findings" from "fewer reviewers ran."
70
+
71
+ **Wave-bound the panel dispatch (issue #1762).** Before dispatching either
72
+ panel (reduced or full), compute its wave split via `dispatch_waves.py` —
73
+ the same `maxParallel` resolution the legacy path uses
74
+ (`DEV_TEAM_MAX_PARALLEL_REVIEW_AGENTS`, default 10; see `SKILL.md` Step 4):
75
+
76
+ ```bash
77
+ sh "$CLAUDE_PLUGIN_ROOT/hooks/py.sh" "$CLAUDE_PLUGIN_ROOT/skills/code-review/scripts/dispatch_waves.py" --agents "<this slice's panel agent names, in order>"
78
+ ```
79
+
80
+ Dispatch one wave at a time, waiting for each wave to fully return before
81
+ dispatching the next — same discipline as the legacy path. A reduced panel
82
+ (2 agents) never exceeds a single wave at the default cap; a full panel can,
83
+ on a slice with many eligible lens/framework agents.
84
+
85
+ ## Persist-and-drop and the progress ledger
86
+
87
+ At the start of a sliced run, initialize the ledger from the partitioned slices:
88
+ `scripts/ledger.py` → `init_ledger(slices, cap, root)` writes
89
+ `.dev-team-reports/code-review/ledger.json` with every slice `pending` and the
90
+ partition cap recorded.
91
+
92
+ Review slices in **bounded parallelism — 2–3 slices at a time** (not the whole
93
+ repo at once). This slice-level concurrency heuristic is unchanged by the
94
+ panel-level wave cap above — the two bound different things: how many slices
95
+ are in flight at once, versus how many agents one slice's own panel dispatches
96
+ in a single message.
97
+
98
+ For each slice, once its panel's waves (per the section above) return:
99
+
100
+ 1. **Reconcile dispatched vs. returned, per wave**: determine each agent's
101
+ contract-valid status the same deterministic way as the legacy path
102
+ (`SKILL.md` Step 4's `validate_review_output.py` call, #1998) — never by
103
+ eyeballing the raw output — then feed the resulting `--returned` set to
104
+ `dispatch_reconcile.py`, the same CLI as the legacy path, scoped to this
105
+ slice's dispatched agents for that wave:
106
+ ```bash
107
+ sh "$CLAUDE_PLUGIN_ROOT/hooks/py.sh" "$CLAUDE_PLUGIN_ROOT/skills/code-review/scripts/dispatch_reconcile.py" --dispatched "<this wave's dispatched agent names>" --returned "<this wave's contract-valid agent names>"
108
+ ```
109
+ Every name in the resulting `"missing"` array is a dispatch failure for
110
+ this slice's current wave.
111
+ 2. **Retry once per agent**: retry each missing agent exactly once,
112
+ individually — same policy as `SKILL.md` Step 4, see there for rationale.
113
+ A recovered dispatch (fails once, retry succeeds) writes an empty
114
+ `dispatchFailures` list and emits no boundary event, mirroring the legacy
115
+ path's own guarantee. **Accumulate unrecovered failures across every wave
116
+ of this slice's panel** (a panel can span more than one wave when it's
117
+ larger than `maxParallel` — see the section above): a wave-1 failure is
118
+ never dropped just because wave 2 returned cleanly — carry the running
119
+ list forward and pass the union to step 3, once, after the slice's last
120
+ wave returns.
121
+ 3. **Persist** its findings: `write_section`'s CLI (`ledger.py write-section`)
122
+ writes `raw/section-<id>.json` (findings + the panel that ran) and flips
123
+ the slice's ledger status to `done`. Pass `--dispatch-failures` with the
124
+ slice's still-unrecovered failures, accumulated across all its waves —
125
+ an empty list (or the flag omitted) when every agent recovered on retry.
126
+ Each entry has the same shape as the legacy path's `dispatchFailures`
127
+ entries (`output-format.md`): `{"agentName": "<name>", "attempts": 2,
128
+ "error": "<message>", "shape": "<shape or null>", "extraction": "<extraction
129
+ or null>"}` — never a different key for the agent name.
130
+ 4. **Emit the boundary event for each unrecovered failure**: at the same
131
+ moment step 3 records the failure, emit the `dispatch-failure` boundary
132
+ event (Slice 1's shared CLI), bound to the `subject_hash` in effect for
133
+ that slice's dispatch (the cosmetic-delta carry-forward lens this used to
134
+ also bind a normalized hash for was specific to the retired commit-time
135
+ gate and was deleted in #1904 — sliced mode never wrote that gate file to
136
+ begin with, so the normalized hash never had a consumer on this path):
137
+ ```bash
138
+ HASH=$(python3 "${CLAUDE_PLUGIN_ROOT}/hooks/lib/review_gate_hash.py" --branch-diff)
139
+ python3 "${CLAUDE_PLUGIN_ROOT}/hooks/lib/boundary_events.py" --event dispatch-failure --agent "<name>" --subject-hash "$HASH"
140
+ ```
141
+ 5. **Drop** the findings from orchestrator context. **Retain only a one-line tally per slice** — e.g. `section-0001: 3 findings (1 error, 2 warnings)`. This
142
+ is the move that keeps context flat regardless of repo size: never hold more
143
+ than the tallies plus the slices currently in flight.
144
+ 6. **Report progress**: emit `slice k of N done` as each slice completes, so a
145
+ long monorepo run is observably advancing.
146
+
147
+ If the run is interrupted, the ledger and the already-written section artifacts
148
+ remain on disk and stay valid. Tell the operator the review is incomplete and
149
+ can be continued: **rerun with `--resume`** to review only the remaining slices.
150
+
151
+ ## Resuming an interrupted run
152
+
153
+ When `--resume` is given, do **not** re-initialize the ledger. Instead:
154
+
155
+ 1. **Guard the cap**: call `ledger.py` → `check_resume_cap(root, cap)`. If the
156
+ `--slice` cap differs from the cap the interrupted run recorded in the
157
+ ledger, **stop with that error** — repartitioning at a different cap would
158
+ desync the new slice ids from the `section-<id>.json` files already on disk.
159
+ Rerun with the recorded cap (or no `--slice`), or start fresh.
160
+ 2. **Review only the pending slices**: `pending_slices(slices, root)` returns
161
+ the slices needing (re-)review. A slice whose `section-<id>.json` does not
162
+ yet exist is pending, same as before — **and, as of issue #1762, a slice
163
+ whose artifact already exists but carries a non-empty `dispatchFailures`
164
+ list is also pending**: it is **not** treated as done on `--resume`; its
165
+ panel is re-dispatched, same as a slice with no artifact at all, so the
166
+ previously-failed agent(s) get a real chance to produce a superseding
167
+ result, per the retry-once policy in `SKILL.md`'s "Dispatch failure
168
+ handling" (Step 4) — see there for the full mechanics, not restated here.
169
+ Every other slice keeps today's rule unchanged: an artifact
170
+ exists with an empty `dispatchFailures` list is skipped and reused as-is
171
+ — disk is the source of truth (a slice with a clean artifact is done even
172
+ if the ledger still says `pending`).
173
+ 3. Consolidation (below) reads **all** section artifacts — the ones reused from
174
+ the prior run and the ones this resume produced.
175
+
176
+ Without `--resume`, a fresh sliced run re-initializes the ledger and reviews
177
+ every slice.
178
+
179
+ ## Consolidation
180
+
181
+ Once every slice has a section artifact (a fresh run's full set, or a
182
+ `--resume` run's reused + newly-written set), consolidate:
183
+
184
+ 1. Run `scripts/consolidate.py` (its `main()` reads every
185
+ `raw/section-*.json`) → the consolidated aggregate (schema in
186
+ [`output-format.md`](output-format.md#consolidated-aggregate-sliced-mode)):
187
+ findings **deduped by `file:line`** with reporting agents merged, a
188
+ **recurring-theme rollup** (dimensions recurring across ≥2 slices), and the
189
+ `reducedPanelSlices` disclosure. A malformed artifact is reported by name,
190
+ never silently dropped.
191
+ 2. Apply `ACCEPTED-RISKS.md` at this consolidation step exactly as the
192
+ legacy path does (SKILL.md step 5a) — suppression happens once, over the
193
+ merged findings.
194
+
195
+ **Report-only.** Sliced mode does **not** run the interactive review-fix loop.
196
+ It is a reporting/consolidation pass:
197
+
198
+ - Write the consolidated prose report to `.dev-team-reports/code-review.md` and
199
+ per-issue correction prompts to `./corrections/` (for `/apply-fixes` to act
200
+ on later). Both paths are repo-relative to the target repo's working
201
+ directory.
202
+ - In `--json` mode, emit the single consolidated aggregate object to **stdout**
203
+ and write **no** file — the existing `--json` contract (SKILL.md step 7),
204
+ now carrying the consolidated `topFindings` / `recurringThemes` /
205
+ `reducedPanelSlices`.