@ngocsangairvds/vsaf 3.1.27 → 3.2.1

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 (303) hide show
  1. package/package.json +2 -2
  2. package/src/global.js +70 -10
  3. package/tools/skills/vds-scripts-skill/.openskills.json +6 -0
  4. package/tools/skills/vds-scripts-skill/QUALITY.md +44 -0
  5. package/tools/skills/vds-scripts-skill/SKILL.md +135 -0
  6. package/tools/skills/vds-scripts-skill/references/audit-commands.md +171 -0
  7. package/tools/skills/vds-scripts-skill/references/capability-index.md +34 -0
  8. package/tools/skills/vds-scripts-skill/references/development-commands.md +12 -0
  9. package/tools/skills/vds-scripts-skill/references/google-sheets.md +73 -0
  10. package/tools/skills/vds-scripts-skill/references/integration-commands.md +17 -0
  11. package/tools/skills/vds-scripts-skill/references/platform-bootstrap.md +31 -0
  12. package/tools/skills/vds-scripts-skill/references/specialist-routing.md +14 -0
  13. package/tools/skills/vds-scripts-skill/references/validation-commands.md +15 -0
  14. package/tools/skills/vsaf-build/SKILL.md +32 -2
  15. package/tools/skills/vsaf-ship/SKILL.md +41 -10
  16. package/tools/skills/vsaf-test/SKILL.md +8 -0
  17. package/tools/vds-scripts/.mcp.json +11 -0
  18. package/tools/vds-scripts/.secrets.baseline +133 -0
  19. package/tools/vds-scripts/AGENTS.md +152 -0
  20. package/tools/vds-scripts/CLAUDE.md +101 -0
  21. package/tools/vds-scripts/CLI_COMMAND_OPTIMIZATION.md +156 -0
  22. package/tools/vds-scripts/PACKAGE_P125B_IMPLEMENTATION_SUMMARY.md +131 -0
  23. package/tools/vds-scripts/PROJECT_COMPLETION_SUMMARY.md +45 -0
  24. package/tools/vds-scripts/README.md +97 -0
  25. package/tools/vds-scripts/bitbucket_manifest_mapping.toml +34 -0
  26. package/tools/vds-scripts/bitbucket_orchestrator/ARCHITECTURE_ANALYSIS.md +258 -0
  27. package/tools/vds-scripts/bitbucket_orchestrator/BITBUCKET_API_PRACTICES.md +393 -0
  28. package/tools/vds-scripts/bitbucket_orchestrator/EVALUATION_REPORT.md +61 -0
  29. package/tools/vds-scripts/bitbucket_orchestrator/FEATURES.md +908 -0
  30. package/tools/vds-scripts/bitbucket_orchestrator/README.md +687 -0
  31. package/tools/vds-scripts/bitbucket_orchestrator/pyproject.toml +40 -0
  32. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/__init__.py +20 -0
  33. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/async_client.py +657 -0
  34. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/cli.py +2108 -0
  35. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/client.py +2534 -0
  36. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/config.py +171 -0
  37. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/errors.py +67 -0
  38. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/factory.py +185 -0
  39. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/protocols.py +244 -0
  40. package/tools/vds-scripts/bitbucket_orchestrator/tests/__init__.py +8 -0
  41. package/tools/vds-scripts/bitbucket_orchestrator/tests/conftest.py +65 -0
  42. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_advanced_search.py +151 -0
  43. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_async_client.py +546 -0
  44. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_branch_permissions.py +145 -0
  45. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_cli.py +115 -0
  46. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client.py +157 -0
  47. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_branch_conditions.py +79 -0
  48. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_code_advanced.py +163 -0
  49. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_code_file.py +32 -0
  50. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_deployment_environments.py +194 -0
  51. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_issues.py +164 -0
  52. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_pipelines_advanced.py +179 -0
  53. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_pr_blockers.py +119 -0
  54. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_repository_variables.py +156 -0
  55. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_code.py +98 -0
  56. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_code_advanced.py +282 -0
  57. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_code_insights.py +335 -0
  58. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_conditions.py +147 -0
  59. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_config.py +131 -0
  60. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_deployment_env.py +352 -0
  61. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_factory.py +371 -0
  62. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_fork_operations.py +204 -0
  63. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_issue_cli.py +261 -0
  64. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_pipeline_advanced.py +270 -0
  65. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_pr_blocker.py +204 -0
  66. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_protocols.py +334 -0
  67. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_repo_settings.py +343 -0
  68. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_repo_variables.py +270 -0
  69. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_webhooks.py +189 -0
  70. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_workspace.py +233 -0
  71. package/tools/vds-scripts/bitbucket_orchestrator/uv.lock +742 -0
  72. package/tools/vds-scripts/confluence_orchestrator/Dockerfile +19 -0
  73. package/tools/vds-scripts/confluence_orchestrator/README.md +412 -0
  74. package/tools/vds-scripts/confluence_orchestrator/SYNC_SCRIPTS.md +127 -0
  75. package/tools/vds-scripts/confluence_orchestrator/SYNC_STANDARDIZATION.md +108 -0
  76. package/tools/vds-scripts/confluence_orchestrator/pyproject.toml +48 -0
  77. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/__init__.py +20 -0
  78. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/cli.py +2532 -0
  79. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/config.py +175 -0
  80. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/content.py +290 -0
  81. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/content_v2.py +94 -0
  82. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/crawl_tree.py +1835 -0
  83. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/errors.py +80 -0
  84. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/eventing.py +109 -0
  85. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/http.py +1114 -0
  86. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/orchestration.py +165 -0
  87. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/reporting.py +78 -0
  88. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/tree.py +121 -0
  89. package/tools/vds-scripts/confluence_orchestrator/sync_pdfs_from_markdown.py +213 -0
  90. package/tools/vds-scripts/confluence_orchestrator/sync_pdfs_to_confluence.py +305 -0
  91. package/tools/vds-scripts/confluence_orchestrator/sync_png_attachments.py +305 -0
  92. package/tools/vds-scripts/confluence_orchestrator/tests/__init__.py +0 -0
  93. package/tools/vds-scripts/confluence_orchestrator/tests/conftest.py +8 -0
  94. package/tools/vds-scripts/confluence_orchestrator/tests/test_advanced_content.py +224 -0
  95. package/tools/vds-scripts/confluence_orchestrator/tests/test_advanced_search.py +188 -0
  96. package/tools/vds-scripts/confluence_orchestrator/tests/test_cache_management.py +247 -0
  97. package/tools/vds-scripts/confluence_orchestrator/tests/test_cli.py +499 -0
  98. package/tools/vds-scripts/confluence_orchestrator/tests/test_config.py +83 -0
  99. package/tools/vds-scripts/confluence_orchestrator/tests/test_content.py +186 -0
  100. package/tools/vds-scripts/confluence_orchestrator/tests/test_content_flags.py +27 -0
  101. package/tools/vds-scripts/confluence_orchestrator/tests/test_crawl_tree.py +2250 -0
  102. package/tools/vds-scripts/confluence_orchestrator/tests/test_draft_management.py +223 -0
  103. package/tools/vds-scripts/confluence_orchestrator/tests/test_eventing.py +71 -0
  104. package/tools/vds-scripts/confluence_orchestrator/tests/test_eventing_chaos.py +37 -0
  105. package/tools/vds-scripts/confluence_orchestrator/tests/test_eventing_rate_limit.py +44 -0
  106. package/tools/vds-scripts/confluence_orchestrator/tests/test_eventing_timeout.py +49 -0
  107. package/tools/vds-scripts/confluence_orchestrator/tests/test_export.py +230 -0
  108. package/tools/vds-scripts/confluence_orchestrator/tests/test_history.py +204 -0
  109. package/tools/vds-scripts/confluence_orchestrator/tests/test_http.py +117 -0
  110. package/tools/vds-scripts/confluence_orchestrator/tests/test_orchestration.py +91 -0
  111. package/tools/vds-scripts/confluence_orchestrator/tests/test_reporting.py +24 -0
  112. package/tools/vds-scripts/confluence_orchestrator/tests/test_search_cql.py +34 -0
  113. package/tools/vds-scripts/confluence_orchestrator/tests/test_space_management.py +237 -0
  114. package/tools/vds-scripts/confluence_orchestrator/tests/test_space_permissions.py +332 -0
  115. package/tools/vds-scripts/confluence_orchestrator/tests/test_user_group_management.py +388 -0
  116. package/tools/vds-scripts/confluence_orchestrator/uv.lock +1023 -0
  117. package/tools/vds-scripts/git_orchestrator/ENHANCEMENT_SUMMARY.md +119 -0
  118. package/tools/vds-scripts/git_orchestrator/README.md +280 -0
  119. package/tools/vds-scripts/git_orchestrator/VERIFICATION_REPORT.md +152 -0
  120. package/tools/vds-scripts/git_orchestrator/pyproject.toml +35 -0
  121. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/__init__.py +7 -0
  122. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/__main__.py +4 -0
  123. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/cli.py +847 -0
  124. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/logging_config.py +63 -0
  125. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/manifest.py +129 -0
  126. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/orchestrator.py +819 -0
  127. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/reporting.py +53 -0
  128. package/tools/vds-scripts/git_orchestrator/tests/__init__.py +0 -0
  129. package/tools/vds-scripts/git_orchestrator/tests/test_cli_settings.py +21 -0
  130. package/tools/vds-scripts/git_orchestrator/tests/test_integration.py +74 -0
  131. package/tools/vds-scripts/git_orchestrator/tests/test_manifest.py +79 -0
  132. package/tools/vds-scripts/git_orchestrator/tests/test_orchestrator.py +204 -0
  133. package/tools/vds-scripts/git_orchestrator/tests/test_public_api.py +236 -0
  134. package/tools/vds-scripts/git_orchestrator/tests/test_resilience.py +345 -0
  135. package/tools/vds-scripts/git_orchestrator/uv.lock +271 -0
  136. package/tools/vds-scripts/jira_orchestrator/README.md +770 -0
  137. package/tools/vds-scripts/jira_orchestrator/pyproject.toml +39 -0
  138. package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/__init__.py +1 -0
  139. package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/adapter.py +1320 -0
  140. package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/cli.py +2271 -0
  141. package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/config.py +138 -0
  142. package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/errors.py +67 -0
  143. package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/reporting.py +65 -0
  144. package/tools/vds-scripts/jira_orchestrator/tests/__init__.py +1 -0
  145. package/tools/vds-scripts/jira_orchestrator/tests/conftest.py +86 -0
  146. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_agile_list_payloads.py +54 -0
  147. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_bulk_operations.py +69 -0
  148. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_components.py +57 -0
  149. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_createmeta.py +45 -0
  150. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_dashboard.py +117 -0
  151. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_issue_properties.py +54 -0
  152. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_permissions_compat.py +42 -0
  153. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_reindex.py +42 -0
  154. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_remote_links.py +76 -0
  155. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_transitions.py +91 -0
  156. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_user_management.py +110 -0
  157. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_version_management.py +133 -0
  158. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_watchers.py +41 -0
  159. package/tools/vds-scripts/jira_orchestrator/tests/test_advanced_search.py +164 -0
  160. package/tools/vds-scripts/jira_orchestrator/tests/test_agile.py +256 -0
  161. package/tools/vds-scripts/jira_orchestrator/tests/test_application_properties.py +193 -0
  162. package/tools/vds-scripts/jira_orchestrator/tests/test_backlog.py +91 -0
  163. package/tools/vds-scripts/jira_orchestrator/tests/test_bulk_operations.py +277 -0
  164. package/tools/vds-scripts/jira_orchestrator/tests/test_cli.py +106 -0
  165. package/tools/vds-scripts/jira_orchestrator/tests/test_components.py +106 -0
  166. package/tools/vds-scripts/jira_orchestrator/tests/test_config.py +164 -0
  167. package/tools/vds-scripts/jira_orchestrator/tests/test_dashboard.py +122 -0
  168. package/tools/vds-scripts/jira_orchestrator/tests/test_discover_fields.py +207 -0
  169. package/tools/vds-scripts/jira_orchestrator/tests/test_filter_management.py +333 -0
  170. package/tools/vds-scripts/jira_orchestrator/tests/test_issue_archiving.py +164 -0
  171. package/tools/vds-scripts/jira_orchestrator/tests/test_issue_links.py +257 -0
  172. package/tools/vds-scripts/jira_orchestrator/tests/test_issue_properties.py +171 -0
  173. package/tools/vds-scripts/jira_orchestrator/tests/test_link_types.py +314 -0
  174. package/tools/vds-scripts/jira_orchestrator/tests/test_parse_set.py +37 -0
  175. package/tools/vds-scripts/jira_orchestrator/tests/test_permissions.py +273 -0
  176. package/tools/vds-scripts/jira_orchestrator/tests/test_reindex.py +81 -0
  177. package/tools/vds-scripts/jira_orchestrator/tests/test_remote_links.py +254 -0
  178. package/tools/vds-scripts/jira_orchestrator/tests/test_security_schemes.py +170 -0
  179. package/tools/vds-scripts/jira_orchestrator/tests/test_transitions_changelog.py +114 -0
  180. package/tools/vds-scripts/jira_orchestrator/tests/test_user_management.py +226 -0
  181. package/tools/vds-scripts/jira_orchestrator/tests/test_version_management.py +339 -0
  182. package/tools/vds-scripts/jira_orchestrator/tests/test_watchers.py +101 -0
  183. package/tools/vds-scripts/jira_orchestrator/tests/test_worklog.py +223 -0
  184. package/tools/vds-scripts/jira_orchestrator/uv.lock +738 -0
  185. package/tools/vds-scripts/mcp_server/Dockerfile +34 -0
  186. package/tools/vds-scripts/mcp_server/README.md +140 -0
  187. package/tools/vds-scripts/mcp_server/pyproject.toml +42 -0
  188. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/__init__.py +4 -0
  189. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/config.py +36 -0
  190. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/server.py +66 -0
  191. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/__init__.py +14 -0
  192. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/bitbucket_tools.py +47 -0
  193. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/confluence_tools.py +59 -0
  194. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/git_tools.py +71 -0
  195. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/jira_tools.py +63 -0
  196. package/tools/vds-scripts/mcp_server/tests/__init__.py +2 -0
  197. package/tools/vds-scripts/mcp_server/tests/conftest.py +29 -0
  198. package/tools/vds-scripts/mcp_server/tests/unit/__init__.py +2 -0
  199. package/tools/vds-scripts/mcp_server/tests/unit/test_bitbucket_tools.py +25 -0
  200. package/tools/vds-scripts/mcp_server/tests/unit/test_confluence_tools.py +25 -0
  201. package/tools/vds-scripts/mcp_server/tests/unit/test_git_tools.py +32 -0
  202. package/tools/vds-scripts/mcp_server/tests/unit/test_jira_tools.py +32 -0
  203. package/tools/vds-scripts/mcp_server/tests/verification/__init__.py +2 -0
  204. package/tools/vds-scripts/mcp_server/tests/verification/test_mcp_confluence_tools.py +40 -0
  205. package/tools/vds-scripts/mcp_server/tests/verification/test_mcp_jira_tools.py +37 -0
  206. package/tools/vds-scripts/mcp_server/tests/verification/test_mcp_tool_registration.py +47 -0
  207. package/tools/vds-scripts/mcp_server/uv.lock +1032 -0
  208. package/tools/vds-scripts/mypy.ini +5 -0
  209. package/tools/vds-scripts/pyproject.toml +29 -0
  210. package/tools/vds-scripts/repo-manifest.yaml +273 -0
  211. package/tools/vds-scripts/repo-manifest.yaml.example +25 -0
  212. package/tools/vds-scripts/scripts/BRD-Validation-API.postman_collection.json +706 -0
  213. package/tools/vds-scripts/scripts/BRD-Validation-README.md +308 -0
  214. package/tools/vds-scripts/scripts/README.md +162 -0
  215. package/tools/vds-scripts/scripts/bootstrap_uv.sh +30 -0
  216. package/tools/vds-scripts/scripts/brd-validation-environment.json +51 -0
  217. package/tools/vds-scripts/scripts/brd-validation-test-results.json +13023 -0
  218. package/tools/vds-scripts/scripts/brd_coverage_report.json +276 -0
  219. package/tools/vds-scripts/scripts/create_memory_session.py +35 -0
  220. package/tools/vds-scripts/scripts/deployment/load_docker_images_offline.sh +90 -0
  221. package/tools/vds-scripts/scripts/final_completion_report.md +139 -0
  222. package/tools/vds-scripts/scripts/folder_structure_report.json +321 -0
  223. package/tools/vds-scripts/scripts/generate_completion_report.py +125 -0
  224. package/tools/vds-scripts/scripts/generate_intellij_modules.py +150 -0
  225. package/tools/vds-scripts/scripts/link_integrity_report.json +807 -0
  226. package/tools/vds-scripts/scripts/move_audit_artifact_pages.py +255 -0
  227. package/tools/vds-scripts/scripts/move_audit_artifact_pages_rest.py +165 -0
  228. package/tools/vds-scripts/scripts/move_wrong_dept_pages.py +216 -0
  229. package/tools/vds-scripts/scripts/save_intellij_memories.py +120 -0
  230. package/tools/vds-scripts/scripts/save_memories_to_vds_ai.py +83 -0
  231. package/tools/vds-scripts/scripts/save_memories_vds_style.py +129 -0
  232. package/tools/vds-scripts/scripts/search_intellij_memories.py +50 -0
  233. package/tools/vds-scripts/scripts/setup_intellij_workspace.py +65 -0
  234. package/tools/vds-scripts/scripts/target-state-automation/README.md +89 -0
  235. package/tools/vds-scripts/scripts/target-state-automation/confluence_sync_coordinator.sh +27 -0
  236. package/tools/vds-scripts/scripts/target-state-automation/coordination.sh +114 -0
  237. package/tools/vds-scripts/scripts/target-state-automation/diagram_coordinator.sh +25 -0
  238. package/tools/vds-scripts/scripts/target-state-automation/docs_root.sh +22 -0
  239. package/tools/vds-scripts/scripts/target-state-automation/generate_diagrams.sh +22 -0
  240. package/tools/vds-scripts/scripts/target-state-automation/markdown_coordinator.sh +25 -0
  241. package/tools/vds-scripts/scripts/target-state-automation/progress_dashboard.sh +17 -0
  242. package/tools/vds-scripts/scripts/target-state-automation/schema_coordinator.sh +25 -0
  243. package/tools/vds-scripts/scripts/target-state-automation/sync_confluence.sh +30 -0
  244. package/tools/vds-scripts/scripts/target-state-automation/update_dependencies.sh +19 -0
  245. package/tools/vds-scripts/scripts/target-state-automation/validate_links.sh +86 -0
  246. package/tools/vds-scripts/scripts/target-state-automation/validate_markdown.sh +52 -0
  247. package/tools/vds-scripts/scripts/target-state-automation/validate_schemas.sh +26 -0
  248. package/tools/vds-scripts/scripts/target-state-automation/validate_structure.sh +98 -0
  249. package/tools/vds-scripts/scripts/update_modules_xml.py +190 -0
  250. package/tools/vds-scripts/scripts/uv-workspace-alignment-verification-2026-03-25.md +128 -0
  251. package/tools/vds-scripts/scripts/validate_brd_coverage.py +179 -0
  252. package/tools/vds-scripts/scripts/validate_folder_structure.py +240 -0
  253. package/tools/vds-scripts/scripts/validate_link_integrity.py +272 -0
  254. package/tools/vds-scripts/scripts/vds_sh_helpers.sh +180 -0
  255. package/tools/vds-scripts/scripts/verification/phase2_portable_paths_ubuntu_docker.sh +26 -0
  256. package/tools/vds-scripts/scripts/worktree_uv.sh +48 -0
  257. package/tools/vds-scripts/uv.lock +8 -0
  258. package/tools/vds-scripts/vds_cli/README.md +126 -0
  259. package/tools/vds-scripts/vds_cli/VERIFICATION_REPORT.md +41 -0
  260. package/tools/vds-scripts/vds_cli/pyproject.toml +38 -0
  261. package/tools/vds-scripts/vds_cli/src/vds_cli/__init__.py +3 -0
  262. package/tools/vds-scripts/vds_cli/src/vds_cli/cli.py +173 -0
  263. package/tools/vds-scripts/vds_cli/src/vds_cli/docs_sync.py +1203 -0
  264. package/tools/vds-scripts/vds_cli/src/vds_cli/env.py +41 -0
  265. package/tools/vds-scripts/vds_cli/src/vds_cli/google_sheets_orchestrator/__init__.py +3 -0
  266. package/tools/vds-scripts/vds_cli/src/vds_cli/google_sheets_orchestrator/google_sheets_orchestrator.py +198 -0
  267. package/tools/vds-scripts/vds_cli/src/vds_cli/router.py +93 -0
  268. package/tools/vds-scripts/vds_cli/src/vds_cli/sync_api.py +647 -0
  269. package/tools/vds-scripts/vds_cli/src/vds_cli/sync_service.py +266 -0
  270. package/tools/vds-scripts/vds_cli/tests/__init__.py +2 -0
  271. package/tools/vds-scripts/vds_cli/tests/conftest.py +49 -0
  272. package/tools/vds-scripts/vds_cli/tests/unit/__init__.py +2 -0
  273. package/tools/vds-scripts/vds_cli/tests/unit/test_cli.py +143 -0
  274. package/tools/vds-scripts/vds_cli/tests/unit/test_docs_sync.py +422 -0
  275. package/tools/vds-scripts/vds_cli/tests/unit/test_env.py +51 -0
  276. package/tools/vds-scripts/vds_cli/tests/unit/test_router.py +72 -0
  277. package/tools/vds-scripts/vds_cli/tests/unit/test_sync_api.py +357 -0
  278. package/tools/vds-scripts/vds_cli/tests/unit/test_sync_service.py +160 -0
  279. package/tools/vds-scripts/vds_cli/tests/verification/__init__.py +2 -0
  280. package/tools/vds-scripts/vds_cli/tests/verification/test_bitbucket_real.py +33 -0
  281. package/tools/vds-scripts/vds_cli/tests/verification/test_confluence_real.py +35 -0
  282. package/tools/vds-scripts/vds_cli/tests/verification/test_jira_real.py +41 -0
  283. package/tools/vds-scripts/vds_cli/uv.lock +524 -0
  284. package/tools/vds-scripts/vds_cli_common/README.md +190 -0
  285. package/tools/vds-scripts/vds_cli_common/pyproject.toml +92 -0
  286. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/__init__.py +34 -0
  287. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/completers.py +139 -0
  288. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/context.py +201 -0
  289. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/env.py +119 -0
  290. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/errors.py +318 -0
  291. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/output.py +284 -0
  292. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/paths.py +78 -0
  293. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/testing.py +213 -0
  294. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/version.py +85 -0
  295. package/tools/vds-scripts/vds_cli_common/tests/__init__.py +1 -0
  296. package/tools/vds-scripts/vds_cli_common/tests/test_completers.py +148 -0
  297. package/tools/vds-scripts/vds_cli_common/tests/test_context.py +192 -0
  298. package/tools/vds-scripts/vds_cli_common/tests/test_env.py +102 -0
  299. package/tools/vds-scripts/vds_cli_common/tests/test_errors.py +186 -0
  300. package/tools/vds-scripts/vds_cli_common/tests/test_output.py +229 -0
  301. package/tools/vds-scripts/vds_cli_common/tests/test_paths.py +61 -0
  302. package/tools/vds-scripts/vds_cli_common/tests/test_testing.py +138 -0
  303. package/tools/vds-scripts/vds_cli_common/tests/test_version.py +64 -0
