vstack 1.3.5__tar.gz → 2.0.0__tar.gz

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 (136) hide show
  1. {vstack-1.3.5 → vstack-2.0.0}/PKG-INFO +12 -8
  2. {vstack-1.3.5 → vstack-2.0.0}/README-pypi.md +11 -7
  3. {vstack-1.3.5 → vstack-2.0.0}/pyproject.toml +1 -1
  4. vstack-2.0.0/src/vstack/cli/base.py +35 -0
  5. vstack-2.0.0/src/vstack/cli/catalog.py +146 -0
  6. vstack-2.0.0/src/vstack/cli/constants.py +82 -0
  7. vstack-2.0.0/src/vstack/cli/helpers.py +8 -0
  8. vstack-2.0.0/src/vstack/cli/install.py +437 -0
  9. vstack-2.0.0/src/vstack/cli/interface.py +93 -0
  10. vstack-2.0.0/src/vstack/cli/manifest.py +69 -0
  11. vstack-2.0.0/src/vstack/cli/parser.py +292 -0
  12. vstack-2.0.0/src/vstack/cli/registry.py +15 -0
  13. vstack-2.0.0/src/vstack/cli/report.py +271 -0
  14. vstack-2.0.0/src/vstack/cli/service.py +264 -0
  15. vstack-2.0.0/src/vstack/cli/status.py +110 -0
  16. vstack-2.0.0/src/vstack/cli/uninstall.py +188 -0
  17. vstack-2.0.0/src/vstack/cli/validate.py +62 -0
  18. vstack-2.0.0/src/vstack/cli/verify.py +292 -0
  19. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/constants.py +1 -1
  20. vstack-2.0.0/src/vstack/main.py +24 -0
  21. vstack-2.0.0/src/vstack/manifest/__init__.py +25 -0
  22. vstack-2.0.0/src/vstack/manifest/store.py +354 -0
  23. vstack-1.3.5/src/vstack/cli/commands.py +0 -596
  24. vstack-1.3.5/src/vstack/cli/constants.py +0 -33
  25. vstack-1.3.5/src/vstack/cli/manifest.py +0 -166
  26. vstack-1.3.5/src/vstack/cli/parser.py +0 -156
  27. vstack-1.3.5/src/vstack/main.py +0 -71
  28. {vstack-1.3.5 → vstack-2.0.0}/LICENSE +0 -0
  29. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/__init__.py +0 -0
  30. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/__main__.py +0 -0
  31. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/agents/_partials/agent-skill-boundary.md +0 -0
  32. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/agents/architect/config.yaml +0 -0
  33. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/agents/architect/template.md +0 -0
  34. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/agents/designer/config.yaml +0 -0
  35. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/agents/designer/template.md +0 -0
  36. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/agents/engineer/config.yaml +0 -0
  37. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/agents/engineer/template.md +0 -0
  38. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/agents/product/config.yaml +0 -0
  39. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/agents/product/template.md +0 -0
  40. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/agents/release/config.yaml +0 -0
  41. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/agents/release/template.md +0 -0
  42. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/agents/tester/config.yaml +0 -0
  43. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/agents/tester/template.md +0 -0
  44. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/instructions/git/config.yaml +0 -0
  45. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/instructions/git/template.md +0 -0
  46. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/instructions/python/config.yaml +0 -0
  47. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/instructions/python/template.md +0 -0
  48. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/prompts/code-review/config.yaml +0 -0
  49. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/prompts/code-review/template.md +0 -0
  50. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/_partials/base-branch.md +0 -0
  51. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/_partials/observability-checklist.md +0 -0
  52. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/_partials/run-tests.md +0 -0
  53. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/_partials/skill-context.md +0 -0
  54. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/adr/config.yaml +0 -0
  55. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/adr/template.md +0 -0
  56. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/analyse/config.yaml +0 -0
  57. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/analyse/template.md +0 -0
  58. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/architecture/config.yaml +0 -0
  59. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/architecture/template.md +0 -0
  60. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/cicd/config.yaml +0 -0
  61. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/cicd/template.md +0 -0
  62. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/code-review/config.yaml +0 -0
  63. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/code-review/template.md +0 -0
  64. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/concise/config.yaml +0 -0
  65. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/concise/template.md +0 -0
  66. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/consult/config.yaml +0 -0
  67. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/consult/template.md +0 -0
  68. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/container/config.yaml +0 -0
  69. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/container/template.md +0 -0
  70. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/debug/config.yaml +0 -0
  71. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/debug/template.md +0 -0
  72. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/dependency/config.yaml +0 -0
  73. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/dependency/template.md +0 -0
  74. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/design/config.yaml +0 -0
  75. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/design/template.md +0 -0
  76. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/docs/config.yaml +0 -0
  77. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/docs/template.md +0 -0
  78. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/explore/config.yaml +0 -0
  79. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/explore/template.md +0 -0
  80. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/guardrails/config.yaml +0 -0
  81. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/guardrails/template.md +0 -0
  82. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/incident/config.yaml +0 -0
  83. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/incident/template.md +0 -0
  84. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/inspect/config.yaml +0 -0
  85. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/inspect/template.md +0 -0
  86. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/migrate/config.yaml +0 -0
  87. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/migrate/template.md +0 -0
  88. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/onboard/config.yaml +0 -0
  89. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/onboard/template.md +0 -0
  90. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/openapi/config.yaml +0 -0
  91. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/openapi/template.md +0 -0
  92. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/performance/config.yaml +0 -0
  93. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/performance/template.md +0 -0
  94. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/pr/config.yaml +0 -0
  95. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/pr/template.md +0 -0
  96. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/refactor/config.yaml +0 -0
  97. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/refactor/template.md +0 -0
  98. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/release-notes/config.yaml +0 -0
  99. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/release-notes/template.md +0 -0
  100. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/requirements/config.yaml +0 -0
  101. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/requirements/template.md +0 -0
  102. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/security/config.yaml +0 -0
  103. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/security/template.md +0 -0
  104. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/verify/config.yaml +0 -0
  105. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/verify/template.md +0 -0
  106. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/vision/config.yaml +0 -0
  107. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/_templates/skills/vision/template.md +0 -0
  108. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/agents/__init__.py +0 -0
  109. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/agents/config.py +0 -0
  110. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/agents/constants.py +0 -0
  111. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/agents/generator.py +0 -0
  112. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/artifacts/__init__.py +0 -0
  113. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/artifacts/config.py +0 -0
  114. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/artifacts/constants.py +0 -0
  115. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/artifacts/generator.py +0 -0
  116. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/artifacts/models.py +0 -0
  117. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/artifacts/protocol.py +0 -0
  118. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/cli/__init__.py +0 -0
  119. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/frontmatter/__init__.py +0 -0
  120. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/frontmatter/parser.py +0 -0
  121. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/frontmatter/schema.py +0 -0
  122. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/frontmatter/serializer.py +0 -0
  123. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/instructions/__init__.py +0 -0
  124. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/instructions/config.py +0 -0
  125. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/instructions/constants.py +0 -0
  126. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/instructions/generator.py +0 -0
  127. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/models.py +0 -0
  128. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/prompts/__init__.py +0 -0
  129. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/prompts/config.py +0 -0
  130. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/prompts/constants.py +0 -0
  131. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/prompts/generator.py +0 -0
  132. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/skills/__init__.py +0 -0
  133. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/skills/config.py +0 -0
  134. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/skills/constants.py +0 -0
  135. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/skills/generator.py +0 -0
  136. {vstack-1.3.5 → vstack-2.0.0}/src/vstack/skills/models.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vstack
