@ngocsangairvds/vsaf 4.0.6 → 4.0.8

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 (1076) hide show
  1. package/README.md +7 -5
  2. package/package.json +2 -2
  3. package/packages/cli/dist/commands/init.d.ts.map +1 -1
  4. package/packages/cli/dist/commands/init.js +25 -14
  5. package/packages/cli/dist/commands/init.js.map +1 -1
  6. package/packages/cli/dist/commands/install.js +1 -1
  7. package/packages/cli/dist/commands/install.js.map +1 -1
  8. package/packages/cli/dist/commands/skill.js +8 -8
  9. package/packages/cli/dist/commands/skill.js.map +1 -1
  10. package/packages/core/dist/skills/skill-loader.d.ts.map +1 -1
  11. package/packages/core/dist/skills/skill-loader.js +9 -4
  12. package/packages/core/dist/skills/skill-loader.js.map +1 -1
  13. package/skills/sdlc/architecture/SKILL.md +22 -8
  14. package/skills/sdlc/bmad-checkpoint-preview/SKILL.md +29 -0
  15. package/skills/sdlc/bmad-checkpoint-preview/generate-trail.md +38 -0
  16. package/skills/sdlc/bmad-checkpoint-preview/step-01-orientation.md +105 -0
  17. package/skills/sdlc/bmad-checkpoint-preview/step-02-walkthrough.md +89 -0
  18. package/skills/sdlc/bmad-checkpoint-preview/step-03-detail-pass.md +106 -0
  19. package/skills/sdlc/bmad-checkpoint-preview/step-04-testing.md +74 -0
  20. package/skills/sdlc/bmad-checkpoint-preview/step-05-wrapup.md +24 -0
  21. package/skills/sdlc/bmad-correct-course/SKILL.md +6 -0
  22. package/skills/sdlc/bmad-correct-course/checklist.md +288 -0
  23. package/skills/sdlc/bmad-correct-course/workflow.md +267 -0
  24. package/skills/sdlc/discovery/SKILL.md +2 -2
  25. package/skills/sdlc/pack.yaml +3 -1
  26. package/skills/sdlc/prd/SKILL.md +20 -5
  27. package/skills/sdlc/review/SKILL.md +9 -5
  28. package/skills/sdlc/sdlc-health/SKILL.md +5 -3
  29. package/skills/sdlc/setup/SKILL.md +1 -1
  30. package/skills/sdlc/srs/SKILL.md +7 -6
  31. package/skills/sdlc/test-design/SKILL.md +10 -6
  32. package/skills/sdlc/workflows/hotfix-tdd.yaml +2 -2
  33. package/skills/sdlc/workflows/hotfix.yaml +5 -5
  34. package/skills/sdlc/workflows/master-sdlc.yaml +9 -9
  35. package/skills/sdlc/workflows/onboarding.yaml +2 -2
  36. package/skills/sdlc/workflows/sdlc-build.yaml +1 -1
  37. package/skills/sdlc/workflows/sdlc-design.yaml +2 -2
  38. package/skills/sdlc/workflows/sdlc-qa.yaml +3 -3
  39. package/skills/sdlc/workflows/sdlc-testcase.yaml +1 -1
  40. package/skills/sdlc/workflows/sdlc-thinking.yaml +2 -2
  41. package/skills/vds-skill/install-deps.mjs +20 -4
  42. package/skills/vds-skill/vds-scripts/.claude/phase7-CLOSURE.md +100 -0
  43. package/skills/vds-skill/vds-scripts/.dockerignore +62 -0
  44. package/skills/vds-skill/vds-scripts/.github/ISSUE_TEMPLATE/cli-change.md +92 -0
  45. package/skills/vds-skill/vds-scripts/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +48 -0
  46. package/skills/vds-skill/vds-scripts/.github/workflows/chaos-smoke.yml +266 -0
  47. package/skills/vds-skill/vds-scripts/.github/workflows/confluence-sync.yml +44 -0
  48. package/skills/vds-skill/vds-scripts/.github/workflows/docs-confluence-evidence.yml +170 -0
  49. package/skills/vds-skill/vds-scripts/.github/workflows/docs-quality.yml +59 -0
  50. package/skills/vds-skill/vds-scripts/.github/workflows/lint-and-test.yml +90 -0
  51. package/skills/vds-skill/vds-scripts/.github/workflows/scheduler-load-smoke.yml +104 -0
  52. package/skills/vds-skill/vds-scripts/.github/workflows/telegram-bridge-ci.yml +131 -0
  53. package/skills/vds-skill/vds-scripts/.graphifyignore +29 -0
  54. package/skills/vds-skill/vds-scripts/.importlinter +86 -0
  55. package/skills/vds-skill/vds-scripts/.mcp.json +11 -0
  56. package/skills/vds-skill/vds-scripts/.pre-commit-config.yaml +62 -0
  57. package/skills/vds-skill/vds-scripts/.ruffignore +3 -0
  58. package/skills/vds-skill/vds-scripts/.secrets.baseline +133 -0
  59. package/skills/vds-skill/vds-scripts/AGENTS.md +250 -0
  60. package/skills/vds-skill/vds-scripts/AGENTS.vi.md +92 -0
  61. package/skills/vds-skill/vds-scripts/ECOSYSTEM-CHANGELOG.md +52 -0
  62. package/skills/vds-skill/vds-scripts/ECOSYSTEM-DOCS.md +602 -0
  63. package/skills/vds-skill/vds-scripts/ECOSYSTEM_ALIGNMENT.md +133 -0
  64. package/skills/vds-skill/vds-scripts/Makefile +119 -0
  65. package/skills/vds-skill/vds-scripts/README.md +103 -0
  66. package/skills/vds-skill/vds-scripts/bitbucket_manifest_mapping.toml +34 -0
  67. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/ARCHITECTURE_ANALYSIS.md +258 -0
  68. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/BITBUCKET_API_PRACTICES.md +393 -0
  69. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/EVALUATION_REPORT.md +61 -0
  70. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/FEATURES.md +908 -0
  71. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/README.md +817 -0
  72. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/pyproject.toml +49 -0
  73. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/__init__.py +50 -0
  74. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/async_client.py +641 -0
  75. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/cli.py +2271 -0
  76. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/client.py +2693 -0
  77. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/config.py +186 -0
  78. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/errors.py +34 -0
  79. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/factory.py +185 -0
  80. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/parsers.py +113 -0
  81. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/protocols.py +244 -0
  82. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/repo_ops.py +325 -0
  83. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/__init__.py +8 -0
  84. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/conftest.py +65 -0
  85. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_advanced_search.py +155 -0
  86. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_async_client.py +505 -0
  87. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_branch_permissions.py +172 -0
  88. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_cli.py +113 -0
  89. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_cli_archive.py +122 -0
  90. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_cli_clone.py +131 -0
  91. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_client.py +207 -0
  92. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_client_archive.py +73 -0
  93. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_client_branch_conditions.py +101 -0
  94. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_client_code_advanced.py +180 -0
  95. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_client_code_file.py +33 -0
  96. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_client_deployment_environments.py +193 -0
  97. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_client_issues.py +163 -0
  98. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_client_pipelines_advanced.py +171 -0
  99. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_client_pr_blockers.py +118 -0
  100. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_client_repository_variables.py +155 -0
  101. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_code.py +98 -0
  102. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_code_advanced.py +279 -0
  103. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_code_insights.py +334 -0
  104. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_conditions.py +149 -0
  105. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_config.py +297 -0
  106. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_deployment_env.py +352 -0
  107. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_errors.py +67 -0
  108. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_factory.py +352 -0
  109. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_fork_operations.py +203 -0
  110. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_issue_cli.py +262 -0
  111. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_pipeline_advanced.py +265 -0
  112. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_pr_blocker.py +206 -0
  113. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_protocols.py +336 -0
  114. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_repo_ops_archive.py +169 -0
  115. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_repo_ops_clone.py +115 -0
  116. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_repo_ops_parsing.py +149 -0
  117. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_repo_settings.py +336 -0
  118. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_repo_variables.py +266 -0
  119. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_webhooks.py +188 -0
  120. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/test_workspace.py +234 -0
  121. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/unit/__init__.py +0 -0
  122. package/skills/vds-skill/vds-scripts/bitbucket_orchestrator/tests/unit/test_parsers.py +254 -0
  123. package/skills/vds-skill/vds-scripts/brd_orchestrator/README.md +29 -0
  124. package/skills/vds-skill/vds-scripts/brd_orchestrator/pyproject.toml +63 -0
  125. package/skills/vds-skill/vds-scripts/brd_orchestrator/src/vds_brd_orchestrator/__init__.py +17 -0
  126. package/skills/vds-skill/vds-scripts/brd_orchestrator/src/vds_brd_orchestrator/cli.py +187 -0
  127. package/skills/vds-skill/vds-scripts/brd_orchestrator/src/vds_brd_orchestrator/validator.py +121 -0
  128. package/skills/vds-skill/vds-scripts/brd_orchestrator/tests/__init__.py +0 -0
  129. package/skills/vds-skill/vds-scripts/brd_orchestrator/tests/test_cli.py +62 -0
  130. package/skills/vds-skill/vds-scripts/brd_orchestrator/tests/test_validator.py +33 -0
  131. package/skills/vds-skill/vds-scripts/code/code_evidence_pack.json +435 -0
  132. package/skills/vds-skill/vds-scripts/confluence_orchestrator/Dockerfile +19 -0
  133. package/skills/vds-skill/vds-scripts/confluence_orchestrator/README.md +479 -0
  134. package/skills/vds-skill/vds-scripts/confluence_orchestrator/SYNC_SCRIPTS.md +127 -0
  135. package/skills/vds-skill/vds-scripts/confluence_orchestrator/SYNC_STANDARDIZATION.md +108 -0
  136. package/skills/vds-skill/vds-scripts/confluence_orchestrator/pyproject.toml +50 -0
  137. package/skills/vds-skill/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/__init__.py +56 -0
  138. package/skills/vds-skill/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/async_client.py +100 -0
  139. package/skills/vds-skill/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/cli.py +3160 -0
  140. package/skills/vds-skill/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/config.py +215 -0
  141. package/skills/vds-skill/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/content.py +368 -0
  142. package/skills/vds-skill/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/content_v2.py +144 -0
  143. package/skills/vds-skill/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/crawl_tree.py +1833 -0
  144. package/skills/vds-skill/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/errors.py +44 -0
  145. package/skills/vds-skill/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/eventing.py +111 -0
  146. package/skills/vds-skill/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/http.py +1850 -0
  147. package/skills/vds-skill/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/orchestration.py +166 -0
  148. package/skills/vds-skill/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/protocols.py +61 -0
  149. package/skills/vds-skill/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/reporting.py +78 -0
  150. package/skills/vds-skill/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/tree.py +122 -0
  151. package/skills/vds-skill/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/tree_copier.py +431 -0
  152. package/skills/vds-skill/vds-scripts/confluence_orchestrator/sync_pdfs_from_markdown.py +203 -0
  153. package/skills/vds-skill/vds-scripts/confluence_orchestrator/sync_pdfs_to_confluence.py +299 -0
  154. package/skills/vds-skill/vds-scripts/confluence_orchestrator/sync_png_attachments.py +299 -0
  155. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/conftest.py +46 -0
  156. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_advanced_content.py +252 -0
  157. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_advanced_search.py +193 -0
  158. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_async_client.py +104 -0
  159. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_cache_management.py +246 -0
  160. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_cli.py +716 -0
  161. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_config.py +130 -0
  162. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_content.py +192 -0
  163. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_content_flags.py +27 -0
  164. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_content_labels.py +94 -0
  165. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_crawl_tree.py +2252 -0
  166. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_degraded_write_safety.py +176 -0
  167. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_draft_management.py +225 -0
  168. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_errors.py +75 -0
  169. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_eventing.py +73 -0
  170. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_eventing_chaos.py +37 -0
  171. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_eventing_rate_limit.py +44 -0
  172. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_eventing_timeout.py +49 -0
  173. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_export.py +231 -0
  174. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_history.py +217 -0
  175. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_http.py +375 -0
  176. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_orchestration.py +93 -0
  177. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_reporting.py +24 -0
  178. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_search_cql.py +36 -0
  179. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_space_management.py +236 -0
  180. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_space_permissions.py +384 -0
  181. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_tree_copier.py +644 -0
  182. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_tree_copier_remap.py +289 -0
  183. package/skills/vds-skill/vds-scripts/confluence_orchestrator/tests/test_user_group_management.py +387 -0
  184. package/skills/vds-skill/vds-scripts/diagram_generator/README.md +663 -0
  185. package/skills/vds-skill/vds-scripts/diagram_generator/ci_validate.sh +16 -0
  186. package/skills/vds-skill/vds-scripts/diagram_generator/docs-nttc/projects/INSURANCE/analysis/current-state/insurance-claim-business/insurance-claim-business-component.png +0 -0
  187. package/skills/vds-skill/vds-scripts/diagram_generator/docs-nttc/projects/INSURANCE/analysis/current-state/insurance-claim-business/insurance-claim-business-component.puml +23 -0
  188. package/skills/vds-skill/vds-scripts/diagram_generator/docs-nttc/projects/INSURANCE/analysis/current-state/insurance-claim-business/insurance-claim-business-sequence.png +0 -0
  189. package/skills/vds-skill/vds-scripts/diagram_generator/docs-nttc/projects/INSURANCE/analysis/current-state/insurance-claim-business/insurance-claim-business-sequence.puml +21 -0
  190. package/skills/vds-skill/vds-scripts/diagram_generator/docs-nttc/projects/INSURANCE/analysis/current-state/insurance-claim-business/insurance-claim-business-usecase.png +0 -0
  191. package/skills/vds-skill/vds-scripts/diagram_generator/docs-nttc/projects/INSURANCE/analysis/current-state/insurance-claim-business/insurance-claim-business-usecase.puml +14 -0
  192. package/skills/vds-skill/vds-scripts/diagram_generator/examples/github-actions-validate.yml +39 -0
  193. package/skills/vds-skill/vds-scripts/diagram_generator/generate_all_diagrams.py +827 -0
  194. package/skills/vds-skill/vds-scripts/diagram_generator/generate_insurance_c4_diagrams.py +261 -0
  195. package/skills/vds-skill/vds-scripts/diagram_generator/generate_insurance_c4_quick.py +486 -0
  196. package/skills/vds-skill/vds-scripts/diagram_generator/pyproject.toml +28 -0
  197. package/skills/vds-skill/vds-scripts/diagram_generator/render_png.py +59 -0
  198. package/skills/vds-skill/vds-scripts/diagram_generator/src/vds_diagram_generator/__init__.py +3 -0
  199. package/skills/vds-skill/vds-scripts/diagram_generator/src/vds_diagram_generator/cli.py +50 -0
  200. package/skills/vds-skill/vds-scripts/diagram_generator/test_c4_hierarchical.py +142 -0
  201. package/skills/vds-skill/vds-scripts/diagram_generator/test_c4_quick.py +131 -0
  202. package/skills/vds-skill/vds-scripts/diagram_generator/tests/__init__.py +0 -0
  203. package/skills/vds-skill/vds-scripts/diagram_generator/tests/test_analyzer_completeness.py +260 -0
  204. package/skills/vds-skill/vds-scripts/diagram_generator/tests/test_c4_syntax_correctness.py +138 -0
  205. package/skills/vds-skill/vds-scripts/diagram_generator/tests/test_component_coverage.py +182 -0
  206. package/skills/vds-skill/vds-scripts/diagram_generator/tests/test_mermaid_output.py +80 -0
  207. package/skills/vds-skill/vds-scripts/diagram_generator/tests/test_png_generation.py +112 -0
  208. package/skills/vds-skill/vds-scripts/diagram_generator/tests/test_scenario_templates.py +15 -0
  209. package/skills/vds-skill/vds-scripts/diagram_generator/tests/test_sequence_accuracy.py +93 -0
  210. package/skills/vds-skill/vds-scripts/diagram_generator/tests/test_structurizr_export.py +177 -0
  211. package/skills/vds-skill/vds-scripts/diagram_generator/tests/test_style_consistency.py +174 -0
  212. package/skills/vds-skill/vds-scripts/diagram_generator/tests/test_usecase_generator.py +201 -0
  213. package/skills/vds-skill/vds-scripts/diagram_generator/tests/test_usecase_integration.py +124 -0
  214. package/skills/vds-skill/vds-scripts/docker/.dockerignore +38 -0
  215. package/skills/vds-skill/vds-scripts/docker/ADR.md +392 -0
  216. package/skills/vds-skill/vds-scripts/docker/Dockerfile +68 -0
  217. package/skills/vds-skill/vds-scripts/docker/MIGRATION.md +453 -0
  218. package/skills/vds-skill/vds-scripts/docker/README.md +347 -0
  219. package/skills/vds-skill/vds-scripts/docker/ROLLBACK.md +596 -0
  220. package/skills/vds-skill/vds-scripts/docker/compose.phase2-verification.yml +31 -0
  221. package/skills/vds-skill/vds-scripts/docker/docker-compose.cli.yml +206 -0
  222. package/skills/vds-skill/vds-scripts/docker/docker-compose.infra.yml +276 -0
  223. package/skills/vds-skill/vds-scripts/docker/docker-compose.services.yml +425 -0
  224. package/skills/vds-skill/vds-scripts/docker/infrastructure/init-schemas.sql +177 -0
  225. package/skills/vds-skill/vds-scripts/docker/infrastructure/pgbouncer/pgbouncer.ini +75 -0
  226. package/skills/vds-skill/vds-scripts/docker/infrastructure/pgbouncer/userlist.txt +50 -0
  227. package/skills/vds-skill/vds-scripts/docker/infrastructure/pgbouncer/userlist.txt.template +36 -0
  228. package/skills/vds-skill/vds-scripts/docs/.confluence-evidence/.gitkeep +0 -0
  229. package/skills/vds-skill/vds-scripts/docs/.confluence-evidence/PREFLIGHT.md +132 -0
  230. package/skills/vds-skill/vds-scripts/docs/.confluence-evidence/README.md +84 -0
  231. package/skills/vds-skill/vds-scripts/docs/.confluence.yaml +157 -0
  232. package/skills/vds-skill/vds-scripts/docs/.freshness.yaml +54 -0
  233. package/skills/vds-skill/vds-scripts/docs/README.md +235 -0
  234. package/skills/vds-skill/vds-scripts/docs/agents/README.md +33 -0
  235. package/skills/vds-skill/vds-scripts/docs/agents/explanation/data-flow.md +132 -0
  236. package/skills/vds-skill/vds-scripts/docs/agents/explanation/development-roadmap.md +49 -0
  237. package/skills/vds-skill/vds-scripts/docs/agents/explanation/features-overview.md +62 -0
  238. package/skills/vds-skill/vds-scripts/docs/agents/explanation/index.md +36 -0
  239. package/skills/vds-skill/vds-scripts/docs/agents/explanation/runtime-verification-and-gap-reporting.md +127 -0
  240. package/skills/vds-skill/vds-scripts/docs/agents/explanation/system-architecture.md +139 -0
  241. package/skills/vds-skill/vds-scripts/docs/agents/explanation/whats-new.md +75 -0
  242. package/skills/vds-skill/vds-scripts/docs/agents/explanation/who-ecosystem-introduction.md +65 -0
  243. package/skills/vds-skill/vds-scripts/docs/agents/explanation/who-ecosystem-model.md +41 -0
  244. package/skills/vds-skill/vds-scripts/docs/agents/how-to/02-using-vds-ai-memory.md +98 -0
  245. package/skills/vds-skill/vds-scripts/docs/agents/how-to/03-memory-cross-agent.md +241 -0
  246. package/skills/vds-skill/vds-scripts/docs/agents/how-to/04-using-progress-reports.md +240 -0
  247. package/skills/vds-skill/vds-scripts/docs/agents/how-to/08-semantic-search.md +46 -0
  248. package/skills/vds-skill/vds-scripts/docs/agents/how-to/apply-phase3-migration.md +148 -0
  249. package/skills/vds-skill/vds-scripts/docs/agents/how-to/choose-the-right-command-or-skill.md +34 -0
  250. package/skills/vds-skill/vds-scripts/docs/agents/how-to/contribute-new-orchestrator.md +149 -0
  251. package/skills/vds-skill/vds-scripts/docs/agents/how-to/decision-tree.md +63 -0
  252. package/skills/vds-skill/vds-scripts/docs/agents/how-to/first-audit-run.md +83 -0
  253. package/skills/vds-skill/vds-scripts/docs/agents/how-to/index.md +49 -0
  254. package/skills/vds-skill/vds-scripts/docs/agents/how-to/install-and-bootstrap-who-scripts-and-skills.md +314 -0
  255. package/skills/vds-skill/vds-scripts/docs/agents/how-to/orchestrator-workflows/analytics-pipeline-workflow.md +165 -0
  256. package/skills/vds-skill/vds-scripts/docs/agents/how-to/orchestrator-workflows/code-quality-gate-workflow.md +138 -0
  257. package/skills/vds-skill/vds-scripts/docs/agents/how-to/orchestrator-workflows/confluence-bitbucket-sync-workflow.md +130 -0
  258. package/skills/vds-skill/vds-scripts/docs/agents/how-to/orchestrator-workflows/document-delivery-workflow.md +142 -0
  259. package/skills/vds-skill/vds-scripts/docs/agents/how-to/orchestrator-workflows/memory-progress-workflow.md +140 -0
  260. package/skills/vds-skill/vds-scripts/docs/agents/how-to/orchestrator-workflows/research-spec-audit-workflow.md +135 -0
  261. package/skills/vds-skill/vds-scripts/docs/agents/how-to/phase131-all-project-preparation.md +211 -0
  262. package/skills/vds-skill/vds-scripts/docs/agents/how-to/phase131-bounded-parallel-analysis.md +123 -0
  263. package/skills/vds-skill/vds-scripts/docs/agents/how-to/phase131-confluence-upload-recovery.md +204 -0
  264. package/skills/vds-skill/vds-scripts/docs/agents/how-to/phase132-department-preparation.md +144 -0
  265. package/skills/vds-skill/vds-scripts/docs/agents/how-to/run-ecosystem-daily-report.md +213 -0
  266. package/skills/vds-skill/vds-scripts/docs/agents/how-to/tips-and-tricks.md +138 -0
  267. package/skills/vds-skill/vds-scripts/docs/agents/how-to/troubleshooting-guide.md +221 -0
  268. package/skills/vds-skill/vds-scripts/docs/agents/reference/agent-operational-contract.md +162 -0
  269. package/skills/vds-skill/vds-scripts/docs/agents/reference/alignment-phase179-report.md +144 -0
  270. package/skills/vds-skill/vds-scripts/docs/agents/reference/audit-triage-playbook.md +256 -0
  271. package/skills/vds-skill/vds-scripts/docs/agents/reference/backup-restore.md +132 -0
  272. package/skills/vds-skill/vds-scripts/docs/agents/reference/bitbucket-orchestrator.md +56 -0
  273. package/skills/vds-skill/vds-scripts/docs/agents/reference/brd-orchestrator.md +52 -0
  274. package/skills/vds-skill/vds-scripts/docs/agents/reference/capability-coverage-review.md +51 -0
  275. package/skills/vds-skill/vds-scripts/docs/agents/reference/ci-workflows.md +98 -0
  276. package/skills/vds-skill/vds-scripts/docs/agents/reference/circular-dependency-orchestrator.md +55 -0
  277. package/skills/vds-skill/vds-scripts/docs/agents/reference/cli-commands.md +583 -0
  278. package/skills/vds-skill/vds-scripts/docs/agents/reference/cli-development-standards.md +41 -0
  279. package/skills/vds-skill/vds-scripts/docs/agents/reference/cli-help-matrix.md +84 -0
  280. package/skills/vds-skill/vds-scripts/docs/agents/reference/common-errors.md +126 -0
  281. package/skills/vds-skill/vds-scripts/docs/agents/reference/configuration-reference.md +128 -0
  282. package/skills/vds-skill/vds-scripts/docs/agents/reference/confluence-orchestrator.md +56 -0
  283. package/skills/vds-skill/vds-scripts/docs/agents/reference/confluence-sync-target.md +111 -0
  284. package/skills/vds-skill/vds-scripts/docs/agents/reference/confluence-sync.md +46 -0
  285. package/skills/vds-skill/vds-scripts/docs/agents/reference/db-query-orchestrator.md +93 -0
  286. package/skills/vds-skill/vds-scripts/docs/agents/reference/diagrams-orchestrator.md +52 -0
  287. package/skills/vds-skill/vds-scripts/docs/agents/reference/ecosystem-daily-report.md +229 -0
  288. package/skills/vds-skill/vds-scripts/docs/agents/reference/elastic-orchestrator.md +57 -0
  289. package/skills/vds-skill/vds-scripts/docs/agents/reference/env-git-helper.md +216 -0
  290. package/skills/vds-skill/vds-scripts/docs/agents/reference/evolution-orchestrator.md +113 -0
  291. package/skills/vds-skill/vds-scripts/docs/agents/reference/excel-orchestrator.md +51 -0
  292. package/skills/vds-skill/vds-scripts/docs/agents/reference/git-orchestrator.md +62 -0
  293. package/skills/vds-skill/vds-scripts/docs/agents/reference/google-sheets-orchestrator.md +51 -0
  294. package/skills/vds-skill/vds-scripts/docs/agents/reference/grafana-orchestrator.md +52 -0
  295. package/skills/vds-skill/vds-scripts/docs/agents/reference/hexagonal-orchestrator.md +64 -0
  296. package/skills/vds-skill/vds-scripts/docs/agents/reference/index.md +36 -0
  297. package/skills/vds-skill/vds-scripts/docs/agents/reference/infrastructure-v2.15.md +67 -0
  298. package/skills/vds-skill/vds-scripts/docs/agents/reference/intellij-orchestrator.md +50 -0
  299. package/skills/vds-skill/vds-scripts/docs/agents/reference/jira-orchestrator.md +60 -0
  300. package/skills/vds-skill/vds-scripts/docs/agents/reference/links-orchestrator.md +57 -0
  301. package/skills/vds-skill/vds-scripts/docs/agents/reference/lint-cli.md +99 -0
  302. package/skills/vds-skill/vds-scripts/docs/agents/reference/lsp-orchestrator.md +51 -0
  303. package/skills/vds-skill/vds-scripts/docs/agents/reference/markdown-orchestrator.md +53 -0
  304. package/skills/vds-skill/vds-scripts/docs/agents/reference/mcp-orchestrator.md +88 -0
  305. package/skills/vds-skill/vds-scripts/docs/agents/reference/memory-orchestrator.md +53 -0
  306. package/skills/vds-skill/vds-scripts/docs/agents/reference/metabase-orchestrator.md +51 -0
  307. package/skills/vds-skill/vds-scripts/docs/agents/reference/migration-playbook.md +71 -0
  308. package/skills/vds-skill/vds-scripts/docs/agents/reference/multi-agent-orchestrator.md +52 -0
  309. package/skills/vds-skill/vds-scripts/docs/agents/reference/openapi-orchestrator.md +57 -0
  310. package/skills/vds-skill/vds-scripts/docs/agents/reference/orchestrator-architecture.md +194 -0
  311. package/skills/vds-skill/vds-scripts/docs/agents/reference/orchestrator-comparison-matrix.md +79 -0
  312. package/skills/vds-skill/vds-scripts/docs/agents/reference/orchestrator-index.md +73 -0
  313. package/skills/vds-skill/vds-scripts/docs/agents/reference/pdf-orchestrator.md +57 -0
  314. package/skills/vds-skill/vds-scripts/docs/agents/reference/portable-paths-and-config.md +0 -0
  315. package/skills/vds-skill/vds-scripts/docs/agents/reference/portable-paths-validation-matrix.md +129 -0
  316. package/skills/vds-skill/vds-scripts/docs/agents/reference/progress-orchestrator.md +51 -0
  317. package/skills/vds-skill/vds-scripts/docs/agents/reference/progress-report-cli.md +215 -0
  318. package/skills/vds-skill/vds-scripts/docs/agents/reference/public-interface-orchestrator.md +73 -0
  319. package/skills/vds-skill/vds-scripts/docs/agents/reference/research-orchestrator.md +53 -0
  320. package/skills/vds-skill/vds-scripts/docs/agents/reference/schema-orchestrator.md +57 -0
  321. package/skills/vds-skill/vds-scripts/docs/agents/reference/search-tools.md +34 -0
  322. package/skills/vds-skill/vds-scripts/docs/agents/reference/skills-commands.md +256 -0
  323. package/skills/vds-skill/vds-scripts/docs/agents/reference/skills-reference.md +32 -0
  324. package/skills/vds-skill/vds-scripts/docs/agents/reference/sonarqube-orchestrator.md +62 -0
  325. package/skills/vds-skill/vds-scripts/docs/agents/reference/spec-orchestrator.md +56 -0
  326. package/skills/vds-skill/vds-scripts/docs/agents/reference/structure-orchestrator.md +69 -0
  327. package/skills/vds-skill/vds-scripts/docs/agents/reference/system-requirements.md +76 -0
  328. package/skills/vds-skill/vds-scripts/docs/agents/reference/tasks-orchestrator.md +53 -0
  329. package/skills/vds-skill/vds-scripts/docs/agents/reference/validation-and-sync-notes.md +54 -0
  330. package/skills/vds-skill/vds-scripts/docs/agents/reference/vds-ai-memory-api.md +51 -0
  331. package/skills/vds-skill/vds-scripts/docs/agents/reference/vds-cli-reference.md +34 -0
  332. package/skills/vds-skill/vds-scripts/docs/agents/reference/who-capability-inventory.md +96 -0
  333. package/skills/vds-skill/vds-scripts/docs/agents/reference/who-capability-routing-matrix.md +14 -0
  334. package/skills/vds-skill/vds-scripts/docs/agents/tutorials/feature-progression-guide.md +112 -0
  335. package/skills/vds-skill/vds-scripts/docs/agents/tutorials/index.md +36 -0
  336. package/skills/vds-skill/vds-scripts/docs/agents/tutorials/quick-start.md +50 -0
  337. package/skills/vds-skill/vds-scripts/docs/agents/tutorials/who-skills-and-scripts-onboarding.md +47 -0
  338. package/skills/vds-skill/vds-scripts/docs/agents/tutorials/zero-to-productive-developer.md +339 -0
  339. package/skills/vds-skill/vds-scripts/docs/confluence/IMPLEMENTATION-SUMMARY.md +78 -0
  340. package/skills/vds-skill/vds-scripts/docs/confluence/SYNC-GUIDE.md +47 -0
  341. package/skills/vds-skill/vds-scripts/docs/deployment/offline-docker-image-load.md +59 -0
  342. package/skills/vds-skill/vds-scripts/docs/evolution-auto-run-rollout.md +325 -0
  343. package/skills/vds-skill/vds-scripts/docs/evolution-loop-deep-integration.md +496 -0
  344. package/skills/vds-skill/vds-scripts/docs/evolution-loop-integration-guide.md +359 -0
  345. package/skills/vds-skill/vds-scripts/docs/openspace-schema-snapshot.md +73 -0
  346. package/skills/vds-skill/vds-scripts/docs/operations/sla-mttr-policy.md +44 -0
  347. package/skills/vds-skill/vds-scripts/docs/p0-closure-evidence/SUMMARY.md +58 -0
  348. package/skills/vds-skill/vds-scripts/docs/p4-closure-evidence/.gitkeep +0 -0
  349. package/skills/vds-skill/vds-scripts/docs/p4-closure-evidence/smoke-20260427T024137Z-b95b586b.json +15 -0
  350. package/skills/vds-skill/vds-scripts/docs/p8-preflight-evidence/alembic-and-runtime-advisory-locks.md +45 -0
  351. package/skills/vds-skill/vds-scripts/docs/p8-preflight-evidence/dbos-listen-notify.md +54 -0
  352. package/skills/vds-skill/vds-scripts/docs/p8-preflight-evidence/pgbouncer-search-path-empirical.md +110 -0
  353. package/skills/vds-skill/vds-scripts/docs/p8-preflight-evidence/pgvector-set-local-audit.md +51 -0
  354. package/skills/vds-skill/vds-scripts/docs/p8-preflight-evidence/topology-decision-session-mode.md +57 -0
  355. package/skills/vds-skill/vds-scripts/docs/phases/CHANGELOG.md +103 -0
  356. package/skills/vds-skill/vds-scripts/docs/phases/PHASE_125_COMPLETION_AND_MERGE.md +212 -0
  357. package/skills/vds-skill/vds-scripts/docs/phases/phase125/IMPLEMENTATION_REPORT.md +227 -0
  358. package/skills/vds-skill/vds-scripts/docs/phases/phase125/TSK-125.10-11-implementation-summary.md +196 -0
  359. package/skills/vds-skill/vds-scripts/docs/phases/phase125/profile-patch-ollama-local-anthropic.md +122 -0
  360. package/skills/vds-skill/vds-scripts/docs/phases/phase125_completion_summary.md +369 -0
  361. package/skills/vds-skill/vds-scripts/docs/phases/phase125_llm_analysis_skill.md +164 -0
  362. package/skills/vds-skill/vds-scripts/docs/phases/phase125_merge_complete.md +147 -0
  363. package/skills/vds-skill/vds-scripts/docs/phases/phase125_skill_runtime_closure_20260321.md +91 -0
  364. package/skills/vds-skill/vds-scripts/docs/phases/phase2-portable-paths/closure-handoff-summary-2026-03-23.md +290 -0
  365. package/skills/vds-skill/vds-scripts/docs/phases/phase2-portable-paths/remaining-risk-register-2026-03-25.md +143 -0
  366. package/skills/vds-skill/vds-scripts/docs/phases/phase2-portable-paths/verification-evidence-2026-03-23.md +135 -0
  367. package/skills/vds-skill/vds-scripts/docs/v0-sunset-known-issues.md +88 -0
  368. package/skills/vds-skill/vds-scripts/docs/vi/TRANSLATION-BACKLOG.md +72 -0
  369. package/skills/vds-skill/vds-scripts/docs/vi/agents/README.md +41 -0
  370. package/skills/vds-skill/vds-scripts/docs/vi/agents/explanation/features-overview.md +29 -0
  371. package/skills/vds-skill/vds-scripts/docs/vi/agents/explanation/index.md +14 -0
  372. package/skills/vds-skill/vds-scripts/docs/vi/agents/explanation/runtime-verification-and-gap-reporting.md +129 -0
  373. package/skills/vds-skill/vds-scripts/docs/vi/agents/explanation/whats-new.md +37 -0
  374. package/skills/vds-skill/vds-scripts/docs/vi/agents/explanation/who-ecosystem-introduction.md +21 -0
  375. package/skills/vds-skill/vds-scripts/docs/vi/agents/explanation/who-ecosystem-model.md +36 -0
  376. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/02-using-vds-ai-memory.md +100 -0
  377. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/03-memory-cross-agent.md +243 -0
  378. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/04-using-progress-reports.md +242 -0
  379. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/08-semantic-search.md +16 -0
  380. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/choose-the-right-command-or-skill.md +36 -0
  381. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/decision-tree.md +77 -0
  382. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/first-audit-run.md +85 -0
  383. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/index.md +21 -0
  384. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/install-and-bootstrap-who-scripts-and-skills.md +156 -0
  385. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/orchestrator-workflows/analytics-pipeline-workflow.md +174 -0
  386. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/orchestrator-workflows/code-quality-gate-workflow.md +147 -0
  387. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/orchestrator-workflows/confluence-bitbucket-sync-workflow.md +139 -0
  388. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/orchestrator-workflows/document-delivery-workflow.md +151 -0
  389. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/orchestrator-workflows/memory-progress-workflow.md +149 -0
  390. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/orchestrator-workflows/research-spec-audit-workflow.md +144 -0
  391. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/phase131-all-project-preparation.md +213 -0
  392. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/phase131-bounded-parallel-analysis.md +125 -0
  393. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/phase131-confluence-upload-recovery.md +206 -0
  394. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/phase132-department-preparation.md +146 -0
  395. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/tips-and-tricks.md +34 -0
  396. package/skills/vds-skill/vds-scripts/docs/vi/agents/how-to/troubleshooting-guide.md +36 -0
  397. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/agent-operational-contract.md +98 -0
  398. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/audit-triage-playbook.md +258 -0
  399. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/bitbucket-orchestrator.md +30 -0
  400. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/brd-orchestrator.md +29 -0
  401. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/capability-coverage-review.md +46 -0
  402. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/circular-dependency-orchestrator.md +29 -0
  403. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/cli-commands.md +409 -0
  404. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/cli-development-standards.md +19 -0
  405. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/cli-help-matrix.md +71 -0
  406. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/common-errors.md +133 -0
  407. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/configuration-reference.md +25 -0
  408. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/confluence-orchestrator.md +30 -0
  409. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/db-query-orchestrator.md +34 -0
  410. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/diagrams-orchestrator.md +31 -0
  411. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/elastic-orchestrator.md +30 -0
  412. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/evolution-orchestrator.md +31 -0
  413. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/excel-orchestrator.md +60 -0
  414. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/git-orchestrator.md +31 -0
  415. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/google-sheets-orchestrator.md +60 -0
  416. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/grafana-orchestrator.md +30 -0
  417. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/hexagonal-orchestrator.md +73 -0
  418. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/index.md +25 -0
  419. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/intellij-orchestrator.md +59 -0
  420. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/jira-orchestrator.md +32 -0
  421. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/links-orchestrator.md +66 -0
  422. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/lsp-orchestrator.md +60 -0
  423. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/markdown-orchestrator.md +62 -0
  424. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/mcp-orchestrator.md +34 -0
  425. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/memory-orchestrator.md +45 -0
  426. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/metabase-orchestrator.md +30 -0
  427. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/multi-agent-orchestrator.md +61 -0
  428. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/openapi-orchestrator.md +66 -0
  429. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/orchestrator-architecture.md +24 -0
  430. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/orchestrator-index.md +73 -0
  431. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/pdf-orchestrator.md +30 -0
  432. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/portable-paths-and-config.md +123 -0
  433. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/portable-paths-validation-matrix.md +131 -0
  434. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/progress-orchestrator.md +43 -0
  435. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/progress-report-cli.md +217 -0
  436. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/public-interface-orchestrator.md +82 -0
  437. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/research-orchestrator.md +45 -0
  438. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/schema-orchestrator.md +66 -0
  439. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/search-tools.md +19 -0
  440. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/skills-reference.md +27 -0
  441. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/sonarqube-orchestrator.md +71 -0
  442. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/spec-orchestrator.md +56 -0
  443. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/structure-orchestrator.md +78 -0
  444. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/system-requirements.md +30 -0
  445. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/tasks-orchestrator.md +45 -0
  446. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/validation-and-sync-notes.md +26 -0
  447. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/vds-ai-memory-api.md +53 -0
  448. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/vds-cli-reference.md +34 -0
  449. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/who-capability-inventory.md +98 -0
  450. package/skills/vds-skill/vds-scripts/docs/vi/agents/reference/who-capability-routing-matrix.md +16 -0
  451. package/skills/vds-skill/vds-scripts/docs/vi/agents/tutorials/feature-progression-guide.md +124 -0
  452. package/skills/vds-skill/vds-scripts/docs/vi/agents/tutorials/index.md +13 -0
  453. package/skills/vds-skill/vds-scripts/docs/vi/agents/tutorials/quick-start.md +30 -0
  454. package/skills/vds-skill/vds-scripts/docs/vi/agents/tutorials/who-skills-and-scripts-onboarding.md +42 -0
  455. package/skills/vds-skill/vds-scripts/docs/vi/agents/tutorials/zero-to-productive-developer.md +137 -0
  456. package/skills/vds-skill/vds-scripts/elastic_orchestrator/README.md +450 -0
  457. package/skills/vds-skill/vds-scripts/elastic_orchestrator/pyproject.toml +97 -0
  458. package/skills/vds-skill/vds-scripts/elastic_orchestrator/src/vds_elastic_orchestrator/__init__.py +81 -0
  459. package/skills/vds-skill/vds-scripts/elastic_orchestrator/src/vds_elastic_orchestrator/cli.py +652 -0
  460. package/skills/vds-skill/vds-scripts/elastic_orchestrator/src/vds_elastic_orchestrator/client.py +743 -0
  461. package/skills/vds-skill/vds-scripts/elastic_orchestrator/src/vds_elastic_orchestrator/config.py +208 -0
  462. package/skills/vds-skill/vds-scripts/elastic_orchestrator/src/vds_elastic_orchestrator/errors.py +34 -0
  463. package/skills/vds-skill/vds-scripts/elastic_orchestrator/src/vds_elastic_orchestrator/py.typed +0 -0
  464. package/skills/vds-skill/vds-scripts/elastic_orchestrator/tests/__init__.py +0 -0
  465. package/skills/vds-skill/vds-scripts/elastic_orchestrator/tests/conftest.py +227 -0
  466. package/skills/vds-skill/vds-scripts/elastic_orchestrator/tests/test_client.py +990 -0
  467. package/skills/vds-skill/vds-scripts/elastic_orchestrator/tests/test_config.py +268 -0
  468. package/skills/vds-skill/vds-scripts/elastic_orchestrator/tests/test_e2e_verification.py +272 -0
  469. package/skills/vds-skill/vds-scripts/elastic_orchestrator/tests/test_errors.py +78 -0
  470. package/skills/vds-skill/vds-scripts/excel_orchestrator/README.md +288 -0
  471. package/skills/vds-skill/vds-scripts/excel_orchestrator/RESEARCH_BASED_UPDATES_REPORT.md +261 -0
  472. package/skills/vds-skill/vds-scripts/excel_orchestrator/add_essential_missing_effort.py +255 -0
  473. package/skills/vds-skill/vds-scripts/excel_orchestrator/adjust_effort_complexity.py +184 -0
  474. package/skills/vds-skill/vds-scripts/excel_orchestrator/brd_analysis_and_task_breakdown.py +632 -0
  475. package/skills/vds-skill/vds-scripts/excel_orchestrator/brd_analysis_comprehensive.py +1029 -0
  476. package/skills/vds-skill/vds-scripts/excel_orchestrator/check_overlaps_and_brd_coverage.py +570 -0
  477. package/skills/vds-skill/vds-scripts/excel_orchestrator/clean_remarks_column.py +127 -0
  478. package/skills/vds-skill/vds-scripts/excel_orchestrator/comprehensive_brd_check.py +322 -0
  479. package/skills/vds-skill/vds-scripts/excel_orchestrator/create_buffered_summary.py +119 -0
  480. package/skills/vds-skill/vds-scripts/excel_orchestrator/create_service_totals_sheet.py +118 -0
  481. package/skills/vds-skill/vds-scripts/excel_orchestrator/examples/basic_operations.py +85 -0
  482. package/skills/vds-skill/vds-scripts/excel_orchestrator/expand_all_tasks.py +341 -0
  483. package/skills/vds-skill/vds-scripts/excel_orchestrator/expand_tasks.py +304 -0
  484. package/skills/vds-skill/vds-scripts/excel_orchestrator/fill_brd_references.py +347 -0
  485. package/skills/vds-skill/vds-scripts/excel_orchestrator/fill_remarks_and_colors.py +132 -0
  486. package/skills/vds-skill/vds-scripts/excel_orchestrator/finalize_brd_and_cleanup.py +295 -0
  487. package/skills/vds-skill/vds-scripts/excel_orchestrator/finalize_brd_coverage.py +327 -0
  488. package/skills/vds-skill/vds-scripts/excel_orchestrator/fix_all_formulas.py +99 -0
  489. package/skills/vds-skill/vds-scripts/excel_orchestrator/fix_detail_presentation.py +113 -0
  490. package/skills/vds-skill/vds-scripts/excel_orchestrator/fix_presentation_and_effort.py +116 -0
  491. package/skills/vds-skill/vds-scripts/excel_orchestrator/fix_presentation_consistency.py +231 -0
  492. package/skills/vds-skill/vds-scripts/excel_orchestrator/fix_remarks_matching.py +179 -0
  493. package/skills/vds-skill/vds-scripts/excel_orchestrator/group_tasks_by_service_id.py +210 -0
  494. package/skills/vds-skill/vds-scripts/excel_orchestrator/increase_brd_coverage.py +497 -0
  495. package/skills/vds-skill/vds-scripts/excel_orchestrator/increase_effort_complexity.py +155 -0
  496. package/skills/vds-skill/vds-scripts/excel_orchestrator/organize_and_deduplicate.py +273 -0
  497. package/skills/vds-skill/vds-scripts/excel_orchestrator/pyproject.toml +64 -0
  498. package/skills/vds-skill/vds-scripts/excel_orchestrator/rebuild_all_formulas.py +146 -0
  499. package/skills/vds-skill/vds-scripts/excel_orchestrator/remove_base_multiplier_and_check_duplicates.py +310 -0
  500. package/skills/vds-skill/vds-scripts/excel_orchestrator/remove_duplicate_brd_tasks.py +137 -0
  501. package/skills/vds-skill/vds-scripts/excel_orchestrator/research_based_updates.py +457 -0
  502. package/skills/vds-skill/vds-scripts/excel_orchestrator/restore_e_values.py +172 -0
  503. package/skills/vds-skill/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/__init__.py +5 -0
  504. package/skills/vds-skill/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/cli.py +746 -0
  505. package/skills/vds-skill/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/config.py +74 -0
  506. package/skills/vds-skill/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/converters.py +226 -0
  507. package/skills/vds-skill/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/errors.py +88 -0
  508. package/skills/vds-skill/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/excel_client.py +443 -0
  509. package/skills/vds-skill/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/formatters.py +211 -0
  510. package/skills/vds-skill/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/logging.py +57 -0
  511. package/skills/vds-skill/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/source_contract.py +29 -0
  512. package/skills/vds-skill/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/target_state_status.py +837 -0
  513. package/skills/vds-skill/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/ulnc_alignment.py +1291 -0
  514. package/skills/vds-skill/vds-scripts/excel_orchestrator/src/vds_excel_orchestrator/validators.py +164 -0
  515. package/skills/vds-skill/vds-scripts/excel_orchestrator/sync_detail_and_total_sheets.py +211 -0
  516. package/skills/vds-skill/vds-scripts/excel_orchestrator/tests/__init__.py +1 -0
  517. package/skills/vds-skill/vds-scripts/excel_orchestrator/tests/conftest.py +36 -0
  518. package/skills/vds-skill/vds-scripts/excel_orchestrator/tests/test_cli.py +383 -0
  519. package/skills/vds-skill/vds-scripts/excel_orchestrator/tests/test_excel_client.py +129 -0
  520. package/skills/vds-skill/vds-scripts/excel_orchestrator/tests/test_ulnc_alignment.py +373 -0
  521. package/skills/vds-skill/vds-scripts/excel_orchestrator/tests/test_validators.py +64 -0
  522. package/skills/vds-skill/vds-scripts/excel_orchestrator/update_api_database_effort.py +261 -0
  523. package/skills/vds-skill/vds-scripts/excel_orchestrator/update_buffers_inline.py +115 -0
  524. package/skills/vds-skill/vds-scripts/excel_orchestrator/update_complex_services_and_add_new.py +336 -0
  525. package/skills/vds-skill/vds-scripts/excel_orchestrator/update_responsibility_and_fix_rows.py +208 -0
  526. package/skills/vds-skill/vds-scripts/excel_orchestrator/update_task_breakdown_vietnamese.py +309 -0
  527. package/skills/vds-skill/vds-scripts/excel_orchestrator/update_vietnamese_and_responsibility.py +415 -0
  528. package/skills/vds-skill/vds-scripts/excel_orchestrator/verify_brd_coverage_comprehensive.py +401 -0
  529. package/skills/vds-skill/vds-scripts/git_orchestrator/ENHANCEMENT_SUMMARY.md +119 -0
  530. package/skills/vds-skill/vds-scripts/git_orchestrator/README.md +286 -0
  531. package/skills/vds-skill/vds-scripts/git_orchestrator/VERIFICATION_REPORT.md +152 -0
  532. package/skills/vds-skill/vds-scripts/git_orchestrator/pyproject.toml +37 -0
  533. package/skills/vds-skill/vds-scripts/git_orchestrator/src/vds_git_orchestrator/__init__.py +30 -0
  534. package/skills/vds-skill/vds-scripts/git_orchestrator/src/vds_git_orchestrator/__main__.py +4 -0
  535. package/skills/vds-skill/vds-scripts/git_orchestrator/src/vds_git_orchestrator/branch_probe.py +271 -0
  536. package/skills/vds-skill/vds-scripts/git_orchestrator/src/vds_git_orchestrator/cli.py +892 -0
  537. package/skills/vds-skill/vds-scripts/git_orchestrator/src/vds_git_orchestrator/logging_config.py +63 -0
  538. package/skills/vds-skill/vds-scripts/git_orchestrator/src/vds_git_orchestrator/manifest.py +249 -0
  539. package/skills/vds-skill/vds-scripts/git_orchestrator/src/vds_git_orchestrator/orchestrator.py +1647 -0
  540. package/skills/vds-skill/vds-scripts/git_orchestrator/src/vds_git_orchestrator/protocols.py +35 -0
  541. package/skills/vds-skill/vds-scripts/git_orchestrator/src/vds_git_orchestrator/reporting.py +55 -0
  542. package/skills/vds-skill/vds-scripts/git_orchestrator/tests/__init__.py +0 -0
  543. package/skills/vds-skill/vds-scripts/git_orchestrator/tests/test_cli_settings.py +19 -0
  544. package/skills/vds-skill/vds-scripts/git_orchestrator/tests/test_integration.py +79 -0
  545. package/skills/vds-skill/vds-scripts/git_orchestrator/tests/test_manifest.py +79 -0
  546. package/skills/vds-skill/vds-scripts/git_orchestrator/tests/test_orchestrator.py +207 -0
  547. package/skills/vds-skill/vds-scripts/git_orchestrator/tests/test_public_api.py +235 -0
  548. package/skills/vds-skill/vds-scripts/git_orchestrator/tests/test_resilience.py +343 -0
  549. package/skills/vds-skill/vds-scripts/git_orchestrator/tests/unit/__init__.py +0 -0
  550. package/skills/vds-skill/vds-scripts/git_orchestrator/tests/unit/test_branch_probe.py +327 -0
  551. package/skills/vds-skill/vds-scripts/git_orchestrator/tests/unit/test_protocols.py +132 -0
  552. package/skills/vds-skill/vds-scripts/google_sheets_orchestrator/README.md +241 -0
  553. package/skills/vds-skill/vds-scripts/google_sheets_orchestrator/pyproject.toml +45 -0
  554. package/skills/vds-skill/vds-scripts/google_sheets_orchestrator/src/vds_google_sheets_orchestrator/__init__.py +69 -0
  555. package/skills/vds-skill/vds-scripts/google_sheets_orchestrator/src/vds_google_sheets_orchestrator/cli.py +568 -0
  556. package/skills/vds-skill/vds-scripts/google_sheets_orchestrator/src/vds_google_sheets_orchestrator/client.py +186 -0
  557. package/skills/vds-skill/vds-scripts/google_sheets_orchestrator/src/vds_google_sheets_orchestrator/config.py +46 -0
  558. package/skills/vds-skill/vds-scripts/google_sheets_orchestrator/src/vds_google_sheets_orchestrator/errors.py +41 -0
  559. package/skills/vds-skill/vds-scripts/google_sheets_orchestrator/tests/__init__.py +1 -0
  560. package/skills/vds-skill/vds-scripts/google_sheets_orchestrator/tests/conftest.py +1 -0
  561. package/skills/vds-skill/vds-scripts/google_sheets_orchestrator/tests/unit/__init__.py +1 -0
  562. package/skills/vds-skill/vds-scripts/google_sheets_orchestrator/tests/unit/test_cli.py +212 -0
  563. package/skills/vds-skill/vds-scripts/google_sheets_orchestrator/tests/unit/test_client.py +24 -0
  564. package/skills/vds-skill/vds-scripts/google_sheets_orchestrator/tests/unit/test_config.py +16 -0
  565. package/skills/vds-skill/vds-scripts/grafana_orchestrator/README.md +572 -0
  566. package/skills/vds-skill/vds-scripts/grafana_orchestrator/pyproject.toml +102 -0
  567. package/skills/vds-skill/vds-scripts/grafana_orchestrator/src/vds_grafana_orchestrator/__init__.py +78 -0
  568. package/skills/vds-skill/vds-scripts/grafana_orchestrator/src/vds_grafana_orchestrator/cli.py +455 -0
  569. package/skills/vds-skill/vds-scripts/grafana_orchestrator/src/vds_grafana_orchestrator/client.py +700 -0
  570. package/skills/vds-skill/vds-scripts/grafana_orchestrator/src/vds_grafana_orchestrator/config.py +243 -0
  571. package/skills/vds-skill/vds-scripts/grafana_orchestrator/src/vds_grafana_orchestrator/errors.py +34 -0
  572. package/skills/vds-skill/vds-scripts/grafana_orchestrator/src/vds_grafana_orchestrator/py.typed +1 -0
  573. package/skills/vds-skill/vds-scripts/grafana_orchestrator/tests/__init__.py +1 -0
  574. package/skills/vds-skill/vds-scripts/grafana_orchestrator/tests/conftest.py +308 -0
  575. package/skills/vds-skill/vds-scripts/grafana_orchestrator/tests/test_client.py +458 -0
  576. package/skills/vds-skill/vds-scripts/grafana_orchestrator/tests/test_config.py +203 -0
  577. package/skills/vds-skill/vds-scripts/grafana_orchestrator/tests/test_errors.py +78 -0
  578. package/skills/vds-skill/vds-scripts/jira_orchestrator/README.md +864 -0
  579. package/skills/vds-skill/vds-scripts/jira_orchestrator/pyproject.toml +43 -0
  580. package/skills/vds-skill/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/__init__.py +65 -0
  581. package/skills/vds-skill/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/adapter.py +1685 -0
  582. package/skills/vds-skill/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/cli.py +2806 -0
  583. package/skills/vds-skill/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/config.py +168 -0
  584. package/skills/vds-skill/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/errors.py +34 -0
  585. package/skills/vds-skill/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/reporting.py +66 -0
  586. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/__init__.py +1 -0
  587. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/conftest.py +86 -0
  588. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_adapter_agile_list_payloads.py +54 -0
  589. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_adapter_bulk_operations.py +91 -0
  590. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_adapter_components.py +56 -0
  591. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_adapter_createmeta.py +45 -0
  592. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_adapter_dashboard.py +119 -0
  593. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_adapter_issue_properties.py +53 -0
  594. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_adapter_permissions_compat.py +41 -0
  595. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_adapter_reindex.py +42 -0
  596. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_adapter_remote_links.py +75 -0
  597. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_adapter_transitions.py +90 -0
  598. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_adapter_user_management.py +116 -0
  599. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_adapter_version_management.py +181 -0
  600. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_adapter_watchers.py +43 -0
  601. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_advanced_search.py +179 -0
  602. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_agile.py +304 -0
  603. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_application_properties.py +243 -0
  604. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_backlog.py +91 -0
  605. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_bulk_operations.py +403 -0
  606. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_cli.py +108 -0
  607. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_components.py +119 -0
  608. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_config.py +166 -0
  609. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_dashboard.py +122 -0
  610. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_discover_fields.py +207 -0
  611. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_errors.py +72 -0
  612. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_filter_management.py +411 -0
  613. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_issue_archiving.py +179 -0
  614. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_issue_links.py +257 -0
  615. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_issue_properties.py +189 -0
  616. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_link_types.py +407 -0
  617. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_parse_set.py +37 -0
  618. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_permissions.py +343 -0
  619. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_reindex.py +81 -0
  620. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_remote_links.py +269 -0
  621. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_security_schemes.py +202 -0
  622. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_transitions_changelog.py +109 -0
  623. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_user_management.py +246 -0
  624. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_version_management.py +503 -0
  625. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_watchers.py +116 -0
  626. package/skills/vds-skill/vds-scripts/jira_orchestrator/tests/test_worklog.py +243 -0
  627. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/README.md +864 -0
  628. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/pyproject.toml +43 -0
  629. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/src/vds_jira_viettelmoney_orchestrator/__init__.py +65 -0
  630. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/src/vds_jira_viettelmoney_orchestrator/adapter.py +1689 -0
  631. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/src/vds_jira_viettelmoney_orchestrator/cli.py +2799 -0
  632. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/src/vds_jira_viettelmoney_orchestrator/config.py +137 -0
  633. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/src/vds_jira_viettelmoney_orchestrator/errors.py +34 -0
  634. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/src/vds_jira_viettelmoney_orchestrator/reporting.py +65 -0
  635. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/__init__.py +1 -0
  636. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/conftest.py +86 -0
  637. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_adapter_agile_list_payloads.py +54 -0
  638. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_adapter_bulk_operations.py +101 -0
  639. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_adapter_components.py +64 -0
  640. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_adapter_createmeta.py +45 -0
  641. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_adapter_dashboard.py +135 -0
  642. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_adapter_issue_properties.py +63 -0
  643. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_adapter_permissions_compat.py +42 -0
  644. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_adapter_reindex.py +42 -0
  645. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_adapter_remote_links.py +89 -0
  646. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_adapter_transitions.py +91 -0
  647. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_adapter_user_management.py +130 -0
  648. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_adapter_version_management.py +189 -0
  649. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_adapter_watchers.py +49 -0
  650. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_advanced_search.py +213 -0
  651. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_agile.py +334 -0
  652. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_application_properties.py +261 -0
  653. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_backlog.py +91 -0
  654. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_bulk_operations.py +443 -0
  655. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_cli.py +106 -0
  656. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_components.py +133 -0
  657. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_config.py +166 -0
  658. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_dashboard.py +130 -0
  659. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_discover_fields.py +207 -0
  660. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_errors.py +61 -0
  661. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_filter_management.py +478 -0
  662. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_issue_archiving.py +181 -0
  663. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_issue_links.py +257 -0
  664. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_issue_properties.py +203 -0
  665. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_link_types.py +426 -0
  666. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_parse_set.py +37 -0
  667. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_permissions.py +358 -0
  668. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_reindex.py +81 -0
  669. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_remote_links.py +292 -0
  670. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_security_schemes.py +218 -0
  671. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_transitions_changelog.py +121 -0
  672. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_user_management.py +283 -0
  673. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_version_management.py +561 -0
  674. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_watchers.py +128 -0
  675. package/skills/vds-skill/vds-scripts/jira_viettelmoney_orchestrator/tests/test_worklog.py +265 -0
  676. package/skills/vds-skill/vds-scripts/llms.txt +159 -0
  677. package/skills/vds-skill/vds-scripts/markdown_orchestrator/README.md +72 -0
  678. package/skills/vds-skill/vds-scripts/markdown_orchestrator/pyproject.toml +39 -0
  679. package/skills/vds-skill/vds-scripts/markdown_orchestrator/src/vds_markdown_orchestrator/__init__.py +5 -0
  680. package/skills/vds-skill/vds-scripts/markdown_orchestrator/src/vds_markdown_orchestrator/cli.py +102 -0
  681. package/skills/vds-skill/vds-scripts/mcp_server/Dockerfile +63 -0
  682. package/skills/vds-skill/vds-scripts/mcp_server/README.md +140 -0
  683. package/skills/vds-skill/vds-scripts/mcp_server/pyproject.toml +41 -0
  684. package/skills/vds-skill/vds-scripts/mcp_server/src/vds_mcp_server/__init__.py +3 -0
  685. package/skills/vds-skill/vds-scripts/mcp_server/src/vds_mcp_server/config.py +36 -0
  686. package/skills/vds-skill/vds-scripts/mcp_server/src/vds_mcp_server/server.py +111 -0
  687. package/skills/vds-skill/vds-scripts/mcp_server/src/vds_mcp_server/tools/__init__.py +15 -0
  688. package/skills/vds-skill/vds-scripts/mcp_server/src/vds_mcp_server/tools/bitbucket_tools.py +47 -0
  689. package/skills/vds-skill/vds-scripts/mcp_server/src/vds_mcp_server/tools/confluence_tools.py +53 -0
  690. package/skills/vds-skill/vds-scripts/mcp_server/src/vds_mcp_server/tools/git_tools.py +71 -0
  691. package/skills/vds-skill/vds-scripts/mcp_server/src/vds_mcp_server/tools/jira_tools.py +63 -0
  692. package/skills/vds-skill/vds-scripts/mcp_server/src/vds_mcp_server/tools/vidp_tools.py +64 -0
  693. package/skills/vds-skill/vds-scripts/mcp_server/tests/__init__.py +1 -0
  694. package/skills/vds-skill/vds-scripts/mcp_server/tests/conftest.py +31 -0
  695. package/skills/vds-skill/vds-scripts/mcp_server/tests/unit/__init__.py +1 -0
  696. package/skills/vds-skill/vds-scripts/mcp_server/tests/unit/test_bitbucket_tools.py +28 -0
  697. package/skills/vds-skill/vds-scripts/mcp_server/tests/unit/test_confluence_tools.py +28 -0
  698. package/skills/vds-skill/vds-scripts/mcp_server/tests/unit/test_git_tools.py +35 -0
  699. package/skills/vds-skill/vds-scripts/mcp_server/tests/unit/test_jira_tools.py +35 -0
  700. package/skills/vds-skill/vds-scripts/mcp_server/tests/verification/__init__.py +6 -0
  701. package/skills/vds-skill/vds-scripts/mcp_server/tests/verification/conftest.py +51 -0
  702. package/skills/vds-skill/vds-scripts/mcp_server/tests/verification/test_mcp_confluence_tools.py +40 -0
  703. package/skills/vds-skill/vds-scripts/mcp_server/tests/verification/test_mcp_jira_tools.py +39 -0
  704. package/skills/vds-skill/vds-scripts/mcp_server/tests/verification/test_mcp_tool_registration.py +50 -0
  705. package/skills/vds-skill/vds-scripts/pdf_orchestrator/.dockerignore +93 -0
  706. package/skills/vds-skill/vds-scripts/pdf_orchestrator/.env.example +40 -0
  707. package/skills/vds-skill/vds-scripts/pdf_orchestrator/.ruff_rules.py +350 -0
  708. package/skills/vds-skill/vds-scripts/pdf_orchestrator/.yamllint.yml +43 -0
  709. package/skills/vds-skill/vds-scripts/pdf_orchestrator/DEVELOPMENT_PLAN.md +80 -0
  710. package/skills/vds-skill/vds-scripts/pdf_orchestrator/Dockerfile +87 -0
  711. package/skills/vds-skill/vds-scripts/pdf_orchestrator/README.md +608 -0
  712. package/skills/vds-skill/vds-scripts/pdf_orchestrator/cli_verification_test/test.md +6 -0
  713. package/skills/vds-skill/vds-scripts/pdf_orchestrator/cli_verification_test/test.pdf +0 -0
  714. package/skills/vds-skill/vds-scripts/pdf_orchestrator/config/alertmanager.yml +83 -0
  715. package/skills/vds-skill/vds-scripts/pdf_orchestrator/config/prometheus.prod.yml +98 -0
  716. package/skills/vds-skill/vds-scripts/pdf_orchestrator/config/prometheus.yml +40 -0
  717. package/skills/vds-skill/vds-scripts/pdf_orchestrator/config/redis.conf +78 -0
  718. package/skills/vds-skill/vds-scripts/pdf_orchestrator/docs/COMPETITIVE_ANALYSIS_REPORT.md +309 -0
  719. package/skills/vds-skill/vds-scripts/pdf_orchestrator/docs/FEATURES_GUIDE.md +518 -0
  720. package/skills/vds-skill/vds-scripts/pdf_orchestrator/docs/MULTI_USER_DEPLOYMENT_GUIDE.md +615 -0
  721. package/skills/vds-skill/vds-scripts/pdf_orchestrator/docs/USER_GUIDE.md +829 -0
  722. package/skills/vds-skill/vds-scripts/pdf_orchestrator/pyproject.toml +87 -0
  723. package/skills/vds-skill/vds-scripts/pdf_orchestrator/pytest.ini +71 -0
  724. package/skills/vds-skill/vds-scripts/pdf_orchestrator/ruff.toml +6 -0
  725. package/skills/vds-skill/vds-scripts/pdf_orchestrator/scripts/debug_security_report.py +59 -0
  726. package/skills/vds-skill/vds-scripts/pdf_orchestrator/scripts/demo_library_selector.py +109 -0
  727. package/skills/vds-skill/vds-scripts/pdf_orchestrator/scripts/generate_project_stats.py +52 -0
  728. package/skills/vds-skill/vds-scripts/pdf_orchestrator/scripts/generate_styled_pdf.py +95 -0
  729. package/skills/vds-skill/vds-scripts/pdf_orchestrator/scripts/migrate_render_pdfs.py +285 -0
  730. package/skills/vds-skill/vds-scripts/pdf_orchestrator/scripts/setup_team.bat +283 -0
  731. package/skills/vds-skill/vds-scripts/pdf_orchestrator/scripts/setup_team.sh +324 -0
  732. package/skills/vds-skill/vds-scripts/pdf_orchestrator/src/vds_pdf_orchestrator/__init__.py +5 -0
  733. package/skills/vds-skill/vds-scripts/pdf_orchestrator/src/vds_pdf_orchestrator/cli.py +542 -0
  734. package/skills/vds-skill/vds-scripts/pdf_orchestrator/src/vds_pdf_orchestrator/config.py +33 -0
  735. package/skills/vds-skill/vds-scripts/pdf_orchestrator/tests/README.md +650 -0
  736. package/skills/vds-skill/vds-scripts/pdf_orchestrator/tests/__init__.py +0 -0
  737. package/skills/vds-skill/vds-scripts/pdf_orchestrator/tests/conftest.py +520 -0
  738. package/skills/vds-skill/vds-scripts/pdf_orchestrator/tests/requirements.txt +51 -0
  739. package/skills/vds-skill/vds-scripts/pdf_orchestrator/tests/run_tests.py +659 -0
  740. package/skills/vds-skill/vds-scripts/pdf_orchestrator/tests/test_config.py +36 -0
  741. package/skills/vds-skill/vds-scripts/platform_core/pyproject.toml +49 -0
  742. package/skills/vds-skill/vds-scripts/platform_core/src/vds_platform_core/__init__.py +16 -0
  743. package/skills/vds-skill/vds-scripts/platform_core/src/vds_platform_core/alembic/__init__.py +18 -0
  744. package/skills/vds-skill/vds-scripts/platform_core/src/vds_platform_core/alembic/runtime.py +139 -0
  745. package/skills/vds-skill/vds-scripts/platform_core/src/vds_platform_core/config.py +88 -0
  746. package/skills/vds-skill/vds-scripts/platform_core/src/vds_platform_core/credentials.py +40 -0
  747. package/skills/vds-skill/vds-scripts/platform_core/src/vds_platform_core/env.py +24 -0
  748. package/skills/vds-skill/vds-scripts/platform_core/src/vds_platform_core/errors.py +127 -0
  749. package/skills/vds-skill/vds-scripts/platform_core/src/vds_platform_core/http/__init__.py +18 -0
  750. package/skills/vds-skill/vds-scripts/platform_core/src/vds_platform_core/http/auth.py +32 -0
  751. package/skills/vds-skill/vds-scripts/platform_core/src/vds_platform_core/http/errors.py +47 -0
  752. package/skills/vds-skill/vds-scripts/platform_core/src/vds_platform_core/http/pagination.py +65 -0
  753. package/skills/vds-skill/vds-scripts/platform_core/src/vds_platform_core/http/retry.py +62 -0
  754. package/skills/vds-skill/vds-scripts/platform_core/src/vds_platform_core/http/stack.py +61 -0
  755. package/skills/vds-skill/vds-scripts/platform_core/src/vds_platform_core/logging.py +132 -0
  756. package/skills/vds-skill/vds-scripts/platform_core/src/vds_platform_core/protocols.py +77 -0
  757. package/skills/vds-skill/vds-scripts/platform_core/src/vds_platform_core/serialization.py +80 -0
  758. package/skills/vds-skill/vds-scripts/platform_core/src/vds_platform_core/severity.py +175 -0
  759. package/skills/vds-skill/vds-scripts/platform_core/tests/__init__.py +0 -0
  760. package/skills/vds-skill/vds-scripts/platform_core/tests/conftest.py +1 -0
  761. package/skills/vds-skill/vds-scripts/platform_core/tests/test_alembic_runtime.py +300 -0
  762. package/skills/vds-skill/vds-scripts/platform_core/tests/test_auth.py +84 -0
  763. package/skills/vds-skill/vds-scripts/platform_core/tests/test_config.py +83 -0
  764. package/skills/vds-skill/vds-scripts/platform_core/tests/test_credentials.py +73 -0
  765. package/skills/vds-skill/vds-scripts/platform_core/tests/test_env.py +56 -0
  766. package/skills/vds-skill/vds-scripts/platform_core/tests/test_errors.py +201 -0
  767. package/skills/vds-skill/vds-scripts/platform_core/tests/test_errors_http.py +74 -0
  768. package/skills/vds-skill/vds-scripts/platform_core/tests/test_http_settings.py +116 -0
  769. package/skills/vds-skill/vds-scripts/platform_core/tests/test_logging.py +148 -0
  770. package/skills/vds-skill/vds-scripts/platform_core/tests/test_pagination.py +153 -0
  771. package/skills/vds-skill/vds-scripts/platform_core/tests/test_protocols.py +132 -0
  772. package/skills/vds-skill/vds-scripts/platform_core/tests/test_retry.py +151 -0
  773. package/skills/vds-skill/vds-scripts/platform_core/tests/test_serialization.py +92 -0
  774. package/skills/vds-skill/vds-scripts/platform_core/tests/test_severity.py +178 -0
  775. package/skills/vds-skill/vds-scripts/platform_core/tests/test_stack.py +130 -0
  776. package/skills/vds-skill/vds-scripts/platform_core/uv.lock +341 -0
  777. package/skills/vds-skill/vds-scripts/pyproject.toml +145 -0
  778. package/skills/vds-skill/vds-scripts/pyrightconfig.json +82 -0
  779. package/skills/vds-skill/vds-scripts/repo-manifest.yaml +380 -0
  780. package/skills/vds-skill/vds-scripts/repo-manifest.yaml.example +25 -0
  781. package/skills/vds-skill/vds-scripts/ruff.toml +100 -0
  782. package/skills/vds-skill/vds-scripts/scripts/BRD-Validation-API.postman_collection.json +706 -0
  783. package/skills/vds-skill/vds-scripts/scripts/BRD-Validation-README.md +308 -0
  784. package/skills/vds-skill/vds-scripts/scripts/README.md +271 -0
  785. package/skills/vds-skill/vds-scripts/scripts/_validate_alias_phase2.py +137 -0
  786. package/skills/vds-skill/vds-scripts/scripts/audit-cli-patterns.sh +135 -0
  787. package/skills/vds-skill/vds-scripts/scripts/audit-dashboard.sh +525 -0
  788. package/skills/vds-skill/vds-scripts/scripts/backup.sh +123 -0
  789. package/skills/vds-skill/vds-scripts/scripts/bootstrap_uv.sh +69 -0
  790. package/skills/vds-skill/vds-scripts/scripts/brd-validation-environment.json +51 -0
  791. package/skills/vds-skill/vds-scripts/scripts/brd-validation-test-results.json +13023 -0
  792. package/skills/vds-skill/vds-scripts/scripts/brd_coverage_report.json +276 -0
  793. package/skills/vds-skill/vds-scripts/scripts/check-future-annotations.py +22 -0
  794. package/skills/vds-skill/vds-scripts/scripts/check-invalid-symlinks.py +183 -0
  795. package/skills/vds-skill/vds-scripts/scripts/check-no-debug-markers.py +21 -0
  796. package/skills/vds-skill/vds-scripts/scripts/check-no-unittest.py +21 -0
  797. package/skills/vds-skill/vds-scripts/scripts/ci/assert_no_openspace_commits.sh +37 -0
  798. package/skills/vds-skill/vds-scripts/scripts/ci/verify_branch_protection.sh +64 -0
  799. package/skills/vds-skill/vds-scripts/scripts/closure/phase1_check.sh +483 -0
  800. package/skills/vds-skill/vds-scripts/scripts/closure/phase2_check.sh +500 -0
  801. package/skills/vds-skill/vds-scripts/scripts/create_memory_session.py +36 -0
  802. package/skills/vds-skill/vds-scripts/scripts/deploy-bootstrap.sh +201 -0
  803. package/skills/vds-skill/vds-scripts/scripts/deployment/load_docker_images_offline.sh +90 -0
  804. package/skills/vds-skill/vds-scripts/scripts/dev/cli_smoke.sh +259 -0
  805. package/skills/vds-skill/vds-scripts/scripts/final_completion_report.md +139 -0
  806. package/skills/vds-skill/vds-scripts/scripts/folder_structure_report.json +321 -0
  807. package/skills/vds-skill/vds-scripts/scripts/generate_completion_report.py +132 -0
  808. package/skills/vds-skill/vds-scripts/scripts/generate_intellij_modules.py +154 -0
  809. package/skills/vds-skill/vds-scripts/scripts/init-pgbouncer-userlist.sh +154 -0
  810. package/skills/vds-skill/vds-scripts/scripts/link_integrity_report.json +807 -0
  811. package/skills/vds-skill/vds-scripts/scripts/move_audit_artifact_pages.py +252 -0
  812. package/skills/vds-skill/vds-scripts/scripts/move_audit_artifact_pages_rest.py +165 -0
  813. package/skills/vds-skill/vds-scripts/scripts/move_wrong_dept_pages.py +235 -0
  814. package/skills/vds-skill/vds-scripts/scripts/openspace_bootstrap.sh +56 -0
  815. package/skills/vds-skill/vds-scripts/scripts/openspace_common.sh +75 -0
  816. package/skills/vds-skill/vds-scripts/scripts/openspace_doctor.sh +61 -0
  817. package/skills/vds-skill/vds-scripts/scripts/openspace_sync_shadow.sh +65 -0
  818. package/skills/vds-skill/vds-scripts/scripts/phase7-baseline.sh +77 -0
  819. package/skills/vds-skill/vds-scripts/scripts/preflight/env_check.sh +102 -0
  820. package/skills/vds-skill/vds-scripts/scripts/repair_autopay_reports.sh +173 -0
  821. package/skills/vds-skill/vds-scripts/scripts/rollback_drill.sh +659 -0
  822. package/skills/vds-skill/vds-scripts/scripts/run-audit-in-tmux.sh +286 -0
  823. package/skills/vds-skill/vds-scripts/scripts/run-department-audit.sh +495 -0
  824. package/skills/vds-skill/vds-scripts/scripts/run-project-audit.sh +267 -0
  825. package/skills/vds-skill/vds-scripts/scripts/save_intellij_memories.py +112 -0
  826. package/skills/vds-skill/vds-scripts/scripts/save_memories_to_vds_ai.py +81 -0
  827. package/skills/vds-skill/vds-scripts/scripts/save_memories_vds_style.py +133 -0
  828. package/skills/vds-skill/vds-scripts/scripts/search_intellij_memories.py +48 -0
  829. package/skills/vds-skill/vds-scripts/scripts/setup_intellij_workspace.py +71 -0
  830. package/skills/vds-skill/vds-scripts/scripts/smoke-test-deploy.sh +137 -0
  831. package/skills/vds-skill/vds-scripts/scripts/smoke_deploy_lib.py +205 -0
  832. package/skills/vds-skill/vds-scripts/scripts/target-state-automation/README.md +89 -0
  833. package/skills/vds-skill/vds-scripts/scripts/target-state-automation/confluence_sync_coordinator.sh +27 -0
  834. package/skills/vds-skill/vds-scripts/scripts/target-state-automation/coordination.sh +114 -0
  835. package/skills/vds-skill/vds-scripts/scripts/target-state-automation/diagram_coordinator.sh +25 -0
  836. package/skills/vds-skill/vds-scripts/scripts/target-state-automation/docs_root.sh +22 -0
  837. package/skills/vds-skill/vds-scripts/scripts/target-state-automation/generate_diagrams.sh +22 -0
  838. package/skills/vds-skill/vds-scripts/scripts/target-state-automation/markdown_coordinator.sh +25 -0
  839. package/skills/vds-skill/vds-scripts/scripts/target-state-automation/progress_dashboard.sh +17 -0
  840. package/skills/vds-skill/vds-scripts/scripts/target-state-automation/schema_coordinator.sh +25 -0
  841. package/skills/vds-skill/vds-scripts/scripts/target-state-automation/sync_confluence.sh +30 -0
  842. package/skills/vds-skill/vds-scripts/scripts/target-state-automation/update_dependencies.sh +19 -0
  843. package/skills/vds-skill/vds-scripts/scripts/target-state-automation/validate_links.sh +86 -0
  844. package/skills/vds-skill/vds-scripts/scripts/target-state-automation/validate_markdown.sh +52 -0
  845. package/skills/vds-skill/vds-scripts/scripts/target-state-automation/validate_schemas.sh +26 -0
  846. package/skills/vds-skill/vds-scripts/scripts/target-state-automation/validate_structure.sh +98 -0
  847. package/skills/vds-skill/vds-scripts/scripts/tests/__init__.py +1 -0
  848. package/skills/vds-skill/vds-scripts/scripts/tests/test_dockerfile_correctness.py +815 -0
  849. package/skills/vds-skill/vds-scripts/scripts/tests/test_makefile_loadouts.py +560 -0
  850. package/skills/vds-skill/vds-scripts/scripts/tests/test_smoke_deploy.py +313 -0
  851. package/skills/vds-skill/vds-scripts/scripts/tests/test_verify_alembic.py +581 -0
  852. package/skills/vds-skill/vds-scripts/scripts/tests/test_verify_infra_topology.py +254 -0
  853. package/skills/vds-skill/vds-scripts/scripts/update_modules_xml.py +194 -0
  854. package/skills/vds-skill/vds-scripts/scripts/uv-workspace-alignment-verification-2026-03-25.md +128 -0
  855. package/skills/vds-skill/vds-scripts/scripts/uv-workspace-alignment-verification-2026-04-18.md +100 -0
  856. package/skills/vds-skill/vds-scripts/scripts/validate-cli-standardization.sh +188 -0
  857. package/skills/vds-skill/vds-scripts/scripts/validate_brd_coverage.py +197 -0
  858. package/skills/vds-skill/vds-scripts/scripts/validate_folder_structure.py +234 -0
  859. package/skills/vds-skill/vds-scripts/scripts/validate_link_integrity.py +274 -0
  860. package/skills/vds-skill/vds-scripts/scripts/vami017-caller-compat-report.md +62 -0
  861. package/skills/vds-skill/vds-scripts/scripts/vami017-phase-b-scaffold-notes.md +79 -0
  862. package/skills/vds-skill/vds-scripts/scripts/vds_sh_helpers.sh +180 -0
  863. package/skills/vds-skill/vds-scripts/scripts/verification/phase2_portable_paths_ubuntu_docker.sh +26 -0
  864. package/skills/vds-skill/vds-scripts/scripts/verify-infra-topology.py +868 -0
  865. package/skills/vds-skill/vds-scripts/scripts/verify-memory-cli-e2e.sh +598 -0
  866. package/skills/vds-skill/vds-scripts/scripts/verify-worktree-features.sh +306 -0
  867. package/skills/vds-skill/vds-scripts/scripts/worktree-add.sh +128 -0
  868. package/skills/vds-skill/vds-scripts/scripts/worktree-remove.sh +112 -0
  869. package/skills/vds-skill/vds-scripts/scripts/worktree_compose.sh +269 -0
  870. package/skills/vds-skill/vds-scripts/scripts/worktree_uv.sh +77 -0
  871. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/IMPLEMENTATION_AUDIT.md +376 -0
  872. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/README.md +507 -0
  873. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/pyproject.toml +106 -0
  874. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/scripts/ensure_symlink.sh +38 -0
  875. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/src/vds_sonarqube_orchestrator/__init__.py +164 -0
  876. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/src/vds_sonarqube_orchestrator/batch.py +212 -0
  877. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/src/vds_sonarqube_orchestrator/cli.py +1407 -0
  878. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/src/vds_sonarqube_orchestrator/client.py +608 -0
  879. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/src/vds_sonarqube_orchestrator/config.py +260 -0
  880. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/src/vds_sonarqube_orchestrator/diff.py +220 -0
  881. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/src/vds_sonarqube_orchestrator/errors.py +34 -0
  882. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/src/vds_sonarqube_orchestrator/external_sca.py +932 -0
  883. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/src/vds_sonarqube_orchestrator/portfolio.py +225 -0
  884. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/src/vds_sonarqube_orchestrator/pr.py +505 -0
  885. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/src/vds_sonarqube_orchestrator/reports.py +342 -0
  886. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/src/vds_sonarqube_orchestrator/scanner.py +351 -0
  887. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/src/vds_sonarqube_orchestrator/webhooks.py +269 -0
  888. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/tests/__init__.py +0 -0
  889. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/tests/conftest.py +134 -0
  890. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/tests/test_batch.py +419 -0
  891. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/tests/test_config.py +145 -0
  892. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/tests/test_errors.py +78 -0
  893. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/tests/test_external_sca.py +466 -0
  894. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/tests/test_pr.py +471 -0
  895. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/tests/test_reports.py +511 -0
  896. package/skills/vds-skill/vds-scripts/sonarqube_orchestrator/tests/test_webhooks.py +660 -0
  897. package/skills/vds-skill/vds-scripts/uv.lock +5046 -0
  898. package/skills/vds-skill/vds-scripts/vds_agent_core/CHANGELOG.md +36 -0
  899. package/skills/vds-skill/vds-scripts/vds_agent_core/README.md +453 -0
  900. package/skills/vds-skill/vds-scripts/vds_agent_core/docs/PHASE9A_ASSESSMENT.md +50 -0
  901. package/skills/vds-skill/vds-scripts/vds_agent_core/docs/embedding.md +468 -0
  902. package/skills/vds-skill/vds-scripts/vds_agent_core/pyproject.toml +51 -0
  903. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/__init__.py +29 -0
  904. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/agents/__init__.py +26 -0
  905. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/agents/hooks.py +119 -0
  906. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/agents/loop.py +864 -0
  907. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/agents/tools.py +41 -0
  908. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/config.py +252 -0
  909. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/llm/__init__.py +55 -0
  910. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/llm/_cascade.py +143 -0
  911. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/llm/budget.py +353 -0
  912. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/llm/cache.py +373 -0
  913. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/llm/embedding.py +815 -0
  914. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/llm/provider.py +173 -0
  915. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/llm/schemas.py +45 -0
  916. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/observability/__init__.py +77 -0
  917. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/observability/decorators.py +258 -0
  918. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/observability/jsonl_exporter.py +236 -0
  919. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/observability/tracer.py +497 -0
  920. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/profiles.py +2015 -0
  921. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/runtime/__init__.py +0 -0
  922. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/runtime/agent_id.py +60 -0
  923. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/security/__init__.py +13 -0
  924. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/security/credentials.py +106 -0
  925. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/skills/__init__.py +1 -0
  926. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/skills/executor.py +238 -0
  927. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/skills/manager.py +381 -0
  928. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/skills/policy.py +568 -0
  929. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/workflows/__init__.py +19 -0
  930. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/workflows/langgraph_runner.py +102 -0
  931. package/skills/vds-skill/vds-scripts/vds_agent_core/src/vds_agent_core/workflows/protocols.py +81 -0
  932. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/__init__.py +0 -0
  933. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/conftest.py +62 -0
  934. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/integration/__init__.py +0 -0
  935. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/integration/test_audit_loop_hooks_integration.py +135 -0
  936. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/integration/test_audit_observability_integration.py +246 -0
  937. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/integration/test_public_api_stability.py +91 -0
  938. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/__init__.py +0 -0
  939. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/llm/__init__.py +0 -0
  940. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/llm/test_call_site_parallelism.py +30 -0
  941. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/llm/test_dimension_guardrail.py +25 -0
  942. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/llm/test_drop_in_provider_extensibility.py +76 -0
  943. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/llm/test_embedding.py +393 -0
  944. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/llm/test_embedding_cache.py +302 -0
  945. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/llm/test_embedding_extra.py +696 -0
  946. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/llm/test_embedding_subclass.py +49 -0
  947. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/llm/test_no_provider_leakage_in_env.py +34 -0
  948. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/llm/test_provider_auto_route.py +48 -0
  949. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/llm/test_runtime_log_clean.py +111 -0
  950. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/llm/test_w7_logic_fixes.py +219 -0
  951. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/profiles/__init__.py +0 -0
  952. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/profiles/test_embedding_block_parser.py +194 -0
  953. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/profiles/test_env_resolver_allowlist.py +141 -0
  954. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/profiles/test_profile_authorization.py +158 -0
  955. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/profiles/test_profiles_w3_extra.py +547 -0
  956. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/profiles/test_real_audit_profile_compat.py +129 -0
  957. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/runtime/__init__.py +0 -0
  958. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/runtime/test_for_agent.py +322 -0
  959. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/runtime/test_w9_cascade_edges.py +369 -0
  960. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/security/__init__.py +0 -0
  961. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/security/test_credentials.py +132 -0
  962. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_agent_loop.py +663 -0
  963. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_agent_loop_coverage.py +429 -0
  964. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_agents_hooks_defaults.py +22 -0
  965. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_budget.py +155 -0
  966. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_budget_coverage.py +264 -0
  967. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_budget_tracking_only.py +71 -0
  968. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_cache.py +251 -0
  969. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_cache_context.py +62 -0
  970. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_config.py +155 -0
  971. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_langgraph_runner.py +45 -0
  972. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_langgraph_runner_coverage.py +98 -0
  973. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_llm_cache_deep.py +113 -0
  974. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_observability_decorators.py +697 -0
  975. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_observability_hooks.py +217 -0
  976. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_observability_jsonl_exporter.py +542 -0
  977. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_observability_jsonl_wiring.py +313 -0
  978. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_observability_tracer.py +896 -0
  979. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_profiles.py +1571 -0
  980. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_profiles_coverage.py +444 -0
  981. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_provider.py +316 -0
  982. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_schemas.py +63 -0
  983. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_skill_executor.py +297 -0
  984. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_skill_manager.py +370 -0
  985. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_skill_manager_coverage.py +364 -0
  986. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_skill_policy.py +402 -0
  987. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_skill_rubric.py +47 -0
  988. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_tools.py +51 -0
  989. package/skills/vds-skill/vds-scripts/vds_agent_core/tests/unit/test_workflow_protocols.py +136 -0
  990. package/skills/vds-skill/vds-scripts/vds_cli/README.md +201 -0
  991. package/skills/vds-skill/vds-scripts/vds_cli/VERIFICATION_REPORT.md +41 -0
  992. package/skills/vds-skill/vds-scripts/vds_cli/pyproject.toml +50 -0
  993. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/__init__.py +3 -0
  994. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/assets/git-credential-helper.py +235 -0
  995. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/cli.py +1126 -0
  996. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/commands/__init__.py +1 -0
  997. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/commands/lint_cli.py +389 -0
  998. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/confluence_sync.py +846 -0
  999. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/docs/consumption/__init__.py +7 -0
  1000. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/docs/consumption/funnel.py +105 -0
  1001. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/docs/consumption/scanner.py +211 -0
  1002. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/docs/freshness/report.py +90 -0
  1003. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/docs/types.py +27 -0
  1004. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/docs_cmd.py +672 -0
  1005. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/docs_metrics.py +75 -0
  1006. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/docs_sync.py +1171 -0
  1007. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/ecosystem/__init__.py +39 -0
  1008. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/ecosystem/report.py +439 -0
  1009. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/ecosystem_docs.py +164 -0
  1010. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/env.py +111 -0
  1011. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/env_git_helper.py +281 -0
  1012. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/google_sheets_orchestrator/__init__.py +3 -0
  1013. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/google_sheets_orchestrator/google_sheets_orchestrator.py +173 -0
  1014. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/router.py +232 -0
  1015. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/skills_cmd.py +274 -0
  1016. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/sync_api.py +613 -0
  1017. package/skills/vds-skill/vds-scripts/vds_cli/src/vds_cli/sync_service.py +283 -0
  1018. package/skills/vds-skill/vds-scripts/vds_cli/tests/conftest.py +62 -0
  1019. package/skills/vds-skill/vds-scripts/vds_cli/tests/test_env_git_helper_lifecycle.py +261 -0
  1020. package/skills/vds-skill/vds-scripts/vds_cli/tests/test_git_credential_helper.py +240 -0
  1021. package/skills/vds-skill/vds-scripts/vds_cli/tests/test_router_help_proxy.py +43 -0
  1022. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_cli.py +241 -0
  1023. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_cli_DOC004.py +110 -0
  1024. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_confluence_sync.py +315 -0
  1025. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_confluence_sync_wave7.py +375 -0
  1026. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_consumption_funnel.py +106 -0
  1027. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_consumption_scanner.py +144 -0
  1028. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_docs_cmd.py +89 -0
  1029. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_docs_cmd_wave8.py +161 -0
  1030. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_docs_metrics.py +16 -0
  1031. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_docs_quality_score.py +61 -0
  1032. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_docs_sync.py +417 -0
  1033. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_ecosystem_cli_dashboard.py +667 -0
  1034. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_ecosystem_cli_dashboard_rendering.py +143 -0
  1035. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_ecosystem_docs.py +63 -0
  1036. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_env.py +85 -0
  1037. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_freshness_report.py +125 -0
  1038. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_lint_cli.py +224 -0
  1039. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_router.py +101 -0
  1040. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_skills_cmd.py +419 -0
  1041. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_sync_api.py +357 -0
  1042. package/skills/vds-skill/vds-scripts/vds_cli/tests/unit/test_sync_service.py +170 -0
  1043. package/skills/vds-skill/vds-scripts/vds_cli/tests/verification/conftest.py +51 -0
  1044. package/skills/vds-skill/vds-scripts/vds_cli/tests/verification/test_bitbucket_real.py +32 -0
  1045. package/skills/vds-skill/vds-scripts/vds_cli/tests/verification/test_confluence_real.py +32 -0
  1046. package/skills/vds-skill/vds-scripts/vds_cli/tests/verification/test_jira_real.py +40 -0
  1047. package/skills/vds-skill/vds-scripts/vds_cli_common/README.md +190 -0
  1048. package/skills/vds-skill/vds-scripts/vds_cli_common/pyproject.toml +96 -0
  1049. package/skills/vds-skill/vds-scripts/vds_cli_common/src/vds_cli_common/__init__.py +36 -0
  1050. package/skills/vds-skill/vds-scripts/vds_cli_common/src/vds_cli_common/app.py +55 -0
  1051. package/skills/vds-skill/vds-scripts/vds_cli_common/src/vds_cli_common/completers.py +139 -0
  1052. package/skills/vds-skill/vds-scripts/vds_cli_common/src/vds_cli_common/context.py +201 -0
  1053. package/skills/vds-skill/vds-scripts/vds_cli_common/src/vds_cli_common/env.py +163 -0
  1054. package/skills/vds-skill/vds-scripts/vds_cli_common/src/vds_cli_common/errors.py +440 -0
  1055. package/skills/vds-skill/vds-scripts/vds_cli_common/src/vds_cli_common/output.py +284 -0
  1056. package/skills/vds-skill/vds-scripts/vds_cli_common/src/vds_cli_common/paths.py +78 -0
  1057. package/skills/vds-skill/vds-scripts/vds_cli_common/src/vds_cli_common/testing.py +211 -0
  1058. package/skills/vds-skill/vds-scripts/vds_cli_common/src/vds_cli_common/version.py +85 -0
  1059. package/skills/vds-skill/vds-scripts/vds_cli_common/tests/__init__.py +0 -0
  1060. package/skills/vds-skill/vds-scripts/vds_cli_common/tests/test_app.py +126 -0
  1061. package/skills/vds-skill/vds-scripts/vds_cli_common/tests/test_completers.py +148 -0
  1062. package/skills/vds-skill/vds-scripts/vds_cli_common/tests/test_context.py +192 -0
  1063. package/skills/vds-skill/vds-scripts/vds_cli_common/tests/test_env.py +235 -0
  1064. package/skills/vds-skill/vds-scripts/vds_cli_common/tests/test_errors.py +275 -0
  1065. package/skills/vds-skill/vds-scripts/vds_cli_common/tests/test_output.py +229 -0
  1066. package/skills/vds-skill/vds-scripts/vds_cli_common/tests/test_paths.py +61 -0
  1067. package/skills/vds-skill/vds-scripts/vds_cli_common/tests/test_testing.py +138 -0
  1068. package/skills/vds-skill/vds-scripts/vds_cli_common/tests/test_version.py +64 -0
  1069. package/skills/vds-skill/vds-scripts/vidp_orchestrator/README.md +31 -0
  1070. package/skills/vds-skill/vds-scripts/vidp_orchestrator/pyproject.toml +50 -0
  1071. package/skills/vds-skill/vds-scripts/vidp_orchestrator/src/vds_vidp_orchestrator/__init__.py +26 -0
  1072. package/skills/vds-skill/vds-scripts/vidp_orchestrator/src/vds_vidp_orchestrator/cli.py +246 -0
  1073. package/skills/vds-skill/vds-scripts/vidp_orchestrator/src/vds_vidp_orchestrator/client.py +104 -0
  1074. package/skills/vds-skill/vds-scripts/vidp_orchestrator/src/vds_vidp_orchestrator/config.py +82 -0
  1075. package/skills/vds-skill/vds-scripts/vidp_orchestrator/src/vds_vidp_orchestrator/workflows.json +3 -0
  1076. package/skills/vds-skill/vds-scripts/vidp_orchestrator/src/vds_vidp_orchestrator/workflows.py +130 -0
