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,141 @@
1
+ #!/usr/bin/env python3
2
+ """Compute a changed-file list with git change-type (#1734).
3
+
4
+ `arch-review` (and every other `Context needs: project-structure` lens —
5
+ `doc-review`, `domain-review`) has no Bash grant, yet its dispatch payload
6
+ today is only "full files + directory tree". Nothing stops the agent from
7
+ reasoning that it should "see what changed" and attempting `git diff` itself
8
+ — a call it does not have, denied, and surfaced as a spurious error in its
9
+ report. The fix is not a new tool grant (that would be a first-of-its-kind
10
+ precedent for a review agent); it is completing the payload the orchestrator
11
+ already has the data for: a changed/added/removed file list alongside the
12
+ full files and tree.
13
+
14
+ This module is that data, computed once from `git diff --name-status` output
15
+ so `/code-review` never invents it twice: `SKILL.md` step 4 feeds it into the
16
+ `project-structure` context payload, and step 3 feeds its `added` list into
17
+ `select_lenses.py`'s `--added-from` flag for `component-architecture-review`'s
18
+ added-only `Scope:` gate (#1733) — one changed-file computation, two
19
+ consumers, not two ways to derive the same fact.
20
+
21
+ **A skipped line narrows, it does not widen.** A line this module cannot
22
+ parse (wrong field count, empty path) is skipped rather than guessed, never
23
+ fabricated — but for the added-only `Scope:` gate that consumes this
24
+ module's `added` list, dropping a genuinely-added path *removes* it from
25
+ `added` while it still reaches `select_lenses.py` independently via
26
+ `--files`, so the gate's `f in added_files` membership test then excludes
27
+ that lens rather than including it. A parse skip is a missed narrowing
28
+ *result* (the lens is lost, not kept) — do not read it as fail-open the way
29
+ this module's caller (`select_lenses.py`) is fail-open for a missing
30
+ `Scope:` declaration; the two failure directions are opposite.
31
+
32
+ **Only `status == "A"` counts as added — renames and copies do not.** A
33
+ rename (`R`) or copy (`C`) produces a path that did not previously exist,
34
+ but it carries no new content to assess (a rename) or duplicates content
35
+ already reviewed elsewhere (a copy, and only reachable at all when a caller
36
+ passes `-C`/`--find-copies`, which none of this module's callers do today).
37
+ This is a deliberate, narrow choice, not an oversight — widen it (e.g.
38
+ `status in ("A", "C")`) only with a test pinning the new behavior.
39
+
40
+ **Known limitation: a path git C-quotes is stored quoted, not unquoted.**
41
+ Git always quotes a control character (including an embedded newline) or a
42
+ literal backslash/double-quote in a path — regardless of `core.quotePath` —
43
+ by wrapping it in `"..."` with C-style escapes (verified empirically: a file
44
+ literally named with an embedded newline round-trips through `git diff
45
+ --name-status` as the single line `"a\nb.txt"`, quotes included). This
46
+ module does not strip that quoting, so such a path reaches `select_lenses.py`
47
+ still wrapped in `"..."`, and its `_matches()` suffix check (`.endswith(...)`)
48
+ then fails against every glob — the file is invisible to every non-`always`
49
+ lens. Narrow in practice (control characters in filenames are rare) and not
50
+ a regression this module introduces (the pre-existing `--name-only` listing
51
+ step 1 uses has the identical exposure); fixing it needs a C-quote-aware
52
+ unquote step here, not attempted in this pass.
53
+
54
+ Pure policy except for the one I/O boundary in `main()` (reading
55
+ `--name-status-from <file>`, guarded against a missing/unreadable path).
56
+ Stdlib-only. See docs/python-hook-contract.md.
57
+ """
58
+
59
+ from __future__ import annotations
60
+
61
+ import argparse
62
+ import json
63
+ import sys
64
+ from collections.abc import Iterable
65
+
66
+
67
+ def parse_name_status(lines: Iterable[str]) -> list[dict]:
68
+ """Parse `git diff --name-status` lines into `[{"path", "status"}, ...]`.
69
+
70
+ Each line is `<status>\\t<path>`, or for a rename/copy
71
+ `<status>\\t<old-path>\\t<new-path>` — the last field is always the
72
+ current path, which is what every consumer here cares about. `status` is
73
+ normalized to its leading letter (`R100` -> `R`) so callers compare
74
+ against `A`/`M`/`D`/`R`/`C` without parsing similarity percentages.
75
+ Unparseable lines are skipped, never raised on and never guessed.
76
+ """
77
+ files: list[dict] = []
78
+ for raw in lines:
79
+ line = raw.rstrip("\n")
80
+ if not line.strip():
81
+ continue
82
+ parts = line.split("\t")
83
+ if len(parts) < 2:
84
+ continue
85
+ status_field = parts[0].strip()
86
+ path = parts[-1].strip()
87
+ if not status_field or not path:
88
+ continue
89
+ files.append({"path": path, "status": status_field[0]})
90
+ return files
91
+
92
+
93
+ def evaluate(lines: Iterable[str]) -> dict:
94
+ """Evaluate `git diff --name-status` lines into the full result dict."""
95
+ files = parse_name_status(lines)
96
+ return {
97
+ "files": files,
98
+ "added": [f["path"] for f in files if f["status"] == "A"],
99
+ }
100
+
101
+
102
+ def main(argv=None) -> int:
103
+ parser = argparse.ArgumentParser(description=__doc__)
104
+ parser.add_argument(
105
+ "--name-status", nargs="*", default=[],
106
+ help="git diff --name-status lines, one per arg (space-separated)",
107
+ )
108
+ parser.add_argument(
109
+ "--name-status-from", default=None,
110
+ help="read newline-separated name-status lines from this file ('-' for stdin)",
111
+ )
112
+ args = parser.parse_args(argv)
113
+
114
+ lines = list(args.name_status)
115
+ if args.name_status_from:
116
+ try:
117
+ if args.name_status_from == "-":
118
+ text = sys.stdin.read()
119
+ else:
120
+ with open(args.name_status_from) as handle:
121
+ text = handle.read()
122
+ except (OSError, ValueError):
123
+ # Missing/unreadable path, closed stdin, or undecodable bytes:
124
+ # contribute no lines rather than crash the whole invocation —
125
+ # consistent with every other unparseable-input case in this
126
+ # module. `ValueError` also covers `UnicodeDecodeError` (a
127
+ # subclass), reachable here because SKILL.md's caller mandates
128
+ # `-c core.quotePath=false`, which makes git emit raw path bytes
129
+ # instead of escaped octal for a non-ASCII path.
130
+ text = ""
131
+ lines.extend(line for line in text.splitlines() if line.strip())
132
+
133
+ print(json.dumps(evaluate(lines), sort_keys=True))
134
+ return 0
135
+
136
+
137
+ if __name__ == "__main__":
138
+ raise SystemExit(main(sys.argv[1:]))
139
+
140
+
141
+ __all__ = ("evaluate", "parse_name_status")
@@ -0,0 +1,187 @@
1
+ #!/usr/bin/env python3
2
+ """Closing-pass composition for `/code-review`'s fix loop (#1626).
3
+
4
+ `/code-review` step 6a used to mandate: after ANY fix-loop iteration ran,
5
+ re-dispatch the **full** original agent panel once more against the final
6
+ staged content. The reason was structural, not editorial — the pre-commit
7
+ gate (#1461) needed `>= 2` distinct dispatches whose `subject_hash` equals the
8
+ FINAL staged hash, and the loop's targeted re-dispatches only cover the
9
+ agents that happened to have findings. So a one-line fix re-triggered an
10
+ 18-agent panel. That is the single biggest cost multiplier in the loop, and
11
+ #1619 paid it repeatedly.
12
+
13
+ This module computes the **closing pass** instead: the minimal dispatch set
14
+ that preserves both properties the full re-panel was defending.
15
+
16
+ ## The two properties, and how each is preserved
17
+
18
+ 1. **The gate's corroboration floor, satisfied by construction.**
19
+ `hooks/pre_pr_review.py`'s `_MIN_DISTINCT_DISPATCHES` is 1 (#2147; lowered
20
+ from 2 — a single `/code-review` dispatch already runs a full panel
21
+ internally, so a second top-level dispatch was never additional
22
+ corroboration). The composition rule below tops up from the resolver's
23
+ eligible roster until at least that many distinct registered agents
24
+ dispatch at the final hash. No hook change, no exemption event, no ledger
25
+ change — the floor is met the same way it is met today, just with 1-2
26
+ dispatches instead of 18 (previously 2-3, under the old floor of 2).
27
+
28
+ 2. **Not a rubber stamp.** Closing-pass agents keep full review authority:
29
+ any actionable finding re-enters the fix loop exactly as before (subject
30
+ to #1625's round cap). What changes is *how many* agents re-read *how
31
+ much* content — never whether their findings count. A pass whose findings
32
+ carried no consequence would be exactly the "dispatch trivial calls purely
33
+ to clear the gate" abuse `pre_commit_review.py`'s own docstring names.
34
+
35
+ ## Scope: the fix delta, not the whole changeset
36
+
37
+ The round-1 panel already reviewed the full changeset. Only the *fix delta*
38
+ — what changed between what the panel reviewed and the final staged content
39
+ — is unreviewed. The closing pass reviews that delta.
40
+
41
+ **Escape hatch.** If the fix delta touches files the original panel never
42
+ targeted, scope grew mid-loop and the delta-only argument no longer holds:
43
+ fall back to the full re-dispatch over the whole changeset. That condition is
44
+ a deterministic set-comparison of two file lists, checked here rather than
45
+ judged in prose.
46
+
47
+ Stdlib-only. See docs/python-hook-contract.md.
48
+ """
49
+
50
+ from __future__ import annotations
51
+
52
+ import argparse
53
+ import json
54
+ import sys
55
+ from pathlib import Path
56
+
57
+ #: Mirrors `hooks/pre_pr_review.py`'s `_MIN_DISTINCT_DISPATCHES`. Kept as
58
+ #: a named constant here (rather than imported) because this script must not
59
+ #: depend on the hook package to compute a dispatch plan; the drift test in
60
+ #: `plugins/dev-team/tests/scripts/test_closing_pass.py` asserts the two stay
61
+ #: equal, so a future change to the gate's floor fails a test rather than
62
+ #: silently under-composing the closing pass.
63
+ MIN_DISTINCT_DISPATCHES = 1
64
+
65
+
66
+ def _normalize(path) -> str:
67
+ text = str(path or "").replace("\\", "/")
68
+ while text.startswith("./"):
69
+ text = text[2:]
70
+ return text
71
+
72
+
73
+ def scope_grew(panel_files, fix_delta_files) -> bool:
74
+ """True when the fix delta touches a file the original panel never
75
+ targeted — the escape-hatch condition. A pure set comparison."""
76
+ panel = {_normalize(p) for p in panel_files if str(p or "").strip()}
77
+ delta = {_normalize(p) for p in fix_delta_files if str(p or "").strip()}
78
+ return not delta.issubset(panel)
79
+
80
+
81
+ def compose(
82
+ fixed_by_agents,
83
+ eligible_roster,
84
+ panel_agents,
85
+ panel_files=(),
86
+ fix_delta_files=(),
87
+ minimum: int = MIN_DISTINCT_DISPATCHES,
88
+ ) -> dict:
89
+ """Compute the closing-pass dispatch plan.
90
+
91
+ Args:
92
+ fixed_by_agents: agents whose findings were fixed during the loop.
93
+ Each verifies its own fixes at the final hash.
94
+ eligible_roster: the resolver's eligible lenses in `select_lenses.py`
95
+ order — cheap-first (non-opus before opus). Top-ups are taken
96
+ from the front, so a top-up never reaches for an opus lens while
97
+ a cheaper eligible one is available.
98
+ panel_agents: the full round-1 panel, used only by the escape hatch.
99
+ panel_files / fix_delta_files: drive `scope_grew`.
100
+ minimum: the gate's distinct-dispatch floor.
101
+
102
+ Returns `{"agents", "scope", "escape_hatch", "reason", "topped_up"}`.
103
+ `scope` is `fix-delta` normally, `full-changeset` under the escape hatch.
104
+ """
105
+ fixed = _dedupe(fixed_by_agents)
106
+ roster = _dedupe(eligible_roster)
107
+ panel = _dedupe(panel_agents)
108
+
109
+ if scope_grew(panel_files, fix_delta_files):
110
+ return {
111
+ "agents": panel or roster,
112
+ "scope": "full-changeset",
113
+ "escape_hatch": True,
114
+ "reason": "fix-delta-touched-files-outside-the-panel-target-set",
115
+ "topped_up": [],
116
+ }
117
+
118
+ agents = list(fixed)
119
+ topped_up = []
120
+ for candidate in roster:
121
+ if len(agents) >= minimum:
122
+ break
123
+ if candidate not in agents:
124
+ agents.append(candidate)
125
+ topped_up.append(candidate)
126
+
127
+ reason = None
128
+ if len(agents) < minimum:
129
+ # The eligible roster itself cannot supply the floor (a tiny or
130
+ # heavily-filtered roster). Say so explicitly rather than emitting a
131
+ # plan that will fail the gate for reasons the operator can't see.
132
+ reason = "eligible-roster-smaller-than-gate-floor"
133
+
134
+ return {
135
+ "agents": agents,
136
+ "scope": "fix-delta",
137
+ "escape_hatch": False,
138
+ "reason": reason,
139
+ "topped_up": topped_up,
140
+ }
141
+
142
+
143
+ def _dedupe(values) -> list:
144
+ seen, out = set(), []
145
+ for value in values or ():
146
+ name = str(value or "").strip()
147
+ if name and name not in seen:
148
+ seen.add(name)
149
+ out.append(name)
150
+ return out
151
+
152
+
153
+ def _load_list(value: str | None) -> list:
154
+ """Accept either a comma-separated inline list or `@path` to a JSON file
155
+ holding a list (or `{"lenses": [...]}`, matching `select_lenses.py`)."""
156
+ if not value:
157
+ return []
158
+ if value.startswith("@"):
159
+ data = json.loads(Path(value[1:]).read_text(encoding="utf-8"))
160
+ if isinstance(data, dict):
161
+ data = data.get("lenses", data.get("agents", []))
162
+ return list(data) if isinstance(data, list) else []
163
+ return [v.strip() for v in value.split(",") if v.strip()]
164
+
165
+
166
+ def main(argv=None) -> int:
167
+ parser = argparse.ArgumentParser(description="Compose the /code-review closing pass.")
168
+ parser.add_argument("--fixed-by", default="", help="Agents whose findings were fixed")
169
+ parser.add_argument("--roster", default="", help="Eligible roster, cheap-first (or @file.json)")
170
+ parser.add_argument("--panel", default="", help="The full round-1 panel (or @file.json)")
171
+ parser.add_argument("--panel-files", default="", help="Files the round-1 panel targeted")
172
+ parser.add_argument("--fix-delta-files", default="", help="Files the cumulative fix touched")
173
+ args = parser.parse_args(argv)
174
+
175
+ plan = compose(
176
+ _load_list(args.fixed_by),
177
+ _load_list(args.roster),
178
+ _load_list(args.panel),
179
+ _load_list(args.panel_files),
180
+ _load_list(args.fix_delta_files),
181
+ )
182
+ print(json.dumps(plan, sort_keys=True))
183
+ return 0
184
+
185
+
186
+ if __name__ == "__main__":
187
+ raise SystemExit(main(sys.argv[1:]))
@@ -0,0 +1,277 @@
1
+ #!/usr/bin/env python3
2
+ """Consolidate per-slice section artifacts into one deduplicated report.
3
+
4
+ Split into a **pure** ``consolidate(sections)`` (takes a list of section dicts,
5
+ returns the aggregated object) and a thin ``main()`` that reads
6
+ ``.dev-team-reports/code-review/raw/section-*.json`` and calls it — the same
7
+ main-wraps-pure convention as ``check_version_drift.py``/``lesson_validate.py``,
8
+ so the aggregation logic is unit-tested with plain dicts and no filesystem.
9
+
10
+ Consolidation:
11
+ - Dedupe findings by ``file:line`` — one entry, reporting agents merged into an
12
+ ``agents[]`` array, severity = the single highest enum (per SKILL.md step 5c).
13
+ - Recurring-theme rollup — a review dimension (agent) whose findings recur across
14
+ two or more slices, so a systemic pattern surfaces above per-slice noise.
15
+ - Disclose which slices ran the reduced (declarative) panel.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import argparse
21
+ import glob
22
+ import json
23
+ import sys
24
+ from pathlib import Path
25
+
26
+ # Reach the sibling ledger.py regardless of cwd or sys.path mode (matches the
27
+ # house pattern in change_shape.py/codebase_recon.py for reaching a sibling
28
+ # module rather than relying on the implicit sys.path[0] a direct script
29
+ # invocation provides).
30
+ _HERE = Path(__file__).resolve().parent
31
+ if str(_HERE) not in sys.path:
32
+ sys.path.insert(0, str(_HERE))
33
+
34
+ from ledger import raw_dir
35
+
36
+ # Single source of truth for the severity vocabulary (step 5c's ranking lived
37
+ # only in prose before): each severity's rank (for highest-wins merge and
38
+ # sorting) and its totals bucket key.
39
+ _SEVERITY = {
40
+ "suggestion": (1, "suggestions"),
41
+ "warning": (2, "warnings"),
42
+ "error": (3, "errors"),
43
+ }
44
+ _DEFAULT_SEVERITY = "suggestion"
45
+
46
+ # A review dimension recurring across at least this many slices is a theme.
47
+ _THEME_MIN_SLICES = 2
48
+
49
+ # Real-world review-agent output drifts from the documented schema (#1261): some
50
+ # agents return their findings list under `issues` (the per-agent key in
51
+ # output-format.md) instead of `findings` (the section-artifact key). Accept
52
+ # either so a mis-keyed list is aggregated, never silently counted as zero. The
53
+ # canonical key is tried first; the alias is a fallback.
54
+ _FINDINGS_KEYS = ("findings", "issues")
55
+
56
+
57
+ def _rank(severity: str) -> int:
58
+ return _SEVERITY.get(severity, (0, ""))[0]
59
+
60
+
61
+ def _bucket(severity: str) -> str:
62
+ return _SEVERITY.get(severity, _SEVERITY[_DEFAULT_SEVERITY])[1]
63
+
64
+
65
+ def _findings_of(container: dict) -> list:
66
+ """Return the findings list from ``container`` tolerating key drift (#1261).
67
+
68
+ Prefers ``findings`` (section-artifact key), falls back to ``issues``
69
+ (per-agent key). A value that is present but not a list is treated as no
70
+ findings rather than crashing the aggregation.
71
+ """
72
+ for key in _FINDINGS_KEYS:
73
+ value = container.get(key)
74
+ if isinstance(value, list):
75
+ return value
76
+ return []
77
+
78
+
79
+ def normalize_agent_result(raw: dict, agent_name: str | None = None) -> list:
80
+ """Coerce one review agent's result into a flat, ``agent``-tagged findings list.
81
+
82
+ Absorbs the schema drift observed in real runs (#1261): the native per-agent
83
+ ``{status, issues, summary}`` shape, findings keyed as ``issues`` **or**
84
+ ``findings``, and any extra top-level keys (e.g. ``summary``) — all of which
85
+ are ignored except the findings list. Each returned finding is tagged with
86
+ its reporting ``agent`` (from ``raw["agentName"]``, else ``agent_name``) so
87
+ ``consolidate()`` can merge reporters per ``file:line`` and roll up themes.
88
+
89
+ Non-dict input, or a findings entry that is not a dict, yields an empty list
90
+ / is skipped — this never raises, so a malformed agent result degrades to
91
+ "reported nothing" rather than aborting the whole aggregation.
92
+ """
93
+ if not isinstance(raw, dict):
94
+ return []
95
+ agent = raw.get("agentName") or agent_name
96
+ out = []
97
+ for finding in _findings_of(raw):
98
+ if not isinstance(finding, dict):
99
+ continue
100
+ tagged = dict(finding)
101
+ tagged.setdefault("agent", agent)
102
+ out.append(tagged)
103
+ return out
104
+
105
+
106
+ def _dedupe_key(finding: dict):
107
+ return (finding.get("file"), finding.get("line"))
108
+
109
+
110
+ def _sorted_ids(ids) -> list:
111
+ """Return the non-None ids, sorted — the shared 'sorted, None-filtered' idiom."""
112
+ return sorted(s for s in ids if s is not None)
113
+
114
+
115
+ def _merge_finding(merged: dict, order: list, finding: dict) -> None:
116
+ """Insert ``finding`` into the ``file:line`` dedup map, or merge it into the
117
+ existing entry: highest severity wins and keeps its message; reporting agents
118
+ accumulate into ``agents[]`` without duplicates.
119
+ """
120
+ key = _dedupe_key(finding)
121
+ agent = finding.get("agent")
122
+ severity = finding.get("severity", _DEFAULT_SEVERITY)
123
+ entry = merged.get(key)
124
+ if entry is None:
125
+ order.append(key)
126
+ merged[key] = {
127
+ "severity": severity,
128
+ "agents": [agent] if agent else [],
129
+ "file": finding.get("file"),
130
+ "line": finding.get("line"),
131
+ "message": finding.get("message"),
132
+ }
133
+ return
134
+ if _rank(severity) > _rank(entry["severity"]):
135
+ entry["severity"] = severity
136
+ entry["message"] = finding.get("message")
137
+ if agent and agent not in entry["agents"]:
138
+ entry["agents"].append(agent)
139
+
140
+
141
+ def _tally_severity(totals: dict, severity: str) -> None:
142
+ totals[_bucket(severity)] += 1
143
+
144
+
145
+ def _tally_theme(theme_slices: dict, theme_counts: dict, agent: str | None, slice_id) -> None:
146
+ """Record one finding's contribution to the recurring-theme rollup for ``agent``."""
147
+ if agent is None:
148
+ return
149
+ theme_slices.setdefault(agent, set()).add(slice_id)
150
+ theme_counts[agent] = theme_counts.get(agent, 0) + 1
151
+
152
+
153
+ def consolidate(sections: list[dict]) -> dict:
154
+ """Aggregate ``sections`` into the consolidated report object.
155
+
156
+ ``sections`` is a list of per-slice artifacts (``id``/``files``/
157
+ ``is_declarative``/``panel``/``findings``). Findings carry the usual
158
+ ``severity``/``file``/``line``/``message`` and an optional ``agent`` naming
159
+ the reporting review dimension. Returns the aggregated object; an empty input
160
+ yields an empty (but well-formed) aggregate.
161
+ """
162
+ merged: dict = {} # (file, line) -> consolidated finding
163
+ order: list = [] # first-seen order of keys, for stable output
164
+ theme_slices: dict = {} # agent -> set of slice ids
165
+ theme_counts: dict = {} # agent -> total findings
166
+ reduced_panel_slices: list = []
167
+ dispatch_failures: list = []
168
+ totals = {"errors": 0, "warnings": 0, "suggestions": 0}
169
+
170
+ for section in sections:
171
+ slice_id = section.get("id")
172
+ if section.get("is_declarative"):
173
+ reduced_panel_slices.append(slice_id)
174
+ section_dispatch_failures = section.get("dispatchFailures")
175
+ if isinstance(section_dispatch_failures, list):
176
+ dispatch_failures.extend(section_dispatch_failures)
177
+ for finding in _findings_of(section):
178
+ severity = finding.get("severity", _DEFAULT_SEVERITY)
179
+ _tally_severity(totals, severity)
180
+ _tally_theme(theme_slices, theme_counts, finding.get("agent"), slice_id)
181
+ _merge_finding(merged, order, finding)
182
+
183
+ top_findings = [merged[k] for k in order]
184
+ top_findings.sort(key=lambda f: (-_rank(f["severity"]), str(f["file"]), f["line"] or 0))
185
+
186
+ recurring_themes = [
187
+ {"agent": agent, "slices": _sorted_ids(slices), "occurrences": theme_counts[agent]}
188
+ for agent, slices in theme_slices.items()
189
+ if len(slices) >= _THEME_MIN_SLICES
190
+ ]
191
+ recurring_themes.sort(key=lambda t: (-t["occurrences"], t["agent"]))
192
+
193
+ overall = "fail" if totals["errors"] else "warn" if totals["warnings"] else "pass"
194
+ # A non-empty dispatchFailures forces overall: fail, unconditionally — applied
195
+ # after the totals-based computation above so it always wins, mirroring the
196
+ # legacy (non-sliced) path's own unconditional-override rule.
197
+ if dispatch_failures:
198
+ overall = "fail"
199
+
200
+ return {
201
+ "sliced": True,
202
+ "sliceCount": len(sections),
203
+ "overall": overall,
204
+ "totals": totals,
205
+ "topFindings": top_findings,
206
+ "recurringThemes": recurring_themes,
207
+ "reducedPanelSlices": _sorted_ids(reduced_panel_slices),
208
+ "dispatchFailures": dispatch_failures,
209
+ "summary": (
210
+ f"{overall.upper()} across {len(sections)} slices — "
211
+ f"{totals['errors']} errors, {totals['warnings']} warnings, "
212
+ f"{totals['suggestions']} suggestions; "
213
+ f"{len(recurring_themes)} recurring theme(s)."
214
+ ),
215
+ }
216
+
217
+
218
+ def _read_sections(root: str) -> tuple[list, list]:
219
+ """Read every ``raw/section-*.json`` under ``root``.
220
+
221
+ Returns ``(sections, malformed_paths)``. A malformed artifact is collected
222
+ into ``malformed_paths`` (reported by the caller), never silently dropped.
223
+ """
224
+ sections, malformed = [], []
225
+ for path in sorted(glob.glob(str(raw_dir(root) / "section-*.json"))):
226
+ try:
227
+ obj = json.loads(Path(path).read_text())
228
+ except (json.JSONDecodeError, OSError):
229
+ malformed.append(path)
230
+ continue
231
+ # Valid JSON of the wrong shape (list, string, ...) is malformed too —
232
+ # otherwise it would crash consolidate() at section.get(...).
233
+ if not isinstance(obj, dict):
234
+ malformed.append(path)
235
+ continue
236
+ sections.append(obj)
237
+ return sections, malformed
238
+
239
+
240
+ def main(argv: list[str] | None = None) -> int:
241
+ parser = argparse.ArgumentParser(description=__doc__)
242
+ parser.add_argument("--root", default=".")
243
+ args = parser.parse_args(argv)
244
+
245
+ sections, malformed = _read_sections(args.root)
246
+ for path in malformed:
247
+ print(f"WARNING: malformed section artifact skipped: {path}", file=sys.stderr)
248
+
249
+ result = consolidate(sections)
250
+ if malformed:
251
+ result["malformedArtifacts"] = malformed
252
+ # A malformed artifact means that slice's findings were never read —
253
+ # the identical coverage gap `dispatchFailures` forces `overall`
254
+ # to "fail" for a few lines up in consolidate(), and for the same
255
+ # reason: an unexamined slice must never ride out as "pass" just
256
+ # because the READABLE sections happened to look clean (#1763
257
+ # security review — /pr --json checks only overall/status). The
258
+ # `summary` string is rebuilt too (#1865) — it must not interpolate
259
+ # the PRE-override `result['summary']` (built from `overall` INSIDE
260
+ # consolidate(), before this override runs): doing so would print a
261
+ # "FAIL ... ; WARN ..." self-contradicting summary. Rebuild it
262
+ # entirely from the already-available totals/recurringThemes instead.
263
+ result["overall"] = "fail"
264
+ totals = result["totals"]
265
+ result["summary"] = (
266
+ f"FAIL across {len(sections)} slices — {len(malformed)} malformed "
267
+ f"artifact(s) unreadable; {totals['errors']} errors, {totals['warnings']} warnings, "
268
+ f"{totals['suggestions']} suggestions from readable slices; "
269
+ f"{len(result['recurringThemes'])} recurring theme(s)."
270
+ )
271
+ print(json.dumps(result, indent=2, sort_keys=True))
272
+ # Non-zero exit if any artifact was unreadable, so a caller notices.
273
+ return 2 if malformed else 0
274
+
275
+
276
+ if __name__ == "__main__":
277
+ raise SystemExit(main(sys.argv[1:]))