3
- Version: 1.3.5
3
+ Version: 2.0.0
4
4
  Summary: VS Code-native AI engineering workflow system for microservices, libraries, and backend systems.
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -25,18 +25,18 @@ Project-URL: Repository, https://github.com/eschaar/vstack
25
25
  Project-URL: Security, https://github.com/eschaar/vstack/blob/main/SECURITY.md
26
26
  Description-Content-Type: text/markdown
27
27
 
28
- # vstack
28
+ <p align="center">
29
+ <img src="https://raw.githubusercontent.com/eschaar/vstack/main/assets/branding/vstack.png" alt="vstack" width="260">
30
+ </p>
29
31
 
30
- [![PyPI version](https://img.shields.io/pypi/v/vstack?color=0B8A6F)](https://pypi.org/project/vstack/)
32
+ [![PyPI version](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fpypi.org%2Fpypi%2Fvstack%2Fjson&query=%24.info.version&label=PyPI&color=0B8A6F&cacheSeconds=300)](https://pypi.org/project/vstack/)
31
33
  [![Python version](https://img.shields.io/badge/python-3.11--3.14-0B8A6F)](https://github.com/eschaar/vstack/blob/main/pyproject.toml)
32
- [![Verify status](https://img.shields.io/github/actions/workflow/status/eschaar/vstack/verify.yml?branch=main&label=verify&color=1D6FA5)](https://github.com/eschaar/vstack/actions/workflows/verify.yml)
33
- [![Security checks](https://img.shields.io/github/actions/workflow/status/eschaar/vstack/security.yml?branch=main&label=security&color=B15E00)](https://github.com/eschaar/vstack/actions/workflows/security.yml)
34
+ [![Verify status](https://img.shields.io/github/actions/workflow/status/eschaar/vstack/verify.yml?label=verify&color=1D6FA5)](https://github.com/eschaar/vstack/actions/workflows/verify.yml)
35
+ [![Security checks](https://img.shields.io/github/actions/workflow/status/eschaar/vstack/security.yml?label=security&color=B15E00)](https://github.com/eschaar/vstack/actions/workflows/security.yml)
34
36
  [![Runtime: stdlib only](https://img.shields.io/badge/runtime-stdlib%20only-5B6C8F)](https://github.com/eschaar/vstack/blob/main/pyproject.toml)
35
37
  [![License: MIT](https://img.shields.io/github/license/eschaar/vstack?color=5F7A1F)](https://github.com/eschaar/vstack/blob/main/LICENSE)
36
38
  [![GitHub Discussions](https://img.shields.io/badge/discussions-ask%20%26%20share-blueviolet?logo=github)](https://github.com/eschaar/vstack/discussions)
37
39
 
38
- ![vstack logo](https://raw.githubusercontent.com/eschaar/vstack/main/assets/branding/vstack.png)
39
-
40
40
  The VS Code-native AI workflow system for backend engineering.
41
41
 
42
42
  vstack installs structured agents, skills, instructions, and prompts into `.github/` so GitHub Copilot Agent Mode can run repeatable backend workflows with clear role boundaries.
@@ -89,7 +89,9 @@ Expected result:
89
89
  vstack --version
90
90
  vstack validate
91
91
  vstack install --target /path/to/your/project
92
- vstack verify --target /path/to/your/project
92
+ vstack manifest verify --target /path/to/your/project
93
+ vstack manifest status --target /path/to/your/project
94
+ vstack manifest upgrade --target /path/to/your/project
93
95
  ```
94
96
 
95
97
  ## Common usage patterns
@@ -106,6 +108,8 @@ Profile-wide install (optional defaults for all projects):
106
108
  vstack install --global
107
109
  ```
108
110
 
111
+ By default, `vstack install` preserves existing unmanaged files and local edits to tracked files by comparing the current file contents with the SHA-256 checksum recorded in `vstack.json`. Use `--adopt-name <artifact-name>` to start tracking one existing unmanaged file without overwriting it. `vstack uninstall` also preserves locally modified tracked files unless you explicitly pass `--force` or `--force-name <artifact-name>`. Use `vstack manifest status --target ...` (or `vstack status --target ...`) to see what still matches the manifest. If a legacy manifest schema is detected, run `vstack manifest upgrade --target ...` first.
112
+
109
113
  ## Fast troubleshooting
110
114
 
111
115
  - Command not found after install: ensure your `pipx` binary path is in `PATH`
@@ -1,15 +1,15 @@
1
- # vstack
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/eschaar/vstack/main/assets/branding/vstack.png" alt="vstack" width="260">
3
+ </p>
2
4
 
3
- [![PyPI version](https://img.shields.io/pypi/v/vstack?color=0B8A6F)](https://pypi.org/project/vstack/)
5
+ [![PyPI version](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fpypi.org%2Fpypi%2Fvstack%2Fjson&query=%24.info.version&label=PyPI&color=0B8A6F&cacheSeconds=300)](https://pypi.org/project/vstack/)
4
6
  [![Python version](https://img.shields.io/badge/python-3.11--3.14-0B8A6F)](https://github.com/eschaar/vstack/blob/main/pyproject.toml)
5
- [![Verify status](https://img.shields.io/github/actions/workflow/status/eschaar/vstack/verify.yml?branch=main&label=verify&color=1D6FA5)](https://github.com/eschaar/vstack/actions/workflows/verify.yml)
6
- [![Security checks](https://img.shields.io/github/actions/workflow/status/eschaar/vstack/security.yml?branch=main&label=security&color=B15E00)](https://github.com/eschaar/vstack/actions/workflows/security.yml)
7
+ [![Verify status](https://img.shields.io/github/actions/workflow/status/eschaar/vstack/verify.yml?label=verify&color=1D6FA5)](https://github.com/eschaar/vstack/actions/workflows/verify.yml)
8
+ [![Security checks](https://img.shields.io/github/actions/workflow/status/eschaar/vstack/security.yml?label=security&color=B15E00)](https://github.com/eschaar/vstack/actions/workflows/security.yml)
7
9
  [![Runtime: stdlib only](https://img.shields.io/badge/runtime-stdlib%20only-5B6C8F)](https://github.com/eschaar/vstack/blob/main/pyproject.toml)
8
10
  [![License: MIT](https://img.shields.io/github/license/eschaar/vstack?color=5F7A1F)](https://github.com/eschaar/vstack/blob/main/LICENSE)
9
11
  [![GitHub Discussions](https://img.shields.io/badge/discussions-ask%20%26%20share-blueviolet?logo=github)](https://github.com/eschaar/vstack/discussions)
10
12
 
11
- ![vstack logo](https://raw.githubusercontent.com/eschaar/vstack/main/assets/branding/vstack.png)
12
-
13
13
  The VS Code-native AI workflow system for backend engineering.
14
14
 
15
15
  vstack installs structured agents, skills, instructions, and prompts into `.github/` so GitHub Copilot Agent Mode can run repeatable backend workflows with clear role boundaries.
@@ -62,7 +62,9 @@ Expected result:
62
62
  vstack --version
63
63
  vstack validate
64
64
  vstack install --target /path/to/your/project
65
- vstack verify --target /path/to/your/project
65
+ vstack manifest verify --target /path/to/your/project
66
+ vstack manifest status --target /path/to/your/project
67
+ vstack manifest upgrade --target /path/to/your/project
66
68
  ```
67
69
 
68
70
  ## Common usage patterns
@@ -79,6 +81,8 @@ Profile-wide install (optional defaults for all projects):
79
81
  vstack install --global
80
82
  ```
81
83
 
84
+ By default, `vstack install` preserves existing unmanaged files and local edits to tracked files by comparing the current file contents with the SHA-256 checksum recorded in `vstack.json`. Use `--adopt-name <artifact-name>` to start tracking one existing unmanaged file without overwriting it. `vstack uninstall` also preserves locally modified tracked files unless you explicitly pass `--force` or `--force-name <artifact-name>`. Use `vstack manifest status --target ...` (or `vstack status --target ...`) to see what still matches the manifest. If a legacy manifest schema is detected, run `vstack manifest upgrade --target ...` first.
85
+
82
86
  ## Fast troubleshooting
83
87
 
84
88
  - Command not found after install: ensure your `pipx` binary path is in `PATH`
@@ -32,7 +32,7 @@ classifiers = [
32
32
  "Topic :: Software Development :: Build Tools",
33
33
  "Topic :: Software Development :: Libraries :: Python Modules",
34
34
  ]
35
- version = "1.3.5"
35
+ version = "2.0.0"
36
36
 
37
37
  [project.urls]
38
38
  Homepage = "https://github.com/eschaar/vstack"
@@ -0,0 +1,35 @@
1
+ """Base command contract for CLI command handlers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from abc import ABC, abstractmethod
6
+ from argparse import Namespace
7
+ from dataclasses import dataclass
8
+ from pathlib import Path
9
+
10
+
11
+ @dataclass(frozen=True)
12
+ class CommandContext:
13
+ """Runtime context passed to every CLI command handler."""
14
+
15
+ args: Namespace
16
+ install_dir: Path | None
17
+ only: list[str] | None
18
+
19
+ def require_install_dir(self, command_name: str) -> Path:
20
+ """Return install_dir or raise when the command requires one."""
21
+ if self.install_dir is None:
22
+ raise ValueError(f"{command_name} requires install_dir")
23
+ return self.install_dir
24
+
25
+
26
+ class BaseCommand(ABC):
27
+ """Abstract base class for top-level CLI command handlers."""
28
+
29
+ @abstractmethod
30
+ def run(
31
+ self,
32
+ *,
33
+ context: CommandContext,
34
+ ) -> int:
35
+ """Execute the command and return a process-style status code."""
@@ -0,0 +1,146 @@
1
+ """Central command catalogs shared by parser, registry, and interface."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Callable
6
+ from dataclasses import dataclass
7
+ from typing import TYPE_CHECKING
8
+
9
+ from vstack.cli.base import BaseCommand
10
+ from vstack.cli.install import InstallCommand
11
+ from vstack.cli.manifest import ManifestCommand
12
+ from vstack.cli.status import StatusCommand
13
+ from vstack.cli.uninstall import UninstallCommand
14
+ from vstack.cli.validate import ValidateCommand
15
+ from vstack.cli.verify import VerifyCommand
16
+
17
+ if TYPE_CHECKING:
18
+ from vstack.cli.service import CommandService
19
+
20
+
21
+ @dataclass(frozen=True)
22
+ class TopLevelCommandConfig:
23
+ """Configuration for one top-level CLI command."""
24
+
25
+ command_factory: Callable[[CommandService], BaseCommand]
26
+ help_text: str
27
+ requires_install_dir: bool
28
+ resolve_only_for_scope: bool
29
+ include_scope_group: bool
30
+ include_only_option: bool
31
+ scope_help: str | None = None
32
+ only_help: str | None = None
33
+ include_status_output_options: bool = False
34
+
35
+
36
+ @dataclass(frozen=True)
37
+ class ManifestSubcommandConfig:
38
+ """Configuration for one ``vstack manifest <action>`` subcommand."""
39
+
40
+ help_text: str
41
+ scope_help: str
42
+ include_only_option: bool
43
+ only_help: str | None = None
44
+ include_status_output_options: bool = False
45
+
46
+
47
+ TOP_LEVEL_COMMAND_ORDER: tuple[str, ...] = (
48
+ "validate",
49
+ "verify",
50
+ "status",
51
+ "manifest",
52
+ "install",
53
+ "uninstall",
54
+ )
55
+
56
+
57
+ COMMAND_CATALOG: dict[str, TopLevelCommandConfig] = {
58
+ "validate": TopLevelCommandConfig(
59
+ command_factory=ValidateCommand,
60
+ help_text="Validate source templates only; does not inspect installed files",
61
+ requires_install_dir=False,
62
+ resolve_only_for_scope=False,
63
+ include_scope_group=False,
64
+ include_only_option=True,
65
+ only_help="Validate only these artifact types, e.g. --only skill agent",
66
+ ),
67
+ "verify": TopLevelCommandConfig(
68
+ command_factory=VerifyCommand,
69
+ help_text="Validate source templates and installed output against the manifest",
70
+ requires_install_dir=True,
71
+ resolve_only_for_scope=True,
72
+ include_scope_group=True,
73
+ include_only_option=True,
74
+ scope_help="Verify output in <dir>/.github/",
75
+ only_help="Verify only these artifact types, e.g. --only agent prompt",
76
+ ),
77
+ "status": TopLevelCommandConfig(
78
+ command_factory=StatusCommand,
79
+ help_text="Inspect installed artifacts against vstack.json checksums and manifest ownership",
80
+ requires_install_dir=True,
81
+ resolve_only_for_scope=True,
82
+ include_scope_group=True,
83
+ include_only_option=True,
84
+ scope_help="Inspect output in <dir>/.github/",
85
+ only_help="Inspect only these artifact types, e.g. --only skill agent",
86
+ include_status_output_options=True,
87
+ ),
88
+ "manifest": TopLevelCommandConfig(
89
+ command_factory=ManifestCommand,
90
+ help_text="Manage manifest lifecycle (upgrade, status, verify)",
91
+ requires_install_dir=True,
92
+ resolve_only_for_scope=True,
93
+ include_scope_group=False,
94
+ include_only_option=False,
95
+ ),
96
+ "install": TopLevelCommandConfig(
97
+ command_factory=InstallCommand,
98
+ help_text="Generate and install artifacts (--only to filter types)",
99
+ requires_install_dir=True,
100
+ resolve_only_for_scope=True,
101
+ include_scope_group=True,
102
+ include_only_option=True,
103
+ scope_help="Install into <dir>/.github/",
104
+ only_help="Install only these artifact types, e.g. --only skill agent",
105
+ ),
106
+ "uninstall": TopLevelCommandConfig(
107
+ command_factory=UninstallCommand,
108
+ help_text="Safely remove vstack-managed files tracked in the manifest",
109
+ requires_install_dir=True,
110
+ resolve_only_for_scope=True,
111
+ include_scope_group=True,
112
+ include_only_option=True,
113
+ scope_help="Uninstall from <dir>/.github/",
114
+ only_help="Uninstall only these artifact types, e.g. --only skill agent",
115
+ ),
116
+ }
117
+
118
+
119
+ MANIFEST_SUBCOMMAND_ORDER: tuple[str, ...] = (
120
+ "upgrade",
121
+ "status",
122
+ "verify",
123
+ )
124
+
125
+
126
+ MANIFEST_SUBCOMMAND_CATALOG: dict[str, ManifestSubcommandConfig] = {
127
+ "upgrade": ManifestSubcommandConfig(
128
+ help_text="Upgrade legacy vstack.json schema to current version",
129
+ scope_help="Upgrade manifest in <dir>/.github/",
130
+ include_only_option=False,
131
+ only_help=None,
132
+ ),
133
+ "status": ManifestSubcommandConfig(
134
+ help_text="Inspect installed artifacts against vstack.json checksums and manifest ownership",
135
+ scope_help="Inspect output in <dir>/.github/",
136
+ include_only_option=True,
137
+ only_help="Inspect only these artifact types, e.g. --only skill agent",
138
+ include_status_output_options=True,
139
+ ),
140
+ "verify": ManifestSubcommandConfig(
141
+ help_text="Verify installed output against manifest ownership and checksums",
142
+ scope_help="Verify output in <dir>/.github/",
143
+ include_only_option=True,
144
+ only_help="Verify only these artifact types, e.g. --only agent prompt",
145
+ ),
146
+ }
@@ -0,0 +1,82 @@
1
+ """Canonical CLI artifact names."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from vstack.agents.config import AGENT_TYPE
6
+ from vstack.instructions.config import INSTRUCTION_TYPE
7
+ from vstack.prompts.config import PROMPT_TYPE
8
+ from vstack.skills.config import SKILL_TYPE
9
+
10
+ EXPECTED_CANONICAL_NAMES = [
11
+ "vision",
12
+ "architecture",
13
+ "requirements",
14
+ "adr",
15
+ "design",
16
+ "consult",
17
+ "concise",
18
+ "code-review",
19
+ "release-notes",
20
+ "pr",
21
+ "verify",
22
+ "inspect",
23
+ "security",
24
+ "debug",
25
+ "performance",
26
+ "analyse",
27
+ "explore",
28
+ "docs",
29
+ "guardrails",
30
+ "container",
31
+ "cicd",
32
+ "migrate",
33
+ "openapi",
34
+ "refactor",
35
+ "onboard",
36
+ "dependency",
37
+ "incident",
38
+ ]
39
+
40
+
41
+ class Colors:
42
+ """ANSI colour codes used in CLI output."""
43
+
44
+ RED = "\033[31m"
45
+ GREEN = "\033[32m"
46
+ YELLOW = "\033[33m"
47
+ CYAN = "\033[36m"
48
+ BLUE = "\033[34m"
49
+ BOLD = "\033[1m"
50
+ DIM = "\033[2m"
51
+ RESET = "\033[0m"
52
+
53
+
54
+ KNOWN_TYPES = [SKILL_TYPE, AGENT_TYPE, INSTRUCTION_TYPE, PROMPT_TYPE]
55
+ KNOWN_TYPE_NAMES = [type_config.type_name for type_config in KNOWN_TYPES]
56
+ GLOBAL_SUPPORTED_TYPE_NAMES = [
57
+ AGENT_TYPE.type_name,
58
+ INSTRUCTION_TYPE.type_name,
59
+ PROMPT_TYPE.type_name,
60
+ SKILL_TYPE.type_name,
61
+ ]
62
+
63
+
64
+ class ArtifactState:
65
+ """Canonical artifact control states returned by CLI state checks."""
66
+
67
+ MANAGED = "managed"
68
+ MANAGED_LEGACY = "managed-legacy"
69
+ MODIFIED = "modified"
70
+ MISSING = "missing"
71
+ UNTRACKED = "untracked"
72
+ ABSENT = "absent"
73
+ UNKNOWN = "unknown"
74
+
75
+
76
+ # Names that must exist for each artifact type (used in verify --source).
77
+ EXPECTED_INPUT_NAMES: dict[str, list[str]] = {
78
+ "skill": EXPECTED_CANONICAL_NAMES,
79
+ "agent": ["architect", "designer", "engineer", "product", "release", "tester"],
80
+ "instruction": ["git", "python"],
81
+ "prompt": ["code-review"],
82
+ }
@@ -0,0 +1,8 @@
1
+ """Shared internal helpers for CLI command handlers."""
2
+
3
+ from __future__ import annotations
4
+
5
+
6
+ def normalize_targeted_names(names: list[str] | None) -> set[str]:
7
+ """Normalize targeted artifact names for force/adopt operations."""
8
+ return {name.strip() for name in names or [] if name.strip()}