@@ -0,0 +1,2271 @@
1
+ """Bitbucket CLI using atlassian-python-api (consistent with VDS orchestrators)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from importlib import metadata
7
+ from pathlib import Path
8
+
9
+ import structlog
10
+ import typer
11
+ from vds_cli_common.context import CLIContext
12
+ from vds_cli_common.output import OutputManager
13
+ from vds_cli_common.paths import get_vds_cache_root
14
+ from vds_platform_core.logging import configure_structlog
15
+
16
+ from .client import BitbucketClient
17
+ from .config import BitbucketSettings, SettingsError, load_settings
18
+ from .errors import (
19
+ NotFoundError,
20
+ VDSClientError,
21
+ )
22
+ from .repo_ops import archive_repo, build_clone_url, clone_repo, parse_repo_identifier
23
+
24
+ _REPORT_DIR = get_vds_cache_root() / "vds-bitbucket-reports"
25
+
26
+ app = typer.Typer(
27
+ name="vds-bitbucket-cli",
28
+ help="Bitbucket operations orchestrator (atlassian-python-api)",
29
+ no_args_is_help=True,
30
+ )
31
+
32
+
33
+ def _version_callback(value: bool | None) -> bool | None:
34
+ """Print CLI version when --version is provided."""
35
+ if value:
36
+ try:
37
+ ver = metadata.version("vds-bitbucket-orchestrator")
38
+ except metadata.PackageNotFoundError:
39
+ ver = "unknown"
40
+ typer.echo(f"vds-bitbucket-orchestrator {ver}")
41
+ raise typer.Exit() from None
42
+ return value
43
+
44
+
45
+ @app.callback()
46
+ def main(
47
+ _version: bool = typer.Option(
48
+ False,
49
+ "--version",
50
+ callback=_version_callback,
51
+ is_eager=True,
52
+ help="Show CLI version and exit",
53
+ ),
54
+ _report_dir: Path | None = typer.Option(
55
+ None, "--report-dir", help="Directory for run reports (default: <vds-scripts>/reports/bitbucket_runs)"
56
+ ),
57
+ _markdown: bool = typer.Option(
58
+ True, "--markdown/--no-markdown", help="Emit Markdown summaries alongside JSON reports"
59
+ ),
60
+ _reports: bool = typer.Option(True, "--_reports/--no-reports", help="Write report files to report-dir"),
61
+ json_only: bool = typer.Option(False, "--json-only", "--json", help="Emit JSON to stdout only"),
62
+ structured_logs: bool = typer.Option(
63
+ False, "--structured-logs/--no-structured-logs", help="Emit structured JSON logs to stderr"
64
+ ),
65
+ _quiet: bool = typer.Option(False, "--quiet", "-q", help="Suppress output"),
66
+ _verbose: bool = typer.Option(False, "--verbose", "-v", help="Structured logs"),
67
+ _no_color: bool = typer.Option(False, "--no-color", help="Disable colour"),
68
+ ) -> None:
69
+ """Global options for Bitbucket CLI."""
70
+ # Configure structlog based on options
71
+ if structured_logs or json_only:
72
+ configure_structlog(
73
+ json_logs=structured_logs, quiet=json_only and not structured_logs, cache_logger=structured_logs
74
+ )
75
+
76
+
77
+ # -----------------------------------------------------------------------------
78
+ # Helper Functions
79
+ # -----------------------------------------------------------------------------
80
+
81
+
82
+ def _build_client(settings: BitbucketSettings) -> BitbucketClient:
83
+ """Build and return a configured BitbucketClient."""
84
+ return BitbucketClient(settings)
85
+
86
+
87
+ def _get_client() -> BitbucketClient:
88
+ """Load settings and create client."""
89
+ settings = load_settings(strict=True)
90
+ return _build_client(settings)
91
+
92
+
93
+ def _handle_error(exc: VDSClientError, out: OutputManager, log: structlog.BoundLogger) -> None:
94
+ """Handle Bitbucket client errors with appropriate output."""
95
+ context = getattr(exc, "context", {})
96
+ log.error("bitbucket_error", message=str(exc), context=context)
97
+ out.output_error(str(exc))
98
+
99
+
100
+ # -----------------------------------------------------------------------------
101
+ # Commands
102
+ # -----------------------------------------------------------------------------
103
+
104
+
105
+ @app.command("fork")
106
+ def fork(
107
+ ctx: typer.Context,
108
+ action: str = typer.Argument(..., help="Action: create, list"),
109
+ project_key: str = typer.Argument(..., help="Source project key"),
110
+ repository_slug: str = typer.Argument(..., help="Source repository slug"),
111
+ new_project_key: str | None = typer.Option(
112
+ None, "--new-project", help="Target project key (for create, if forking to new project)"
113
+ ),
114
+ new_repository_slug: str | None = typer.Option(None, "--new-repo", help="Target repository slug (for create)"),
115
+ yes: bool = typer.Option(False, "--yes", help="Confirm write operation (for create)"),
116
+ ) -> None:
117
+ """Fork repository operations."""
118
+ out = OutputManager(CLIContext.from_typer_context(ctx))
119
+ log = structlog.get_logger(__name__)
120
+ report_dir = _REPORT_DIR
121
+
122
+ try:
123
+ load_settings(strict=True)
124
+ with _get_client() as client:
125
+ if action == "create":
126
+ if not yes:
127
+ raise typer.BadParameter("Refusing to fork repository without --yes")
128
+ result = client.fork_repository(project_key, repository_slug, new_project_key, new_repository_slug)
129
+
130
+ output_path = report_dir / f"{project_key}_{repository_slug}_forked.md"
131
+ output_path.parent.mkdir(parents=True, exist_ok=True)
132
+
133
+ with output_path.open("w") as f:
134
+ f.write("# Repository Forked\n\n")
135
+ f.write(f"- **Source**: {project_key}/{repository_slug}\n")
136
+ if new_project_key:
137
+ f.write(f"- **Target Project**: {new_project_key}\n")
138
+ if new_repository_slug:
139
+ f.write(f"- **Target Repository**: {new_repository_slug}\n")
140
+ f.write(f"- **Forked Repository**: {result.get('slug', 'N/A')}\n")
141
+
142
+ log.info(
143
+ "fork_reported",
144
+ path=str(output_path),
145
+ project_key=project_key,
146
+ repository=repository_slug,
147
+ )
148
+
149
+ payload = {
150
+ "status": "success",
151
+ "source_project": project_key,
152
+ "source_repository": repository_slug,
153
+ "forked_repository": result,
154
+ }
155
+ out.output_json(payload)
156
+
157
+ elif action == "list":
158
+ result = client.get_forked_repositories(project_key, repository_slug)
159
+
160
+ output_path = report_dir / f"{project_key}_{repository_slug}_forks.md"
161
+ output_path.parent.mkdir(parents=True, exist_ok=True)
162
+
163
+ with output_path.open("w") as f:
164
+ f.write(f"# Forks of {project_key}/{repository_slug}\n\n")
165
+ f.write(f"Found {len(result)} forks:\n\n")
166
+ for fork in result:
167
+ name = fork.get("name", "N/A")
168
+ slug = fork.get("slug", "N/A")
169
+ f.write(f"- **{slug}**: {name}\n")
170
+
171
+ log.info(
172
+ "forks_reported",
173
+ path=str(output_path),
174
+ project_key=project_key,
175
+ repository=repository_slug,
176
+ count=len(result),
177
+ )
178
+
179
+ payload = {
180
+ "source_project": project_key,
181
+ "source_repository": repository_slug,
182
+ "forks": result,
183
+ "count": len(result),
184
+ }
185
+ out.output_json(payload)
186
+ else:
187
+ raise typer.BadParameter(f"Unknown action: {action}")
188
+
189
+ except (VDSClientError, typer.BadParameter) as exc:
190
+ _handle_error(exc, out, log)
191
+ raise typer.Exit(1) from None
192
+ except Exception as exc:
193
+ log.exception("unexpected_error", message=str(exc))
194
+ out.output_error(str(exc))
195
+ raise typer.Exit(1) from None
196
+
197
+
198
+ @app.command()
199
+ def projects(
200
+ ctx: typer.Context,
201
+ limit: int = typer.Option(25, "--limit", help="Maximum number of projects to list"),
202
+ ) -> None:
203
+ """List all Bitbucket projects."""
204
+ out = OutputManager(CLIContext.from_typer_context(ctx))
205
+ log = structlog.get_logger(__name__)
206
+ report_dir = _REPORT_DIR
207
+
208
+ try:
209
+ load_settings(strict=True)
210
+ with _get_client() as client:
211
+ projects = client.list_projects(limit=limit)
212
+
213
+ output_path = report_dir / "projects.md"
214
+ output_path.parent.mkdir(parents=True, exist_ok=True)
215
+
216
+ with output_path.open("w") as f:
217
+ f.write("# Bitbucket Projects\n\n")
218
+ f.write(f"Found {len(projects)} projects:\n\n")
219
+ for project in projects:
220
+ key = project.get("key", "N/A")
221
+ name = project.get("name", "N/A")
222
+ f.write(f"- **{key}**: {name}\n")
223
+
224
+ log.info("projects_reported", path=str(output_path), count=len(projects))
225
+
226
+ out.output_json({"projects": projects})
227
+
228
+ except (VDSClientError, SettingsError, ValueError) as exc:
229
+ _handle_error(exc, out, log)
230
+ raise typer.Exit(1) from None
231
+ except Exception as exc:
232
+ log.exception("unexpected_error", message=str(exc))
233
+ out.output_error(str(exc))
234
+ raise typer.Exit(1) from None
235
+
236
+
237
+ @app.command()
238
+ def create_project(
239
+ ctx: typer.Context,
240
+ key: str = typer.Argument(..., help="Project key"),
241
+ name: str = typer.Argument(..., help="Project name"),
242
+ description: str = typer.Option(
243
+ "Project created via VDS orchestrator", "--description", help="Project description"
244
+ ),
245
+ ) -> None:
246
+ """Create a new Bitbucket project."""
247
+ out = OutputManager(CLIContext.from_typer_context(ctx))
248
+ log = structlog.get_logger(__name__)
249
+ report_dir = _REPORT_DIR
250
+
251
+ try:
252
+ load_settings(strict=True)
253
+ with _get_client() as client:
254
+ result = client.create_project(key, name, description)
255
+
256
+ output_path = report_dir / "project_created.md"
257
+ output_path.parent.mkdir(parents=True, exist_ok=True)
258
+
259
+ with output_path.open("w") as f:
260
+ f.write("# Project Created\n\n")
261
+ f.write(f"- **Key**: {result.get('key', key)}\n")
262
+ f.write(f"- **Name**: {result.get('name', name)}\n")
263
+ f.write(f"- **Description**: {result.get('description', description)}\n")
264
+
265
+ log.info("project_created_reported", path=str(output_path), key=key)
266
+
267
+ out.output_json(result)
268
+
269
+ except VDSClientError as exc:
270
+ log.exception("bitbucket_error", message=str(exc), context=getattr(exc, "context", {}))
271
+ typer.echo(f"Error: {exc}")
272
+ raise typer.Exit(1) from None
273
+ except Exception as exc:
274
+ log.exception("unexpected_error", message=str(exc))
275
+ typer.echo(f"Error: {exc}")
276
+ raise typer.Exit(1) from None
277
+
278
+
279
+ @app.command()
280
+ def repositories(
281
+ ctx: typer.Context,
282
+ project_key: str = typer.Argument(..., help="Project key"),
283
+ limit: int = typer.Option(25, "--limit", help="Maximum number of repositories to list"),
284
+ ) -> None:
285
+ """List repositories in a project."""
286
+ out = OutputManager(CLIContext.from_typer_context(ctx))
287
+ log = structlog.get_logger(__name__)
288
+ report_dir = _REPORT_DIR
289
+
290
+ try:
291
+ load_settings(strict=True)
292
+ with _get_client() as client:
293
+ repos = client.list_repositories(project_key, limit=limit)
294
+
295
+ output_path = report_dir / f"{project_key}_repositories.md"
296
+ output_path.parent.mkdir(parents=True, exist_ok=True)
297
+
298
+ with output_path.open("w") as f:
299
+ f.write(f"# {project_key} Repositories\n\n")
300
+ f.write(f"Found {len(repos)} repositories:\n\n")
301
+ for repo in repos:
302
+ name = repo.get("name", "N/A")
303
+ slug = repo.get("slug", "N/A")
304
+ f.write(f"- **{slug}**: {name}\n")
305
+
306
+ log.info("repositories_reported", path=str(output_path), project_key=project_key, count=len(repos))
307
+
308
+ out.output_json({"repositories": repos})
309
+
310
+ except VDSClientError as exc:
311
+ log.exception("bitbucket_error", message=str(exc), context=getattr(exc, "context", {}))
312
+ typer.echo(f"Error: {exc}")
313
+ raise typer.Exit(1) from None
314
+ except Exception as exc:
315
+ log.exception("unexpected_error", message=str(exc))
316
+ typer.echo(f"Error: {exc}")
317
+ raise typer.Exit(1) from None
318
+
319
+
320
+ @app.command()
321
+ def pull_requests(
322
+ ctx: typer.Context,
323
+ project_key: str = typer.Argument(..., help="Project key"),
324
+ repository_slug: str = typer.Argument(..., help="Repository slug"),
325
+ state: str = typer.Option("OPEN", "--state", help="PR state (OPEN, MERGED, DECLINED)"),
326
+ order: str = typer.Option("newest", "--order", help="Sort order (newest, oldest)"),
327
+ limit: int = typer.Option(100, "--limit", help="Maximum number of PRs to list"),
328
+ start: int = typer.Option(0, "--start", help="Start index for pagination"),
329
+ ) -> None:
330
+ """List pull requests for a repository."""
331
+ out = OutputManager(CLIContext.from_typer_context(ctx))
332
+ log = structlog.get_logger(__name__)
333
+ report_dir = _REPORT_DIR
334
+
335
+ try:
336
+ load_settings(strict=True)
337
+ with _get_client() as client:
338
+ prs = client.list_pull_requests(
339
+ project_key, repository_slug, state=state, order=order, limit=limit, start=start
340
+ )
341
+
342
+ output_path = report_dir / f"{project_key}_{repository_slug}_pull_requests.md"
343
+ output_path.parent.mkdir(parents=True, exist_ok=True)
344
+
345
+ with output_path.open("w") as f:
346
+ f.write(f"# Pull Requests - {project_key}/{repository_slug}\n\n")
347
+ f.write(f"Found {len(prs)} {state.lower()} pull requests:\n\n")
348
+ for pr in prs:
349
+ title = pr.get("title", "N/A")
350
+ pr_id = pr.get("id", "N/A")
351
+ author = pr.get("author", {}).get("displayName", "N/A")
352
+ f.write(f"- **#{pr_id}**: {title} (by {author})\n")
353
+
354
+ log.info(
355
+ "pull_requests_reported",
356
+ path=str(output_path),
357
+ project_key=project_key,
358
+ repository=repository_slug,
359
+ count=len(prs),
360
+ )
361
+
362
+ out.output_json({"pull_requests": prs})
363
+
364
+ except VDSClientError as exc:
365
+ log.exception("bitbucket_error", message=str(exc), context=getattr(exc, "context", {}))
366
+ typer.echo(f"Error: {exc}")
367
+ raise typer.Exit(1) from None
368
+ except Exception as exc:
369
+ log.exception("unexpected_error", message=str(exc))
370
+ typer.echo(f"Error: {exc}")
371
+ raise typer.Exit(1) from None
372
+
373
+
374
+ @app.command()
375
+ def pipelines(
376
+ ctx: typer.Context,
377
+ workspace: str = typer.Argument(..., help="Workspace (Bitbucket Cloud only)"),
378
+ repository: str = typer.Argument(..., help="Repository name"),
379
+ limit: int = typer.Option(10, "--limit", help="Maximum number of pipelines to list"),
380
+ ) -> None:
381
+ """List pipelines (Bitbucket Cloud only)."""
382
+ out = OutputManager(CLIContext.from_typer_context(ctx))
383
+ log = structlog.get_logger(__name__)
384
+ report_dir = _REPORT_DIR
385
+
386
+ try:
387
+ settings = load_settings(strict=True)
388
+ if not settings.is_cloud_mode:
389
+ log.error("cloud_mode_required", message="Pipelines are only available in Bitbucket Cloud mode")
390
+ out.output_error("Pipelines are only available in Bitbucket Cloud mode")
391
+ raise typer.Exit(1) from None
392
+
393
+ with _get_client() as client:
394
+ pipelines = client.list_pipelines(workspace, repository, limit=limit)
395
+
396
+ output_path = report_dir / f"{workspace}_{repository}_pipelines.md"
397
+ output_path.parent.mkdir(parents=True, exist_ok=True)
398
+
399
+ with output_path.open("w") as f:
400
+ f.write(f"# Pipelines - {workspace}/{repository}\n\n")
401
+ f.write(f"Found {len(pipelines)} pipelines:\n\n")
402
+ for pipeline in pipelines:
403
+ pipeline_uuid = pipeline.get("uuid", "N/A")
404
+ pipeline_state = pipeline.get("state", {}).get("name", "N/A")
405
+ f.write(f"- **{pipeline_uuid}**: {pipeline_state}\n")
406
+
407
+ log.info(
408
+ "pipelines_reported",
409
+ path=str(output_path),
410
+ workspace=workspace,
411
+ repository=repository,
412
+ count=len(pipelines),
413
+ )
414
+
415
+ out.output_json({"pipelines": pipelines})
416
+
417
+ except VDSClientError as exc:
418
+ log.exception("bitbucket_error", message=str(exc), context=getattr(exc, "context", {}))
419
+ typer.echo(f"Error: {exc}")
420
+ raise typer.Exit(1) from None
421
+ except Exception as exc:
422
+ log.exception("unexpected_error", message=str(exc))
423
+ typer.echo(f"Error: {exc}")
424
+ raise typer.Exit(1) from None
425
+
426
+
427
+ @app.command()
428
+ def groups(
429
+ ctx: typer.Context,
430
+ filter: str | None = typer.Option(None, "--filter", help="Filter string to search for specific groups"),
431
+ limit: int = typer.Option(50, "--limit", help="Maximum number of groups to list"),
432
+ ) -> None:
433
+ """List all available Bitbucket groups."""
434
+ out = OutputManager(CLIContext.from_typer_context(ctx))
435
+ log = structlog.get_logger(__name__)
436
+ report_dir = _REPORT_DIR
437
+
438
+ try:
439
+ load_settings(strict=True)
440
+ with _get_client() as client:
441
+ groups = client.list_groups(group_filter=filter, limit=limit)
442
+
443
+ output_path = report_dir / "groups.md"
444
+ output_path.parent.mkdir(parents=True, exist_ok=True)
445
+
446
+ with output_path.open("w") as f:
447
+ f.write("# Bitbucket Groups\n\n")
448
+ f.write(f"Found {len(groups)} groups:\n\n")
449
+ for group in groups:
450
+ f.write(f"- **{group}**\n")
451
+
452
+ log.info("groups_reported", path=str(output_path), count=len(groups))
453
+
454
+ out.output_json({"groups": groups})
455
+
456
+ except VDSClientError as exc:
457
+ log.exception("bitbucket_error", message=str(exc), context=getattr(exc, "context", {}))
458
+ typer.echo(f"Error: {exc}")
459
+ raise typer.Exit(1) from None
460
+ except Exception as exc:
461
+ log.exception("unexpected_error", message=str(exc))
462
+ typer.echo(f"Error: {exc}")
463
+ raise typer.Exit(1) from None
464
+
465
+
466
+ @app.command()
467
+ def project_users(
468
+ ctx: typer.Context,
469
+ project_key: str = typer.Argument(..., help="Project key"),
470
+ filter: str | None = typer.Option(None, "--filter", help="Filter string to search for specific users"),
471
+ limit: int = typer.Option(25, "--limit", help="Maximum number of users to list"),
472
+ ) -> None:
473
+ """List users with permissions for a project."""
474
+ out = OutputManager(CLIContext.from_typer_context(ctx))
475
+ log = structlog.get_logger(__name__)
476
+ report_dir = _REPORT_DIR
477
+
478
+ try:
479
+ load_settings(strict=True)
480
+ with _get_client() as client:
481
+ users = client.list_project_users(project_key, filter_str=filter, limit=limit)
482
+
483
+ output_path = report_dir / f"{project_key}_users.md"
484
+ output_path.parent.mkdir(parents=True, exist_ok=True)
485
+
486
+ with output_path.open("w") as f:
487
+ f.write(f"# {project_key} Project Users\n\n")
488
+ f.write(f"Found {len(users)} users:\n\n")
489
+ for user in users:
490
+ name = user.get("name", "N/A")
491
+ email = user.get("emailAddress", "N/A")
492
+ permission = user.get("permission", "N/A")
493
+ f.write(f"- **{name}** ({email}) - {permission}\n")
494
+
495
+ log.info("project_users_reported", path=str(output_path), project_key=project_key, count=len(users))
496
+
497
+ out.output_json({"users": users})
498
+
499
+ except VDSClientError as exc:
500
+ log.exception("bitbucket_error", message=str(exc), context=getattr(exc, "context", {}))
501
+ typer.echo(f"Error: {exc}")
502
+ raise typer.Exit(1) from None
503
+ except Exception as exc:
504
+ log.exception("unexpected_error", message=str(exc))
505
+ typer.echo(f"Error: {exc}")
506
+ raise typer.Exit(1) from None
507
+
508
+
509
+ @app.command()
510
+ def project_groups(
511
+ ctx: typer.Context,
512
+ project_key: str = typer.Argument(..., help="Project key"),
513
+ filter: str | None = typer.Option(None, "--filter", help="Filter string to search for specific groups"),
514
+ limit: int = typer.Option(25, "--limit", help="Maximum number of groups to list"),
515
+ ) -> None:
516
+ """List groups with permissions for a project."""
517
+ out = OutputManager(CLIContext.from_typer_context(ctx))
518
+ log = structlog.get_logger(__name__)
519
+ report_dir = _REPORT_DIR
520
+
521
+ try:
522
+ load_settings(strict=True)
523
+ with _get_client() as client:
524
+ groups = client.list_project_groups(project_key, filter_str=filter, limit=limit)
525
+
526
+ output_path = report_dir / f"{project_key}_groups.md"
527
+ output_path.parent.mkdir(parents=True, exist_ok=True)
528
+
529
+ with output_path.open("w") as f:
530
+ f.write(f"# {project_key} Project Groups\n\n")
531
+ f.write(f"Found {len(groups)} groups:\n\n")
532
+ for group in groups:
533
+ f.write(f"- **{group}**\n")
534
+
535
+ log.info("project_groups_reported", path=str(output_path), project_key=project_key, count=len(groups))
536
+
537
+ out.output_json({"groups": groups})
538
+
539
+ except VDSClientError as exc:
540
+ log.exception("bitbucket_error", message=str(exc), context=getattr(exc, "context", {}))
541
+ typer.echo(f"Error: {exc}")
542
+ raise typer.Exit(1) from None
543
+ except Exception as exc:
544
+ log.exception("unexpected_error", message=str(exc))
545
+ typer.echo(f"Error: {exc}")
546
+ raise typer.Exit(1) from None
547
+
548
+
549
+ @app.command()
550
+ def grant_group_repo(
551
+ ctx: typer.Context,
552
+ project_key: str = typer.Argument(..., help="Project key"),
553
+ repository_slug: str = typer.Argument(..., help="Repository slug"),
554
+ group_name: str = typer.Argument(..., help="Group name"),
555
+ permission: str = typer.Argument(..., help="Permission level (read, write, admin)"),
556
+ ) -> None:
557
+ """Grant group permissions to a repository."""
558
+ out = OutputManager(CLIContext.from_typer_context(ctx))
559
+ log = structlog.get_logger(__name__)
560
+ report_dir = _REPORT_DIR
561
+
562
+ try:
563
+ load_settings(strict=True)
564
+ with _get_client() as client:
565
+ result = client.grant_group_repository_permissions(project_key, repository_slug, group_name, permission)
566
+
567
+ output_path = report_dir / f"{project_key}_{repository_slug}_group_granted.md"
568
+ output_path.parent.mkdir(parents=True, exist_ok=True)
569
+
570
+ with output_path.open("w") as f:
571
+ f.write("# Group Permission Granted\n\n")
572
+ f.write(f"- **Project**: {project_key}\n")
573
+ f.write(f"- **Repository**: {repository_slug}\n")
574
+ f.write(f"- **Group**: {group_name}\n")
575
+ f.write(f"- **Permission**: {permission}\n")
576
+ f.write("- **Result**: Success\n")
577
+
578
+ log.info(
579
+ "group_permission_granted",
580
+ path=str(output_path),
581
+ project_key=project_key,
582
+ repository=repository_slug,
583
+ group=group_name,
584
+ permission=permission,
585
+ )
586
+
587
+ out.output_json(result)
588
+
589
+ except VDSClientError as exc:
590
+ log.exception("bitbucket_error", message=str(exc), context=getattr(exc, "context", {}))
591
+ typer.echo(f"Error: {exc}")
592
+ raise typer.Exit(1) from None
593
+ except Exception as exc:
594
+ log.exception("unexpected_error", message=str(exc))
595
+ typer.echo(f"Error: {exc}")
596
+ raise typer.Exit(1) from None
597
+
598
+
599
+ @app.command()
600
+ def branch_permissions(
601
+ ctx: typer.Context,
602
+ action: str = typer.Argument(..., help="Action: list, get, set, delete"),
603
+ project_key: str = typer.Argument(..., help="Project key"),
604
+ permission_id: int | None = typer.Option(None, "--permission-id", help="Permission ID (for get/delete)"),
605
+ repository_slug: str | None = typer.Option(None, "--repo", help="Repository slug"),
606
+ matcher_type: str | None = typer.Option(None, "--matcher-type", help="Matcher type (for set)"),
607
+ matcher_value: str | None = typer.Option(None, "--matcher-value", help="Matcher value (for set)"),
608
+ permission_type: str | None = typer.Option(None, "--permission-type", help="Permission type (for set)"),
609
+ start: int = typer.Option(0, "--start", help="Start index for list pagination"),
610
+ limit: int = typer.Option(25, "--limit", help="Max items for list pagination"),
611
+ yes: bool = typer.Option(False, "--yes", help="Confirm write operation"),
612
+ ) -> None:
613
+ """Branch permissions management."""
614
+ out = OutputManager(CLIContext.from_typer_context(ctx))
615
+ log = structlog.get_logger(__name__)
616
+ report_dir = _REPORT_DIR
617
+
618
+ try:
619
+ load_settings(strict=True)
620
+ with _get_client() as client:
621
+ if action == "list":
622
+ if not repository_slug:
623
+ raise typer.BadParameter("--repo required for list")
624
+ result = client.list_branch_permissions(
625
+ project_key,
626
+ repository_slug=repository_slug,
627
+ start=start,
628
+ limit=limit,
629
+ )
630
+ elif action == "get":
631
+ if not permission_id:
632
+ raise typer.BadParameter("--permission-id required for get")
633
+ result = client.get_branch_permission(project_key, permission_id, repository_slug=repository_slug)
634
+ elif action == "set":
635
+ if not yes:
636
+ raise typer.BadParameter("Refusing to set permissions without --yes")
637
+ if not matcher_type or not matcher_value or not permission_type:
638
+ raise typer.BadParameter("--matcher-type, --matcher-value, and --permission-type required for set")
639
+ result = client.set_branches_permissions(
640
+ project_key,
641
+ matcher_type=matcher_type,
642
+ matcher_value=matcher_value,
643
+ permission_type=permission_type,
644
+ repository_slug=repository_slug,
645
+ )
646
+ elif action == "delete":
647
+ if not yes:
648
+ raise typer.BadParameter("Refusing to delete without --yes")
649
+ if not permission_id:
650
+ raise typer.BadParameter("--permission-id required for delete")
651
+ client.delete_branch_permission(project_key, permission_id, repository_slug=repository_slug)
652
+ result = {"deleted": permission_id}
653
+ else:
654
+ raise typer.BadParameter(f"Unknown action: {action}")
655
+
656
+ output_path = report_dir / f"{project_key}_branch_permissions_{action}.md"
657
+ output_path.parent.mkdir(parents=True, exist_ok=True)
658
+ with output_path.open("w") as f:
659
+ f.write(f"# Branch Permissions - {action}\n\n")
660
+ f.write(f"- **Project**: {project_key}\n")
661
+ if repository_slug:
662
+ f.write(f"- **Repository**: {repository_slug}\n")
663
+ f.write(f"- **Action**: {action}\n")
664
+ log.info("branch_permissions_reported", path=str(output_path), action=action)
665
+
666
+ if action == "list":
667
+ out.output_json({"branch_permissions": result})
668
+ else:
669
+ out.output_json(result)
670
+
671
+ except VDSClientError as exc:
672
+ log.exception("bitbucket_error", message=str(exc), context=getattr(exc, "context", {}))
673
+ typer.echo(f"Error: {exc}")
674
+ raise typer.Exit(1) from None
675
+ except Exception as exc:
676
+ log.exception("unexpected_error", message=str(exc))
677
+ typer.echo(f"Error: {exc}")
678
+ raise typer.Exit(1) from None
679
+
680
+
681
+ @app.command()
682
+ def conditions(
683
+ ctx: typer.Context,
684
+ action: str = typer.Argument(..., help="Action: list, get, create, update, delete"),
685
+ project_key: str = typer.Argument(..., help="Project key"),
686
+ repository_slug: str | None = typer.Option(None, "--repo", help="Repository slug (for repo conditions)"),
687
+ condition_id: int | None = typer.Option(None, "--condition-id", help="Condition ID (for get/update/delete)"),
688
+ condition_file: Path | None = typer.Option(
689
+ None, "--condition-file", help="JSON file with condition data (for create/update)"
690
+ ),
691
+ yes: bool = typer.Option(False, "--yes", help="Confirm write operation"),
692
+ ) -> None:
693
+ """Conditions-Reviewers management."""
694
+ out = OutputManager(CLIContext.from_typer_context(ctx))
695
+ log = structlog.get_logger(__name__)
696
+ report_dir = _REPORT_DIR
697
+
698
+ try:
699
+ import json
700
+
701
+ load_settings(strict=True)
702
+ with _get_client() as client:
703
+ if action == "list":
704
+ if repository_slug:
705
+ result = client.get_repo_conditions(project_key, repository_slug)
706
+ else:
707
+ result = client.get_project_conditions(project_key)
708
+ elif action == "get":
709
+ if not condition_id:
710
+ raise typer.BadParameter("--condition-id required for get")
711
+ if repository_slug:
712
+ result = client.get_repo_condition(project_key, repository_slug, condition_id)
713
+ else:
714
+ result = client.get_project_condition(project_key, condition_id)
715
+ elif action == "create":
716
+ if not yes:
717
+ raise typer.BadParameter("Refusing to create without --yes")
718
+ if not condition_file:
719
+ raise typer.BadParameter("--condition-file required for create")
720
+ with condition_file.open() as f:
721
+ condition_data = json.load(f)
722
+ if repository_slug:
723
+ result = client.create_repo_condition(project_key, repository_slug, condition_data)
724
+ else:
725
+ result = client.create_project_condition(project_key, condition_data)
726
+ elif action == "update":
727
+ if not yes:
728
+ raise typer.BadParameter("Refusing to update without --yes")
729
+ if not condition_id or not condition_file:
730
+ raise typer.BadParameter("--condition-id and --condition-file required for update")
731
+ with condition_file.open() as f:
732
+ condition_data = json.load(f)
733
+ if repository_slug:
734
+ result = client.update_repo_condition(project_key, repository_slug, condition_data, condition_id)
735
+ else:
736
+ result = client.update_project_condition(project_key, condition_data, condition_id)
737
+ elif action == "delete":
738
+ if not yes:
739
+ raise typer.BadParameter("Refusing to delete without --yes")
740
+ if not condition_id:
741
+ raise typer.BadParameter("--condition-id required for delete")
742
+ if repository_slug:
743
+ client.delete_repo_condition(project_key, repository_slug, condition_id)
744
+ else:
745
+ client.delete_project_condition(project_key, condition_id)
746
+ result = {"deleted": condition_id}
747
+ else:
748
+ raise typer.BadParameter(f"Unknown action: {action}")
749
+
750
+ output_path = report_dir / f"{project_key}_conditions_{action}.md"
751
+ output_path.parent.mkdir(parents=True, exist_ok=True)
752
+ with output_path.open("w") as f:
753
+ f.write(f"# Conditions - {action}\n\n")
754
+ f.write(f"- **Project**: {project_key}\n")
755
+ if repository_slug:
756
+ f.write(f"- **Repository**: {repository_slug}\n")
757
+ f.write(f"- **Action**: {action}\n")
758
+ log.info("conditions_reported", path=str(output_path), action=action)
759
+
760
+ out.output_json(result)
761
+
762
+ except VDSClientError as exc:
763
+ log.exception("bitbucket_error", message=str(exc), context=getattr(exc, "context", {}))
764
+ typer.echo(f"Error: {exc}")
765
+ raise typer.Exit(1) from None
766
+ except Exception as exc:
767
+ log.exception("unexpected_error", message=str(exc))
768
+ typer.echo(f"Error: {exc}")
769
+ raise typer.Exit(1) from None
770
+
771
+
772
+ @app.command()
773
+ def code(
774
+ ctx: typer.Context,
775
+ action: str = typer.Argument(..., help="Action: file, commits, diff, changelog"),
776
+ project_key: str = typer.Argument(..., help="Project key"),
777
+ repository_slug: str = typer.Argument(..., help="Repository slug"),
778
+ filename: str | None = typer.Option(None, "--file", help="File path (for file/diff)"),
779
+ at: str | None = typer.Option(None, "--at", help="Revision/ref (for file)"),
780
+ hash_oldest: str | None = typer.Option(
781
+ None, "--hash-oldest", help="Oldest commit hash (for commits/diff/changelog)"
782
+ ),
783
+ hash_newest: str | None = typer.Option(
784
+ None, "--hash-newest", help="Newest commit hash (for commits/diff/changelog)"
785
+ ),
786
+ ref_from: str | None = typer.Option(None, "--ref-from", help="From ref (for changelog)"),
787
+ ref_to: str | None = typer.Option(None, "--ref-to", help="To ref (for changelog)"),
788
+ limit: int = typer.Option(100, "--limit", help="Maximum number of results"),
789
+ ) -> None:
790
+ """Code/file content operations."""
791
+ out = OutputManager(CLIContext.from_typer_context(ctx))
792
+ log = structlog.get_logger(__name__)
793
+ report_dir = _REPORT_DIR
794
+
795
+ try:
796
+ load_settings(strict=True)
797
+ with _get_client() as client:
798
+ if action == "file":
799
+ if not filename:
800
+ raise typer.BadParameter("--file required for file action")
801
+ result = client.get_content_of_file(project_key, repository_slug, filename, at=at)
802
+ output_path = report_dir / f"{project_key}_{repository_slug}_{filename.replace('/', '_')}.txt"
803
+ output_path.parent.mkdir(parents=True, exist_ok=True)
804
+ with output_path.open("w") as f:
805
+ f.write(result)
806
+ log.info("file_content_reported", path=str(output_path))
807
+ out.output_json({"content": result, "path": str(output_path)})
808
+ return
809
+ elif action == "commits":
810
+ result = client.get_commits(project_key, repository_slug, hash_oldest, hash_newest, limit=limit)
811
+ elif action == "diff":
812
+ if not filename or not hash_oldest or not hash_newest:
813
+ raise typer.BadParameter("--file, --hash-oldest, and --hash-newest required for diff")
814
+ result = client.get_diff(project_key, repository_slug, filename, hash_oldest, hash_newest)
815
+ elif action == "changelog":
816
+ if not ref_from or not ref_to:
817
+ raise typer.BadParameter("--ref-from and --ref-to required for changelog")
818
+ result = client.get_changelog(project_key, repository_slug, ref_from, ref_to, limit=limit)
819
+ else:
820
+ raise typer.BadParameter(f"Unknown action: {action}")
821
+
822
+ output_path = report_dir / f"{project_key}_{repository_slug}_code_{action}.md"
823
+ output_path.parent.mkdir(parents=True, exist_ok=True)
824
+ with output_path.open("w") as f:
825
+ f.write(f"# Code Operations - {action}\n\n")
826
+ f.write(f"- **Project**: {project_key}\n")
827
+ f.write(f"- **Repository**: {repository_slug}\n")
828
+ f.write(f"- **Action**: {action}\n")
829
+ log.info("code_operation_reported", path=str(output_path), action=action)
830
+ out.output_json(result)
831
+
832
+ except VDSClientError as exc:
833
+ log.exception("bitbucket_error", message=str(exc), context=getattr(exc, "context", {}))
834
+ typer.echo(f"Error: {exc}")
835
+ raise typer.Exit(1) from None
836
+ except Exception as exc:
837
+ log.exception("unexpected_error", message=str(exc))
838
+ typer.echo(f"Error: {exc}")
839
+ raise typer.Exit(1) from None
840
+
841
+
842
+ @app.command()
843
+ def webhooks(
844
+ ctx: typer.Context,
845
+ action: str = typer.Argument(..., help="Action: list, get, create, update, delete"),
846
+ project_key: str = typer.Argument(..., help="Project key"),
847
+ repository_slug: str = typer.Argument(..., help="Repository slug"),
848
+ webhook_id: int | None = typer.Option(None, "--webhook-id", help="Webhook ID (get/update/delete)"),
849
+ name: str | None = typer.Option(None, "--name", help="Webhook name (create/update)"),
850
+ url: str | None = typer.Option(None, "--url", help="Webhook URL (create/update)"),
851
+ events: list[str] = typer.Option(
852
+ [],
853
+ "--event",
854
+ help="Webhook event key (repeatable). Required for create; optional for update.",
855
+ ),
856
+ filter_event: str | None = typer.Option(
857
+ None, "--filter-event", help="Filter by event when listing repository webhooks"
858
+ ),
859
+ statistics: bool = typer.Option(
860
+ False, "--statistics/--no-statistics", help="Include webhook statistics when listing"
861
+ ),
862
+ active_flag: bool = typer.Option(True, "--active/--inactive", help="Set active flag when creating a webhook"),
863
+ set_active: bool | None = typer.Option(
864
+ None, "--set-active/--set-inactive", help="Set active flag when updating a webhook"
865
+ ),
866
+ secret: str | None = typer.Option(None, "--secret", help="Webhook secret (create/update)"),
867
+ yes: bool = typer.Option(False, "--yes", help="Confirm write operation"),
868
+ ) -> None:
869
+ """Manage Bitbucket Cloud repository webhooks."""
870
+ out = OutputManager(CLIContext.from_typer_context(ctx))
871
+ log = structlog.get_logger(__name__)
872
+ report_dir = _REPORT_DIR
873
+
874
+ try:
875
+ settings = load_settings(strict=True)
876
+ if not settings.is_cloud_mode:
877
+ log.error("cloud_mode_required", message="Webhooks are only available in Bitbucket Cloud mode")
878
+ out.output_error("Webhooks are only available in Bitbucket Cloud mode")
879
+ raise typer.Exit(1) from None
880
+
881
+ with _get_client() as client:
882
+ result: dict | None = None
883
+ if action == "list":
884
+ if events:
885
+ raise typer.BadParameter("--event is not applicable for list; use --filter-event")
886
+ payload = client.list_webhooks(
887
+ project_key,
888
+ repository_slug,
889
+ event=filter_event,
890
+ statistics=statistics,
891
+ )
892
+ result = {"webhooks": payload}
893
+ elif action == "get":
894
+ if webhook_id is None:
895
+ raise typer.BadParameter("--webhook-id required for get")
896
+ payload = client.get_webhook(project_key, repository_slug, webhook_id)
897
+ result = {"webhook": payload}
898
+ elif action == "create":
899
+ if not yes:
900
+ raise typer.BadParameter("Refusing to create webhook without --yes")
901
+ if not name:
902
+ raise typer.BadParameter("--name required for create")
903
+ if not url:
904
+ raise typer.BadParameter("--url required for create")
905
+ if not events:
906
+ raise typer.BadParameter("--event required at least once for create")
907
+ payload = client.create_webhook(
908
+ project_key,
909
+ repository_slug,
910
+ name,
911
+ events,
912
+ url,
913
+ active=active_flag,
914
+ secret=secret,
915
+ )
916
+ result = {"webhook": payload}
917
+ elif action == "update":
918
+ if not yes:
919
+ raise typer.BadParameter("Refusing to update webhook without --yes")
920
+ if webhook_id is None:
921
+ raise typer.BadParameter("--webhook-id required for update")
922
+ has_changes = any(
923
+ [
924
+ name is not None,
925
+ url is not None,
926
+ bool(events),
927
+ set_active is not None,
928
+ secret is not None,
929
+ ]
930
+ )
931
+ if not has_changes:
932
+ raise typer.BadParameter("Must provide at least one field to update (name/url/event/secret/active)")
933
+ payload = client.update_webhook(
934
+ project_key,
935
+ repository_slug,
936
+ webhook_id,
937
+ name=name,
938
+ webhook_url=url,
939
+ events=events or None,
940
+ active=set_active,
941
+ secret=secret,
942
+ )
943
+ result = {"webhook": payload}
944
+ elif action == "delete":
945
+ if not yes:
946
+ raise typer.BadParameter("Refusing to delete webhook without --yes")
947
+ if webhook_id is None:
948
+ raise typer.BadParameter("--webhook-id required for delete")
949
+ client.delete_webhook(project_key, repository_slug, webhook_id)
950
+ result = {"deleted": webhook_id}
951
+ else:
952
+ raise typer.BadParameter(f"Unknown action: {action}")
953
+
954
+ output_path = report_dir / f"{project_key}_{repository_slug}_webhooks_{action}.md"
955
+ output_path.parent.mkdir(parents=True, exist_ok=True)
956
+ with output_path.open("w") as f:
957
+ f.write(f"# Webhooks - {action}\n\n")
958
+ f.write(f"- **Project**: {project_key}\n")
959
+ f.write(f"- **Repository**: {repository_slug}\n")
960
+ f.write(f"- **Action**: {action}\n")
961
+ if action == "list":
962
+ hooks = result.get("webhooks", []) if result else []
963
+ f.write(f"- **Count**: {len(hooks)}\n")
964
+ elif action in {"get", "create", "update"}:
965
+ hook = result.get("webhook", {}) if result else {}
966
+ f.write(f"- **Webhook ID**: {hook.get('id', 'N/A')}\n")
967
+ f.write(f"- **Name**: {hook.get('name', name)}\n")
968
+ f.write(f"- **URL**: {hook.get('url', url)}\n")
969
+ elif action == "delete":
970
+ f.write(f"- **Deleted ID**: {webhook_id}\n")
971
+ log.info("webhooks_reported", path=str(output_path), action=action)
972
+ out.output_json(result or {})
973
+
974
+ except VDSClientError as exc:
975
+ log.exception("bitbucket_error", message=str(exc), context=getattr(exc, "context", {}))
976
+ typer.echo(f"Error: {exc}")
977
+ raise typer.Exit(1) from None
978
+ except Exception as exc:
979
+ log.exception("unexpected_error", message=str(exc))
980
+ typer.echo(f"Error: {exc}")
981
+ raise typer.Exit(1) from None
982
+
983
+
984
+ @app.command()
985
+ def code_insights(
986
+ ctx: typer.Context,
987
+ action: str = typer.Argument(..., help="Action: create, get, annotate, delete"),
988
+ project_key: str = typer.Argument(..., help="Project key"),
989
+ repository_slug: str = typer.Argument(..., help="Repository slug"),
990
+ commit_id: str = typer.Argument(..., help="Commit hash"),
991
+ report_key: str | None = typer.Option(None, "--report-key", help="Report key (required for all actions)"),
992
+ report_title: str | None = typer.Option(None, "--title", help="Report title (for create)"),
993
+ reporter: str | None = typer.Option(None, "--reporter", help="Reporter name (for create)"),
994
+ result: str | None = typer.Option(None, "--result", help="Report result: PASSED, FAILED, PENDING (for create)"),
995
+ data_file: Path | None = typer.Option(None, "--data-file", help="Path to JSON file with report data (for create)"),
996
+ annotations_file: Path | None = typer.Option(
997
+ None, "--annotations-file", help="Path to JSON file with annotations (for annotate)"
998
+ ),
999
+ report_type: str | None = typer.Option(None, "--report-type", help="Report type (e.g., SECURITY, COVERAGE, TEST)"),
1000
+ details: str | None = typer.Option(None, "--details", help="Report details text"),
1001
+ link_text: str | None = typer.Option(None, "--link-text", help="External link text"),
1002
+ link_url: str | None = typer.Option(None, "--link-url", help="External link URL"),
1003
+ yes: bool = typer.Option(False, "--yes", help="Confirm write operation"),
1004
+ ) -> None:
1005
+ """Manage Bitbucket Cloud Code Insights reports."""
1006
+ out = OutputManager(CLIContext.from_typer_context(ctx))
1007
+ log = structlog.get_logger(__name__)
1008
+ report_dir = _REPORT_DIR
1009
+
1010
+ try:
1011
+ settings = load_settings(strict=True)
1012
+ if not settings.is_cloud_mode:
1013
+ log.error("cloud_mode_required", message="Code Insights are only available in Bitbucket Cloud mode")
1014
+ out.output_error("Code Insights are only available in Bitbucket Cloud mode")
1015
+ raise typer.Exit(1) from None
1016
+
1017
+ with _get_client() as client:
1018
+ result_obj: dict | None = None
1019
+
1020
+ if not report_key:
1021
+ raise typer.BadParameter("--report-key required for all actions")
1022
+
1023
+ if action == "create":
1024
+ if not yes:
1025
+ raise typer.BadParameter("Refusing to create report without --yes")
1026
+ if not report_title:
1027
+ raise typer.BadParameter("--title required for create")
1028
+ if not reporter:
1029
+ raise typer.BadParameter("--reporter required for create")
1030
+ if not result:
1031
+ raise typer.BadParameter("--result required for create")
1032
+
1033
+ data = None
1034
+ if data_file:
1035
+ if not data_file.exists():
1036
+ raise typer.BadParameter(f"Data file not found: {data_file}")
1037
+ with data_file.open() as f:
1038
+ data = json.load(f)
1039
+ if not isinstance(data, list):
1040
+ raise typer.BadParameter("Data file must contain a JSON array")
1041
+
1042
+ report_params: dict = {}
1043
+ if report_type:
1044
+ report_params["report_type"] = report_type
1045
+ if details:
1046
+ report_params["details"] = details
1047
+ if link_text and link_url:
1048
+ report_params["link"] = {"text": link_text, "href": link_url}
1049
+
1050
+ payload = client.create_code_insights_report(
1051
+ project_key=project_key,
1052
+ repository_slug=repository_slug,
1053
+ commit_id=commit_id,
1054
+ report_key=report_key,
1055
+ report_title=report_title,
1056
+ reporter=reporter,
1057
+ result=result,
1058
+ data=data,
1059
+ **report_params,
1060
+ )
1061
+ result_obj = {"report": payload}
1062
+
1063
+ elif action == "get":
1064
+ payload = client.get_code_insights_report(project_key, repository_slug, commit_id, report_key)
1065
+ result_obj = {"report": payload}
1066
+
1067
+ elif action == "annotate":
1068
+ if not yes:
1069
+ raise typer.BadParameter("Refusing to add annotations without --yes")
1070
+ if not annotations_file:
1071
+ raise typer.BadParameter("--annotations-file required for annotate")
1072
+ if not annotations_file.exists():
1073
+ raise typer.BadParameter(f"Annotations file not found: {annotations_file}")
1074
+
1075
+ with annotations_file.open() as f:
1076
+ annotations = json.load(f)
1077
+ if not isinstance(annotations, list):
1078
+ raise typer.BadParameter("Annotations file must contain a JSON array")
1079
+
1080
+ payload = client.add_code_insights_annotations_to_report(
1081
+ project_key, repository_slug, commit_id, report_key, annotations
1082
+ )
1083
+ result_obj = {"annotations": payload}
1084
+
1085
+ elif action == "delete":
1086
+ if not yes:
1087
+ raise typer.BadParameter("Refusing to delete report without --yes")
1088
+ client.delete_code_insights_report(project_key, repository_slug, commit_id, report_key)
1089
+ result_obj = {"deleted": report_key}
1090
+
1091
+ else:
1092
+ raise typer.BadParameter(f"Unknown action: {action}")
1093
+
1094
+ output_path = report_dir / f"{project_key}_{repository_slug}_code_insights_{action}.md"
1095
+ output_path.parent.mkdir(parents=True, exist_ok=True)
1096
+ with output_path.open("w") as f:
1097
+ f.write(f"# Code Insights - {action}\n\n")
1098
+ f.write(f"- **Project**: {project_key}\n")
1099
+ f.write(f"- **Repository**: {repository_slug}\n")
1100
+ f.write(f"- **Commit**: {commit_id}\n")
1101
+ f.write(f"- **Report Key**: {report_key}\n")
1102
+ f.write(f"- **Action**: {action}\n")
1103
+ if action == "create" and result_obj:
1104
+ report = result_obj.get("report", {})
1105
+ f.write(f"- **Title**: {report.get('title', report_title)}\n")
1106
+ f.write(f"- **Result**: {report.get('result', result)}\n")
1107
+ log.info("code_insights_reported", path=str(output_path), action=action)
1108
+ out.output_json(result_obj or {})
1109
+
1110
+ except VDSClientError as exc:
1111
+ _handle_error(exc, out, log)
1112
+ raise typer.Exit(1) from None
1113
+ except typer.BadParameter as exc:
1114
+ log.exception("parameter_error", message=str(exc))
1115
+ out.output_error(str(exc))
1116
+ raise typer.Exit(1) from None
1117
+ except Exception as exc:
1118
+ log.exception("unexpected_error", message=str(exc))
1119
+ out.output_error(str(exc))
1120
+ raise typer.Exit(1) from None
1121
+
1122
+
1123
+ @app.command("repo-variables")
1124
+ def repo_variables(
1125
+ ctx: typer.Context,
1126
+ action: str = typer.Argument(..., help="Action: list, get, create, update, delete"),
1127
+ workspace: str = typer.Option(..., "--workspace", "-w", help="Workspace slug (Cloud only)"),
1128
+ repo_slug: str = typer.Option(..., "--repo-slug", "-r", help="Repository slug"),
1129
+ variable_uuid: str | None = typer.Option(None, "--uuid", help="Variable UUID (for get/update/delete)"),
1130
+ key: str | None = typer.Option(None, "--key", help="Variable key (for create/update)"),
1131
+ value: str | None = typer.Option(None, "--value", help="Variable value (for create/update)"),
1132
+ secured: str | None = typer.Option(None, "--secured", help="Set secured flag (true/false)"),
1133
+ yes: bool = typer.Option(False, "--yes", help="Confirm write operations (create/update/delete)"),
1134
+ ) -> None:
1135
+ """Manage repository variables (Bitbucket Cloud only)."""
1136
+ out = OutputManager(CLIContext.from_typer_context(ctx))
1137
+ log = structlog.get_logger(__name__)
1138
+ report_dir = _REPORT_DIR
1139
+
1140
+ try:
1141
+ settings = load_settings(strict=True)
1142
+ if not settings.is_cloud_mode:
1143
+ log.error(
1144
+ "cloud_mode_required",
1145
+ message="Repository variable operations are only available in Bitbucket Cloud mode",
1146
+ )
1147
+ out.output_error("Repository variable operations are only available in Bitbucket Cloud mode")
1148
+ raise typer.Exit(1) from None
1149
+
1150
+ with _get_client() as client:
1151
+
1152
+ def _coerce_secured(raw_value: str | None) -> bool | None:
1153
+ if raw_value is None:
1154
+ return None
1155
+ normalized = raw_value.strip().lower()
1156
+ if normalized in {"true", "1", "yes"}:
1157
+ return True
1158
+ if normalized in {"false", "0", "no"}:
1159
+ return False
1160
+ raise typer.BadParameter("--secured must be true/false")
1161
+
1162
+ if action == "list":
1163
+ variables = client.list_repository_variables(workspace, repo_slug)
1164
+ output_path = report_dir / f"{workspace}_{repo_slug}_repository_variables.md"
1165
+ output_path.parent.mkdir(parents=True, exist_ok=True)
1166
+ with output_path.open("w") as f:
1167
+ f.write(f"# Repository Variables - {workspace}/{repo_slug}\n\n")
1168
+ f.write(f"- **Count**: {len(variables)}\n\n")
1169
+ for variable in variables:
1170
+ key_value = variable.get("key", "unknown")
1171
+ uuid_value = variable.get("uuid", "unknown")
1172
+ secured_value = variable.get("secured", False)
1173
+ f.write(f"- `{key_value}` (uuid={uuid_value}, secured={secured_value})\n")
1174
+ log.info(
1175
+ "repo_variables_reported",
1176
+ workspace=workspace,
1177
+ repository_slug=repo_slug,
1178
+ count=len(variables),
1179
+ path=str(output_path),
1180
+ )
1181
+ out.output_json(
1182
+ {"workspace": workspace, "repository": repo_slug, "count": len(variables), "variables": variables}
1183
+ )
1184
+
1185
+ elif action == "get":
1186
+ if not variable_uuid:
1187
+ raise typer.BadParameter("--uuid required for get")
1188
+ variable = client.get_repository_variable(workspace, repo_slug, variable_uuid)
1189
+ out.output_json(variable)
1190
+
1191
+ elif action == "create":
1192
+ if not yes:
1193
+ raise typer.BadParameter("Refusing to create variable without --yes")
1194
+ if not key:
1195
+ raise typer.BadParameter("--key required for create")
1196
+ if value is None:
1197
+ raise typer.BadParameter("--value required for create")
1198
+ secured_value = _coerce_secured(secured)
1199
+ secured_flag = secured_value if secured_value is not None else False
1200
+ variable = client.create_repository_variable(workspace, repo_slug, key, value, secured=secured_flag)
1201
+ out.output_json(variable)
1202
+
1203
+ elif action == "update":
1204
+ if not yes:
1205
+ raise typer.BadParameter("Refusing to update variable without --yes")
1206
+ if not variable_uuid:
1207
+ raise typer.BadParameter("--uuid required for update")
1208
+ secured_value = _coerce_secured(secured)
1209
+ if key is None and value is None and secured_value is None:
1210
+ raise typer.BadParameter("Provide at least one of --key/--value/--secured to update")
1211
+ variable = client.update_repository_variable(
1212
+ workspace,
1213
+ repo_slug,
1214
+ variable_uuid,
1215
+ key=key,
1216
+ value=value,
1217
+ secured=secured_value,
1218
+ )
1219
+ out.output_json(variable)
1220
+
1221
+ elif action == "delete":
1222
+ if not yes:
1223
+ raise typer.BadParameter("Refusing to delete variable without --yes")
1224
+ if not variable_uuid:
1225
+ raise typer.BadParameter("--uuid required for delete")
1226
+ client.delete_repository_variable(workspace, repo_slug, variable_uuid)
1227
+ out.output_json({"status": "deleted", "uuid": variable_uuid})
1228
+
1229
+ else:
1230
+ raise typer.BadParameter(f"Unknown action: {action}")
1231
+
1232
+ except VDSClientError as exc:
1233
+ _handle_error(exc, out, log)
1234
+ raise typer.Exit(1) from None
1235
+ except typer.BadParameter as exc:
1236
+ log.exception("parameter_error", message=str(exc))
1237
+ out.output_error(str(exc))
1238
+ raise typer.Exit(1) from None
1239
+ except Exception as exc:
1240
+ log.exception("unexpected_error", message=str(exc))
1241
+ out.output_error(str(exc))
1242
+ raise typer.Exit(1) from None
1243
+
1244
+
1245
+ @app.command("deployment-env")
1246
+ def deployment_env(
1247
+ ctx: typer.Context,
1248
+ action: str = typer.Argument(..., help="Action: list, get, vars"),
1249
+ sub_action: str | None = typer.Argument(None, help="Sub-action for vars: list, create, update, delete"),
1250
+ workspace: str = typer.Option(..., "--workspace", "-w", help="Workspace slug (Cloud only)"),
1251
+ repo_slug: str = typer.Option(..., "--repo-slug", "-r", help="Repository slug"),
1252
+ env_uuid: str | None = typer.Option(None, "--env-uuid", help="Deployment environment UUID"),
1253
+ variable_uuid: str | None = typer.Option(None, "--var-uuid", help="Deployment environment variable UUID"),
1254
+ key: str | None = typer.Option(None, "--key", help="Variable key (for create/update)"),
1255
+ value: str | None = typer.Option(None, "--value", help="Variable value (for create/update)"),
1256
+ secured: str | None = typer.Option(None, "--secured", help="Set secured flag (true/false)"),
1257
+ pagelen: int = typer.Option(10, "--pagelen", help="Pagelen for variable listing"),
1258
+ yes: bool = typer.Option(False, "--yes", help="Confirm write operations (vars create/update/delete)"),
1259
+ ) -> None:
1260
+ """Manage deployment environments and their variables (Bitbucket Cloud only)."""
1261
+ out = OutputManager(CLIContext.from_typer_context(ctx))
1262
+ log = structlog.get_logger(__name__)
1263
+ report_dir = _REPORT_DIR
1264
+
1265
+ try:
1266
+ settings = load_settings(strict=True)
1267
+ if not settings.is_cloud_mode:
1268
+ log.error(
1269
+ "cloud_mode_required",
1270
+ message="Deployment environment operations are only available in Bitbucket Cloud mode",
1271
+ )
1272
+ out.output_error("Deployment environment operations are only available in Bitbucket Cloud mode")
1273
+ raise typer.Exit(1) from None
1274
+
1275
+ with _get_client() as client:
1276
+
1277
+ def _coerce_secured(raw_value: str | None) -> bool | None:
1278
+ if raw_value is None:
1279
+ return None
1280
+ normalized = raw_value.strip().lower()
1281
+ if normalized in {"true", "1", "yes"}:
1282
+ return True
1283
+ if normalized in {"false", "0", "no"}:
1284
+ return False
1285
+ raise typer.BadParameter("--secured must be true/false")
1286
+
1287
+ if action == "list":
1288
+ environments = client.list_deployment_environments(workspace, repo_slug)
1289
+ output_path = report_dir / f"{workspace}_{repo_slug}_deployment_environments.md"
1290
+ output_path.parent.mkdir(parents=True, exist_ok=True)
1291
+ with output_path.open("w") as f:
1292
+ f.write(f"# Deployment Environments - {workspace}/{repo_slug}\n\n")
1293
+ f.write(f"- **Count**: {len(environments)}\n\n")
1294
+ for env in environments:
1295
+ f.write(
1296
+ f"- `{env.get('uuid', 'unknown')}` "
1297
+ f"(name={env.get('name', 'unknown')}, category={env.get('category', 'unknown')})\n"
1298
+ )
1299
+ log.info(
1300
+ "deployment_env_reported",
1301
+ workspace=workspace,
1302
+ repository_slug=repo_slug,
1303
+ count=len(environments),
1304
+ path=str(output_path),
1305
+ )
1306
+ out.output_json({"workspace": workspace, "repository": repo_slug, "environments": environments})
1307
+
1308
+ elif action == "get":
1309
+ if not env_uuid:
1310
+ raise typer.BadParameter("--env-uuid required for get")
1311
+ environment = client.get_deployment_environment(workspace, repo_slug, env_uuid)
1312
+ out.output_json(environment)
1313
+
1314
+ elif action == "vars":
1315
+ if sub_action is None:
1316
+ raise typer.BadParameter("Sub-action required for vars (list, create, update, delete)")
1317
+ if sub_action not in {"list", "create", "update", "delete"}:
1318
+ raise typer.BadParameter(f"Unknown vars sub-action: {sub_action}")
1319
+ if not env_uuid:
1320
+ raise typer.BadParameter("--env-uuid required for vars actions")
1321
+
1322
+ if sub_action == "list":
1323
+ variables = client.list_deployment_environment_variables(
1324
+ workspace, repo_slug, env_uuid, pagelen=pagelen
1325
+ )
1326
+ output_path = report_dir / f"{workspace}_{repo_slug}_{env_uuid}_deployment_env_variables.md"
1327
+ output_path.parent.mkdir(parents=True, exist_ok=True)
1328
+ with output_path.open("w") as f:
1329
+ f.write(f"# Deployment Environment Variables - {env_uuid}\n\n")
1330
+ f.write(f"- **Count**: {len(variables)}\n\n")
1331
+ for variable in variables:
1332
+ f.write(
1333
+ f"- `{variable.get('key', 'unknown')}` "
1334
+ f"(uuid={variable.get('uuid', 'unknown')}, secured={variable.get('secured', False)})\n"
1335
+ )
1336
+ log.info(
1337
+ "deployment_env_vars_reported",
1338
+ workspace=workspace,
1339
+ repository_slug=repo_slug,
1340
+ environment_uuid=env_uuid,
1341
+ count=len(variables),
1342
+ path=str(output_path),
1343
+ )
1344
+ out.output_json(
1345
+ {
1346
+ "workspace": workspace,
1347
+ "repository": repo_slug,
1348
+ "environment_uuid": env_uuid,
1349
+ "count": len(variables),
1350
+ "variables": variables,
1351
+ }
1352
+ )
1353
+
1354
+ elif sub_action == "create":
1355
+ if not yes:
1356
+ raise typer.BadParameter("Refusing to create variable without --yes")
1357
+ if not key:
1358
+ raise typer.BadParameter("--key required for vars create")
1359
+ if value is None:
1360
+ raise typer.BadParameter("--value required for vars create")
1361
+ secured_value = _coerce_secured(secured)
1362
+ secured_flag = secured_value if secured_value is not None else False
1363
+ variable = client.create_deployment_environment_variable(
1364
+ workspace, repo_slug, env_uuid, key, value, secured=secured_flag
1365
+ )
1366
+ out.output_json(variable)
1367
+
1368
+ elif sub_action == "update":
1369
+ if not yes:
1370
+ raise typer.BadParameter("Refusing to update variable without --yes")
1371
+ if not variable_uuid:
1372
+ raise typer.BadParameter("--var-uuid required for vars update")
1373
+ secured_value = _coerce_secured(secured)
1374
+ if key is None and value is None and secured_value is None:
1375
+ raise typer.BadParameter("Provide at least one of --key/--value/--secured to update")
1376
+ variable = client.update_deployment_environment_variable(
1377
+ workspace,
1378
+ repo_slug,
1379
+ env_uuid,
1380
+ variable_uuid,
1381
+ key=key,
1382
+ value=value,
1383
+ secured=secured_value,
1384
+ )
1385
+ out.output_json(variable)
1386
+
1387
+ elif sub_action == "delete":
1388
+ if not yes:
1389
+ raise typer.BadParameter("Refusing to delete variable without --yes")
1390
+ if not variable_uuid:
1391
+ raise typer.BadParameter("--var-uuid required for vars delete")
1392
+ client.delete_deployment_environment_variable(workspace, repo_slug, env_uuid, variable_uuid)
1393
+ out.output_json({"status": "deleted", "uuid": variable_uuid})
1394
+
1395
+ else:
1396
+ raise typer.BadParameter(f"Unknown action: {action}")
1397
+
1398
+ except VDSClientError as exc:
1399
+ _handle_error(exc, out, log)
1400
+ raise typer.Exit(1) from None
1401
+ except typer.BadParameter as exc:
1402
+ log.exception("parameter_error", message=str(exc))
1403
+ out.output_error(str(exc))
1404
+ raise typer.Exit(1) from None
1405
+ except Exception as exc:
1406
+ log.exception("unexpected_error", message=str(exc))
1407
+ out.output_error(str(exc))
1408
+ raise typer.Exit(1) from None
1409
+
1410
+
1411
+ @app.command("pr-blocker")
1412
+ def pr_blocker(
1413
+ ctx: typer.Context,
1414
+ action: str = typer.Argument(..., help="Action: list, add, delete"),
1415
+ workspace: str = typer.Option(..., "--workspace", "-w", help="Workspace slug (Cloud only)"),
1416
+ repo_slug: str = typer.Option(..., "--repo-slug", "-r", help="Repository slug"),
1417
+ pull_request_id: str = typer.Option(..., "--pull-request-id", "-p", help="Pull request ID"),
1418
+ blocker_uuid: str | None = typer.Option(None, "--blocker-uuid", help="Blocker UUID (for delete)"),
1419
+ message: str | None = typer.Option(None, "--message", help="Blocker message (for add)"),
1420
+ reason: str | None = typer.Option(None, "--reason", help="Blocker reason (for add)"),
1421
+ severity: str | None = typer.Option(None, "--severity", help="Blocker severity (for add)"),
1422
+ search: str | None = typer.Option(None, "--search", help="Filter expression (for list)"),
1423
+ yes: bool = typer.Option(False, "--yes", help="Confirm delete operation"),
1424
+ ) -> None:
1425
+ """Manage pull request blockers (Bitbucket Cloud only)."""
1426
+ out = OutputManager(CLIContext.from_typer_context(ctx))
1427
+ log = structlog.get_logger(__name__)
1428
+ report_dir = _REPORT_DIR
1429
+
1430
+ try:
1431
+ settings = load_settings(strict=True)
1432
+ if not settings.is_cloud_mode:
1433
+ log.error(
1434
+ "cloud_mode_required",
1435
+ message="Pull request blocker operations are only available in Bitbucket Cloud mode",
1436
+ )
1437
+ out.output_error("Pull request blocker operations are only available in Bitbucket Cloud mode")
1438
+ raise typer.Exit(1) from None
1439
+
1440
+ with _get_client() as client:
1441
+ if action == "list":
1442
+ blockers = client.list_pull_request_blockers(
1443
+ workspace,
1444
+ repo_slug,
1445
+ pull_request_id,
1446
+ query=search,
1447
+ )
1448
+ output_path = report_dir / f"{workspace}_{repo_slug}_{pull_request_id}_pr_blockers.md"
1449
+ output_path.parent.mkdir(parents=True, exist_ok=True)
1450
+ with output_path.open("w") as f:
1451
+ f.write(f"# Pull Request Blockers - {pull_request_id}\n\n")
1452
+ f.write(f"- **Count**: {len(blockers)}\n\n")
1453
+ for blocker in blockers:
1454
+ f.write(
1455
+ f"- `{blocker.get('uuid', 'unknown')}` "
1456
+ f"(message={blocker.get('message', '')}, reason={blocker.get('reason')})\n"
1457
+ )
1458
+ log.info(
1459
+ "pull_request_blockers_reported",
1460
+ workspace=workspace,
1461
+ repository_slug=repo_slug,
1462
+ pull_request_id=pull_request_id,
1463
+ count=len(blockers),
1464
+ path=str(output_path),
1465
+ )
1466
+ out.output_json({"blockers": blockers})
1467
+
1468
+ elif action == "add":
1469
+ if not message:
1470
+ raise typer.BadParameter("--message required for add")
1471
+ blocker = client.add_pull_request_blocker(
1472
+ workspace,
1473
+ repo_slug,
1474
+ pull_request_id,
1475
+ message,
1476
+ reason=reason,
1477
+ severity=severity,
1478
+ )
1479
+ out.output_json(blocker)
1480
+
1481
+ elif action == "delete":
1482
+ if not yes:
1483
+ raise typer.BadParameter("Refusing to delete blocker without --yes")
1484
+ if not blocker_uuid:
1485
+ raise typer.BadParameter("--blocker-uuid required for delete")
1486
+ client.delete_pull_request_blocker(
1487
+ workspace,
1488
+ repo_slug,
1489
+ pull_request_id,
1490
+ blocker_uuid,
1491
+ )
1492
+ out.output_json({"status": "deleted", "uuid": blocker_uuid})
1493
+
1494
+ else:
1495
+ raise typer.BadParameter(f"Unknown action: {action}")
1496
+
1497
+ except VDSClientError as exc:
1498
+ _handle_error(exc, out, log)
1499
+ raise typer.Exit(1) from None
1500
+ except typer.BadParameter as exc:
1501
+ log.exception("parameter_error", message=str(exc))
1502
+ out.output_error(str(exc))
1503
+ raise typer.Exit(1) from None
1504
+ except Exception as exc:
1505
+ log.exception("unexpected_error", message=str(exc))
1506
+ out.output_error(str(exc))
1507
+ raise typer.Exit(1) from None
1508
+
1509
+
1510
+ @app.command("issue")
1511
+ def issue(
1512
+ ctx: typer.Context,
1513
+ action: str = typer.Argument(..., help="Action: list, get, create, update, delete"),
1514
+ workspace: str = typer.Option(..., "--workspace", "-w", help="Workspace slug (Cloud only)"),
1515
+ repo_slug: str = typer.Option(..., "--repo-slug", "-r", help="Repository slug"),
1516
+ issue_id: str | None = typer.Option(None, "--issue-id", "-i", help="Issue ID (for get/update/delete)"),
1517
+ title: str | None = typer.Option(None, "--title", help="Issue title (for create/update)"),
1518
+ description: str | None = typer.Option(None, "--description", help="Issue description (for create/update)"),
1519
+ kind: str | None = typer.Option(None, "--kind", help="Issue kind (bug, enhancement, proposal, task)"),
1520
+ priority: str | None = typer.Option(
1521
+ None, "--priority", help="Issue priority (trivial, minor, major, critical, blocker)"
1522
+ ),
1523
+ state: str | None = typer.Option(None, "--state", help="Issue state (for update)"),
1524
+ query: str | None = typer.Option(None, "--query", help="Filtering query (for list)"),
1525
+ sort: str | None = typer.Option(None, "--sort", help="Sort clause (for list)"),
1526
+ yes: bool = typer.Option(False, "--yes", help="Confirm delete operation"),
1527
+ ) -> None:
1528
+ """Manage Bitbucket Cloud issues for repositories."""
1529
+ out = OutputManager(CLIContext.from_typer_context(ctx))
1530
+ log = structlog.get_logger(__name__)
1531
+ report_dir = _REPORT_DIR
1532
+
1533
+ try:
1534
+ settings = load_settings(strict=True)
1535
+ if not settings.is_cloud_mode:
1536
+ log.error(
1537
+ "cloud_mode_required",
1538
+ message="Repository issue operations are only available in Bitbucket Cloud mode",
1539
+ )
1540
+ out.output_error("Repository issue operations are only available in Bitbucket Cloud mode")
1541
+ raise typer.Exit(1) from None
1542
+
1543
+ with _get_client() as client:
1544
+ if action == "list":
1545
+ issues = client.list_repository_issues(workspace, repo_slug, query=query, sort=sort)
1546
+ output_path = report_dir / f"{workspace}_{repo_slug}_issues.md"
1547
+ output_path.parent.mkdir(parents=True, exist_ok=True)
1548
+ with output_path.open("w") as f:
1549
+ f.write(f"# Repository Issues - {workspace}/{repo_slug}\n\n")
1550
+ f.write(f"- **Count**: {len(issues)}\n\n")
1551
+ for issue_obj in issues:
1552
+ f.write(
1553
+ f"- `{issue_obj.get('id', 'unknown')}` "
1554
+ f"(title={issue_obj.get('title', '')}, state={issue_obj.get('state', '')})\n"
1555
+ )
1556
+ log.info(
1557
+ "repository_issues_reported",
1558
+ workspace=workspace,
1559
+ repository_slug=repo_slug,
1560
+ count=len(issues),
1561
+ query=query,
1562
+ sort=sort,
1563
+ path=str(output_path),
1564
+ )
1565
+ out.output_json({"issues": issues})
1566
+
1567
+ elif action == "get":
1568
+ if not issue_id:
1569
+ raise typer.BadParameter("--issue-id required for get")
1570
+ issue_obj = client.get_repository_issue(workspace, repo_slug, issue_id)
1571
+ out.output_json(issue_obj)
1572
+
1573
+ elif action == "create":
1574
+ if not title:
1575
+ raise typer.BadParameter("--title required for create")
1576
+ create_kind = kind or "task"
1577
+ create_priority = priority or "major"
1578
+ issue_obj = client.create_repository_issue(
1579
+ workspace,
1580
+ repo_slug,
1581
+ title,
1582
+ description or "",
1583
+ kind=create_kind,
1584
+ priority=create_priority,
1585
+ )
1586
+ out.output_json(issue_obj)
1587
+
1588
+ elif action == "update":
1589
+ if not issue_id:
1590
+ raise typer.BadParameter("--issue-id required for update")
1591
+ if title is None and description is None and kind is None and priority is None and state is None:
1592
+ raise typer.BadParameter(
1593
+ "Provide at least one field to update (--title/--description/--kind/--priority/--state)"
1594
+ )
1595
+ issue_obj = client.update_repository_issue(
1596
+ workspace,
1597
+ repo_slug,
1598
+ issue_id,
1599
+ title=title,
1600
+ description=description,
1601
+ kind=kind,
1602
+ priority=priority,
1603
+ state=state,
1604
+ )
1605
+ out.output_json(issue_obj)
1606
+
1607
+ elif action == "delete":
1608
+ if not issue_id:
1609
+ raise typer.BadParameter("--issue-id required for delete")
1610
+ if not yes:
1611
+ raise typer.BadParameter("Refusing to delete issue without --yes")
1612
+ client.delete_repository_issue(workspace, repo_slug, issue_id)
1613
+ out.output_json({"status": "deleted", "issue_id": issue_id})
1614
+
1615
+ else:
1616
+ raise typer.BadParameter(f"Unknown action: {action}")
1617
+
1618
+ except VDSClientError as exc:
1619
+ _handle_error(exc, out, log)
1620
+ raise typer.Exit(1) from None
1621
+ except typer.BadParameter as exc:
1622
+ log.exception("parameter_error", message=str(exc))
1623
+ out.output_error(str(exc))
1624
+ raise typer.Exit(1) from None
1625
+ except Exception as exc:
1626
+ log.exception("unexpected_error", message=str(exc))
1627
+ out.output_error(str(exc))
1628
+ raise typer.Exit(1) from None
1629
+
1630
+
1631
+ @app.command("pipeline-advanced")
1632
+ def pipeline_advanced(
1633
+ ctx: typer.Context,
1634
+ action: str = typer.Argument(..., help="Action: get, steps, step, log, stop"),
1635
+ workspace: str = typer.Option(..., "--workspace", "-w", help="Workspace slug (Cloud only)"),
1636
+ repo_slug: str = typer.Option(..., "--repo-slug", "-r", help="Repository slug"),
1637
+ pipeline_uuid: str | None = typer.Option(None, "--pipeline-uuid", help="Pipeline UUID"),
1638
+ step_uuid: str | None = typer.Option(None, "--step-uuid", help="Step UUID (for step/log)"),
1639
+ start: int | None = typer.Option(None, "--start", help="Start byte for log range"),
1640
+ end: int | None = typer.Option(None, "--end", help="End byte for log range"),
1641
+ output: Path | None = typer.Option(None, "--output", help="Optional file path to write log output"),
1642
+ yes: bool = typer.Option(False, "--yes", help="Confirm stop operation"),
1643
+ ) -> None:
1644
+ """Advanced pipeline operations (Bitbucket Cloud only)."""
1645
+ out = OutputManager(CLIContext.from_typer_context(ctx))
1646
+ log = structlog.get_logger(__name__)
1647
+ report_dir = _REPORT_DIR
1648
+
1649
+ try:
1650
+ settings = load_settings(strict=True)
1651
+ if not settings.is_cloud_mode:
1652
+ log.error(
1653
+ "cloud_mode_required",
1654
+ message="Advanced pipeline operations are only available in Bitbucket Cloud mode",
1655
+ )
1656
+ out.output_error("Advanced pipeline operations are only available in Bitbucket Cloud mode")
1657
+ raise typer.Exit(1) from None
1658
+
1659
+ with _get_client() as client:
1660
+ if action == "get":
1661
+ if not pipeline_uuid:
1662
+ raise typer.BadParameter("--pipeline-uuid required for get")
1663
+ pipeline = client.get_pipeline(workspace, repo_slug, pipeline_uuid)
1664
+ out.output_json(pipeline)
1665
+
1666
+ elif action == "steps":
1667
+ if not pipeline_uuid:
1668
+ raise typer.BadParameter("--pipeline-uuid required for steps")
1669
+ steps = client.list_pipeline_steps(workspace, repo_slug, pipeline_uuid)
1670
+ output_path = report_dir / f"{workspace}_{repo_slug}_{pipeline_uuid}_pipeline_steps.md"
1671
+ output_path.parent.mkdir(parents=True, exist_ok=True)
1672
+ with output_path.open("w") as f:
1673
+ f.write(f"# Pipeline Steps - {pipeline_uuid}\n\n")
1674
+ f.write(f"- **Count**: {len(steps)}\n\n")
1675
+ for step in steps:
1676
+ f.write(
1677
+ f"- `{step.get('uuid', 'unknown')}` "
1678
+ f"(state={step.get('state', 'unknown')}, duration={step.get('duration_in_seconds')})\n"
1679
+ )
1680
+ log.info(
1681
+ "pipeline_steps_reported",
1682
+ workspace=workspace,
1683
+ repository_slug=repo_slug,
1684
+ pipeline_uuid=pipeline_uuid,
1685
+ count=len(steps),
1686
+ path=str(output_path),
1687
+ )
1688
+ out.output_json({"pipeline_uuid": pipeline_uuid, "steps": steps})
1689
+
1690
+ elif action == "step":
1691
+ if not pipeline_uuid:
1692
+ raise typer.BadParameter("--pipeline-uuid required for step")
1693
+ if not step_uuid:
1694
+ raise typer.BadParameter("--step-uuid required for step")
1695
+ step = client.get_pipeline_step(workspace, repo_slug, pipeline_uuid, step_uuid)
1696
+ out.output_json(step)
1697
+
1698
+ elif action == "log":
1699
+ if not pipeline_uuid:
1700
+ raise typer.BadParameter("--pipeline-uuid required for log")
1701
+ if not step_uuid:
1702
+ raise typer.BadParameter("--step-uuid required for log")
1703
+ payload = client.get_pipeline_step_log(
1704
+ workspace,
1705
+ repo_slug,
1706
+ pipeline_uuid,
1707
+ step_uuid,
1708
+ start=start,
1709
+ end=end,
1710
+ )
1711
+ content = payload.get("content", "")
1712
+ if output:
1713
+ output.parent.mkdir(parents=True, exist_ok=True)
1714
+ output.write_text(content)
1715
+ log.info(
1716
+ "pipeline_step_log_written",
1717
+ workspace=workspace,
1718
+ repository_slug=repo_slug,
1719
+ pipeline_uuid=pipeline_uuid,
1720
+ step_uuid=step_uuid,
1721
+ path=str(output),
1722
+ )
1723
+ out.output_json({"status": "written", "path": str(output), **payload})
1724
+ else:
1725
+ output_path = report_dir / f"{workspace}_{repo_slug}_{pipeline_uuid}_{step_uuid}_pipeline_log.txt"
1726
+ output_path.parent.mkdir(parents=True, exist_ok=True)
1727
+ output_path.write_text(content)
1728
+ log.info(
1729
+ "pipeline_step_log_reported",
1730
+ workspace=workspace,
1731
+ repository_slug=repo_slug,
1732
+ pipeline_uuid=pipeline_uuid,
1733
+ step_uuid=step_uuid,
1734
+ path=str(output_path),
1735
+ )
1736
+ out.output_json({"status": "written", "path": str(output_path), **payload})
1737
+
1738
+ elif action == "stop":
1739
+ if not pipeline_uuid:
1740
+ raise typer.BadParameter("--pipeline-uuid required for stop")
1741
+ if not yes:
1742
+ raise typer.BadParameter("Refusing to stop pipeline without --yes")
1743
+ payload = client.stop_pipeline(workspace, repo_slug, pipeline_uuid)
1744
+ output_path = report_dir / f"{workspace}_{repo_slug}_{pipeline_uuid}_pipeline_stop.md"
1745
+ output_path.parent.mkdir(parents=True, exist_ok=True)
1746
+ with output_path.open("w") as f:
1747
+ f.write(f"# Pipeline Stop - {pipeline_uuid}\n\n")
1748
+ f.write(f"- **Status**: {payload.get('status', 'stopped')}\n")
1749
+ log.info(
1750
+ "pipeline_stop_reported",
1751
+ workspace=workspace,
1752
+ repository_slug=repo_slug,
1753
+ pipeline_uuid=pipeline_uuid,
1754
+ path=str(output_path),
1755
+ )
1756
+ out.output_json(payload)
1757
+
1758
+ else:
1759
+ raise typer.BadParameter(f"Unknown action: {action}")
1760
+
1761
+ except VDSClientError as exc:
1762
+ _handle_error(exc, out, log)
1763
+ raise typer.Exit(1) from None
1764
+ except typer.BadParameter as exc:
1765
+ log.exception("parameter_error", message=str(exc))
1766
+ out.output_error(str(exc))
1767
+ raise typer.Exit(1) from None
1768
+ except Exception as exc:
1769
+ log.exception("unexpected_error", message=str(exc))
1770
+ out.output_error(str(exc))
1771
+ raise typer.Exit(1) from None
1772
+
1773
+
1774
+ @app.command()
1775
+ def repo_settings(
1776
+ ctx: typer.Context,
1777
+ category: str = typer.Argument(..., help="Category: branching-model, default-branch, hooks, lfs"),
1778
+ action: str = typer.Argument(..., help="Action: get, set, enable, disable (varies by category)"),
1779
+ project_key: str = typer.Argument(..., help="Project key"),
1780
+ repository_slug: str = typer.Argument(..., help="Repository slug"),
1781
+ model_file: Path | None = typer.Option(
1782
+ None, "--model-file", help="Path to JSON file with branching model (for set)"
1783
+ ),
1784
+ branch: str | None = typer.Option(None, "--branch", help="Branch name (for default-branch set)"),
1785
+ hook_key: str | None = typer.Option(None, "--hook-key", help="Hook key (for hooks enable/disable)"),
1786
+ enabled: bool | None = typer.Option(None, "--enabled/--disabled", help="Enable/disable LFS (for lfs set)"),
1787
+ start: int = typer.Option(0, "--start", help="Start index for pagination (for hooks get)"),
1788
+ limit: int | None = typer.Option(None, "--limit", help="Limit for pagination (for hooks get)"),
1789
+ filter_type: str | None = typer.Option(None, "--filter-type", help="Filter type (for hooks get)"),
1790
+ yes: bool = typer.Option(False, "--yes", help="Confirm write operation"),
1791
+ ) -> None:
1792
+ """Manage Bitbucket repository settings."""
1793
+ out = OutputManager(CLIContext.from_typer_context(ctx))
1794
+ log = structlog.get_logger(__name__)
1795
+ report_dir = _REPORT_DIR
1796
+
1797
+ try:
1798
+ load_settings(strict=True)
1799
+ with _get_client() as client:
1800
+ result_obj: dict | None = None
1801
+
1802
+ if category == "branching-model":
1803
+ if action == "get":
1804
+ payload = client.get_branching_model(project_key, repository_slug)
1805
+ result_obj = {"branching_model": payload}
1806
+ elif action == "set":
1807
+ if not yes:
1808
+ raise typer.BadParameter("Refusing to set branching model without --yes")
1809
+ if not model_file:
1810
+ raise typer.BadParameter("--model-file required for set")
1811
+ if not model_file.exists():
1812
+ raise typer.BadParameter(f"Model file not found: {model_file}")
1813
+ with model_file.open() as f:
1814
+ model = json.load(f)
1815
+ payload = client.set_branching_model(project_key, repository_slug, model)
1816
+ result_obj = {"branching_model": payload}
1817
+ elif action == "enable":
1818
+ if not yes:
1819
+ raise typer.BadParameter("Refusing to enable branching model without --yes")
1820
+ payload = client.enable_branching_model(project_key, repository_slug)
1821
+ result_obj = {"branching_model": payload}
1822
+ elif action == "disable":
1823
+ if not yes:
1824
+ raise typer.BadParameter("Refusing to disable branching model without --yes")
1825
+ payload = client.disable_branching_model(project_key, repository_slug)
1826
+ result_obj = {"branching_model": payload}
1827
+ else:
1828
+ raise typer.BadParameter(f"Unknown action for branching-model: {action}")
1829
+
1830
+ elif category == "default-branch":
1831
+ if action == "get":
1832
+ payload = client.get_default_branch(project_key, repository_slug)
1833
+ result_obj = {"default_branch": payload}
1834
+ elif action == "set":
1835
+ if not yes:
1836
+ raise typer.BadParameter("Refusing to set default branch without --yes")
1837
+ if not branch:
1838
+ raise typer.BadParameter("--branch required for set")
1839
+ payload = client.set_default_branch(project_key, repository_slug, branch)
1840
+ result_obj = {"default_branch": payload}
1841
+ else:
1842
+ raise typer.BadParameter(f"Unknown action for default-branch: {action}")
1843
+
1844
+ elif category == "hooks":
1845
+ if action == "get":
1846
+ payload = client.get_repo_hook_settings(
1847
+ project_key, repository_slug, start=start, limit=limit, filter_type=filter_type
1848
+ )
1849
+ result_obj = {"hooks": payload}
1850
+ elif action == "enable":
1851
+ if not yes:
1852
+ raise typer.BadParameter("Refusing to enable hook without --yes")
1853
+ if not hook_key:
1854
+ raise typer.BadParameter("--hook-key required for enable")
1855
+ payload = client.enable_repo_hook_settings(project_key, repository_slug, hook_key)
1856
+ result_obj = {"hook": payload}
1857
+ elif action == "disable":
1858
+ if not yes:
1859
+ raise typer.BadParameter("Refusing to disable hook without --yes")
1860
+ if not hook_key:
1861
+ raise typer.BadParameter("--hook-key required for disable")
1862
+ payload = client.disable_repo_hook_settings(project_key, repository_slug, hook_key)
1863
+ result_obj = {"hook": payload}
1864
+ else:
1865
+ raise typer.BadParameter(f"Unknown action for hooks: {action}")
1866
+
1867
+ elif category == "lfs":
1868
+ if action == "get":
1869
+ payload = client.get_lfs_repo_status(project_key, repository_slug)
1870
+ result_obj = {"lfs": payload}
1871
+ elif action == "set":
1872
+ if not yes:
1873
+ raise typer.BadParameter("Refusing to set LFS status without --yes")
1874
+ if enabled is None:
1875
+ raise typer.BadParameter("--enabled or --disabled required for set")
1876
+ payload = client.set_lfs_repo_status(project_key, repository_slug, enabled)
1877
+ result_obj = {"lfs": payload}
1878
+ else:
1879
+ raise typer.BadParameter(f"Unknown action for lfs: {action}")
1880
+
1881
+ else:
1882
+ raise typer.BadParameter(f"Unknown category: {category}")
1883
+
1884
+ output_path = report_dir / f"{project_key}_{repository_slug}_repo_settings_{category}_{action}.md"
1885
+ output_path.parent.mkdir(parents=True, exist_ok=True)
1886
+ with output_path.open("w") as f:
1887
+ f.write(f"# Repository Settings - {category} - {action}\n\n")
1888
+ f.write(f"- **Project**: {project_key}\n")
1889
+ f.write(f"- **Repository**: {repository_slug}\n")
1890
+ f.write(f"- **Category**: {category}\n")
1891
+ f.write(f"- **Action**: {action}\n")
1892
+ log.info("repo_settings_reported", path=str(output_path), category=category, action=action)
1893
+ out.output_json(result_obj or {})
1894
+
1895
+ except VDSClientError as exc:
1896
+ _handle_error(exc, out, log)
1897
+ raise typer.Exit(1) from None
1898
+ except typer.BadParameter as exc:
1899
+ log.exception("parameter_error", message=str(exc))
1900
+ out.output_error(str(exc))
1901
+ raise typer.Exit(1) from None
1902
+ except Exception as exc:
1903
+ log.exception("unexpected_error", message=str(exc))
1904
+ out.output_error(str(exc))
1905
+ raise typer.Exit(1) from None
1906
+
1907
+
1908
+ @app.command()
1909
+ def code_advanced(
1910
+ ctx: typer.Context,
1911
+ action: str = typer.Argument(..., help="Action: file-list, commit-info, commit-changes, search, search-advanced"),
1912
+ project_key: str | None = typer.Option(
1913
+ None, "--project-key", help="Project key (for file-list, commit-info, commit-changes)"
1914
+ ),
1915
+ repository_slug: str | None = typer.Option(
1916
+ None, "--repository-slug", help="Repository slug (for file-list, commit-info, commit-changes)"
1917
+ ),
1918
+ sub_folder: str | None = typer.Option(None, "--sub-folder", help="Subfolder path (for file-list)"),
1919
+ query: str | None = typer.Option(None, "--query", help="Query string for filtering (for file-list)"),
1920
+ commit: str | None = typer.Option(None, "--commit", help="Commit hash (for commit-info)"),
1921
+ commit_id: str | None = typer.Option(None, "--commit-id", help="Commit ID (for commit-changes)"),
1922
+ hash_newest: str | None = typer.Option(None, "--hash-newest", help="Newest commit hash (for commit-changes)"),
1923
+ path: str | None = typer.Option(None, "--path", help="File path (for commit-info)"),
1924
+ merges: str = typer.Option(
1925
+ "include", "--merges", help="How to handle merges: include, exclude, only (for commit-changes)"
1926
+ ),
1927
+ team: str | None = typer.Option(None, "--team", help="Team/workspace name (for search, Cloud-only)"),
1928
+ search_query: str | None = typer.Option(None, "--search-query", help="Search query string (for search)"),
1929
+ repository: str | None = typer.Option(None, "--repository", help="Repository slug filter (for search-advanced)"),
1930
+ start: int = typer.Option(0, "--start", help="Start index for pagination"),
1931
+ limit: int | None = typer.Option(None, "--limit", help="Limit for pagination"),
1932
+ page: int = typer.Option(1, "--page", help="Page number (for search)"),
1933
+ ) -> None:
1934
+ """Advanced code operations."""
1935
+ out = OutputManager(CLIContext.from_typer_context(ctx))
1936
+ log = structlog.get_logger(__name__)
1937
+ report_dir = _REPORT_DIR
1938
+
1939
+ try:
1940
+ settings = load_settings(strict=True)
1941
+ with _get_client() as client:
1942
+ result_obj: dict | None = None
1943
+
1944
+ if action == "file-list":
1945
+ if not project_key:
1946
+ raise typer.BadParameter("--project-key required for file-list")
1947
+ if not repository_slug:
1948
+ raise typer.BadParameter("--repository-slug required for file-list")
1949
+ payload = client.get_file_list(
1950
+ project_key, repository_slug, sub_folder=sub_folder, query=query, start=start, limit=limit
1951
+ )
1952
+ result_obj = {"files": payload}
1953
+
1954
+ elif action == "commit-info":
1955
+ if not project_key:
1956
+ raise typer.BadParameter("--project-key required for commit-info")
1957
+ if not repository_slug:
1958
+ raise typer.BadParameter("--repository-slug required for commit-info")
1959
+ if not commit:
1960
+ raise typer.BadParameter("--commit required for commit-info")
1961
+ payload = client.get_commit_info(project_key, repository_slug, commit, path=path)
1962
+ result_obj = {"commit": payload}
1963
+
1964
+ elif action == "commit-changes":
1965
+ if not project_key:
1966
+ raise typer.BadParameter("--project-key required for commit-changes")
1967
+ if not repository_slug:
1968
+ raise typer.BadParameter("--repository-slug required for commit-changes")
1969
+ if not commit_id and not hash_newest:
1970
+ raise typer.BadParameter("--commit-id or --hash-newest required for commit-changes")
1971
+ payload = client.get_commit_changes(
1972
+ project_key, repository_slug, commit_id=commit_id, hash_newest=hash_newest, merges=merges
1973
+ )
1974
+ result_obj = {"changes": payload}
1975
+
1976
+ elif action == "search":
1977
+ if not settings.is_cloud_mode:
1978
+ log.error("cloud_mode_required", message="Code search is only available in Bitbucket Cloud mode")
1979
+ out.output_error("Code search is only available in Bitbucket Cloud mode")
1980
+ raise typer.Exit(1) from None
1981
+ if not team:
1982
+ raise typer.BadParameter("--team required for search")
1983
+ if not search_query:
1984
+ raise typer.BadParameter("--search-query required for search")
1985
+ payload = client.search_code(team, search_query, page=page, limit=limit or 10)
1986
+ result_obj = {"results": payload}
1987
+ elif action == "search-advanced":
1988
+ if not settings.is_cloud_mode:
1989
+ log.error("cloud_mode_required", message="Code search is only available in Bitbucket Cloud mode")
1990
+ out.output_error("Code search is only available in Bitbucket Cloud mode")
1991
+ raise typer.Exit(1) from None
1992
+ if not team:
1993
+ raise typer.BadParameter("--team required for search-advanced")
1994
+ if not search_query:
1995
+ raise typer.BadParameter("--search-query required for search-advanced")
1996
+ payload = client.search_code_advanced(
1997
+ team, search_query, page=page, limit=limit or 10, repository=repository
1998
+ )
1999
+ result_obj = {"results": payload, "repository_filter": repository}
2000
+
2001
+ else:
2002
+ raise typer.BadParameter(f"Unknown action: {action}")
2003
+
2004
+ output_path = report_dir / f"{project_key or team}_code_advanced_{action}.md"
2005
+ output_path.parent.mkdir(parents=True, exist_ok=True)
2006
+ with output_path.open("w") as f:
2007
+ f.write(f"# Advanced Code Operations - {action}\n\n")
2008
+ if project_key:
2009
+ f.write(f"- **Project**: {project_key}\n")
2010
+ if repository_slug:
2011
+ f.write(f"- **Repository**: {repository_slug}\n")
2012
+ if team:
2013
+ f.write(f"- **Team**: {team}\n")
2014
+ f.write(f"- **Action**: {action}\n")
2015
+ log.info("code_advanced_reported", path=str(output_path), action=action)
2016
+ out.output_json(result_obj or {})
2017
+
2018
+ except VDSClientError as exc:
2019
+ _handle_error(exc, out, log)
2020
+ raise typer.Exit(1) from None
2021
+ except typer.BadParameter as exc:
2022
+ log.exception("parameter_error", message=str(exc))
2023
+ out.output_error(str(exc))
2024
+ raise typer.Exit(1) from None
2025
+ except Exception as exc:
2026
+ log.exception("unexpected_error", message=str(exc))
2027
+ out.output_error(str(exc))
2028
+ raise typer.Exit(1) from None
2029
+
2030
+
2031
+ @app.command()
2032
+ def workspace(
2033
+ ctx: typer.Context,
2034
+ action: str = typer.Argument(..., help="Action: list, get, permissions, projects, project"),
2035
+ workspace_slug: str | None = typer.Option(
2036
+ None, "--workspace-slug", help="Workspace slug (required for all actions except list)"
2037
+ ),
2038
+ repo_slug: str | None = typer.Option(None, "--repo-slug", help="Repository slug (for permissions action)"),
2039
+ project_key: str | None = typer.Option(None, "--project-key", help="Project key (for project action)"),
2040
+ ) -> None:
2041
+ """Cloud workspace operations (Cloud-only)."""
2042
+ out = OutputManager(CLIContext.from_typer_context(ctx))
2043
+ log = structlog.get_logger(__name__)
2044
+ report_dir = _REPORT_DIR
2045
+
2046
+ try:
2047
+ settings = load_settings(strict=True)
2048
+
2049
+ if not settings.is_cloud_mode:
2050
+ log.error("cloud_mode_required", message="Workspace operations are only available in Bitbucket Cloud mode")
2051
+ out.output_error("Workspace operations are only available in Bitbucket Cloud mode")
2052
+ raise typer.Exit(1) from None
2053
+
2054
+ with _get_client() as client:
2055
+ result_obj: dict | None = None
2056
+
2057
+ if action == "list":
2058
+ payload = client.list_workspaces()
2059
+ result_obj = {"workspaces": payload, "count": len(payload)}
2060
+
2061
+ elif action == "get":
2062
+ if not workspace_slug:
2063
+ raise typer.BadParameter("--workspace-slug required for get")
2064
+ payload = client.get_workspace(workspace_slug)
2065
+ result_obj = {"workspace": payload}
2066
+
2067
+ elif action == "permissions":
2068
+ if not workspace_slug:
2069
+ raise typer.BadParameter("--workspace-slug required for permissions")
2070
+ if repo_slug:
2071
+ payload = client.get_workspace_repository_permissions(workspace_slug, repo_slug=repo_slug)
2072
+ result_obj = {"repository_permissions": payload}
2073
+ else:
2074
+ payload = client.get_workspace_permissions(workspace_slug)
2075
+ result_obj = {"workspace_permissions": payload, "count": len(payload)}
2076
+
2077
+ elif action == "projects":
2078
+ if not workspace_slug:
2079
+ raise typer.BadParameter("--workspace-slug required for projects")
2080
+ payload = client.list_workspace_projects(workspace_slug)
2081
+ result_obj = {"projects": payload, "count": len(payload)}
2082
+
2083
+ elif action == "project":
2084
+ if not workspace_slug:
2085
+ raise typer.BadParameter("--workspace-slug required for project")
2086
+ if not project_key:
2087
+ raise typer.BadParameter("--project-key required for project")
2088
+ payload = client.get_workspace_project(workspace_slug, project_key)
2089
+ result_obj = {"project": payload}
2090
+
2091
+ else:
2092
+ raise typer.BadParameter(f"Unknown action: {action}")
2093
+
2094
+ output_path = report_dir / f"{workspace_slug or 'all'}_workspace_{action}.md"
2095
+ output_path.parent.mkdir(parents=True, exist_ok=True)
2096
+ with output_path.open("w") as f:
2097
+ f.write(f"# Workspace Operations - {action}\n\n")
2098
+ if workspace_slug:
2099
+ f.write(f"- **Workspace**: {workspace_slug}\n")
2100
+ if repo_slug:
2101
+ f.write(f"- **Repository**: {repo_slug}\n")
2102
+ if project_key:
2103
+ f.write(f"- **Project**: {project_key}\n")
2104
+ f.write(f"- **Action**: {action}\n")
2105
+ log.info("workspace_reported", path=str(output_path), action=action, workspace_slug=workspace_slug)
2106
+ out.output_json(result_obj or {})
2107
+
2108
+ except VDSClientError as exc:
2109
+ _handle_error(exc, out, log)
2110
+ raise typer.Exit(1) from None
2111
+ except typer.BadParameter as exc:
2112
+ log.exception("parameter_error", message=str(exc))
2113
+ out.output_error(str(exc))
2114
+ raise typer.Exit(1) from None
2115
+ except Exception as exc:
2116
+ log.exception("unexpected_error", message=str(exc))
2117
+ out.output_error(str(exc))
2118
+ raise typer.Exit(1) from None
2119
+
2120
+
2121
+ @app.command()
2122
+ def clone(
2123
+ ctx: typer.Context,
2124
+ identifier: str = typer.Argument(
2125
+ ..., help="Repository identifier: PROJECT/repo, browse URL, clone URL, or SSH URL"
2126
+ ),
2127
+ target: Path | None = typer.Option(None, "--target", "-t", help="Target directory (default: VDS cache root)"),
2128
+ branch: str | None = typer.Option(None, "--branch", "-b", help="Branch to clone"),
2129
+ shallow: bool = typer.Option(False, "--shallow", help="Shallow clone (depth 1)"),
2130
+ force: bool = typer.Option(False, "--force", help="Force reclone if directory exists"),
2131
+ ) -> None:
2132
+ """Clone a Bitbucket repository to the local VDS cache."""
2133
+ out = OutputManager(CLIContext.from_typer_context(ctx))
2134
+ log = structlog.get_logger(__name__)
2135
+
2136
+ try:
2137
+ ref = parse_repo_identifier(identifier)
2138
+ except ValueError as exc:
2139
+ log.exception("invalid_identifier", message=str(exc))
2140
+ out.output_error(str(exc))
2141
+ raise typer.Exit(1) from None
2142
+
2143
+ try:
2144
+ settings = load_settings(strict=True)
2145
+
2146
+ with BitbucketClient(settings) as client:
2147
+ client.get_repository(ref.project_key, ref.repo_slug)
2148
+
2149
+ resolved_branch = branch
2150
+ if not resolved_branch:
2151
+ default = client.get_default_branch(ref.project_key, ref.repo_slug)
2152
+ if isinstance(default, dict):
2153
+ resolved_branch = default.get("displayId") or default.get("id")
2154
+
2155
+ clone_url = build_clone_url(
2156
+ ref,
2157
+ settings.get_url(),
2158
+ username=settings.username,
2159
+ token=settings.token,
2160
+ )
2161
+
2162
+ cache_root = get_vds_cache_root()
2163
+ dest = target or cache_root / "repos" / f"{ref.project_key}-project" / ref.repo_slug
2164
+
2165
+ result = clone_repo(
2166
+ ref,
2167
+ clone_url,
2168
+ dest,
2169
+ branch=resolved_branch,
2170
+ shallow=shallow,
2171
+ force_reclone=force,
2172
+ )
2173
+
2174
+ payload = {
2175
+ "status": "success",
2176
+ "operation": result.operation,
2177
+ "project": ref.project_key,
2178
+ "repo": ref.repo_slug,
2179
+ "branch": result.branch,
2180
+ "path": str(result.path),
2181
+ }
2182
+ out.output_json(payload)
2183
+
2184
+ except NotFoundError as exc:
2185
+ log.exception("repo_not_found", message=str(exc))
2186
+ out.output_error(str(exc))
2187
+ raise typer.Exit(1) from None
2188
+ except (VDSClientError, SettingsError) as exc:
2189
+ log.exception("bitbucket_error", message=str(exc))
2190
+ out.output_error(str(exc))
2191
+ raise typer.Exit(1) from None
2192
+ except Exception as exc:
2193
+ log.exception("unexpected_error", message=str(exc))
2194
+ out.output_error(str(exc))
2195
+ raise typer.Exit(1) from None
2196
+
2197
+
2198
+ @app.command()
2199
+ def archive(
2200
+ ctx: typer.Context,
2201
+ identifier: str = typer.Argument(
2202
+ ..., help="Repository identifier: PROJECT/repo, browse URL, clone URL, or SSH URL"
2203
+ ),
2204
+ output: Path | None = typer.Option(None, "--output", "-o", help="Output archive path (default: VDS cache)"),
2205
+ format: str = typer.Option("zip", "--format", "-f", help="Archive format: zip, tar.gz, tgz, tar"),
2206
+ branch: str | None = typer.Option(None, "--branch", "-b", help="Branch/tag/commit to archive"),
2207
+ path: str | None = typer.Option(None, "--path", help="Limit archive to path prefix"),
2208
+ include_git: bool = typer.Option(False, "--include-git", help="Include .git directory (forces local-zip method)"),
2209
+ ) -> None:
2210
+ """Download a Bitbucket repository as an archive (zip or tar.gz)."""
2211
+ out = OutputManager(CLIContext.from_typer_context(ctx))
2212
+ log = structlog.get_logger(__name__)
2213
+
2214
+ try:
2215
+ ref = parse_repo_identifier(identifier)
2216
+ except ValueError as exc:
2217
+ log.exception("invalid_identifier", message=str(exc))
2218
+ out.output_error(str(exc))
2219
+ raise typer.Exit(1) from None
2220
+
2221
+ try:
2222
+ settings = load_settings(strict=True)
2223
+ cache_root = get_vds_cache_root()
2224
+
2225
+ clone_url = build_clone_url(
2226
+ ref,
2227
+ settings.get_url(),
2228
+ username=settings.username,
2229
+ token=settings.token,
2230
+ )
2231
+
2232
+ ext = "tar.gz" if format in ("tar.gz", "tgz") else format
2233
+ archive_path = output or (cache_root / "archives" / f"{ref.project_key}-{ref.repo_slug}.{ext}")
2234
+ archive_path.parent.mkdir(parents=True, exist_ok=True)
2235
+
2236
+ with BitbucketClient(settings) as client:
2237
+ result = archive_repo(
2238
+ ref,
2239
+ client,
2240
+ clone_url,
2241
+ cache_root,
2242
+ archive_path,
2243
+ format=format,
2244
+ at=branch,
2245
+ path=path,
2246
+ include_git=include_git,
2247
+ )
2248
+
2249
+ payload = {
2250
+ "status": "success",
2251
+ "project": ref.project_key,
2252
+ "repo": ref.repo_slug,
2253
+ "archive_path": str(result.archive_path),
2254
+ "format": result.format,
2255
+ "size_bytes": result.size_bytes,
2256
+ "method": result.method,
2257
+ }
2258
+ out.output_json(payload)
2259
+
2260
+ except NotFoundError as exc:
2261
+ log.exception("repo_not_found", message=str(exc))
2262
+ out.output_error(str(exc))
2263
+ raise typer.Exit(1) from None
2264
+ except (VDSClientError, SettingsError) as exc:
2265
+ log.exception("bitbucket_error", message=str(exc))
2266
+ out.output_error(str(exc))
2267
+ raise typer.Exit(1) from None
2268
+ except Exception as exc:
2269
+ log.exception("unexpected_error", message=str(exc))
2270
+ out.output_error(str(exc))
2271
+ raise typer.Exit(1) from None