@@ -0,0 +1,53 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from collections.abc import Iterable
5
+ from datetime import datetime
6
+ from pathlib import Path
7
+
8
+ from rich.console import Console
9
+ from rich.table import Table
10
+
11
+ from .orchestrator import RepoResult, RunSummary
12
+
13
+
14
+ def print_summary(summary: RunSummary) -> None:
15
+ console = Console()
16
+
17
+ header = (
18
+ f"Total: {summary.total} | "
19
+ f"Successes: {summary.successes} | "
20
+ f"Updated: {summary.updates} | "
21
+ f"Failures: {summary.failures}"
22
+ )
23
+ console.print(f"[bold cyan]Git operation summary[/bold cyan] :: {header}")
24
+
25
+ if summary.failures == 0:
26
+ return
27
+
28
+ console.print("[bold red]Failures:[/bold red]")
29
+ table = Table("Repository", "Project", "Message", show_lines=False)
30
+ for result in _failed(summary.results.values()):
31
+ table.add_row(result.repo.name, result.repo.project, result.message or "")
32
+ console.print(table)
33
+
34
+
35
+ def _failed(results: Iterable[RepoResult]) -> list[RepoResult]:
36
+ return [result for result in results if not result.success]
37
+
38
+
39
+ def write_json_report(
40
+ summary: RunSummary,
41
+ report_dir: Path,
42
+ metadata: dict | None = None,
43
+ ) -> Path:
44
+ report_dir.mkdir(parents=True, exist_ok=True)
45
+ timestamp = datetime.utcnow().strftime("%Y%m%dT%H%M%SZ")
46
+ payload = {
47
+ "timestamp": timestamp,
48
+ "metadata": metadata or {},
49
+ "summary": summary.to_dict(),
50
+ }
51
+ path = report_dir / f"git-run-{timestamp}.json"
52
+ path.write_text(json.dumps(payload, indent=2, ensure_ascii=False))
53
+ return path
@@ -0,0 +1,21 @@
1
+ import os
2
+
3
+ from vds_git_orchestrator.cli import _default_concurrency
4
+
5
+
6
+ def test_default_concurrency_from_env(monkeypatch):
7
+ monkeypatch.setenv("VDS_GIT_CONCURRENCY_DEFAULT", "12")
8
+ assert _default_concurrency() == 12
9
+
10
+
11
+ def test_default_concurrency_cpu_fallback(monkeypatch):
12
+ monkeypatch.delenv("VDS_GIT_CONCURRENCY_DEFAULT", raising=False)
13
+ monkeypatch.setattr(os, "cpu_count", lambda: 6)
14
+ assert _default_concurrency() == 3 # max(2, 6//2)=3 within cap
15
+
16
+
17
+ def test_default_concurrency_invalid_env(monkeypatch):
18
+ monkeypatch.setenv("VDS_GIT_CONCURRENCY_DEFAULT", "bad")
19
+ monkeypatch.setattr(os, "cpu_count", lambda: 32)
20
+ # cpu fallback -> max(2, 16)=16, capped at 8
21
+ assert _default_concurrency() == 8
@@ -0,0 +1,74 @@
1
+ import os
2
+ import subprocess
3
+ from pathlib import Path
4
+
5
+ import pytest
6
+ from vds_git_orchestrator.manifest import Manifest, ManifestFilters, Repository
7
+ from vds_git_orchestrator.orchestrator import GitOperation, orchestrate_repositories
8
+
9
+
10
+ def _create_remote_repo(base: Path, project: str, name: str) -> None:
11
+ remote_path = base / project / f"{name}.git"
12
+ remote_path.mkdir(parents=True, exist_ok=True)
13
+ subprocess.run(["git", "init", "--bare", str(remote_path)], check=True, stdout=subprocess.DEVNULL)
14
+
15
+ seed = base.parent / "seed"
16
+ subprocess.run(["git", "init", "-b", "release", str(seed)], check=True, stdout=subprocess.DEVNULL)
17
+ readme = seed / "README.md"
18
+ readme.write_text("seed repo")
19
+
20
+ env = {
21
+ **os.environ,
22
+ "GIT_AUTHOR_NAME": "VDS Bot",
23
+ "GIT_AUTHOR_EMAIL": "vds@example.com",
24
+ "GIT_COMMITTER_NAME": "VDS Bot",
25
+ "GIT_COMMITTER_EMAIL": "vds@example.com",
26
+ }
27
+
28
+ subprocess.run(["git", "-C", str(seed), "add", "README.md"], check=True, env=env, stdout=subprocess.DEVNULL)
29
+ subprocess.run(["git", "-C", str(seed), "commit", "-m", "seed"], check=True, env=env, stdout=subprocess.DEVNULL)
30
+ subprocess.run(["git", "-C", str(seed), "remote", "add", "origin", str(remote_path)], check=True, stdout=subprocess.DEVNULL)
31
+ subprocess.run(["git", "-C", str(seed), "push", "origin", "release"], check=True, env=env, stdout=subprocess.DEVNULL)
32
+
33
+
34
+ @pytest.mark.asyncio
35
+ async def test_clone_against_local_bare_repo(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
36
+ remote_root = tmp_path / "remote"
37
+ _create_remote_repo(remote_root, "lep", "service-a")
38
+
39
+ monkeypatch.setenv("VDS_BITBUCKET_HTTP_BASE", remote_root.as_uri())
40
+ monkeypatch.delenv("VDS_USERNAME", raising=False)
41
+ monkeypatch.delenv("VDS_PASSWORD", raising=False)
42
+
43
+ workspace = tmp_path / "workspace"
44
+ repo = Repository(
45
+ name="service-a",
46
+ path=workspace / "service-a",
47
+ project="lep",
48
+ branch="release",
49
+ tags=set(),
50
+ )
51
+
52
+ manifest = Manifest([repo])
53
+ summary = await orchestrate_repositories(
54
+ manifest=manifest,
55
+ operation=GitOperation.CLONE,
56
+ filters=ManifestFilters(),
57
+ concurrency=2,
58
+ dry_run=False,
59
+ run_id="integration",
60
+ )
61
+
62
+ assert summary.total == 1
63
+ assert summary.successes == 1
64
+ assert summary.updates == 1
65
+ assert (workspace / "service-a/.git").exists()
66
+
67
+ # Ensure the release branch was checked out
68
+ result = subprocess.run(
69
+ ["git", "-C", str(workspace / "service-a"), "rev-parse", "--abbrev-ref", "HEAD"],
70
+ check=True,
71
+ capture_output=True,
72
+ text=True,
73
+ )
74
+ assert result.stdout.strip() == "release"
@@ -0,0 +1,79 @@
1
+ from pathlib import Path
2
+
3
+ from vds_git_orchestrator.manifest import Manifest, ManifestFilters, Repository, load_manifest
4
+
5
+
6
+ def test_load_manifest_roundtrip(tmp_path: Path) -> None:
7
+ manifest_path = tmp_path / "repos.yaml"
8
+ manifest_path.write_text(
9
+ """
10
+ repositories:
11
+ - name: service-a
12
+ path: services/service-a
13
+ project: lep
14
+ branch: release
15
+ tags: ["core", "backend"]
16
+ hooks:
17
+ pre_pull:
18
+ - "./scripts/check.sh"
19
+ - name: web-ui
20
+ path: web/web-ui
21
+ project: insurance
22
+ branch: main
23
+ """
24
+ )
25
+
26
+ manifest = load_manifest(manifest_path)
27
+
28
+ assert len(manifest.repositories) == 2
29
+ repo_a = manifest.repositories[0]
30
+ assert repo_a.name == "service-a"
31
+ assert repo_a.path == Path("services/service-a")
32
+ assert repo_a.project == "lep"
33
+ assert repo_a.branch == "release"
34
+ assert repo_a.tags == {"core", "backend"}
35
+ assert repo_a.hooks["pre_pull"] == ["./scripts/check.sh"]
36
+
37
+ repo_b = manifest.repositories[1]
38
+ assert repo_b.name == "web-ui"
39
+ assert repo_b.branch == "main"
40
+ assert repo_b.tags == set()
41
+
42
+
43
+ def test_manifest_filtering_by_project_tag_and_name(tmp_path: Path) -> None:
44
+ repo_root = tmp_path / "workspace"
45
+ repo_root.mkdir()
46
+
47
+ manifest = Manifest(
48
+ repositories=[
49
+ Repository(
50
+ name="service-a",
51
+ path=repo_root / "service-a",
52
+ project="lep",
53
+ branch="release",
54
+ tags={"core", "backend"},
55
+ ),
56
+ Repository(
57
+ name="service-b",
58
+ path=repo_root / "service-b",
59
+ project="insurance",
60
+ branch="release",
61
+ tags={"event"},
62
+ ),
63
+ Repository(
64
+ name="web-ui",
65
+ path=repo_root / "web-ui",
66
+ project="insurance",
67
+ branch="main",
68
+ tags={"frontend"},
69
+ ),
70
+ ]
71
+ )
72
+
73
+ filters = ManifestFilters(project="insurance", include_tags={"frontend"})
74
+ results = manifest.filter(filters)
75
+ assert [repo.name for repo in results] == ["web-ui"]
76
+
77
+ filters = ManifestFilters(name_match="service-*", exclude_tags={"event"})
78
+ results = manifest.filter(filters)
79
+ assert [repo.name for repo in results] == ["service-a"]
@@ -0,0 +1,204 @@
1
+ from pathlib import Path
2
+
3
+ import pytest
4
+ from vds_git_orchestrator.manifest import Manifest, ManifestFilters, Repository
5
+ from vds_git_orchestrator.orchestrator import GitOperation, orchestrate_repositories
6
+
7
+
8
+ @pytest.mark.asyncio
9
+ async def test_orchestrate_repositories_dry_run_skips_hooks(tmp_path: Path) -> None:
10
+ repo_dir = tmp_path / "dry-run"
11
+ repo_dir.mkdir()
12
+ repo = Repository(
13
+ name="dry-run-repo",
14
+ path=repo_dir,
15
+ project="lep",
16
+ branch="release",
17
+ tags=set(),
18
+ hooks={
19
+ "pre_pull": ["touch pre.txt"],
20
+ "post_pull": ["touch post.txt"],
21
+ },
22
+ )
23
+
24
+ manifest = Manifest([repo])
25
+ summary = await orchestrate_repositories(
26
+ manifest=manifest,
27
+ operation=GitOperation.PULL,
28
+ filters=ManifestFilters(),
29
+ concurrency=2,
30
+ dry_run=True,
31
+ run_id="test",
32
+ )
33
+
34
+ assert summary.total == 1
35
+ assert summary.successes == 1
36
+ assert summary.failures == 0
37
+ assert summary.serial_retries == 0
38
+ assert summary.results["dry-run-repo"].message == "dry-run"
39
+ assert not (repo_dir / "pre.txt").exists()
40
+ assert not (repo_dir / "post.txt").exists()
41
+
42
+
43
+ def _success_git_result() -> tuple[int, str, str]:
44
+ return 0, "Fast-forward", ""
45
+
46
+
47
+ @pytest.mark.asyncio
48
+ async def test_orchestrate_repositories_runs_hooks_on_success(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
49
+ repo_dir = tmp_path / "real-run"
50
+ repo_dir.mkdir()
51
+
52
+ pre_marker = repo_dir / "pre.marker"
53
+ post_marker = repo_dir / "post.marker"
54
+
55
+ repo = Repository(
56
+ name="real-run-repo",
57
+ path=repo_dir,
58
+ project="insurance",
59
+ branch="release",
60
+ tags=set(),
61
+ hooks={
62
+ "pre_pull": [f"touch {pre_marker.name}"],
63
+ "post_pull": [f"touch {post_marker.name}"],
64
+ },
65
+ )
66
+
67
+ # Patch _run_git to avoid invoking the real git binary.
68
+ from vds_git_orchestrator import orchestrator as orchestrator_module
69
+
70
+ async def fake_run_git(*args, **kwargs): # type: ignore[no-untyped-def]
71
+ return _success_git_result()
72
+
73
+ monkeypatch.setattr(orchestrator_module, "_run_git", fake_run_git)
74
+
75
+ manifest = Manifest([repo])
76
+ summary = await orchestrate_repositories(
77
+ manifest=manifest,
78
+ operation=GitOperation.PULL,
79
+ filters=ManifestFilters(),
80
+ concurrency=1,
81
+ dry_run=False,
82
+ run_id="run",
83
+ retries=0,
84
+ )
85
+
86
+ assert summary.total == 1
87
+ assert summary.successes == 1
88
+ assert summary.updates == 1
89
+ assert summary.serial_retries == 0
90
+ assert pre_marker.exists()
91
+ assert post_marker.exists()
92
+
93
+
94
+ @pytest.mark.asyncio
95
+ async def test_orchestrate_repositories_serial_retry(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
96
+ repo_dir = tmp_path / "net"
97
+ repo_dir.mkdir()
98
+
99
+ repo = Repository(
100
+ name="net-repo",
101
+ path=repo_dir,
102
+ project="lep",
103
+ branch="release",
104
+ tags=set(),
105
+ )
106
+
107
+ from vds_git_orchestrator import orchestrator as orchestrator_module
108
+
109
+ attempts = {repo.name: 0}
110
+
111
+ async def fake_run_git(target_repo: Repository, args: list[str]): # type: ignore[no-untyped-def]
112
+ idx = attempts.setdefault(target_repo.name, 0)
113
+ attempts[target_repo.name] = idx + 1
114
+ if idx == 0:
115
+ return 1, "", "Failed to connect to server"
116
+ return 0, "Already up to date", ""
117
+
118
+ monkeypatch.setattr(orchestrator_module, "_run_git", fake_run_git)
119
+
120
+ manifest = Manifest([repo])
121
+ summary = await orchestrate_repositories(
122
+ manifest=manifest,
123
+ operation=GitOperation.PULL,
124
+ filters=ManifestFilters(),
125
+ concurrency=2,
126
+ dry_run=False,
127
+ run_id="serial",
128
+ retries=0,
129
+ )
130
+
131
+ assert summary.total == 1
132
+ assert summary.successes == 1
133
+ assert summary.failures == 0
134
+ assert summary.serial_retries == 1
135
+ # two attempts: first parallel, second serial fallback
136
+ assert attempts[repo.name] == 2
137
+
138
+
139
+ @pytest.mark.asyncio
140
+ async def test_clone_dry_run(tmp_path: Path) -> None:
141
+ repo = Repository(
142
+ name="service-a",
143
+ path=tmp_path / "service-a",
144
+ project="lep",
145
+ branch="release",
146
+ tags=set(),
147
+ )
148
+
149
+ manifest = Manifest([repo])
150
+ summary = await orchestrate_repositories(
151
+ manifest=manifest,
152
+ operation=GitOperation.CLONE,
153
+ filters=ManifestFilters(),
154
+ concurrency=2,
155
+ dry_run=True,
156
+ run_id="clone-dry",
157
+ )
158
+
159
+ assert summary.total == 1
160
+ assert summary.successes == 1
161
+ assert summary.results["service-a"].message == "dry-run"
162
+ assert summary.serial_retries == 0
163
+ assert not repo.absolute_path.exists()
164
+
165
+
166
+ @pytest.mark.asyncio
167
+ async def test_clone_executes_git(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
168
+ repo = Repository(
169
+ name="service-a",
170
+ path=tmp_path / "service-a",
171
+ project="lep",
172
+ branch="release",
173
+ tags=set(),
174
+ )
175
+
176
+ calls: list[tuple[list[str], Path]] = []
177
+
178
+ from vds_git_orchestrator import orchestrator as orchestrator_module
179
+
180
+ async def fake_run_process(command: list[str], cwd: Path): # type: ignore[no-untyped-def]
181
+ calls.append((command, cwd))
182
+ repo.absolute_path.mkdir(parents=True, exist_ok=True)
183
+ return 0, "cloned", ""
184
+
185
+ monkeypatch.setattr(orchestrator_module, "_run_process", fake_run_process)
186
+
187
+ manifest = Manifest([repo])
188
+ summary = await orchestrate_repositories(
189
+ manifest=manifest,
190
+ operation=GitOperation.CLONE,
191
+ filters=ManifestFilters(),
192
+ concurrency=1,
193
+ dry_run=False,
194
+ run_id="clone",
195
+ )
196
+
197
+ assert summary.successes == 1
198
+ assert summary.updates == 1
199
+ assert summary.serial_retries == 0
200
+ assert repo.absolute_path.parent.exists()
201
+ # first argument should be git clone
202
+ assert calls
203
+ assert calls[0][0][0] == "git"
204
+ assert "clone" in calls[0][0]
@@ -0,0 +1,236 @@
1
+ """
2
+ Tests for vds_git_orchestrator public API exports (TSK-221).
3
+
4
+ Validates FR-21.1.2: Export Repository, Manifest, ManifestFilters, GitOperation,
5
+ RunSummary, orchestrate_repositories from vds_git_orchestrator.__init__
6
+
7
+ These tests verify that:
8
+ 1. All public symbols can be imported from the package root
9
+ 2. The __all__ list contains all expected symbols
10
+ 3. Imported symbols are the correct types/classes
11
+ 4. Basic functionality works when using package-level imports
12
+ """
13
+
14
+ from pathlib import Path
15
+
16
+ import pytest
17
+
18
+
19
+ class TestPublicAPIExports:
20
+ """Test that all public symbols are exported from package root."""
21
+
22
+ def test_import_repository_from_package_root(self) -> None:
23
+ """Verify Repository can be imported from vds_git_orchestrator."""
24
+ from vds_git_orchestrator import Repository
25
+
26
+ # Verify it's the correct class by checking it's a dataclass
27
+ assert hasattr(Repository, "__dataclass_fields__")
28
+ assert "name" in Repository.__dataclass_fields__
29
+ assert "path" in Repository.__dataclass_fields__
30
+ assert "project" in Repository.__dataclass_fields__
31
+ assert "branch" in Repository.__dataclass_fields__
32
+
33
+ def test_import_manifest_from_package_root(self) -> None:
34
+ """Verify Manifest can be imported from vds_git_orchestrator."""
35
+ from vds_git_orchestrator import Manifest
36
+
37
+ # Verify it's the correct class
38
+ assert hasattr(Manifest, "__dataclass_fields__")
39
+ assert "repositories" in Manifest.__dataclass_fields__
40
+ assert hasattr(Manifest, "merge")
41
+ assert hasattr(Manifest, "filter")
42
+
43
+ def test_import_manifest_filters_from_package_root(self) -> None:
44
+ """Verify ManifestFilters can be imported from vds_git_orchestrator."""
45
+ from vds_git_orchestrator import ManifestFilters
46
+
47
+ # Verify it's the correct class
48
+ assert hasattr(ManifestFilters, "__dataclass_fields__")
49
+ assert "project" in ManifestFilters.__dataclass_fields__
50
+ assert "name_match" in ManifestFilters.__dataclass_fields__
51
+ assert "include_tags" in ManifestFilters.__dataclass_fields__
52
+ assert "exclude_tags" in ManifestFilters.__dataclass_fields__
53
+
54
+ def test_import_git_operation_from_package_root(self) -> None:
55
+ """Verify GitOperation can be imported from vds_git_orchestrator."""
56
+ from vds_git_orchestrator import GitOperation
57
+
58
+ # Verify it's an Enum with expected values
59
+ assert hasattr(GitOperation, "FETCH")
60
+ assert hasattr(GitOperation, "PULL")
61
+ assert hasattr(GitOperation, "CLONE")
62
+ assert hasattr(GitOperation, "STATUS")
63
+ assert GitOperation.PULL.value == "pull"
64
+
65
+ def test_import_run_summary_from_package_root(self) -> None:
66
+ """Verify RunSummary can be imported from vds_git_orchestrator."""
67
+ from vds_git_orchestrator import RunSummary
68
+
69
+ # Verify it's the correct class
70
+ assert hasattr(RunSummary, "__dataclass_fields__")
71
+ assert "total" in RunSummary.__dataclass_fields__
72
+ assert "successes" in RunSummary.__dataclass_fields__
73
+ assert "failures" in RunSummary.__dataclass_fields__
74
+ assert hasattr(RunSummary, "from_results")
75
+ assert hasattr(RunSummary, "to_dict")
76
+
77
+ def test_import_orchestrate_repositories_from_package_root(self) -> None:
78
+ """Verify orchestrate_repositories can be imported from vds_git_orchestrator."""
79
+ from vds_git_orchestrator import orchestrate_repositories
80
+
81
+ # Verify it's a callable (async function)
82
+ import inspect
83
+
84
+ assert callable(orchestrate_repositories)
85
+ assert inspect.iscoroutinefunction(orchestrate_repositories)
86
+
87
+
88
+ class TestAllList:
89
+ """Test that __all__ contains all expected public symbols."""
90
+
91
+ def test_all_list_contains_manifest_symbols(self) -> None:
92
+ """Verify __all__ includes Repository, Manifest, ManifestFilters."""
93
+ import vds_git_orchestrator
94
+
95
+ assert "Repository" in vds_git_orchestrator.__all__
96
+ assert "Manifest" in vds_git_orchestrator.__all__
97
+ assert "ManifestFilters" in vds_git_orchestrator.__all__
98
+
99
+ def test_all_list_contains_orchestrator_symbols(self) -> None:
100
+ """Verify __all__ includes GitOperation, RunSummary, orchestrate_repositories."""
101
+ import vds_git_orchestrator
102
+
103
+ assert "GitOperation" in vds_git_orchestrator.__all__
104
+ assert "RunSummary" in vds_git_orchestrator.__all__
105
+ assert "orchestrate_repositories" in vds_git_orchestrator.__all__
106
+
107
+ def test_all_list_has_exactly_six_symbols(self) -> None:
108
+ """Verify __all__ contains exactly the 6 expected public symbols."""
109
+ import vds_git_orchestrator
110
+
111
+ expected_symbols = {
112
+ "Repository",
113
+ "Manifest",
114
+ "ManifestFilters",
115
+ "GitOperation",
116
+ "RunSummary",
117
+ "orchestrate_repositories",
118
+ }
119
+ assert set(vds_git_orchestrator.__all__) == expected_symbols
120
+
121
+
122
+ class TestImportEquivalence:
123
+ """Test that package-level imports are equivalent to module-level imports."""
124
+
125
+ def test_repository_import_equivalence(self) -> None:
126
+ """Verify package import equals module import for Repository."""
127
+ from vds_git_orchestrator import Repository as PkgRepository
128
+ from vds_git_orchestrator.manifest import Repository as ModRepository
129
+
130
+ assert PkgRepository is ModRepository
131
+
132
+ def test_manifest_import_equivalence(self) -> None:
133
+ """Verify package import equals module import for Manifest."""
134
+ from vds_git_orchestrator import Manifest as PkgManifest
135
+ from vds_git_orchestrator.manifest import Manifest as ModManifest
136
+
137
+ assert PkgManifest is ModManifest
138
+
139
+ def test_manifest_filters_import_equivalence(self) -> None:
140
+ """Verify package import equals module import for ManifestFilters."""
141
+ from vds_git_orchestrator import ManifestFilters as PkgFilters
142
+ from vds_git_orchestrator.manifest import ManifestFilters as ModFilters
143
+
144
+ assert PkgFilters is ModFilters
145
+
146
+ def test_git_operation_import_equivalence(self) -> None:
147
+ """Verify package import equals module import for GitOperation."""
148
+ from vds_git_orchestrator import GitOperation as PkgOp
149
+ from vds_git_orchestrator.orchestrator import GitOperation as ModOp
150
+
151
+ assert PkgOp is ModOp
152
+
153
+ def test_run_summary_import_equivalence(self) -> None:
154
+ """Verify package import equals module import for RunSummary."""
155
+ from vds_git_orchestrator import RunSummary as PkgSummary
156
+ from vds_git_orchestrator.orchestrator import RunSummary as ModSummary
157
+
158
+ assert PkgSummary is ModSummary
159
+
160
+ def test_orchestrate_repositories_import_equivalence(self) -> None:
161
+ """Verify package import equals module import for orchestrate_repositories."""
162
+ from vds_git_orchestrator import orchestrate_repositories as pkg_func
163
+ from vds_git_orchestrator.orchestrator import orchestrate_repositories as mod_func
164
+
165
+ assert pkg_func is mod_func
166
+
167
+
168
+ class TestBasicFunctionality:
169
+ """Test basic functionality using package-level imports."""
170
+
171
+ def test_create_repository_from_package_import(self, tmp_path: Path) -> None:
172
+ """Verify Repository can be instantiated using package import."""
173
+ from vds_git_orchestrator import Repository
174
+
175
+ repo = Repository(
176
+ name="test-repo",
177
+ path=tmp_path / "test-repo",
178
+ project="insurance",
179
+ branch="release",
180
+ tags={"core", "backend"},
181
+ )
182
+
183
+ assert repo.name == "test-repo"
184
+ assert repo.project == "insurance"
185
+ assert repo.branch == "release"
186
+ assert repo.tags == {"core", "backend"}
187
+
188
+ def test_create_manifest_from_package_import(self, tmp_path: Path) -> None:
189
+ """Verify Manifest can be instantiated using package import."""
190
+ from vds_git_orchestrator import Manifest, Repository
191
+
192
+ repo = Repository(
193
+ name="test-repo",
194
+ path=tmp_path / "test-repo",
195
+ project="insurance",
196
+ branch="release",
197
+ )
198
+ manifest = Manifest(repositories=[repo])
199
+
200
+ assert len(manifest.repositories) == 1
201
+ assert manifest.repositories[0].name == "test-repo"
202
+
203
+ def test_filter_manifest_from_package_import(self, tmp_path: Path) -> None:
204
+ """Verify ManifestFilters works with package imports."""
205
+ from vds_git_orchestrator import Manifest, ManifestFilters, Repository
206
+
207
+ repos = [
208
+ Repository(
209
+ name="service-a",
210
+ path=tmp_path / "service-a",
211
+ project="insurance",
212
+ branch="release",
213
+ ),
214
+ Repository(
215
+ name="service-b",
216
+ path=tmp_path / "service-b",
217
+ project="lep",
218
+ branch="release",
219
+ ),
220
+ ]
221
+ manifest = Manifest(repositories=repos)
222
+ filters = ManifestFilters(project="insurance")
223
+
224
+ filtered = manifest.filter(filters)
225
+
226
+ assert len(filtered) == 1
227
+ assert filtered[0].name == "service-a"
228
+
229
+ def test_git_operation_enum_from_package_import(self) -> None:
230
+ """Verify GitOperation enum works with package import."""
231
+ from vds_git_orchestrator import GitOperation
232
+
233
+ assert GitOperation.PULL.value == "pull"
234
+ assert GitOperation.FETCH.value == "fetch"
235
+ assert GitOperation.CLONE.value == "clone"
236
+ assert GitOperation.STATUS.value == "status"