vstack 2.0.3__tar.gz → 2.1.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.
- {vstack-2.0.3 → vstack-2.1.0}/PKG-INFO +10 -2
- {vstack-2.0.3 → vstack-2.1.0}/README-pypi.md +9 -1
- {vstack-2.0.3 → vstack-2.1.0}/pyproject.toml +1 -1
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/artifacts/protocol.py +6 -3
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/cli/install.py +83 -12
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/cli/parser.py +11 -4
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/cli/service.py +13 -10
- {vstack-2.0.3 → vstack-2.1.0}/LICENSE +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/__init__.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/__main__.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/agents/_partials/agent-skill-boundary.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/agents/architect/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/agents/architect/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/agents/designer/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/agents/designer/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/agents/engineer/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/agents/engineer/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/agents/product/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/agents/product/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/agents/release/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/agents/release/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/agents/tester/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/agents/tester/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/instructions/git/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/instructions/git/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/instructions/python/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/instructions/python/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/prompts/code-review/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/prompts/code-review/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/_partials/base-branch.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/_partials/observability-checklist.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/_partials/run-tests.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/_partials/skill-context.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/adr/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/adr/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/analyse/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/analyse/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/architecture/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/architecture/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/cicd/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/cicd/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/code-review/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/code-review/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/concise/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/concise/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/consult/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/consult/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/container/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/container/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/debug/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/debug/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/dependency/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/dependency/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/design/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/design/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/docs/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/docs/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/explore/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/explore/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/guardrails/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/guardrails/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/incident/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/incident/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/inspect/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/inspect/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/migrate/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/migrate/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/onboard/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/onboard/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/openapi/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/openapi/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/performance/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/performance/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/pr/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/pr/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/refactor/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/refactor/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/release-notes/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/release-notes/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/requirements/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/requirements/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/security/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/security/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/verify/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/verify/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/vision/config.yaml +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/vision/template.md +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/agents/__init__.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/agents/config.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/agents/constants.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/agents/generator.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/artifacts/__init__.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/artifacts/config.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/artifacts/constants.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/artifacts/generator.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/artifacts/models.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/cli/__init__.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/cli/base.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/cli/catalog.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/cli/constants.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/cli/helpers.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/cli/interface.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/cli/manifest.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/cli/registry.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/cli/report.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/cli/status.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/cli/uninstall.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/cli/validate.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/cli/verify.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/constants.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/frontmatter/__init__.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/frontmatter/parser.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/frontmatter/schema.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/frontmatter/serializer.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/instructions/__init__.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/instructions/config.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/instructions/constants.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/instructions/generator.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/main.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/manifest/__init__.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/manifest/store.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/models.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/prompts/__init__.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/prompts/config.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/prompts/constants.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/prompts/generator.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/skills/__init__.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/skills/config.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/skills/constants.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/skills/generator.py +0 -0
- {vstack-2.0.3 → vstack-2.1.0}/src/vstack/skills/models.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vstack
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.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
|
|
@@ -108,7 +108,15 @@ Profile-wide install (optional defaults for all projects):
|
|
|
108
108
|
vstack install --global
|
|
109
109
|
```
|
|
110
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 <
|
|
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 <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 <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
|
+
|
|
113
|
+
If you already have agents, skills, or other files in `.github/`, run a dry-run first to see what would be preserved before committing:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
vstack install --dry-run --target /path/to/your/project
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The summary lists preserved files as `type/name` selectors (e.g. `agent/engineer`). Resolve each conflict with `--force-name type/name` to overwrite, `--adopt-name type/name` to take ownership without overwriting, or `--force` to overwrite everything.
|
|
112
120
|
|
|
113
121
|
## Fast troubleshooting
|
|
114
122
|
|
|
@@ -81,7 +81,15 @@ Profile-wide install (optional defaults for all projects):
|
|
|
81
81
|
vstack install --global
|
|
82
82
|
```
|
|
83
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 <
|
|
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 <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 <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
|
+
|
|
86
|
+
If you already have agents, skills, or other files in `.github/`, run a dry-run first to see what would be preserved before committing:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
vstack install --dry-run --target /path/to/your/project
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The summary lists preserved files as `type/name` selectors (e.g. `agent/engineer`). Resolve each conflict with `--force-name type/name` to overwrite, `--adopt-name type/name` to take ownership without overwriting, or `--force` to overwrite everything.
|
|
85
93
|
|
|
86
94
|
## Fast troubleshooting
|
|
87
95
|
|
|
@@ -15,9 +15,12 @@ from vstack.models import ValidationResult
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class ArtifactGenerator(Protocol):
|
|
18
|
-
"""Structural protocol satisfied by
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
"""Structural protocol satisfied by all artifact generators.
|
|
19
|
+
|
|
20
|
+
Implemented by :class:`~vstack.skills.generator.SkillGenerator`,
|
|
21
|
+
:class:`~vstack.agents.generator.AgentGenerator`,
|
|
22
|
+
:class:`~vstack.instructions.generator.InstructionGenerator`, and
|
|
23
|
+
:class:`~vstack.prompts.generator.PromptGenerator`.
|
|
21
24
|
"""
|
|
22
25
|
|
|
23
26
|
def generate(self, output_dir: Path) -> ArtifactResult:
|
|
@@ -128,22 +128,21 @@ class InstallCommand(BaseCommand):
|
|
|
128
128
|
"""Print install/update/skip output line for one artifact."""
|
|
129
129
|
if action == "adopt":
|
|
130
130
|
print(
|
|
131
|
-
f" {colors.CYAN}≈{colors.RESET} {rel}"
|
|
131
|
+
f" {prefix}{colors.CYAN}≈{colors.RESET} {rel}"
|
|
132
132
|
f" {colors.DIM}adopted — {reason}{colors.RESET}"
|
|
133
133
|
)
|
|
134
134
|
return
|
|
135
135
|
|
|
136
136
|
if action == "preserve":
|
|
137
|
-
force_hint = " Use --force or --force-name for this artifact."
|
|
138
137
|
print(
|
|
139
|
-
f" {colors.YELLOW}↷{colors.RESET} {rel}"
|
|
140
|
-
f" {colors.DIM}preserved — {reason}
|
|
138
|
+
f" {prefix}{colors.YELLOW}↷{colors.RESET} {rel}"
|
|
139
|
+
f" {colors.DIM}preserved — {reason}{colors.RESET}"
|
|
141
140
|
)
|
|
142
141
|
return
|
|
143
142
|
|
|
144
143
|
if action == "skip":
|
|
145
144
|
print(
|
|
146
|
-
f" {colors.YELLOW}↷{colors.RESET} {rel}"
|
|
145
|
+
f" {prefix}{colors.YELLOW}↷{colors.RESET} {rel}"
|
|
147
146
|
f" {colors.DIM}skipped — already v{existing_version}{colors.RESET}"
|
|
148
147
|
)
|
|
149
148
|
return
|
|
@@ -245,16 +244,24 @@ class InstallCommand(BaseCommand):
|
|
|
245
244
|
existing_entries,
|
|
246
245
|
new_entries,
|
|
247
246
|
checksum_algorithm: str,
|
|
248
|
-
) ->
|
|
249
|
-
"""Apply install decision flow for one rendered artifact."""
|
|
247
|
+
) -> str:
|
|
248
|
+
"""Apply install decision flow for one rendered artifact and return the action taken."""
|
|
250
249
|
out_file = out_dir / gen.output_path(artifact.name)
|
|
251
250
|
new_version = (artifact.frontmatter or {}).get("version") or VERSION
|
|
252
251
|
key = f"{gen.config.type_name}/{artifact.name}"
|
|
253
252
|
existing_entry = existing_entries.get(key)
|
|
254
253
|
existing_version = existing_entry.version if existing_entry is not None else None
|
|
255
254
|
rel = service.label(out_file)
|
|
256
|
-
force_name =
|
|
257
|
-
|
|
255
|
+
force_name = (
|
|
256
|
+
artifact.name in targeted_force_names
|
|
257
|
+
or key in targeted_force_names
|
|
258
|
+
or rel in targeted_force_names
|
|
259
|
+
)
|
|
260
|
+
adopt_name = (
|
|
261
|
+
artifact.name in targeted_adopt_names
|
|
262
|
+
or key in targeted_adopt_names
|
|
263
|
+
or rel in targeted_adopt_names
|
|
264
|
+
)
|
|
258
265
|
adopted_values: tuple[str | None, str] | None = None
|
|
259
266
|
|
|
260
267
|
if artifact.unresolved:
|
|
@@ -306,7 +313,7 @@ class InstallCommand(BaseCommand):
|
|
|
306
313
|
checksum=content_hash(artifact.content),
|
|
307
314
|
checksum_algorithm=checksum_algorithm,
|
|
308
315
|
)
|
|
309
|
-
return
|
|
316
|
+
return action
|
|
310
317
|
|
|
311
318
|
if action == "adopt" and adopted_values is not None:
|
|
312
319
|
adopted_version, adopted_checksum = adopted_values
|
|
@@ -318,7 +325,7 @@ class InstallCommand(BaseCommand):
|
|
|
318
325
|
checksum=adopted_checksum,
|
|
319
326
|
checksum_algorithm=checksum_algorithm,
|
|
320
327
|
)
|
|
321
|
-
return
|
|
328
|
+
return action
|
|
322
329
|
|
|
323
330
|
if existing_entry is not None:
|
|
324
331
|
preserve_existing_entry(
|
|
@@ -326,6 +333,7 @@ class InstallCommand(BaseCommand):
|
|
|
326
333
|
manifest_key=gen.config.manifest_key,
|
|
327
334
|
existing_entry=existing_entry,
|
|
328
335
|
)
|
|
336
|
+
return action
|
|
329
337
|
|
|
330
338
|
@staticmethod
|
|
331
339
|
def _write_manifest(
|
|
@@ -347,6 +355,57 @@ class InstallCommand(BaseCommand):
|
|
|
347
355
|
manifest_file.write(manifest)
|
|
348
356
|
print(f" {colors.DIM}wrote {service.label(manifest_file.path)}{colors.RESET}")
|
|
349
357
|
|
|
358
|
+
@staticmethod
|
|
359
|
+
def _print_summary(
|
|
360
|
+
*,
|
|
361
|
+
colors,
|
|
362
|
+
action_counts: dict[str, int],
|
|
363
|
+
preserved_selectors: list[str],
|
|
364
|
+
dry_run: bool,
|
|
365
|
+
) -> None:
|
|
366
|
+
"""Print a readable summary and conflict guidance after an install run."""
|
|
367
|
+
installed = action_counts.get("install", 0)
|
|
368
|
+
updated = action_counts.get("update", 0)
|
|
369
|
+
preserved = action_counts.get("preserve", 0)
|
|
370
|
+
skipped = action_counts.get("skip", 0)
|
|
371
|
+
adopted = action_counts.get("adopt", 0)
|
|
372
|
+
|
|
373
|
+
install_label = "installed"
|
|
374
|
+
summary_title = "Summary (dry-run)" if dry_run else "Summary"
|
|
375
|
+
total = installed + updated + preserved + skipped + adopted
|
|
376
|
+
|
|
377
|
+
print()
|
|
378
|
+
print(f" {colors.BOLD}{summary_title}{colors.RESET}")
|
|
379
|
+
print(f" total processed : {colors.BOLD}{total}{colors.RESET}")
|
|
380
|
+
print(f" {install_label:<15}: {colors.BOLD}{installed}{colors.RESET}")
|
|
381
|
+
print(f" updated : {colors.BOLD}{updated}{colors.RESET}")
|
|
382
|
+
print(f" preserved : {colors.BOLD}{preserved}{colors.RESET}")
|
|
383
|
+
print(f" skipped : {colors.BOLD}{skipped}{colors.RESET}")
|
|
384
|
+
print(f" adopted : {colors.BOLD}{adopted}{colors.RESET}")
|
|
385
|
+
|
|
386
|
+
if preserved:
|
|
387
|
+
noun = "file" if preserved == 1 else "files"
|
|
388
|
+
selectors_suffix = " Preserved selectors:" if preserved_selectors else ""
|
|
389
|
+
print()
|
|
390
|
+
print(
|
|
391
|
+
f" {colors.YELLOW}⚠{colors.RESET} "
|
|
392
|
+
f"{preserved} {noun} preserved — existing files were not overwritten."
|
|
393
|
+
f"{selectors_suffix}"
|
|
394
|
+
)
|
|
395
|
+
if preserved_selectors:
|
|
396
|
+
for selector in sorted(preserved_selectors):
|
|
397
|
+
print(f" - {selector}")
|
|
398
|
+
print(" Next steps:")
|
|
399
|
+
print(f" {colors.DIM}--force{colors.RESET} overwrite all")
|
|
400
|
+
print(
|
|
401
|
+
f" {colors.DIM}--force-name <name|type/name>{colors.RESET} "
|
|
402
|
+
"overwrite one artifact"
|
|
403
|
+
)
|
|
404
|
+
print(
|
|
405
|
+
f" {colors.DIM}--adopt-name <name|type/name>{colors.RESET} "
|
|
406
|
+
"take ownership without overwriting"
|
|
407
|
+
)
|
|
408
|
+
|
|
350
409
|
@staticmethod
|
|
351
410
|
def execute(
|
|
352
411
|
service: CommandService,
|
|
@@ -377,13 +436,15 @@ class InstallCommand(BaseCommand):
|
|
|
377
436
|
|
|
378
437
|
prefix = f"{colors.DIM}[dry-run]{colors.RESET} " if dry_run else ""
|
|
379
438
|
all_ok = True
|
|
439
|
+
action_counts: dict[str, int] = {}
|
|
440
|
+
preserved_selectors: set[str] = set()
|
|
380
441
|
|
|
381
442
|
for gen in gens:
|
|
382
443
|
out_dir = install_dir / gen.config.output_subdir
|
|
383
444
|
artifacts = gen.render_all()
|
|
384
445
|
|
|
385
446
|
for artifact in artifacts:
|
|
386
|
-
InstallCommand._install_single_artifact(
|
|
447
|
+
artifact_action = InstallCommand._install_single_artifact(
|
|
387
448
|
service=service,
|
|
388
449
|
gen=gen,
|
|
389
450
|
artifact=artifact,
|
|
@@ -399,6 +460,9 @@ class InstallCommand(BaseCommand):
|
|
|
399
460
|
new_entries=new_entries,
|
|
400
461
|
checksum_algorithm=checksum_algorithm,
|
|
401
462
|
)
|
|
463
|
+
action_counts[artifact_action] = action_counts.get(artifact_action, 0) + 1
|
|
464
|
+
if artifact_action == "preserve":
|
|
465
|
+
preserved_selectors.add(f"{gen.config.type_name}/{artifact.name}")
|
|
402
466
|
|
|
403
467
|
# Verify source for unresolvable issues.
|
|
404
468
|
verify_result = gen.verify_input()
|
|
@@ -407,6 +471,13 @@ class InstallCommand(BaseCommand):
|
|
|
407
471
|
print(f" ERROR [{gen.config.type_name}]: {msg.message}", file=sys.stderr)
|
|
408
472
|
all_ok = False
|
|
409
473
|
|
|
474
|
+
InstallCommand._print_summary(
|
|
475
|
+
colors=colors,
|
|
476
|
+
action_counts=action_counts,
|
|
477
|
+
preserved_selectors=sorted(preserved_selectors),
|
|
478
|
+
dry_run=dry_run,
|
|
479
|
+
)
|
|
480
|
+
|
|
410
481
|
if not dry_run:
|
|
411
482
|
InstallCommand._write_manifest(
|
|
412
483
|
service=service,
|
|
@@ -177,17 +177,24 @@ class CommandLineParser:
|
|
|
177
177
|
"--force-name",
|
|
178
178
|
dest="force_names",
|
|
179
179
|
action="append",
|
|
180
|
-
metavar="<
|
|
181
|
-
help=
|
|
180
|
+
metavar="<name|type/name>",
|
|
181
|
+
help=(
|
|
182
|
+
"Force install one named artifact without overwriting everything. "
|
|
183
|
+
"Accepts a plain name (e.g. engineer) or a type/name selector "
|
|
184
|
+
"(e.g. agent/engineer) to disambiguate when multiple artifact types "
|
|
185
|
+
"share the same name. Repeat to target multiple artifacts."
|
|
186
|
+
),
|
|
182
187
|
)
|
|
183
188
|
parser.add_argument(
|
|
184
189
|
"--adopt-name",
|
|
185
190
|
action="append",
|
|
186
191
|
default=None,
|
|
187
|
-
metavar="
|
|
192
|
+
metavar="<name|type/name>",
|
|
188
193
|
help=(
|
|
189
194
|
"Adopt only the named existing unmanaged artifact into the manifest without overwriting it. "
|
|
190
|
-
"
|
|
195
|
+
"Accepts a plain name (e.g. engineer) or a type/name selector "
|
|
196
|
+
"(e.g. agent/engineer) to disambiguate when multiple artifact types "
|
|
197
|
+
"share the same name. Repeat to target multiple artifacts."
|
|
191
198
|
),
|
|
192
199
|
)
|
|
193
200
|
parser.add_argument(
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
"""Shared coordinator for vstack CLI command handlers.
|
|
2
|
+
|
|
3
|
+
:class:`CommandService` wires artifact-type generators and manifest access
|
|
4
|
+
into the services that individual :class:`~vstack.cli.base.BaseCommand`
|
|
5
|
+
subclasses use when executing. Commands live in their own modules
|
|
6
|
+
(``install``, ``verify``, ``uninstall``, ``validate``, ``manifest``,
|
|
7
|
+
``status``) and receive a :class:`~vstack.cli.base.CommandContext` at
|
|
8
|
+
dispatch time.
|
|
9
|
+
|
|
10
|
+
The service is type-generic: it iterates over
|
|
11
|
+
:data:`~vstack.artifacts.type_config.KNOWN_TYPES` rather than hard-coding
|
|
12
|
+
skill-specific or agent-specific logic. Per-type sub-directories are
|
|
13
|
+
derived from
|
|
11
14
|
:attr:`~vstack.artifacts.type_config.ArtifactTypeConfig.output_subdir`.
|
|
12
15
|
"""
|
|
13
16
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/agents/_partials/agent-skill-boundary.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vstack-2.0.3 → vstack-2.1.0}/src/vstack/_templates/skills/_partials/observability-checklist.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|