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,163 @@
1
+ #!/usr/bin/env python3
2
+ """gherkin_stub_gate.py — fail closed while bdd-runner step definitions are
3
+ still pending (issue #1391).
4
+
5
+ `bdd-runner` mode wires a real native Gherkin parser (cucumber-js, Reqnroll,
6
+ cucumber-jvm, godog) and `gherkin-derive/SKILL.md` Step 4 generates **pending**
7
+ step-definition stubs so the suite compiles and fails intentionally (red
8
+ before green) — that scaffolding step is correct on its own. Choosing
9
+ `bdd-runner` mode is a decision to end up with fully executing, Gherkin-bound
10
+ tests, not a decision to scaffold placeholders that may or may not get
11
+ finished. This script is the completion gate: it greps the step-definition
12
+ files for the per-language pending marker and fails, listing every remaining
13
+ file:line, when any stub was never filled in.
14
+
15
+ Per-language pending markers (`gherkin-derive/SKILL.md` Step 4's table,
16
+ reused here — not re-derived). The extension -> (language label, markers)
17
+ table itself lives in `lib/_bdd_markers.py` (issue #1421 bug 5) — shared with
18
+ `lib/stub_extractors/__init__.py`, which needs the same mapping and used to
19
+ reach up into this module's `_MARKERS_BY_EXT` via a `sys.path` layer
20
+ inversion to get it. C# carries two markers: `PendingStepException`
21
+ is Reqnroll's current auto-suggested stub, and `StepIsPending()` is its
22
+ deprecated-since-3.3.4 predecessor — still recognized so an older or
23
+ not-yet-regenerated stub isn't a false negative
24
+ (`knowledge/test-stack-profiles/bdd-frameworks.md`):
25
+
26
+ | Language | Framework | Pending marker(s) |
27
+ |----------|-------------------------------------|----------------------------------------------|
28
+ | JS/TS | Cucumber.js | `this.pending()` |
29
+ | Java | Cucumber-JVM | `PendingException` |
30
+ | C# | Reqnroll (xUnit/NUnit/MSTest) | `PendingStepException`, `StepIsPending()` |
31
+ | Go | Godog | `godog.ErrPending` |
32
+
33
+ The language for a given step-definition file is resolved from its
34
+ extension, matched **case-insensitively** — `.js`/`.ts`/`.mjs`/`.cjs` →
35
+ JS/TS, `.java` → Java, `.cs` → C#, `.go` → Go. Files with an unrecognized
36
+ extension are skipped (not every file under a step-definitions directory is
37
+ necessarily a step-definition file). Vendored/generated trees
38
+ (`.git`, `node_modules`, `vendor`, `dist`, `build`, and virtualenv
39
+ directories) are pruned during the scan — the same exclusion set
40
+ `detect_bdd_convention.py` uses — so a stray dependency tree under a scanned
41
+ directory is never walked or grepped — via the shared `_vendored_tree.py`
42
+ helper (issue #1420), also used by `detect_bdd_convention.py` and
43
+ `gherkin_failure_path_gate.py`.
44
+
45
+ Stdlib-only. (ADR 0014/0015).
46
+
47
+ Usage:
48
+ python3 gherkin_stub_gate.py --dir <step-definitions-dir> [--dir <dir> ...]
49
+ python3 gherkin_stub_gate.py --dir features/test-improve/my-slug --json
50
+ """
51
+
52
+ from __future__ import annotations
53
+
54
+ import argparse
55
+ import json
56
+ import sys
57
+ from pathlib import Path
58
+
59
+ _HERE = Path(__file__).resolve().parent
60
+ sys.path.insert(0, str(_HERE / "lib"))
61
+
62
+ from _bdd_markers import MARKERS_BY_EXT as _MARKERS_BY_EXT
63
+ from _gherkin_text import safe_for_terminal as _safe_for_terminal
64
+ from _vendored_tree import find_files as _find_files
65
+
66
+
67
+ def find_step_definition_files(directories: list[Path]) -> list[Path]:
68
+ """Return every file under `directories` whose extension is a known
69
+ step-definition language (matched case-insensitively), pruning vendored
70
+ trees, sorted for deterministic output."""
71
+ return _find_files(directories, lambda path: path.suffix.lower() in _MARKERS_BY_EXT)
72
+
73
+
74
+ def _matching_marker(line: str, markers: tuple) -> str | None:
75
+ """Return the first marker in `markers` that occurs in `line`, or
76
+ `None` — the innermost scan of `find_pending_stubs`, extracted so that
77
+ function stays at 2 levels of nesting instead of 4."""
78
+ return next((marker for marker in markers if marker in line), None)
79
+
80
+
81
+ def find_pending_stubs(files: list[Path]) -> list[dict]:
82
+ """Return one entry per pending-marker occurrence: {file, line, language, text}."""
83
+ pending: list[dict] = []
84
+ for path in files:
85
+ language, markers = _MARKERS_BY_EXT[path.suffix.lower()]
86
+ text = path.read_text(encoding="utf-8", errors="replace")
87
+ for line_no, line in enumerate(text.splitlines(), start=1):
88
+ marker = _matching_marker(line, markers)
89
+ if marker is not None:
90
+ pending.append(
91
+ {
92
+ "file": str(path),
93
+ "line": line_no,
94
+ "language": language,
95
+ "marker": marker,
96
+ "text": line.strip(),
97
+ }
98
+ )
99
+ return pending
100
+
101
+
102
+ def main(argv: list[str] | None = None) -> int:
103
+ parser = argparse.ArgumentParser(
104
+ prog="gherkin_stub_gate.py",
105
+ description=(
106
+ "Fail closed when any bdd-runner step-definition file still "
107
+ "carries a pending-stub marker."
108
+ ),
109
+ )
110
+ parser.add_argument(
111
+ "--dir",
112
+ dest="dirs",
113
+ action="append",
114
+ type=Path,
115
+ required=True,
116
+ help="Step-definitions directory to scan (repeatable).",
117
+ )
118
+ parser.add_argument("--json", action="store_true", help="machine-readable output")
119
+ args = parser.parse_args(argv)
120
+
121
+ files = find_step_definition_files(args.dirs)
122
+
123
+ if not files:
124
+ # Mirrors gherkin_failure_path_gate.py's identical fix: a --dir that
125
+ # doesn't exist (or resolves to zero step-definition files) used to
126
+ # silently report "OK: 0 ... scanned, no pending stubs remain" — an
127
+ # affirmative all-clear for zero evidence. --dir is composed by
128
+ # gherkin-derive from a probe of the target repo, not always typed
129
+ # by a human, so a gate that scanned nothing must say so distinctly.
130
+ dirs_display = ", ".join(str(d) for d in args.dirs)
131
+ message = f"no step-definition files found under {dirs_display} — gate did not run"
132
+ if args.json:
133
+ print(json.dumps({"scanned": [], "pending": [], "warning": message}, indent=2))
134
+ else:
135
+ # --dir is composed by gherkin-derive from a probe of the target
136
+ # repo, not always typed by a human — the same untrusted-path
137
+ # class as a scanned file's path, sanitized the same way.
138
+ print(
139
+ f"WARN: no step-definition files found under "
140
+ f"{_safe_for_terminal(dirs_display)} — gate did not run"
141
+ )
142
+ return 2
143
+
144
+ pending = find_pending_stubs(files)
145
+
146
+ if args.json:
147
+ print(json.dumps({"scanned": [str(f) for f in files], "pending": pending}, indent=2))
148
+ return 1 if pending else 0
149
+
150
+ if pending:
151
+ print(f"FAIL: {len(pending)} pending step definition(s) — bdd-runner mode is not done:")
152
+ for entry in pending:
153
+ path = _safe_for_terminal(entry["file"])
154
+ text = _safe_for_terminal(entry["text"])
155
+ print(f" - {path}:{entry['line']} ({entry['language']}) — {text}")
156
+ return 1
157
+
158
+ print(f"OK: {len(files)} step-definition file(s) scanned, no pending stubs remain.")
159
+ return 0
160
+
161
+
162
+ if __name__ == "__main__": # pragma: no cover
163
+ sys.exit(main())
@@ -0,0 +1,479 @@
1
+ #!/usr/bin/env python3
2
+ """gherkin_stub_merge.py — merge newly-derived step-definition stubs into an
3
+ existing step-definition file without clobbering an already-implemented step
4
+ (issue #1421).
5
+
6
+ `gherkin-derive`'s `bdd-runner` mode used to regenerate step-definition stubs
7
+ unconditionally on every run, silently discarding any step a human (or
8
+ `/build`) had already implemented. This module gives it a safe alternative,
9
+ mirroring `gherkin_feature_merge.py`'s read-before-write/merge discipline:
10
+ parse the existing file via `scripts/lib/stub_extractors` (one
11
+ lexically-aware, brace-balance-bounded extractor per language), skip any
12
+ candidate whose step-pattern text already exists there — regardless of
13
+ whether that existing binding is pending or already implemented — and append
14
+ only genuinely-new candidates as pending stubs after the last existing
15
+ binding. An existing binding's body is never rewritten or reordered.
16
+
17
+ `stub_extractors.parse_existing_steps` refuses to guess a span when a file's
18
+ brackets don't lexically balance, or a marker has no attached, boundable
19
+ body — reported as one of two structural-error sentinels
20
+ (`unbalanced-braces`, `dangling-annotation`, re-exported here), plus
21
+ `unsafe-path` at this script's own level for a `--existing` path containing a
22
+ `..` component, `malformed-candidates` when the `--candidates` scratch
23
+ file itself can't be bounded, `unreadable-candidates` when that file is
24
+ missing or can't be read at all, and `unsupported-extension` for an `--ext`
25
+ naming no known step-definition language. Every error leaves the existing
26
+ file completely untouched.
27
+
28
+ Stdlib-only. (ADR 0014/0015).
29
+
30
+ Usage:
31
+ python3 gherkin_stub_merge.py merge --existing <path> --candidates <path> \
32
+ --ext <.js|.ts|.mjs|.cjs|.java|.cs|.go> [--dry-run] [--json]
33
+ """
34
+
35
+ from __future__ import annotations
36
+
37
+ import argparse
38
+ import json
39
+ import os
40
+ import sys
41
+ import tempfile
42
+ from dataclasses import dataclass
43
+ from pathlib import Path
44
+
45
+ _HERE = Path(__file__).resolve().parent
46
+ sys.path.insert(0, str(_HERE / "lib"))
47
+
48
+ from _gherkin_text import safe_for_terminal as _safe_for_terminal
49
+ from stub_extractors import (
50
+ ERROR_DANGLING_ANNOTATION, # noqa: F401
51
+ ERROR_UNBALANCED_BRACES, # noqa: F401
52
+ parse_existing_steps,
53
+ )
54
+ from stub_extractors import go as _go_extractor
55
+
56
+ # This script's own error sentinels — distinct from the two structural
57
+ # sentinels stub_extractors returns (re-exported above), the same split
58
+ # gherkin_feature_merge.py makes between its own ERROR_UNSAFE_PATH/
59
+ # ERROR_MALFORMED_CANDIDATES and the parser's ERROR_FEATURE_NOT_FOUND/
60
+ # ERROR_MALFORMED_FEATURE_BLOCK.
61
+ ERROR_UNSAFE_PATH = "unsafe-path"
62
+ ERROR_MALFORMED_CANDIDATES = "malformed-candidates"
63
+ # issue #1421 bug 6: a missing/unreadable --candidates path and an
64
+ # unrecognized --ext (argparse has no `choices=` for it) used to escape
65
+ # _cmd_merge as raw, uncaught Python exceptions instead of one of these
66
+ # sentinels through the same exit-2 --json contract every other structural
67
+ # problem uses.
68
+ ERROR_UNREADABLE_CANDIDATES = "unreadable-candidates"
69
+ ERROR_UNSUPPORTED_EXTENSION = "unsupported-extension"
70
+
71
+
72
+ @dataclass
73
+ class StepCandidate:
74
+ """One newly-derived step-definition stub to merge in — pre-composed,
75
+ language-appropriate source text (the caller, `gherkin-derive/SKILL.md`
76
+ Step 4, is responsible for its exact shape), plus the step-pattern text
77
+ used to detect whether it already exists.
78
+
79
+ `decl_text` is Go-only (`None` for JS/TS, Java, C#): Go's registration
80
+ call and the top-level function it references are non-adjacent source
81
+ regions, so `text` (the registration call alone) is insufficient on its
82
+ own — `decl_text` carries the function declaration that must be spliced
83
+ in at a different, top-level-safe position (see `merge_steps`).
84
+ `parse_candidate_steps` populates it automatically from a `--candidates`
85
+ scratch file; a caller building `StepCandidate` by hand for Go must
86
+ supply it explicitly or the merged file will fail to compile."""
87
+
88
+ pattern: str
89
+ text: str
90
+ decl_text: str | None = None
91
+
92
+
93
+ @dataclass
94
+ class MergeResult:
95
+ text: str
96
+ added_patterns: list
97
+ skipped_duplicate_patterns: list
98
+ error: str | None
99
+
100
+
101
+ def _dedupe_candidates(candidates: list) -> tuple:
102
+ """Return `(deduped_candidates, self_duplicate_patterns)`. Two candidates
103
+ sharing a trimmed pattern would otherwise both be appended, mirroring the
104
+ identical fix `gherkin_feature_merge._dedupe_candidate_units` applies to
105
+ scenario titles."""
106
+ seen = set()
107
+ deduped = []
108
+ duplicates = []
109
+ for candidate in candidates:
110
+ key = candidate.pattern.strip()
111
+ if key in seen:
112
+ duplicates.append(candidate.pattern)
113
+ continue
114
+ seen.add(key)
115
+ deduped.append(candidate)
116
+ return deduped, duplicates
117
+
118
+
119
+ def _insert_at(text: str, idx: int, insertion: str) -> str:
120
+ """Splice `insertion` into `text` at char offset `idx`, restoring a
121
+ missing line terminator right at the splice point (matching
122
+ `gherkin_feature_merge.merge_scenarios`'s identical guard) so neither
123
+ side's content is ever rewritten — only the separator whose absence
124
+ would otherwise fuse two lines together. No-op when `insertion` is empty."""
125
+ if not insertion:
126
+ return text
127
+ prefix = text[:idx]
128
+ suffix = text[idx:]
129
+ if prefix and not prefix.endswith("\n"):
130
+ prefix += "\n"
131
+ if not insertion.endswith("\n"):
132
+ insertion += "\n"
133
+ return prefix + insertion + suffix
134
+
135
+
136
+ def _existing_bindings_use_blank_line_separator(existing_text: str, bindings: list) -> bool:
137
+ """Infer whether this file's existing step bindings are separated by a
138
+ blank line, from the joins between consecutive existing bindings —
139
+ excluding the boundary after the very last binding, which sits at the
140
+ file's end and may have nothing after it to separate from for reasons
141
+ unrelated to the file's own convention. A binding's `.end` (from
142
+ `extend_to_line_end`) stops at its own closing line, so the gap between
143
+ one binding's end and the next binding's start is exactly whatever sits
144
+ between them — empty when the file has no blank line there, the blank
145
+ line's own line terminator when it does, or just the next binding's
146
+ leading indentation when the language wraps bindings in an indented
147
+ block (Java, C#, a class-wrapped JS/TS style) and there is no blank
148
+ line. That last case is whitespace-only but has no newline in it —
149
+ `gap.strip() == ""` alone can't tell it apart from a genuine blank
150
+ line, so a join is only counted as separated when the gap is BOTH
151
+ whitespace-only AND actually contains a newline (a blank line always
152
+ has one; bare indentation never does). Defaults to `True` when there
153
+ are fewer than two bindings to compare, matching the
154
+ blank-line-between-methods style most existing step-definition files
155
+ already use."""
156
+ comparable = bindings[:-1]
157
+ if not comparable:
158
+ return True
159
+ separated = sum(
160
+ 1
161
+ for i, binding in enumerate(comparable)
162
+ if (gap := existing_text[binding.end : bindings[i + 1].start])
163
+ and gap.strip() == ""
164
+ and "\n" in gap
165
+ )
166
+ return separated * 2 >= len(comparable)
167
+
168
+
169
+ def _splice_single_point(existing_text: str, bindings: list, new_candidates: list) -> str:
170
+ """The default splice: append every new candidate's text as one block
171
+ right after the last existing binding (or at file end with no existing
172
+ bindings) — correct whenever a binding's `text` already contains
173
+ everything the language needs (JS/TS, Java, C#).
174
+
175
+ The last existing binding sits at the splice point with nothing after
176
+ it, so its own text alone can't say whether this file puts a blank
177
+ line between step definitions — infer that from the *other* existing
178
+ joins instead (`_existing_bindings_use_blank_line_separator`) and
179
+ reproduce it here, so a splice landing flush against the last existing
180
+ method's closing brace doesn't silently drop the blank line every
181
+ other method boundary in the file already has."""
182
+ insertion_point = bindings[-1].end if bindings else len(existing_text)
183
+ insertion = "".join(candidate.text for candidate in new_candidates)
184
+ if bindings and insertion and _existing_bindings_use_blank_line_separator(existing_text, bindings):
185
+ insertion = "\n" + insertion
186
+ return _insert_at(existing_text, insertion_point, insertion)
187
+
188
+
189
+ def _splice_go_two_part(existing_text: str, bindings: list, new_candidates: list) -> str:
190
+ """Go-only splice: a new step needs its function declaration inserted
191
+ at the top level (safe anywhere alongside the other existing step
192
+ functions — Go has no forward-declaration ordering requirement) and its
193
+ `sc.Step(...)` registration inserted separately, inside the existing
194
+ registration function (right after the last existing registration,
195
+ `bindings[-1].end` — unchanged from the single-point case). Applying
196
+ the two splices from the higher offset down means neither invalidates
197
+ the other's not-yet-applied position.
198
+
199
+ When `bindings` is empty — an existing, non-empty `.go` file whose
200
+ `InitializeScenario` has no `sc.Step(...)` calls yet (issue #1421 bug 1)
201
+ — there is no existing binding to anchor against. Anchor the call just
202
+ before `InitializeScenario`'s own closing brace (so it lands inside a
203
+ function body, not as an invalid top-level statement) and the
204
+ declaration at that function's own top-level start. Falls back to
205
+ appending both at file end (declaration first) only if
206
+ `InitializeScenario` itself can't be found or bounded — a shape this
207
+ module's own tests never produce, but still handled rather than raising."""
208
+ decl_text = "".join(c.decl_text or "" for c in new_candidates)
209
+ call_text = "".join(c.text for c in new_candidates)
210
+
211
+ if bindings:
212
+ decl_starts = [b.decl_start for b in bindings if b.decl_start is not None]
213
+ call_anchor = bindings[-1].end
214
+ decl_anchor = min(decl_starts) if decl_starts else call_anchor
215
+ else:
216
+ registration_body = _go_extractor.find_scenario_initializer_body(existing_text)
217
+ if registration_body is not None and registration_body.error is None:
218
+ call_anchor = registration_body.end - 1 # just before the closing '}'
219
+ decl_anchor = registration_body.decl_start
220
+ else:
221
+ call_anchor = decl_anchor = len(existing_text)
222
+
223
+ if call_anchor >= decl_anchor:
224
+ text = _insert_at(existing_text, call_anchor, call_text)
225
+ text = _insert_at(text, decl_anchor, decl_text)
226
+ else:
227
+ text = _insert_at(existing_text, decl_anchor, decl_text)
228
+ text = _insert_at(text, call_anchor, call_text)
229
+ return text
230
+
231
+
232
+ def merge_steps(existing_text: str, ext: str, candidate_steps: list) -> MergeResult:
233
+ """Append-only merge of `candidate_steps` into `existing_text`.
234
+
235
+ Relays `parse_existing_steps`'s structural-error sentinel unchanged when
236
+ the existing file can't be bounded — this function never re-derives or
237
+ guesses the cause. When `existing_text` is empty, the candidates' own
238
+ text is the entire file (no skeleton is synthesized — that is the
239
+ caller's concern, mirroring `merge_scenarios`'s identical empty-file
240
+ branch; for Go specifically this means a caller composing a genuinely
241
+ new file must supply a complete registration-function wrapper in one
242
+ candidate's `text`/`decl_text` — this function only concatenates, it
243
+ never synthesizes one)."""
244
+ candidate_steps, self_duplicate_patterns = _dedupe_candidates(candidate_steps)
245
+
246
+ if not existing_text:
247
+ decl_body = "".join(candidate.decl_text or "" for candidate in candidate_steps)
248
+ call_body = "".join(candidate.text for candidate in candidate_steps)
249
+ return MergeResult(
250
+ text=decl_body + call_body,
251
+ added_patterns=[candidate.pattern for candidate in candidate_steps],
252
+ skipped_duplicate_patterns=self_duplicate_patterns,
253
+ error=None,
254
+ )
255
+
256
+ result = parse_existing_steps(existing_text, ext)
257
+ if result.error is not None:
258
+ return MergeResult(
259
+ text=existing_text,
260
+ added_patterns=[],
261
+ skipped_duplicate_patterns=[],
262
+ error=result.error,
263
+ )
264
+
265
+ existing_patterns = {binding.pattern.strip() for binding in result.bindings}
266
+ new_candidates = [c for c in candidate_steps if c.pattern.strip() not in existing_patterns]
267
+ skipped = self_duplicate_patterns + [
268
+ c.pattern for c in candidate_steps if c.pattern.strip() in existing_patterns
269
+ ]
270
+
271
+ if not new_candidates:
272
+ return MergeResult(
273
+ text=existing_text, added_patterns=[], skipped_duplicate_patterns=skipped, error=None
274
+ )
275
+
276
+ is_go = ext.lower() == ".go"
277
+ if is_go:
278
+ merged_text = _splice_go_two_part(existing_text, result.bindings, new_candidates)
279
+ else:
280
+ merged_text = _splice_single_point(existing_text, result.bindings, new_candidates)
281
+
282
+ return MergeResult(
283
+ text=merged_text,
284
+ added_patterns=[c.pattern for c in new_candidates],
285
+ skipped_duplicate_patterns=skipped,
286
+ error=None,
287
+ )
288
+
289
+
290
+ def parse_candidate_steps(text: str, ext: str) -> tuple:
291
+ """Parse a `--candidates` scratch file's step-definition text (the same
292
+ syntax as an existing file's bindings — a candidates file is just
293
+ syntactically-valid step-definition fragments, no separate schema)
294
+ into `(candidates, error)`. Mirrors
295
+ `gherkin_feature_merge.parse_candidate_units`'s reuse of the same parser
296
+ used for existing content."""
297
+ result = parse_existing_steps(text, ext)
298
+ if result.error is not None:
299
+ return [], result.error
300
+ candidates = [
301
+ StepCandidate(pattern=b.pattern, text=b.text, decl_text=b.decl_text) for b in result.bindings
302
+ ]
303
+ return candidates, None
304
+
305
+
306
+ def _write_error(message: str) -> None:
307
+ sys.stderr.write(message + "\n")
308
+
309
+
310
+ def _reject_path_traversal(raw: str) -> str | None:
311
+ """Return an error message if `raw` contains a `..` path component, else
312
+ `None`. `--existing` is composed by `gherkin-derive/SKILL.md` Step 4 from
313
+ a surface name derived from the target repository's own content, not
314
+ always typed by a human — mirrors
315
+ `gherkin_feature_merge._reject_path_traversal` exactly."""
316
+ if ".." in Path(raw).parts:
317
+ return f"--existing {raw!r} must not contain a '..' path component"
318
+ return None
319
+
320
+
321
+ def _merge_payload(written: bool, added=(), skipped=(), error=None) -> dict:
322
+ """The one JSON shape every `merge` response uses, named once so a future
323
+ field addition touches this single place rather than every call site
324
+ rebuilding the dict by hand — mirrors `gherkin_feature_merge._merge_payload`."""
325
+ return {
326
+ "written": written,
327
+ "added_patterns": list(added),
328
+ "skipped_duplicate_patterns": list(skipped),
329
+ "error": error,
330
+ }
331
+
332
+
333
+ def _write_atomic(path: Path, text: str) -> None:
334
+ """Write `text` to `path` via a same-directory temp file + os.replace, so
335
+ a crash or kill mid-write can never leave a truncated/corrupted
336
+ step-definition file — identical pattern to
337
+ `gherkin_feature_merge._write_atomic`."""
338
+ fd, tmp_name = tempfile.mkstemp(dir=str(path.parent), prefix=f".{path.name}.", suffix=".tmp")
339
+ try:
340
+ with os.fdopen(fd, "w", encoding="utf-8") as tmp_file:
341
+ tmp_file.write(text)
342
+ os.replace(tmp_name, path)
343
+ except BaseException:
344
+ Path(tmp_name).unlink(missing_ok=True)
345
+ raise
346
+
347
+
348
+ def _cmd_merge(args: argparse.Namespace) -> int:
349
+ # Known limitation (concurrency-review, issue #1421 consistency with
350
+ # gherkin_feature_merge.py): read-then-write here is still a TOCTOU race
351
+ # if two `merge` invocations ever target the same --existing path
352
+ # concurrently — whichever writes last silently wins (the atomic write
353
+ # below only rules out a truncated file, not a lost update between two
354
+ # racing invocations). Not fixed: gherkin-derive's own design invokes
355
+ # this once per surface, sequentially, never in parallel against the
356
+ # same file (see gherkin-derive/SKILL.md Step 4), so there is no known
357
+ # live trigger; a cross-platform lock (fcntl vs. msvcrt) would close
358
+ # this remaining gap but is a design call for a human to make, not a
359
+ # mechanical fix — deliberately left to a human decision rather than
360
+ # guessed at here.
361
+ path_error = _reject_path_traversal(args.existing)
362
+ if path_error is not None:
363
+ if args.json:
364
+ print(json.dumps(_merge_payload(written=False, error=ERROR_UNSAFE_PATH)))
365
+ else:
366
+ _write_error(f"gherkin_stub_merge: {path_error} — no steps merged")
367
+ return 2
368
+
369
+ existing_path = Path(args.existing)
370
+ existing_text = existing_path.read_text(encoding="utf-8") if existing_path.is_file() else ""
371
+
372
+ try:
373
+ candidates_text = Path(args.candidates).read_text(encoding="utf-8")
374
+ except OSError as exc:
375
+ # Missing/unreadable --candidates (not found, a directory, denied
376
+ # permission, bad encoding, ...) used to escape as a raw traceback —
377
+ # issue #1421 bug 6.
378
+ if args.json:
379
+ print(json.dumps(_merge_payload(written=False, error=ERROR_UNREADABLE_CANDIDATES)))
380
+ else:
381
+ _write_error(
382
+ f"gherkin_stub_merge: --candidates {_safe_for_terminal(args.candidates)} "
383
+ f"could not be read ({exc}) — no steps merged"
384
+ )
385
+ return 2
386
+
387
+ try:
388
+ candidate_steps, candidates_error = parse_candidate_steps(candidates_text, args.ext)
389
+ except ValueError:
390
+ # An --ext with no known step-definition language (argparse has no
391
+ # `choices=` for it) used to escape parse_existing_steps's
392
+ # ValueError as a raw traceback — issue #1421 bug 6.
393
+ if args.json:
394
+ print(json.dumps(_merge_payload(written=False, error=ERROR_UNSUPPORTED_EXTENSION)))
395
+ else:
396
+ _write_error(
397
+ f"gherkin_stub_merge: --ext {args.ext!r} is not a supported "
398
+ "step-definition extension — no steps merged"
399
+ )
400
+ return 2
401
+
402
+ if candidates_error is not None:
403
+ if args.json:
404
+ print(json.dumps(_merge_payload(written=False, error=ERROR_MALFORMED_CANDIDATES)))
405
+ else:
406
+ _write_error(
407
+ f"gherkin_stub_merge: candidates file {_safe_for_terminal(args.candidates)} "
408
+ f"is malformed (error={candidates_error}) — no steps merged, existing file "
409
+ f"left untouched"
410
+ )
411
+ return 2
412
+
413
+ result = merge_steps(existing_text, args.ext, candidate_steps)
414
+
415
+ if result.error is not None:
416
+ if args.json:
417
+ print(json.dumps(_merge_payload(written=False, error=result.error)))
418
+ else:
419
+ _write_error(
420
+ f"gherkin_stub_merge: {_safe_for_terminal(args.existing)} structure could not "
421
+ f"be parsed (error={result.error}) — no steps merged, existing file left "
422
+ f"untouched"
423
+ )
424
+ return 2
425
+
426
+ if args.dry_run:
427
+ if args.json:
428
+ print(
429
+ json.dumps(
430
+ _merge_payload(
431
+ written=False,
432
+ added=result.added_patterns,
433
+ skipped=result.skipped_duplicate_patterns,
434
+ )
435
+ )
436
+ )
437
+ else:
438
+ sys.stdout.write(result.text)
439
+ return 0
440
+
441
+ existing_path.parent.mkdir(parents=True, exist_ok=True)
442
+ _write_atomic(existing_path, result.text)
443
+
444
+ if args.json:
445
+ print(
446
+ json.dumps(
447
+ _merge_payload(
448
+ written=True,
449
+ added=result.added_patterns,
450
+ skipped=result.skipped_duplicate_patterns,
451
+ )
452
+ )
453
+ )
454
+ else:
455
+ print(
456
+ f"OK: merged {len(result.added_patterns)} new step(s) into "
457
+ f"{_safe_for_terminal(args.existing)}"
458
+ )
459
+ return 0
460
+
461
+
462
+ def main(argv: list | None = None) -> int:
463
+ parser = argparse.ArgumentParser(prog="gherkin_stub_merge.py")
464
+ sub = parser.add_subparsers(dest="command", required=True)
465
+
466
+ merge_parser = sub.add_parser("merge")
467
+ merge_parser.add_argument("--existing", required=True)
468
+ merge_parser.add_argument("--candidates", required=True)
469
+ merge_parser.add_argument("--ext", required=True)
470
+ merge_parser.add_argument("--dry-run", action="store_true")
471
+ merge_parser.add_argument("--json", action="store_true")
472
+ merge_parser.set_defaults(func=_cmd_merge)
473
+
474
+ args = parser.parse_args(argv)
475
+ return args.func(args)
476
+
477
+
478
+ if __name__ == "__main__": # pragma: no cover
479
+ sys.exit(main())