# Roadmap: release individual Go modules Status: planned feature; scope and ownership decisions resolved. ## Purpose Implement [ADR 0005](../adr/0005-module-release-scope.md) so a consumer can check, publish, build, and deliver one selected Go module in a shared repository through ReleaseKit's API and CLI. CommandKit's core and optional integrations provide the initial consumer case. Each invocation should require only module selection, product settings, and a semantic version, with ReleaseKit owning the common mechanics. This roadmap defines the target state and its scope and ownership decisions. The [implementation plan](implementation.md) owns the ordered work from the current baseline. This roadmap does not select a ReleaseKit release version. ## Current baseline The baseline is ReleaseKit v0.3.0 plus accepted ADR 0005; module selection is not implemented. - `ReleaseRequest` selects a repository, product, and version. `Candidate` and `PublicationResult` expose the version without a distinct module or tag name. - Candidate capture reads `docs/releases/.md` from the captured commit. Local and remote uniqueness checks, tag creation, push, and reconciliation use the version as the Git tag. - The shared validation path runs tests, selected vet, and package compilation from the repository directory. Optional content checks inspect the committed repository tree, including nested-module contents. - Profiles support shared validation and additional commands. CLI product checks run from the repository directory with candidate/version context. - Artifact builds and delivery also use repository/version assumptions. The consumer Woodpecker template selects `refs/tags/v*` and bootstraps ReleaseKit from repository-root module files. The existing candidate capture, declarative validation, exact-object publication, and outcome reporting provide the foundation. Scope and identity need to be carried through those paths together. ## Targeted end state An invocation selects one module and one semantic version. Omitted selection means the repository-root module. For example: | Selected directory | Semantic version | Complete tag | Committed release note | | --- | --- | --- | --- | | Root | `v0.1.0` | `v0.1.0` | `docs/releases/v0.1.0.md` | | `integrations/ckconfig` | `v0.2.0` | `integrations/ckconfig/v0.2.0` | `integrations/ckconfig/docs/releases/v0.2.0.md` | | `integrations/ckprompt` | `v0.1.0` | `integrations/ckprompt/v0.1.0` | `integrations/ckprompt/docs/releases/v0.1.0.md` | All mandatory and selected optional release checks use the selected module's scope. Independently released nested modules are excluded from their parent's automatic validation inputs. Shared file selections follow the [resolved shared-file rules](#shared-file-validation-inputs). Checks may read referenced material elsewhere in the captured repository without adding that material's surrounding files to the input set. The checkout remains the boundary for outside-checkout link checks. Repository cleanliness, branch, candidate commit, remote endpoint, and publication guards remain repository-wide. The complete selected tag governs uniqueness, publication, and recovery. A successful source-tag push remains completion. Consumers prepare dependencies before offline candidate validation and choose sibling release ordering. Dependency preparation for delivery targets the selected module through the existing preparation operation when needed. The feature covers individual releases. Batch publication, automatic release selection, dependency-driven versioning, and arbitrary tag templates remain outside this roadmap. Artifact builds, hosted delivery, and CI use the same selected module and release identity. Delivery remains asynchronous and supports both page-only and binary profiles. This work adds no consumer-installation, proxy-availability, CI, or hosted-delivery publication completion gate. ## Capability requirements ### Module and release identity Repository directory, physical module directory, declared module path, semantic version, and complete Git tag are distinct and available throughout operations and public evidence. Shared derivation follows standard Go conventions, including major-version layouts with and without a physical major directory. A `/v2` module at either `integrations/ckconfig` or `integrations/ckconfig/v2` uses `integrations/ckconfig/v2.0.0` for `v2.0.0`. Failure evidence retains resolved identity alongside existing commit, endpoint, phase, state, and tag-object fields as available. Facade conversions preserve underlying causes. ### Coherent validation scope Tests, vet, and package compilation execute in the selected module with offline and workspace-disabled settings. Formatting, distribution checks, file size, and Markdown share ordered committed module and selected shared-file inputs. Product checks receive the selected module's context. File checks retain complete repository lookup for targeted reference reads. Existing optional check rules, error identities, cancellation, and causes apply within that scope. ### Notes, publication, and recovery Each module's committed note identifies its product and semantic version at its module-local note path. Local and remote uniqueness, annotated tag creation, exact-object push, and bounded reconciliation address the complete tag. Repository-wide guards and publication outcomes remain in place. Different modules can use equal semantic versions with distinct notes and tags. ### Builds, receipts, and hosted delivery Standalone builds, candidate build checks, managed delivery builds, and prebuilt delivery use the selected module. Module-owned execution and output paths use that module's directory. Binaries report semantic versions; hosted pages and source links use full tags and module-local notes. Builds and receipts carry module and source evidence. Delivery validates that evidence and actual artifact content before hosted requests, retaining page/asset conflicts, additive retries, and partial outcomes. Page-only profiles require no application binary or Go environment discovery. ### CLI and module-selected CI Profiles express the API's module and shared-file selections through existing profile lookup. Product commands receive both module and repository context. A small shared launcher selects profiles and semantic versions. Mapped CI selects the physical module and profile from the verified tagged checkout before bootstrapping its selected tool. Local launchers and CI share one consumer selection declaration. ReleaseKit verifies selection against derived identity. Root-only consumers retain default bootstrap and profile behavior without a map. Retries use the original tagged source's selection and tool configuration. ### Complete adoption guidance and behavioral evidence Canonical API, CLI, configuration, consumer, integration, and recovery documents and maintained examples describe the complete interface. The next release's migration guidance covers API and profile updates, receipt regeneration, CI selection, and root-module scope changes, including nested fixture modules. Focused owner tests and representative assembled workflows establish the target behavior with local repositories, HTTP fixtures, and isolated synthetic dependency caches. The [implementation plan](implementation.md#acceptance-coverage-audit) owns the concrete acceptance coverage and execution steps. ## Resolved decisions ### Resolve identity once Each ReleaseKit operation resolves repository directory, selected module directory and declaration, semantic version, and complete tag once through shared resolution logic. Pass that identity through candidate handling, validation, callbacks, publication, builds, receipts, delivery, and evidence. Subsystems consume the resolved module and tag. Repository-state, tagged-source, and artifact verification continue against that identity through their existing guards. ### Operation prerequisites and identity Shared resolution supplies module and tag identity to each operation. Candidate checking and publication retain clean source on the primary branch, committed release notes, and their existing unused-tag checks. Delivery retains clean tagged-source verification and supports historical releases and detached checkouts. Ordinary builds retain their support for modified source and operate independently of release-note and publication prerequisites. Composite operations pass resolved identity to their internal collaborators. Standalone operations use the same resolver at entry, with declaration source selected by the operation as described below. ### Declaration source by operation Candidate checks, publication, and tagged delivery resolve identity from committed module declarations. Standalone builds read the selected module's working-tree `go.mod`, so their identity corresponds to the declaration Go uses for compilation. This supports local development of changed module paths and new module directories before commit. The operation selects the declaration source and uses shared identity derivation logic. Composite candidate and delivery builds receive their already resolved committed identity. Existing source-verification observations remain in place; delivery requires a build verified against its committed tagged source. ### One validation input set and full repository lookup Construct file inputs when enabled checks or explicit shared-file validation need them. Compute module boundaries and the ordered, deduplicated input set once using committed metadata. File checks consume that set. Keep the full repository lookup available for targeted reads and reference resolution, with scoped reader ownership and cancellation preserved. Deduplicate inputs by path. Reuse parsed results by blob identity while retaining each source path's findings and relative destinations. This preserves the existing selective caches and avoids retaining all inspected raw content. ### Version and tag boundaries Keep semantic version and complete tag distinct in internal requests and evidence. Version injection, artifact filenames, smoke checks, and note titles use the semantic version. Git publication, recovery, and hosted release identity use the complete tag. URL construction belongs to each protocol owner, which encodes the literal tag for its route. Verify slash-containing tags in API and source links. ### Failure evidence Populate available module, version, tag, and commit evidence as resolution progresses. Later failures retain that evidence alongside the operation's existing phase, endpoint, tag-object, and outcome fields as available. Shared facade conversions preserve these fields and the underlying error causes. ### Go environment ownership Lazily discover effective Go settings for the selected module and reuse them within the operation's validation and build phases when environment inputs are unchanged. Ownership and reuse are operation-local. Dependency preparation keeps its separate network-capable environment. Page-only delivery retains its path without Go-tool discovery or application dependency preparation. ### Build settings, receipts, and asset verification Normalize build settings once and reuse that representation for execution, receipt binding, and comparisons. The new receipt format binds module identity alongside existing source and artifact evidence. Loading validates structure, identity, and file declarations. Delivery owns the content-verification pass before hosted requests, for both API and CLI callers. Build-time hashing records the produced bytes; delivery-time verification establishes that the selected files still match them. Candidate and managed delivery output stays outside the whole repository. Ordinary output paths use the selected module's path base. ### CI bootstrap and checkout ownership For module-mapped workflows, use one small committed consumer selection declaration shared by the launcher and CI. Bootstrap verifies the triggering tag and commit, selects the physical module and profile, and builds the tool from that module's configuration. ReleaseKit verifies selection against the derived identity. The workflow prepares the checkout before tool bootstrap. Subsequent delivery reuses that checkout with fresh read-only source checks. Standalone CI delivery performs preparation when needed. Share verification behavior across these entry paths, keeping root defaults and tagged-source selection on retries. ### Simple single-module experience Ordinary root-module consumers use the new interface's defaults: omitted module selection means the repository root, the complete tag equals the semantic version, notes use `docs/releases/.md`, and validation and builds run from the root module. Shared-file defaults apply with input deduplication. Root-tag CI uses the ordinary profile and repository-root tool bootstrap. Routine use requires no additional configuration fields, module mapping declarations, or recurring consumer decisions. A representative root-module profile, launcher, and CI workflow remain equally small after migration. Consumers supply their existing product facts through the new interface. One-time API updates and receipt regeneration belong in the next release's migration guidance under the clean-cutover decision below. ### Module boundaries Use committed nested `go.mod` locations as module boundaries for ordinary source directories. This follows Go's module structure and avoids a second registry of independently versioned products. Vendored material remains part of the selected module's file-check inputs. Nested fixture modules are excluded from automatic parent file checks and can be exercised through the parent's tests or product checks. Document this distinction and verify representative cases. A repository-level workspace file outside the selected nested module's scope does not fail that module's workspace-file check merely because it exists. Shared release materials and referenced destinations receive the targeted inspection described above. ### Shared file-validation inputs Provide an optional shared-file list in the public request and profile. Its selection applies only to shared file-validation inputs. Existing validation selections control which checks are enabled. Enabled checks retain their rules, and Go tests, vet, and package compilation retain the selected module's scope. | Selection | Shared files added automatically | | --- | --- | | Omitted list | Repository-root `COPYRIGHT`, `LICENSE`, and `docs/oss/attribution.md`, when present. | | Explicit list | The listed files replace the defaults. | | Explicit empty list | No shared files. | In Go, a nil slice selects the defaults; a non-nil empty slice selects none. In JSON, omission or `null` selects the defaults; `[]` selects none. Preserve this distinction through profile mapping and facade conversions, including slice copying and profile serialization. Resolve the defaults once. Exact field names belong in API design. Paths are repository-relative literal file paths. This initial selection supports individual files. Resolve presence and file identity from the captured committed tree. Missing explicitly selected files produce a configuration or validation error identifying the selected path, including when optional file checks are disabled. Defaults are optional when absent. Deduplicate the combined module and shared-file inputs by committed path, so a file already in module scope or repeated in the list is checked once. Explicit selection may name a file in another module; include that file alone. Reference resolution continues to inspect destinations using existing rules and leaves those destinations outside the input set unless independently selected. ### Relative paths and product commands Anchor module selection and profile lookup at the repository. Anchor module-owned validation and build paths, including file-size exclusions, and configured product-command execution at the selected module. Keep diagnostic file paths repository-relative and expose both directories to product commands. Markdown destinations remain relative to their source documents. Normalize selections and resolve path bases at a shared boundary. Translate file selections and exclusions to canonical repository-relative paths before checks consume them. Use module-based filesystem paths for execution and output, and retain repository-relative diagnostic paths through conversions. Root profiles use the repository-root module by default. Nested-module launchers use the provided repository context for shared scripts. These conventions keep per-module profiles self-contained without adding per-check path-base switches. ### Complete operation support Implement module selection across checking, publication, artifact builds, hosted delivery, and CI in this feature. The target is a coherent release API for root and nested modules. CommandKit's current source-only use supplies an adoption case while the feature supports the full existing release workflow. Feature completion includes all of these operations. Omitted module selection uses the root module, and source publication and asynchronous delivery retain their separate outcomes. ### Clean API and receipt cutover Implement one current API and module-bound receipt format as the complete supported interface after cutover. Consumers update their calls, profiles, and CI declarations to that interface and regenerate prior receipts through the updated build operation. Compatibility shims and legacy receipt readers are outside the implementation scope. Migration means guidance supplied in the next release's documentation. That guidance explains the required consumer changes and the root-module validation scope change; implementation completion covers the new interface directly.