Support per-repository release versions and tags for multi-repo milestones
Pre-submission checklist
- I have searched existing issues and discussions — this has not been proposed and declined before
- I have read CONTRIBUTING.md and understand that I must wait for
approved-featurebefore writing any code - I have read the existing GSD commands and workflows and confirmed this feature does not duplicate existing behavior
- This feature solves a problem for solo developers using AI coding tools, not a personal preference or workflow I happen to like
Feature name
Per-repository release mapping and tags for multi-repo milestones
Type of addition
New planning concept (milestone-scoped release mapping), extending the existing multi-repo and milestone-completion workflows.
The solo developer problem
When one GSD milestone delivers a feature across multiple independently versioned repositories, the developer cannot represent the real release outcome accurately. GSD currently has one milestone version and one git.create_tag boolean, and the completion workflow creates one v[X.Y] tag in the current repository.
This forces a choice between creating a misleading shared tag, disabling tags and losing release traceability, or manually tracking and tagging every repository outside the milestone workflow. It is especially error-prone when some repositories are released, some are only deployed to development, and each repository has its own version sequence.
What this feature adds
Extend /gsd-complete-milestone with an optional multi-repository release mapping when planning.sub_repos is configured:
- Enumerate the affected repositories declared for the project.
- Let the developer record, for each repository:
- release version or tag;
- commit or PR reference;
- target environment and delivery status;
- whether a local annotated tag should be created or tagging should be skipped.
- Allow different tags per repository, including no tag for unreleased repositories.
- Preflight every requested tag before writing anything: repository exists, commit resolves, tag does not already conflict, and requested values are valid.
- Show one consolidated confirmation before creating tags.
- Create tags with
git -C <repo> tag ..., report success or failure per repository, and never push without a separate explicit confirmation. - Persist the release mapping in the milestone archive/MILESTONES history even when tag creation is disabled.
Example completion summary:
Milestone v1.2 — Read API
Repository Release Reference Environment Tag
dashboard v5.78.0 PR #412 production create
functions v3.116.0 PR #287 production create
lib v2.14.1 PR #91 npm create
composers unreleased abc1234 development skipSingle-repository projects should keep the current behavior unchanged.
Full scope of changes
Likely runtime/workflow changes:
gsd-core/workflows/complete-milestone.md— route milestone completion through a multi-repository release-map step when configured.gsd-core/workflows/complete-milestone/steps/git-tag.md— support validated per-repository tag creation and per-repository push confirmation.src/init.ctsand generated SDK/runtime output — exposeplanning.sub_reposand the effective repository-tagging mode to milestone completion.src/config.cts, config schema/default manifests, andgsd-core/templates/config.json— add an optional backward-compatible repository-tagging mode while preservinggit.create_tagboolean behavior.- Git helper/query layer — resolve repository paths safely and execute read/write operations against the intended repository with no cwd ambiguity.
- Milestone archive/MILESTONES rendering — persist the release mapping as historical evidence.
gsd-core/workflows/settings.mdandgsd-core/references/planning-config.md— expose and document the option.docs/CONFIGURATION.md,docs/FEATURES.md, and relevant translated documentation — document behavior and migration.- Tests covering configuration compatibility, repository resolution, preflight, mixed tagged/skipped repositories, collisions, partial failure reporting, and no-push-by-default behavior.
Systems affected:
- Multi-repo project-root resolution.
- Milestone completion and archival.
- Git tag creation and optional pushing.
- Configuration schema and generated manifests.
User stories
- As a solo developer shipping one feature across several repositories, I want to associate a different release version with each repository so that the GSD milestone reflects what was actually shipped.
- As a solo developer whose repositories have independent release pipelines, I want to record release evidence without forcing GSD to create tags so that planning history remains accurate without interfering with deployment automation.
- As a solo developer completing a partially released milestone, I want to mark some repositories as unreleased or development-only so that GSD does not invent versions or tags for them.
Acceptance criteria
- Existing single-repository projects with
git.create_tag: trueretain their current behavior. - Existing projects with
git.create_tag: falsestill archive milestones without creating tags. - When multi-repository tagging is enabled, every declared affected repository can have an independent tag value or an explicit skip value.
- The completion workflow records tag/version, commit or PR, environment, and delivery status per repository.
- All requested repositories and tag values are preflighted before the first tag is created.
- Existing conflicting tags are reported per repository and never overwritten.
- Tags are created in the correct repositories regardless of the invoking cwd.
- A failure in one repository is reported clearly, including which tags were already created; retries are idempotent.
- No tag is pushed without explicit confirmation, and push confirmation identifies the repository and remote.
- Skipped or unreleased repositories remain in the archived release mapping without receiving tags.
- Milestone archives preserve the complete release mapping for later audits and summaries.
- Automated tests cover single-repo compatibility, mixed per-repo values, duplicate tags, invalid repo paths, detached HEAD, partial failures, retries, and push refusal.
- Documentation explains that a GSD milestone version may differ from repository release versions.
Which area does this primarily affect?
Multiple areas: core milestone workflow, planning history, multi-repo support, configuration, and Git integration.
Applicable runtimes
- All runtimes
Breaking changes assessment
None if implemented as an opt-in extension. The existing git.create_tag boolean remains valid and retains current single-repository semantics. Projects without planning.sub_repos or without the new mode behave exactly as before. Any new release-map data must be optional so existing planning artifacts continue to parse.
Maintenance burden
- No new external dependency should be required; existing Git subprocess helpers can perform repository-scoped operations.
- The release-map schema and archive renderer must remain backward compatible.
- Multi-repository tag creation introduces partial-failure and retry cases that require explicit tests and idempotent behavior.
- Repository path validation must reuse the existing multi-repo resolution and safety boundaries.
- Documentation and generated config manifests must remain synchronized when related Git settings change.
- The workflow must preserve the existing explicit confirmation boundary for remote pushes across every runtime.
Alternatives considered
- Use the GSD milestone version as the tag in every repository. Rejected because independently released repositories do not share a version sequence and may not all be released.
- Synchronize the GSD milestone number with one primary repository. Rejected because it privileges one repository and still misrepresents the others.
- Set
git.create_tag: falseand maintain a release table manually. This is the safest current workaround, but it loses validation, consistent archival, and optional per-repository tag automation. - Run an external release script after GSD completion. Valid for tag creation, but the resulting versions and release statuses are not part of GSD milestone evidence and can drift from planning history.
- Create one GSD project per repository. Rejected for features whose requirements, phases, and acceptance criteria are intentionally cross-repository.
Prior art and references
- Existing
planning.sub_repossupport already scopes commits and resolves project roots across repositories. - Existing
git.create_tagsupports enabling or disabling one milestone tag. - Existing milestone archives provide the natural durable location for the per-repository release mapping.
Additional context
The motivating case is a solo-maintained product composed of several frontend, backend, shared-library, and service repositories. Most user-visible features require coordinated changes across them, while every repository keeps its own semantic version and publication pipeline. The desired result is not to replace those release pipelines, but to let GSD accurately connect one cross-repository milestone to the real releases it produced.
Source: open-gsd/gsd-core