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,446 @@
1
+ #!/usr/bin/env python3
2
+ """deterministic_recon — structural reconnaissance without LLM.
3
+
4
+ The deterministic half of `codebase_recon.py` (this file's sibling one
5
+ directory up): produces a recon envelope conforming (approximately) to
6
+ `../../knowledge/schemas/recon-envelope-v1.json` by running file-system and
7
+ grep-based heuristics. It covers the structural fields (repo metadata,
8
+ languages, entry points, security surface by grep) but produces empty
9
+ `architecture.notable_anti_patterns` and thin prose in `architecture.summary`
10
+ since those need reasoning — `codebase_recon.py` fills that gap with an
11
+ optional LLM step (`claude -p`) layered on top of this module's output.
12
+
13
+ Usage:
14
+ python3 ${CLAUDE_PLUGIN_ROOT}/scripts/lib/deterministic_recon.py <target-path> [<output-json>]
15
+
16
+ Emits JSON to stdout (or to <output-json> if given).
17
+ """
18
+ from __future__ import annotations
19
+
20
+ import json
21
+ import re
22
+ import subprocess
23
+ import sys
24
+ from collections import Counter
25
+ from datetime import datetime, timezone
26
+ from pathlib import Path
27
+ from typing import Any
28
+
29
+ LANGUAGE_BY_EXT = {
30
+ ".py": "Python", ".js": "JavaScript", ".jsx": "JavaScript",
31
+ ".ts": "TypeScript", ".tsx": "TypeScript", ".go": "Go",
32
+ ".java": "Java", ".kt": "Kotlin", ".rb": "Ruby",
33
+ ".rs": "Rust", ".php": "PHP", ".cs": "C#", ".scala": "Scala",
34
+ ".swift": "Swift", ".sh": "Shell", ".bash": "Shell",
35
+ ".sql": "SQL", ".yml": "YAML", ".yaml": "YAML",
36
+ }
37
+
38
+ ENTRY_POINT_SIGNALS = [
39
+ # (pattern, kind)
40
+ (re.compile(r"^#!/usr/bin/env (?:python3?|bash|sh)"), "cli"),
41
+ (re.compile(r"if __name__ == ['\"]__main__['\"]:"), "cli"),
42
+ (re.compile(r"app\.(listen|run)\s*\("), "http-server"),
43
+ (re.compile(r"uvicorn\.run\s*\("), "http-server"),
44
+ (re.compile(r"@app\.(get|post|put|delete|patch)\s*\("), "http-server"),
45
+ (re.compile(r"@router\.(get|post|put|delete|patch)\s*\("), "http-server"),
46
+ (re.compile(r"server\.listen\s*\("), "http-server"),
47
+ (re.compile(r"exports\.handler\s*="), "lambda"),
48
+ ]
49
+
50
+ SECURITY_SURFACE_PATTERNS = {
51
+ "auth_paths": [
52
+ re.compile(r"\b(login|logout|jwt\.sign|jwt\.verify|oauth|passport|authenticat|authoriz|session)\b", re.IGNORECASE),
53
+ ],
54
+ "network_egress": [
55
+ re.compile(r"\b(fetch\(|axios\.|httpx\.|requests\.(get|post|put|delete)|http\.Get\(|URLSession|urllib\.request\.)"),
56
+ ],
57
+ "secrets_referenced": [
58
+ re.compile(r"(process\.env\.[A-Z_]+|os\.environ(?:\.get)?(?:\[|\()|os\.getenv\(|ENV\[)"),
59
+ ],
60
+ "crypto_calls": [
61
+ re.compile(r"\b(crypto\.|hashlib\.|bcrypt|scrypt|argon2|ed25519|AES\.new|Cipher\(|\.encrypt\(|\.decrypt\()"),
62
+ ],
63
+ "ml_models_loaded": [
64
+ re.compile(r"\b(onnx\.load|pickle\.loads?|joblib\.load|torch\.load|AutoModel\.from_pretrained|SafeTensors\.load)\b"),
65
+ ],
66
+ }
67
+
68
+ SENSITIVE_FILE_PATTERNS = [
69
+ re.compile(r"\.env(\.[a-z]+)?$", re.IGNORECASE),
70
+ re.compile(r"\.(pem|key|p12|pfx|crt)$", re.IGNORECASE),
71
+ re.compile(r"credentials?", re.IGNORECASE),
72
+ re.compile(r"secret", re.IGNORECASE),
73
+ re.compile(r"id_(rsa|ed25519|ecdsa|dsa)", re.IGNORECASE),
74
+ ]
75
+
76
+
77
+ def detect_package_manager(root: Path) -> str:
78
+ has = {
79
+ "npm": (root / "package-lock.json").exists(),
80
+ "pnpm": (root / "pnpm-lock.yaml").exists(),
81
+ "yarn": (root / "yarn.lock").exists(),
82
+ "poetry": (root / "poetry.lock").exists(),
83
+ "pipenv": (root / "Pipfile.lock").exists(),
84
+ "pip": (root / "requirements.txt").exists(),
85
+ "go-modules": (root / "go.mod").exists(),
86
+ "cargo": (root / "Cargo.lock").exists(),
87
+ "maven": (root / "pom.xml").exists(),
88
+ "gradle": (root / "build.gradle").exists() or (root / "build.gradle.kts").exists(),
89
+ }
90
+ present = [k for k, v in has.items() if v]
91
+ if len(present) == 0:
92
+ return "unknown"
93
+ if len(present) == 1:
94
+ return present[0]
95
+ return "mixed"
96
+
97
+
98
+ def detect_monorepo(root: Path) -> tuple[bool, list[str]]:
99
+ pkg_json = root / "package.json"
100
+ if pkg_json.exists():
101
+ try:
102
+ data = json.loads(pkg_json.read_text(encoding="utf-8", errors="replace"))
103
+ if isinstance(data.get("workspaces"), list):
104
+ return True, [str(w) for w in data["workspaces"]]
105
+ if isinstance(data.get("workspaces"), dict):
106
+ packages = data["workspaces"].get("packages", [])
107
+ return True, [str(w) for w in packages]
108
+ except (json.JSONDecodeError, OSError):
109
+ pass
110
+ # Conventional monorepo shape — packages/ + apps/ + services/ dirs present
111
+ has_ws_dirs = [(root / d).is_dir() for d in ("packages", "apps", "services")]
112
+ if sum(has_ws_dirs) >= 1:
113
+ # Not a formal monorepo but has workspace-like structure
114
+ all_workspaces = []
115
+ for d in ("packages", "apps", "services"):
116
+ if (root / d).is_dir():
117
+ for sub in (root / d).iterdir():
118
+ if sub.is_dir():
119
+ all_workspaces.append(f"{d}/{sub.name}")
120
+ return bool(all_workspaces), all_workspaces
121
+ return False, []
122
+
123
+
124
+ def walk_source_files(root: Path) -> list[Path]:
125
+ """Walk the tree, skipping common junk directories."""
126
+ skip_dirs = {".git", "node_modules", ".venv", "venv", "__pycache__",
127
+ "dist", "build", ".tox", ".mypy_cache", ".ruff_cache",
128
+ "target", ".next", ".nuxt"}
129
+ out: list[Path] = []
130
+ for p in root.rglob("*"):
131
+ if not p.is_file():
132
+ continue
133
+ if any(part in skip_dirs for part in p.parts):
134
+ continue
135
+ out.append(p)
136
+ return out
137
+
138
+
139
+ def enumerate_languages(files: list[Path]) -> list[dict]:
140
+ counts: Counter[str] = Counter()
141
+ for f in files:
142
+ lang = LANGUAGE_BY_EXT.get(f.suffix.lower())
143
+ if lang:
144
+ counts[lang] += 1
145
+ return [
146
+ {"name": name, "file_count": count, "dominant_framework": None}
147
+ for name, count in counts.most_common()
148
+ if count >= 3
149
+ ]
150
+
151
+
152
+ def identify_entry_points(files: list[Path], root: Path) -> list[dict]:
153
+ out: list[dict] = []
154
+ for f in files:
155
+ if f.suffix.lower() not in {".py", ".js", ".ts", ".jsx", ".tsx", ".go", ".java", ".rb", ".sh"}:
156
+ continue
157
+ try:
158
+ text = f.read_text(encoding="utf-8", errors="replace")
159
+ except OSError:
160
+ continue
161
+ lines = text.splitlines()
162
+ for i, line in enumerate(lines[:200], start=1): # check first 200 lines
163
+ for pattern, kind in ENTRY_POINT_SIGNALS:
164
+ if pattern.search(line):
165
+ rel = str(f.relative_to(root))
166
+ rationale = f"Pattern match at line {i}: {line.strip()[:80]}"
167
+ lang = LANGUAGE_BY_EXT.get(f.suffix.lower(), "unknown")
168
+ # Dedupe on path
169
+ if not any(ep["path"] == rel for ep in out):
170
+ out.append({
171
+ "path": rel,
172
+ "kind": kind,
173
+ "rationale": rationale,
174
+ "language": lang,
175
+ })
176
+ break # one signal per file is enough
177
+ # Package.json main
178
+ pkg_json = root / "package.json"
179
+ if pkg_json.exists():
180
+ try:
181
+ data = json.loads(pkg_json.read_text(encoding="utf-8", errors="replace"))
182
+ main = data.get("main")
183
+ if main:
184
+ rel = main.lstrip("./")
185
+ if not any(ep["path"] == rel for ep in out):
186
+ out.append({
187
+ "path": rel,
188
+ "kind": "module-index",
189
+ "rationale": "Listed as 'main' in package.json",
190
+ "language": "JavaScript/TypeScript",
191
+ })
192
+ except (json.JSONDecodeError, OSError):
193
+ pass
194
+ return out
195
+
196
+
197
+ def identify_dependencies(root: Path) -> dict:
198
+ deps: dict[str, list[str]] = {}
199
+
200
+ # Python requirements.txt
201
+ req = root / "requirements.txt"
202
+ if req.exists():
203
+ try:
204
+ text = req.read_text(encoding="utf-8")
205
+ pkgs = [line.split("==")[0].split(">=")[0].split("<=")[0].strip()
206
+ for line in text.splitlines()
207
+ if line.strip() and not line.strip().startswith("#")]
208
+ _classify_deps(pkgs, deps)
209
+ except OSError:
210
+ pass
211
+
212
+ # Node package.json
213
+ pkg_json = root / "package.json"
214
+ if pkg_json.exists():
215
+ try:
216
+ data = json.loads(pkg_json.read_text(encoding="utf-8", errors="replace"))
217
+ pkgs = list((data.get("dependencies") or {}).keys())
218
+ _classify_deps(pkgs, deps)
219
+ except (json.JSONDecodeError, OSError):
220
+ pass
221
+
222
+ return deps
223
+
224
+
225
+ def _classify_deps(pkgs: list[str], deps: dict):
226
+ """Heuristic classification of deps into web/data/crypto/auth/messaging/ml."""
227
+ buckets = {
228
+ "web": {"express", "fastapi", "flask", "django", "koa", "hapi", "starlette", "sanic", "bottle"},
229
+ "data": {"sqlalchemy", "mongodb", "mongoose", "pg", "mysql2", "redis", "psycopg2", "pymongo", "cassandra-driver"},
230
+ "crypto": {"pycryptodome", "cryptography", "bcrypt", "argon2", "scrypt", "jsonwebtoken", "jose"},
231
+ "auth": {"passport", "pyjwt", "python-jose", "authlib", "jsonwebtoken", "oauth2"},
232
+ "messaging": {"nats-py", "aio-pika", "kafka-python", "pika", "amqplib"},
233
+ "ml": {"onnx", "torch", "tensorflow", "scikit-learn", "joblib", "safetensors"},
234
+ }
235
+ for pkg in pkgs:
236
+ pkg_lower = pkg.lower()
237
+ for bucket, names in buckets.items():
238
+ if pkg_lower in names or any(pkg_lower.startswith(n) for n in names):
239
+ deps.setdefault(bucket, []).append(pkg)
240
+ break
241
+ else:
242
+ deps.setdefault("other_notable", []).append(pkg)
243
+
244
+
245
+ def grep_security_surface(files: list[Path], root: Path) -> dict:
246
+ out: dict[str, list[str]] = {k: [] for k in SECURITY_SURFACE_PATTERNS}
247
+ out["csp_headers"] = []
248
+ for f in files:
249
+ if f.suffix.lower() not in {".py", ".js", ".ts", ".jsx", ".tsx", ".go", ".java", ".rb"}:
250
+ continue
251
+ try:
252
+ text = f.read_text(encoding="utf-8", errors="replace")
253
+ except OSError:
254
+ continue
255
+ rel = str(f.relative_to(root))
256
+ for kind, patterns in SECURITY_SURFACE_PATTERNS.items():
257
+ if any(p.search(text) for p in patterns) and rel not in out[kind]:
258
+ out[kind].append(rel)
259
+ return out
260
+
261
+
262
+ def probe_git_history(root: Path, notes: list | None = None) -> dict:
263
+ """Probe branch/activity/sensitive-file history.
264
+
265
+ `notes` (#1651): an optional sink for degrade warnings. The
266
+ sensitive-file scan shells out to `git log --all --name-only` under a
267
+ timeout, and swallowing that timeout leaves `sensitive_file_history`
268
+ empty — indistinguishable from "scanned the whole history, found
269
+ nothing." On a large repo those are opposite conclusions, and the empty
270
+ one reads as the reassuring answer. When a sink is supplied, a degraded
271
+ probe says so; #1636 established this pattern for the jsonschema-absent
272
+ case in `codebase_recon.py` rather than degrading silently.
273
+ """
274
+ out: dict[str, Any] = {
275
+ "branches": {"current": "", "main_count": 0, "feature_count": 0, "names": []},
276
+ "recent_activity": {"last_commit_date": "1970-01-01T00:00:00Z", "commits_last_30d": 0, "authors_last_30d": 0},
277
+ "sensitive_file_history": [],
278
+ }
279
+ if not (root / ".git").exists():
280
+ return out
281
+
282
+ try:
283
+ branches = subprocess.run(["git", "-C", str(root), "branch", "--list"],
284
+ capture_output=True, text=True, timeout=10, check=False).stdout.splitlines()
285
+ branch_names = [b.strip().lstrip("* ") for b in branches]
286
+ current = subprocess.run(["git", "-C", str(root), "rev-parse", "--abbrev-ref", "HEAD"],
287
+ capture_output=True, text=True, timeout=10, check=False).stdout.strip()
288
+ out["branches"]["current"] = current
289
+ out["branches"]["names"] = branch_names[:20]
290
+ out["branches"]["main_count"] = sum(1 for b in branch_names if b in ("main", "master", "develop"))
291
+ out["branches"]["feature_count"] = max(0, len(branch_names) - out["branches"]["main_count"])
292
+
293
+ last = subprocess.run(["git", "-C", str(root), "log", "-1", "--format=%cI"],
294
+ capture_output=True, text=True, timeout=10, check=False).stdout.strip()
295
+ if last:
296
+ out["recent_activity"]["last_commit_date"] = last
297
+
298
+ commits = subprocess.run(
299
+ ["git", "-C", str(root), "log", "--since=30 days ago", "--oneline"],
300
+ capture_output=True, text=True, timeout=10, check=False,
301
+ ).stdout.strip().splitlines()
302
+ authors = subprocess.run(
303
+ ["git", "-C", str(root), "log", "--since=30 days ago", "--format=%ae"],
304
+ capture_output=True, text=True, timeout=10, check=False,
305
+ ).stdout.strip().splitlines()
306
+ out["recent_activity"]["commits_last_30d"] = len(commits)
307
+ out["recent_activity"]["authors_last_30d"] = len({a for a in authors if a})
308
+
309
+ # Sensitive file history — files ever touched
310
+ tree_files = subprocess.run(
311
+ ["git", "-C", str(root), "log", "--all", "--name-only", "--format="],
312
+ capture_output=True, text=True, timeout=30, check=False,
313
+ ).stdout.splitlines()
314
+ for path in {p for p in tree_files if p}:
315
+ for pattern in SENSITIVE_FILE_PATTERNS:
316
+ if pattern.search(path):
317
+ in_tree = (root / path).exists()
318
+ out["sensitive_file_history"].append({
319
+ "path": path,
320
+ "in_current_tree": in_tree,
321
+ "appeared_in_history": True,
322
+ "first_seen_commit": None,
323
+ "removed_commit": None,
324
+ })
325
+ break
326
+ except (subprocess.TimeoutExpired, subprocess.SubprocessError) as exc:
327
+ if notes is not None:
328
+ kind = (
329
+ "timed out"
330
+ if isinstance(exc, subprocess.TimeoutExpired)
331
+ else "failed"
332
+ )
333
+ notes.append(
334
+ f"DEGRADED: the git-history probe {kind}, so branch, recent-activity, "
335
+ "and sensitive-file-history fields are partial or empty. An empty "
336
+ "sensitive_file_history here does NOT mean none was found — the scan "
337
+ "did not complete."
338
+ )
339
+ return out
340
+
341
+
342
+ def build_architecture(files: list[Path], root: Path) -> dict:
343
+ """Identify layers from directory naming. Summary is thin without LLM."""
344
+ known_layers = ["domain", "core", "adapters", "infrastructure", "ports",
345
+ "handlers", "routes", "services", "repositories", "models",
346
+ "controllers", "views", "backend", "frontend", "api", "worker"]
347
+ layer_files: dict[str, list[str]] = {}
348
+ for f in files:
349
+ for layer in known_layers:
350
+ if f"/{layer}/" in str(f) or str(f).startswith(f"{layer}/"):
351
+ rel_dir = str(f.parent.relative_to(root))
352
+ layer_files.setdefault(layer, [])
353
+ if rel_dir not in layer_files[layer]:
354
+ layer_files[layer].append(rel_dir)
355
+ break
356
+
357
+ layers = [
358
+ {"name": k, "paths": sorted(set(v))[:5], "purpose": ""}
359
+ for k, v in layer_files.items() if len(v) >= 1
360
+ ]
361
+
362
+ # Summary is deterministic but thin
363
+ summary_parts = []
364
+ if layers:
365
+ layer_names = [layer["name"] for layer in layers]
366
+ summary_parts.append(f"Code organized into {len(layers)} identifiable layer(s): {', '.join(layer_names)}.")
367
+ else:
368
+ summary_parts.append("No conventional layer structure detected.")
369
+
370
+ return {
371
+ "summary": " ".join(summary_parts) + " [Deterministic recon — LLM narrative skipped.]",
372
+ "layers": layers,
373
+ "notable_anti_patterns": [], # Requires LLM
374
+ }
375
+
376
+
377
+ def build_recon(root: Path) -> dict:
378
+ root = root.resolve()
379
+ files = walk_source_files(root)
380
+ monorepo, workspaces = detect_monorepo(root)
381
+
382
+ # Built before the envelope so probes can append degrade warnings to it
383
+ # (#1651). `probe_git_history` mutates this list in place, and the dict
384
+ # literal below evaluates that call before reading `notes`, so anything
385
+ # appended during the probe is present in the emitted envelope.
386
+ notes = [
387
+ (
388
+ "Deterministic recon produced by "
389
+ "plugins/dev-team/scripts/lib/deterministic_recon.py. No LLM reasoning "
390
+ "applied; semantic fields (architecture.summary prose, "
391
+ "notable_anti_patterns) are omitted or minimal."
392
+ )
393
+ ]
394
+
395
+ return {
396
+ "schema_version": "1.0",
397
+ "generated_at": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
398
+ "repo": {
399
+ "name": root.name,
400
+ "root": str(root),
401
+ "package_manager": detect_package_manager(root),
402
+ "monorepo": monorepo,
403
+ "workspaces": workspaces,
404
+ "vcs": {
405
+ "kind": "git" if (root / ".git").exists() else "none",
406
+ "remote_host": None,
407
+ "default_branch": None,
408
+ },
409
+ },
410
+ "entry_points": identify_entry_points(files, root),
411
+ "languages": enumerate_languages(files),
412
+ "dependencies": identify_dependencies(root),
413
+ "architecture": build_architecture(files, root),
414
+ "security_surface": grep_security_surface(files, root),
415
+ "git_history": probe_git_history(root, notes),
416
+ "notes": notes,
417
+ }
418
+
419
+
420
+ def main() -> int:
421
+ if len(sys.argv) < 2 or len(sys.argv) > 3:
422
+ print("usage: deterministic_recon.py <target-path> [<output-json>]", file=sys.stderr)
423
+ return 2
424
+
425
+ target = Path(sys.argv[1])
426
+ if not target.is_dir():
427
+ print(f"error: target is not a directory: {target}", file=sys.stderr)
428
+ return 2
429
+
430
+ recon = build_recon(target)
431
+
432
+ if len(sys.argv) == 3:
433
+ out_path = Path(sys.argv[2])
434
+ out_path.parent.mkdir(parents=True, exist_ok=True)
435
+ with out_path.open("w") as f:
436
+ json.dump(recon, f, indent=2)
437
+ print(f"wrote {out_path}", file=sys.stderr)
438
+ else:
439
+ json.dump(recon, sys.stdout, indent=2)
440
+ sys.stdout.write("\n")
441
+
442
+ return 0
443
+
444
+
445
+ if __name__ == "__main__":
446
+ sys.exit(main())
@@ -0,0 +1,211 @@
1
+ #!/usr/bin/env python3
2
+ """Shared plumbing for the code-intelligence MCP tool-grant checks.
3
+
4
+ Three sibling check scripts consume this module as peers — none is any other's
5
+ library:
6
+
7
+ - ``check_review_agent_mcp_tools.py`` — the 24 read-only ``*-review`` agents, all
8
+ granted the same ``BASE_MCP_TOOLS`` set (#1102).
9
+ - ``check_agent_tool_mapping.py`` — the non-review team agents, granted per-tier
10
+ sets built from ``BASE_MCP_TOOLS`` (± ``GET_WHY``) (#1108).
11
+ - ``check_security_assessment_mcp_tools.py`` — the security-assessment plugin's
12
+ code-reading agents, granted the same ``BASE_MCP_TOOLS`` set as the review-agent
13
+ check above, but discovered via a named roster rather than a filename glob
14
+ (#1388).
15
+
16
+ This module owns the canonical tool-name constants and the frontmatter
17
+ ``tools:``-line parse/fix plumbing all three checks need. The fix helpers take a
18
+ caller-supplied ``required`` list so each check can request its own set (the
19
+ 5-name review/narrow set, or the 6-name rationale set) without duplicating the
20
+ merge logic.
21
+ """
22
+
23
+ import re
24
+
25
+ # CodeGraph + the four Repowise tools granted to every read-only review agent,
26
+ # and the shared base of the non-review tiers (#1102's canonical set). A granted
27
+ # tool whose MCP server is absent is simply unavailable at runtime (no error);
28
+ # agents fall back to Read/Grep/Glob.
29
+ BASE_MCP_TOOLS = [
30
+ "mcp__codegraph__codegraph_explore",
31
+ "mcp__plugin_repowise_repowise__get_context",
32
+ "mcp__plugin_repowise_repowise__get_symbol",
33
+ "mcp__plugin_repowise_repowise__search_codebase",
34
+ "mcp__plugin_repowise_repowise__get_risk",
35
+ ]
36
+
37
+ # The rationale/decision tier additionally grants get_why (code-existence
38
+ # rationale) — see check_agent_tool_mapping.py.
39
+ GET_WHY = "mcp__plugin_repowise_repowise__get_why"
40
+
41
+ # Reassigned-tools tier (#1467): health scoring and dead-code detection granted
42
+ # to specific review agents in place of get_risk/search_codebase — see
43
+ # check_review_agent_mcp_tools.py's REASSIGNED_TOOLS mapping.
44
+ GET_HEALTH = "mcp__plugin_repowise_repowise__get_health"
45
+ GET_DEAD_CODE = "mcp__plugin_repowise_repowise__get_dead_code"
46
+
47
+ # Match the inline `tools:` line only. Group 1 (`tools:` + horizontal space) and
48
+ # group 3 (trailing horizontal space) use `[ \t]` — NOT `\s` — so the match can
49
+ # never cross a newline into a YAML block-scalar/sequence form
50
+ # (`tools:\n - Read`). Group 2 is the inline value (no newline).
51
+ _TOOLS_RE = re.compile(r"^(tools:[ \t]*)([^\n]*?)([ \t]*)$", re.MULTILINE)
52
+
53
+
54
+ def parse_tools(text):
55
+ """Return the comma-separated tokens on the inline ``tools:`` line, or None.
56
+
57
+ Returns None when there is no ``tools:`` line, or when it has no inline value
58
+ (an empty line, or a YAML block form with the list on following lines) — such
59
+ a line is not safely appendable, so callers treat None as *unfixable* rather
60
+ than mangling it.
61
+ """
62
+ m = _TOOLS_RE.search(text)
63
+ if not m:
64
+ return None
65
+ value = m.group(2).strip()
66
+ if not value:
67
+ return None
68
+ return [tok.strip() for tok in value.split(",") if tok.strip()]
69
+
70
+
71
+ def _server_wildcard_forms(name):
72
+ """Return the ``mcp__<server>__*`` and bare ``mcp__<server>`` forms that
73
+ satisfy a specific ``mcp__<server>__<tool>`` grant requirement, per
74
+ agent-contract.json's tools: value_format ("mcp__<server> or
75
+ mcp__<server>__*" grants every tool from that server).
76
+ """
77
+ parts = name.split("__")
78
+ if len(parts) < 3 or parts[0] != "mcp":
79
+ return ()
80
+ server = "__".join(parts[:2])
81
+ return (f"{server}__*", server)
82
+
83
+
84
+ def _is_satisfied(name, present):
85
+ """True if ``name`` is granted exactly, or via a server-wide wildcard grant."""
86
+ if name in present:
87
+ return True
88
+ return any(form in present for form in _server_wildcard_forms(name))
89
+
90
+
91
+ def _compute_missing(present, required):
92
+ """Return the ``required`` names not satisfied by the ``present`` grant set."""
93
+ return [name for name in required if not _is_satisfied(name, present)]
94
+
95
+
96
+ def missing_tools(text, required):
97
+ """Return the ``required`` tool names absent from the agent's ``tools:`` line.
98
+
99
+ A required ``mcp__<server>__<tool>`` name is considered present when the
100
+ agent instead grants ``mcp__<server>__*`` or bare ``mcp__<server>`` —
101
+ both equivalent, broader grants per the official contract.
102
+
103
+ Returns the full ``required`` list when the agent has no parseable ``tools:``
104
+ line at all.
105
+ """
106
+ tokens = parse_tools(text)
107
+ if tokens is None:
108
+ return list(required)
109
+ return _compute_missing(set(tokens), required)
110
+
111
+
112
+ def fix_tools_line(text, required):
113
+ """Append any missing ``required`` names to the ``tools:`` line. Idempotent.
114
+
115
+ Returns ``(new_text, added_names)``. Order-preserving: existing tokens keep
116
+ their order; missing names are appended in ``required`` order. A line already
117
+ containing every required name is returned unchanged (``added == []``). A file
118
+ with no parseable ``tools:`` line is returned unchanged (``added == []``).
119
+ """
120
+ m = _TOOLS_RE.search(text)
121
+ if not m:
122
+ return text, []
123
+ tokens = parse_tools(text)
124
+ if tokens is None:
125
+ # No inline value (block form or empty) — unfixable, never mangle it.
126
+ return text, []
127
+ added = _compute_missing(set(tokens), required)
128
+ if not added:
129
+ return text, []
130
+ new_tokens = tokens + added
131
+ new_line = m.group(1) + ", ".join(new_tokens)
132
+ new_text = text[: m.start()] + new_line + text[m.end() - len(m.group(3)) :]
133
+ return new_text, added
134
+
135
+
136
+ def run_grants_check(targets, apply_fix=False):
137
+ """Single read+parse pass per target, shared by all three grant-check scripts.
138
+
139
+ ``targets`` is ``{name: (path, required)}``. Each target's file is read from
140
+ disk **at most once** regardless of ``apply_fix`` — the offender computation
141
+ below reuses the (possibly just-fixed) in-memory text rather than re-reading,
142
+ which is what let ``--fix`` runs silently do a second full read+parse pass
143
+ per file in the three callers before this helper existed (#1392).
144
+
145
+ Returns ``(offenders, fixed, unfixable)``:
146
+ - ``offenders``: ``{name: [missing tool names]}``, reflecting the
147
+ post-fix state when ``apply_fix`` is true.
148
+ - ``fixed``: ``{name: [tool names added]}`` — populated only when
149
+ ``apply_fix`` is true.
150
+ - ``unfixable``: ``[name, ...]`` — targets whose file exists but has no
151
+ appendable inline ``tools:`` line — populated only when ``apply_fix``
152
+ is true (mirrors each caller's prior ``apply_fixes()`` semantics).
153
+ """
154
+ offenders = {}
155
+ fixed = {}
156
+ unfixable = []
157
+ for name, (path, required) in targets.items():
158
+ if not path.is_file():
159
+ offenders[name] = list(required)
160
+ continue
161
+ text = path.read_text(encoding="utf-8")
162
+ if apply_fix:
163
+ if parse_tools(text) is None:
164
+ unfixable.append(name)
165
+ else:
166
+ new_text, added = fix_tools_line(text, required)
167
+ if added:
168
+ path.write_text(new_text, encoding="utf-8")
169
+ fixed[name] = added
170
+ text = new_text
171
+ missing = missing_tools(text, required)
172
+ if missing:
173
+ offenders[name] = missing
174
+ return offenders, fixed, unfixable
175
+
176
+
177
+ def build_json_report(check, evaluated, offenders, ok, fixed=None, unfixable=None, unclassified=None, notes=None):
178
+ """Build the common ``--json`` envelope shared by all three grant-check scripts (#1393).
179
+
180
+ Each script's ``--json`` output previously diverged in shape (``reviewed`` vs
181
+ ``covered``, an ``unclassified`` key present on two scripts but absent on the
182
+ third, ``fixed``/``unfixable`` only appearing conditionally on ``--fix``) — a
183
+ caller wanting to aggregate "which grant checks are failing" across scripts had
184
+ no uniform surface to read. This helper gives every script the same top-level
185
+ keys, always present, so a future aggregator never needs a per-script branch:
186
+
187
+ - ``check``: a stable slug identifying which script produced the report.
188
+ - ``evaluated``: every target name the check looked at.
189
+ - ``offenders``: ``{name: [missing tool names]}`` (post-fix state if fixed).
190
+ - ``unclassified``: names present but classified into neither a required nor
191
+ an excluded bucket — ``[]`` when the check has no such concept.
192
+ - ``fixed`` / ``unfixable``: from ``run_grants_check`` — empty when detection
193
+ only (no ``--fix``).
194
+ - ``ok``: the caller's own exit-code decision, passed through rather than
195
+ re-derived here — some checks (e.g. the review-agent script's skill-prose
196
+ check) fail for reasons ``offenders``/``unclassified`` alone don't capture,
197
+ so this helper must not guess at "ok" from the other fields.
198
+ - ``notes``: a namespaced bag for the one or two fields that are genuinely
199
+ script-specific (e.g. ``skill_missing_phrases``, ``swept``) rather than
200
+ forcing every script into an identical key set that doesn't fit.
201
+ """
202
+ return {
203
+ "check": check,
204
+ "evaluated": list(evaluated),
205
+ "offenders": offenders,
206
+ "unclassified": list(unclassified or []),
207
+ "fixed": fixed or {},
208
+ "unfixable": list(unfixable or []),
209
+ "ok": ok,
210
+ "notes": notes or {},
211
+ }