diff --git a/docs/roadmap/commandkit-feature-request.md b/docs/roadmap/commandkit-feature-request.md new file mode 100644 index 0000000..d0e8558 --- /dev/null +++ b/docs/roadmap/commandkit-feature-request.md @@ -0,0 +1,158 @@ +# CommandKit feature request: publish individual modules in a shared repository + +Status: requested upstream capability; not an implemented ReleaseKit contract. + +## Consumer context + +CommandKit uses ReleaseKit v0.3.0 for source-only publication. CommandKit is +still an unreleased prototype and is preparing to separate its core from +optional integrations into three independently versioned Go modules: + +| Repository directory | Module path | Illustrative version | Corresponding Git tag | +| --- | --- | --- | --- | +| Root | `gitea.maximumdirect.net/eric/CommandKit` | `v0.1.0` | `v0.1.0` | +| `integrations/ckconfig` | `gitea.maximumdirect.net/eric/CommandKit/integrations/ckconfig` | `v0.2.0` | `integrations/ckconfig/v0.2.0` | +| `integrations/ckprompt` | `gitea.maximumdirect.net/eric/CommandKit/integrations/ckprompt` | `v0.1.0` | `integrations/ckprompt/v0.1.0` | + +These versions illustrate independent numbering; they are not selected initial +release versions. Integration versions will describe their own changes rather +than matching either CommandKit core or upstream library versions. + +The dependency direction is `ckprompt` toward `ckconfig` and core, and +`ckconfig` toward core. Consumers should acquire only their selected integrations +and their dependencies. Each integration therefore needs its own module files, +validation, release notes, and publication identity. More integration modules may +follow without requiring a new publication mechanism for each one. + +Go requires repository-subdirectory prefixes on nested module version tags. +The semantic module version remains `vMAJOR.MINOR.PATCH`; the complete Git tag +additionally identifies the module directory. See the +[Go module reference](https://go.dev/ref/mod#vcs-version). + +## Issue with the current publication contract + +ReleaseKit's documented [CLI](../cli.md), [profile](../config.md), and +[publication API](../consumers/publish.md) assume one release version/tag and +one standard Go suite. Release notes use repository-root +`docs/releases/.md`, and publication accepts stable +`vMAJOR.MINOR.PATCH` rather than a nested module's prefixed tag. + +Changing the product name or choosing another profile does not provide a +separate module directory, semantic version, and Git tag identity. Running the +root module's suite also does not validate packages belonging to nested modules. + +CommandKit would otherwise need to implement its own integration publication +path, duplicating functionality already owned by ReleaseKit. We would prefer +ReleaseKit to support selecting one Go module within the shared repository. + +## Requested feature + +Support checking and publishing one explicitly selected module per invocation, +through the public library API and native CLI/profile interface. The request is +about observable behavior; ReleaseKit should select its own internal design. + +### Repository and module selection + +- Distinguish the Git repository from the selected module's directory within it. +- Keep repository state, candidate commit, branch, remote, and publication guards + scoped to the shared repository. +- Execute the standard Go validation suite in the selected module. Its tests, + and any selected module-specific vet or package compilation, should operate on + that module rather than implicitly validating only the repository-root module. +- Preserve ordinary root-module publication when no nested module is selected. +- Permit a shared repository launcher to choose small per-module profiles without + requiring separate Git repositories or duplicated publication logic. + +### Version and tag identity + +- Accept the selected module's semantic version separately from its repository + subdirectory, deriving the corresponding Go module tag from those inputs. +- Use the complete tag for uniqueness checks, tag creation, publication, and + failed or ambiguous publication recovery. +- Make both module version and complete tag identifiable in public results and + CLI output, alongside the candidate commit and existing publication evidence. +- Allow modules to publish different versions and to release individually. + Equal semantic versions in different modules identify different tags. + +No arbitrary tag-template language is needed by CommandKit. Standard Go module +tag conventions meet its requirements. + +### Release notes + +Support a distinct committed note for each module release, even when two modules +use the same semantic version. CommandKit's preferred layout is module-local +`docs/releases/.md`, for example: + +```text +docs/releases/v0.1.0.md +integrations/ckconfig/docs/releases/v0.2.0.md +integrations/ckprompt/docs/releases/v0.1.0.md +``` + +Validate the selected note against its product and semantic version in the +captured candidate. The complete tag remains the immutable source identity for +note links, licensing links, and publication recovery. A documented explicit +note-path setting would also be acceptable if module-local discovery is not the +selected public design. + +Document how module version, complete tag, note title, and note location relate; +align affected release-policy language with the selected conventions rather than +treating the current single-module note path as an obstacle. + +### Validation and completion + +Run the selected module's standard suite once for the publication candidate, +retaining ReleaseKit's offline validation and existing publication outcome model. +Additional product checks may cover CommandKit-specific composition or dependency +boundaries without repeating the selected standard suite. + +CommandKit will prepare dependencies before offline validation. Its published +modules will require actual released dependency versions; local workspace +composition is useful during development but does not establish ordinary consumer +resolution. For releases requiring new sibling versions, CommandKit can publish +core, then `ckconfig`, then `ckprompt`, preparing each candidate as needed. + +Successful source-tag publication should remain the completion point. This +request does not add CI polling, hosted release pages, artifact delivery, module +proxy availability, or consumer installation as publication completion gates. + +## Illustrative consumer interface + +Conceptually, a request would supply: + +```text +Repository: /work/CommandKit +Module directory: integrations/ckconfig +Product: CommandKit ConfigKit integration +Module version: v0.2.0 +``` + +ReleaseKit would select that module's suite and committed note, and publish +`integrations/ckconfig/v0.2.0` for the captured repository candidate. Exact Go +field names, CLI options, and profile syntax remain ReleaseKit design choices. +CommandKit could then expose a small convenience launcher such as +`./scripts/release ckconfig v0.2.0`; that is illustrative consumer syntax, not a +request for ReleaseKit to hard-code CommandKit's module names. + +## Acceptance scenarios + +1. Publish the root module using ordinary unprefixed tags and existing defaults. +2. Publish either nested integration with its Go-required prefixed tag and its + own committed note, without publishing unrelated module tags. +3. Identify validation failures from the selected nested module and prevent its + publication, even if the root suite would pass. +4. Publish two modules using the same semantic version without note or tag + collisions; preserve existing guards against reusing a published full tag. +5. Report the complete selected tag in known-failure or unresolved-publication + results so recovery addresses the exact destination and tag object. + +## Follow-up possibilities + +Publishing an explicit set of independently versioned modules in one operation +could later reduce repeated repository checks and support coordinated releases. +Batch or atomic multi-tag publication is not needed for this initial request. +Neither are automatic module discovery, dependency-driven version selection, +matching version numbers, or a generic release-orchestration framework. + +CommandKit can adopt single-module selection first and revisit release sets when +concrete maintenance needs justify them. diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md new file mode 100644 index 0000000..387ec3f --- /dev/null +++ b/docs/roadmap/implementation.md @@ -0,0 +1,647 @@ +# Implementation plan: individual Go module releases + +Status: ready for implementation. + +## Objective and authority + +Implement the complete target in the [module-release roadmap](module-releases.md), +including its resolved decisions, and [ADR 0005](../adr/0005-module-release-scope.md). +The [CommandKit request](commandkit-feature-request.md) supplies consumer context. +The implementation covers checking, publication, standalone and composite builds, +prebuilt receipts, hosted delivery, CLI profiles, launchers, and Woodpecker. + +This document is an ordered implementation guide for a Luna coding agent. +Complete Stage 1 through Stage 15 in order. Each stage is a focused implementation +unit with its own behavioral verification. Intermediate stages represent partial +implementation; completion means that all stages are complete. Proceed through +the plan without pilot integrations, intermediate releases, external actions, or +human review gates. Architecture review and subsequent adoption testing follow +completion of this plan. + +Read [development](../development.md) and the applicable policies before working. +Use the codebase graph for code discovery and inspect the current source before +editing. Follow the [agent policy](../policy/agents.md) for scoped commits after +completed nonempty units. Record completion under each stage with a short account +of the change and verification. Keep behavior documentation aligned as each +capability lands; the feature roadmap owns the desired scope and policy choices. + +## Baseline and implementation boundaries + +The starting point is the v0.3.0 implementation with accepted module-release +decisions. Current entry points are the root facade's `Check`, `Publish`, `Build`, +`Deliver`, `PrepareTaggedCheckout`, and `PrepareBuildDependencies`. + +| Current owner | Change needed | +| --- | --- | +| `check.go`, `publish.go`, `build.go`, `delivery.go`, `preparation.go` | Facade-owned selection and evidence types, explicit conversions. | +| `internal/candidate`, `internal/publish` | Committed module identity, module-local notes, full-tag publication and recovery. | +| `internal/validation` | One selected input set, full repository reference lookup, selected-module Go execution. | +| `internal/git`, `internal/preparation` | Literal full-tag operations and shared tagged-source verification. | +| `internal/gotool`, `internal/build`, `internal/artifact` | Operation-local Go settings, normalized build settings, module-based execution and output. | +| `internal/delivery`, `internal/gitea` | Committed delivery identity, module-bound artifacts, full-tag hosted identity. | +| `cmd/releasekit`, `cmd/releasekit/internal/cli` | Profile mapping, command context, receipts, CI event handling. | +| `examples/woodpecker/`, consumer guides | Root defaults and module-selected bootstrap from tagged source. | +| `internal/apicheck` | Compiled facade ownership and dependency checks for the current API. | + +Keep implementation behind the existing facades. `buildinfo` keeps its small +independent runtime dependency graph. Use the existing pure-Go build baseline, +standard version injection, target rules, error causes, publication outcomes, +and delivery recovery behavior. Network-capable preparation remains separate +from offline validation and compilation. + +The feature is a clean API and receipt cutover. Update callers and fixtures to +the current interface directly. Migration is documentation for the next release. +Implement individual module releases without batch publication, automatic module +discovery, dependency ordering, arbitrary tag templates, or compatibility shims. + +## Concrete interface and ownership choices + +These choices settle routine design details needed to execute the stages. GoDoc +and canonical references become their owners when the corresponding code lands. + +### Selection and evidence + +- Add `ModuleDir string` to `ReleaseRequest`, `BuildRequest`, and + `DeliveryRequest`. Input values are repository-relative; omission or `.` selects + the repository-root module. Keep `Version` as the stable semantic version. +- Add `ModuleDir`, `ModulePath`, and `Tag` to `Candidate`, `PublicationResult`, + `BuildResult`, and `DeliveryResult`. Result `ModuleDir` is the resolved absolute + execution directory; `ModulePath` is the declared import path; `Tag` is the + complete derived Git tag. Retain existing repository, commit, and outcome + fields, adding `RepositoryDir` to results that currently lack it. +- Use one private identity value in `internal/releaseidentity`, containing the + absolute repository and module directories, canonical repository-relative + module subdirectory, declared module path, semantic version, complete tag, and + repository-relative note path. Source commit remains captured operation + evidence. Facades own their exported types and explicitly convert this value. +- Add `SharedFiles []string` to `ValidationSpec`. Profile syntax is + `validation.shared_files`; profile module selection is top-level `module_dir`. + Preserve nil versus non-nil empty slices through all conversions and JSON + round trips. Existing `--config` selects the profile; the initial CLI adds no + separate module override. +- Change `PrepareBuildDependencies` to accept a facade-owned + `DependencyPreparationRequest` containing `RepositoryDir` and `ModuleDir`. + Preparation selects the working-tree module directory and performs the + existing network-capable preparation there. It needs no release version or tag. +- Replace `TaggedCheckoutRequest.Version` with `Tag`. Add `VerifyOnly bool`: + the default prepares the checkout, while `true` performs read-only verification + of an already prepared checkout against `Tag` and `ExpectedCommit`. +- Add optional `DeliveryRequest.ExpectedTag` for the CI event's literal tag. + Delivery compares it with the resolved tag before builds or hosted requests. + Ordinary callers omit it. The field expresses exact event identity. + +Identity derivation is shared; operation prerequisites remain with their owners. +Check and publication read declarations from the captured commit. Delivery reads +committed declarations from its source checkout and verifies the derived tag. +Standalone builds read working-tree declarations. Composite builds receive the +owner's already resolved identity. Populate evidence as it becomes available, +including on errors; an unresolved field remains unset. + +### CLI events, receipts, and consumer mapping + +- `check`, `publish`, `build`, and ordinary `deliver` continue to accept a + semantic `VERSION`. `ci-deliver` accepts a complete `TAG`; its last path + component supplies the semantic version and its full value supplies + `ExpectedTag`. The selected profile supplies the physical module directory. +- Add `ci-deliver --prepared` to select `VerifyOnly`. The maintained workflows + use it after bootstrap's verified checkout. Standalone `ci-deliver` retains + checkout preparation by default. Both paths require `--commit` and perform + fresh read-only tag, HEAD, cleanliness, and expected-commit checks. +- Add optional `--expected-module DIR` to `publish` and `ci-deliver` for mapped + launchers. Compare its normalized repository-relative selection with the + profile's selection before application work. This equality expectation binds + the bootstrap module to the profile; module selection still comes from the + profile. Root-only invocations omit it. +- Keep `.releasekit-build.json` as the private receipt filename. The new schema + requires `schema_version: 1`, absolute `module_dir`, declared `module_path`, + and complete `tag`, alongside the existing fields. The current unversioned + receipt is rejected with regeneration guidance. Implement one schema reader. +- For the maintained multi-module example, use a small committed + `release-modules.tsv` shared by the launcher and CI. Each row contains four + tab-separated fields: selector, event-tag shell pattern, repository-relative + physical module directory, repository-relative profile path. Use `.` for root. + A shared POSIX shell helper reads the table for either a selector or an event + tag. An event must match exactly one row; ambiguity is a selection error. + Tag patterns select a row; the library remains the authority for tag derivation. + The maintained example owns this integration declaration. + Root-only consumers continue without a mapping file or helper. + +For example, root v0/v1 and root `v2` directory layouts can use separate rows +with patterns `v[01].*` and `v2.*`. A nested `/v2` module can map +`integrations/ckconfig/v2.*` to either physical layout. Keep patterns quoted and +evaluate them as shell patterns without `eval`. Document the table's literal +tab-separated syntax. No matching pattern changes the derived release tag. + +## Stage 1: Implement shared identity derivation and literal tag operations + +**Outcome:** One internal owner derives release identity for both source modes; +Git primitives accept full tag names independently of semantic-version rules. + +**Steps:** + +1. Introduce `internal/releaseidentity` with a selection resolver and shared pure + derivation. Resolve module paths once from repository-relative input, with + ordinary normalization and a final location inside the repository. Keep root + defaults. Require the selected module's own declaration; do not silently + fall back to an ancestor module or require a repository-root `go.mod` for a + nested selection. +2. Provide committed and working-tree declaration readers. Reuse existing Git + committed-file and reference resolution where needed. Preserve cause and + cancellation handling. Do not fetch module metadata or infer identity from + the remote host, a root module declaration, or a directory-name registry. +3. Extract the module directive with the existing `modfile.ModulePath` helper + and apply `module.SplitPathVersion`/`module.CheckPathMajor`. Full `go.mod` + inspection retains its selected validation owner. Retain stable-version + syntax and use the shared module-path major-version rules. + Derive the tag prefix from the physical repository-relative directory, + removing a final physical major-version component only when it equals the + declaration's slash major suffix. Distinguish a normal directory named `v2` + from a physical `/v2` layout using the declaration. Retain standard special + path-major handling supplied by `x/mod`. +4. Derive `/docs/releases/.md` from the physical directory, + including a physical major-version directory. Keep tag prefix and note path + as distinct values. The + [Go module reference](https://go.dev/ref/mod#vcs-version) and + [path-major helpers](https://pkg.go.dev/golang.org/x/mod/module#CheckPathMajor) + define the relevant Go rules. +5. Replace Git's version-shaped tag validation with literal tag-reference + validation using Git's reference rules. Rename parameters and internal + fields that actually represent tags. Preserve exact ref/object operations, + supported tag object types, and repository-state checks. Semantic-version + validation stays at release identity boundaries. + +**Verification:** Owner tests cover root, nested, root physical `v2`, nested +physical `v2`, `/v2` declarations without physical major directories, a normal +directory named `v2`, incompatible version majors, normalized selection, missing +or malformed declarations, and selection outside the repository. Test committed +versus working-tree readers and full slash-containing Git refs. Update synthetic +fixtures that need genuine module declarations. Run affected package tests. + +## Stage 2: Carry identity through facade types and candidate capture + +**Outcome:** Candidate capture supplies module-local notes and recoverable identity +through the public facade. + +**Steps:** + +1. Add the selection and evidence fields specified above to facade-owned types + and their internal counterparts. Use focused conversion helpers where they + remove repeated evidence construction. Preserve `errors.Is`/`errors.As` + behavior and existing callback signatures using facade-owned `Candidate`. +2. In `internal/candidate.Capture`, capture repository state and commit, resolve + committed identity once, then read the selected module's committed note and + apply existing product/version title validation. Use the full tag for the + local unused-tag guard. +3. Return progressively populated candidate evidence when later capture, + validation, or recheck work fails. Update the public `Check` conversion so + it preserves returned evidence alongside the error instead of replacing it + with an empty candidate. +4. Pass identity through candidate validation and post-validation callbacks. + Keep clean `main`, repository-wide status, capture/recheck behavior, and note + bytes with their current owners. Prepare internal request wiring for later + validation and build stages without adding alternate legacy paths. +5. Update compiled API checks and fixtures for the chosen facade declarations. + Keep internal identity types out of exported signatures and fields. + +**Verification:** Root notes retain their path and title. A nested candidate uses +its own note, including a physical major directory. Note/title/tag conflicts and +later validation failures retain available module, version, tag, and commit +evidence. An unrelated sibling worktree change still fails the repository guard. +Run candidate/facade tests and `go run ./internal/apicheck`. + +## Stage 3: Publish and reconcile the complete selected tag + +**Outcome:** Publication addresses one module's exact tag and retains its current +known-failure, confirmed, and unknown outcomes. + +**Steps:** + +1. Thread captured identity through `internal/publish`; use `Tag` for remote + uniqueness, annotated-tag creation, exact-object push, and reconciliation. + Continue using `Version` for product/version messages where it is semantic. +2. Preserve the authoritative endpoint, expected push URL comparison, remote + branch/commit guards, local rechecks, bounded reconciliation, and tag object + evidence. These checks verify state against the captured identity and do not + invoke identity derivation again. +3. Populate `PublicationResult` identity before later failures and preserve it + through facade conversions. Recovery output identifies the full tag and + authoritative endpoint rather than constructing a ref from the version. + +**Verification:** Publish two modules with the same version at the same captured +commit to a temporary local remote; only their separate intended tags appear. +Reject reuse of the full tag. Add representative nested-tag rejected-push and +unknown-outcome evidence cases. Reuse existing endpoint and lost-acknowledgment +tests for unchanged recovery mechanics. Run publication and Git tests. + +## Stage 4: Construct the selected committed file inputs + +**Outcome:** One ordered path set defines automatic validation inputs, while the +full committed repository remains available for reference lookup. + +**Steps:** + +1. Add scope selection beside `CandidateTree` metadata handling. Select entries + beneath the module directory, excluding descendants belonging to nested + committed `go.mod` boundaries. Boundary detection uses locations and does + not parse unrelated declarations. Treat vendored contents as selected-module + material; vendored `go.mod` entries do not establish exclusion boundaries. +2. Preserve the complete repository index and committed resolver separately. + Add a selected-input view used by checks; avoid replacing the complete tree + with a filtered map that breaks cross-module links or committed symlinks. +3. Resolve `SharedFiles` once against committed entries. Apply the roadmap's + optional defaults, replacement list, explicit empty list, missing-explicit + errors, and explicit cross-module file selection. Literal paths identify + individual files; metacharacters have no selection semantics. Retain existing + symlink/reference behavior where applicable. +4. Merge selected module entries and shared files in stable repository-path + order, deduplicating by committed path. Preserve per-path context when + different paths share a blob. A referenced destination joins the input set + only through independent module or explicit-file selection. +5. Create inputs only when enabled file checks or explicit shared-file validation + require them. An explicit missing file fails even with all file checks off; + a default-only request with no file checks needs no file-input construction. + Keep lazy blob access, operation context, cancellation, and reader cleanup. + +**Verification:** Scope tests cover root and nested modules, independent sibling +and nested fixture modules, vendor inclusion, optional defaults, replacement, +empty, missing explicit, duplicates, and selected files in another module. +Use committed files rather than worktree presence. Show that full lookup still +resolves an excluded module's destination. Metadata-only selection starts no +batch content reader. Run validation tree/scope tests. + +## Stage 5: Apply selected inputs to every optional file check + +**Outcome:** Formatting, workspace, local replacement, file-size, and Markdown +checks use the same selected inputs with their existing individual rules. + +**Steps:** + +1. Update checker iteration to consume the selected-input view from Stage 4. + Retain the full repository resolver for targeted source and destination reads. + An unrelated sibling declaration or root workspace file outside a nested + module's inputs does not independently fail that module's check. +2. Translate module-relative file-size exclusions once into canonical + repository-relative paths before checker execution. Preserve existing literal + file/directory exclusion matching, limits, findings, and check order. +3. Retain formatter selection, symlink treatment, committed replacement + inspection, Markdown syntax and fragment rules, boundary observations, + source locations, cause propagation, and the existing per-blob caches. + Diagnostics remain repository-relative; Markdown links remain relative to + each source document. +4. Keep content-reader cleanup attributed to the last check that actually read + content. Do not reintroduce full raw-content retention or per-check tree + scans merely to carry module scope. +5. Give explicit shared-file selection errors a public validation identity + `shared-files`, with the selected repository-relative path and cause. Add its + facade conversion and CLI presentation through the existing failure model. + Shared-file selection itself enables no content check. + +**Verification:** Place real violations inside and outside selection and show +that only in-scope inputs fail each selected checker. Cover shared files under +enabled checks, module-relative exclusions, and a cross-module Markdown heading +read that leaves unrelated destination documents unchecked. Equal Markdown blobs +at different paths keep distinct relative-link findings. Confirm selection +errors with content checks disabled and preserve cancellation/cleanup regressions. +Run affected validation and facade tests. + +## Stage 6: Execute Go validation in the module with reusable local settings + +**Outcome:** One selected standard suite runs in the module, and later composite +builds can reuse its effective Go environment. + +**Steps:** + +1. Change validation Go command directories to resolved `ModuleDir`. Preserve + offline, readonly, workspace-disabled behavior and selected race, full vet, + target compilation, output, and command ordering. +2. Introduce a small operation-local lazy Go-tool owner alongside the existing + `gotool.Tool`. Candidate validation and subsequent build callbacks share it; + delivery and standalone builds own separate instances. It acquires settings + only when a Go command needs them. +3. Reuse the discovered tool while effective environment inputs are unchanged. + Retain a snapshot of inherited environment and the persistent Go settings + source used for discovery; after consumer callbacks, compare those inputs + and rediscover if they changed. Use simple value/file comparisons within + this owner. Keep preparation's network-capable settings separate. Introduce + neither a public session object nor a process-global tool cache. +4. Pass the private owner through internal candidate/build coordination. Preserve + repository-wide state rechecks and the single shared validation invocation. + +**Verification:** A failing nested test suite prevents its release while root +tests pass. An unrelated sibling failing suite does not run. Selected vet and +compile targets use the same module and existing baseline. Observe one standard +suite and reused discovery in an unchanged validation/build operation; changing +environment inputs through an additional callback triggers fresh settings. +Run Go-tool, validation, and candidate coordination tests. + +## Stage 7: Build the selected module and bind output evidence + +**Outcome:** Standalone and composite builds use the correct declaration source, +version injection, path base, and identity. + +**Steps:** + +1. Make public standalone `Build` resolve working-tree identity once, then call + an internal build path that consumes resolved identity. Candidate and managed + delivery builds call that path with committed identity and their Go-tool + owner. They do not call standalone resolution as a nested operation. +2. Consolidate normalized build settings in `internal/artifact`, including main + package, binary name, and normalized target pairs. Reuse this representation + for execution, evidence, later receipt binding, and settings comparisons. + Preserve supported target and artifact-name rules. +3. Build main packages from `ModuleDir`; resolve relative ordinary output there, + with default `/dist`. Keep absolute output usable. Candidate and + managed delivery output, including disposable native smoke output, stays + outside the entire repository through the existing temporary-directory owner. +4. Use semantic `Version` for linker injection, filenames, and exact native + version checks. Populate build identity before later errors and retain partial + artifacts, produced-byte digests, compiler evidence, and source observations. + An empty target set performs no compiler or Go-environment discovery. +5. Preserve standalone modified-source support and existing `SourceVerified` + observations. A build does not require a note, unused tag, clean `main`, or + publication. Delivery still requires verified committed tagged source. + +**Verification:** Build and run a nested native consumer using `buildinfo` and +cross-compile one supported second target. Filenames and output contain the +semantic version and retain ordinary filename components. Cover dirty declaration +changes and a new uncommitted module directory for standalone builds, committed +identity for composites, empty targets, and partial failures. Confirm temporary output is +outside the repository even with a nested selection and source-local `TMPDIR`. +Run build and runtime-boundary tests. + +## Stage 8: Deliver module-local notes and assets to full-tag pages + +**Outcome:** Page-only, managed-build, and API prebuilt delivery share committed +module identity and existing recovery behavior. + +**Steps:** + +1. Capture checkout commit and resolve committed identity once in delivery; + inspect the derived literal tag against that checkout. Compare optional + `ExpectedTag`. Keep historical lightweight tags, detached checkouts, clean + source, and the existing post-build source recheck. +2. Read and validate the module-local committed note. Populate delivery evidence + as resolution progresses, including build and hosted failures. Use Stage 7's + resolved build path for managed builds. +3. Bind prebuilt results to repository, module directory, declared module path, + version, tag, commit, and existing artifact/settings evidence. Require + `SourceVerified` for binary delivery and preserve caller ownership of files. +4. Give Gitea requests a distinct full-tag field; stop applying stable-version + syntax to that field. Use the literal tag for hosted tag lookup, release + lookup/create, and conflicts. Titles remain from the version-bearing note. + Encode tags at HTTP/source-route owners and verify escaped slash behavior. +5. Preserve one local digest-and-size verification before hosted requests, + deterministic manifests, remote exact comparisons, additive retries, and + existing failure states. Page-only delivery performs no application build, + Go environment discovery, application download, receipt, or manifest work. + +**Verification:** Local HTTP fixtures receive correctly encoded nested tags and +their semantic-version note titles. Two module tags at one commit create +separate pages. Cover nested managed builds and reject an API prebuilt result +for another module before hosted requests. Reuse established tampering, conflict, +partial/unknown, historical-tag, and cleanup tests. Run delivery/Gitea tests. + +## Stage 9: Replace receipts with the module-bound schema + +**Outcome:** CLI prebuilt delivery uses one current receipt format and one +delivery-owned content verification pass. + +**Steps:** + +1. Implement the schema specified above in CLI receipt read/write and public + build conversions. Keep the existing private filename and write/partial-build + lifecycle. Require all identity fields, even for a root build. +2. Validate the schema version, field structure, source identity relationships, + normalized settings, artifact declarations, and receipt/output location. + Check internal tag/module/version consistency through shared pure derivation + using recorded identity, without resolving a new operation's source. +3. Reject old/unversioned or unknown-schema receipts with guidance to regenerate + through the updated build command. Do not migrate or accept their old shape. +4. Remove artifact content hashing from receipt loading and adjacent prebuilt + declaration/comparison work. Loading validates declared paths and digests; + Stage 8 delivery verifies actual bytes and sizes before any hosted request. + Build-time hashing records produced bytes independently. +5. Reuse normalized settings in profile-to-receipt comparisons. Keep structural + validation distinct from source verification and actual asset verification. + +**Verification:** Round-trip a root and nested receipt. Reject old schema, +malformed identity, and mismatched module or settings. A loaded receipt with +changed or missing artifact bytes fails during delivery before hosted requests. +Protect verification ownership through an observable read boundary rather than +tests tied to private helper choreography. Run receipt and CLI prebuilt tests. + +## Stage 10: Map profiles and product commands to module operations + +**Outcome:** Local check, publication, and build commands express the new API with +small profiles and module context. + +**Steps:** + +1. Add strict profile decoding and mapping for `module_dir` and + `validation.shared_files`. Omission/null versus explicit empty selections + survive loading, copying, serialization, and facade mapping. Do not use + `omitempty` serialization that collapses explicit empty shared-file lists. +2. Keep profile lookup relative to the repository, including `--config`, and + pass module-relative owned paths to the common normalization boundary. Avoid + resolving identity a second time in CLI mapping. +3. Run configured product commands with `Candidate.ModuleDir` as CWD. Keep + existing version/commit context and add `RELEASEKIT_REPOSITORY_DIR`, + `RELEASEKIT_MODULE_DIR`, `RELEASEKIT_MODULE_PATH`, and `RELEASEKIT_TAG`. + Supply captured context without modifying the parent process environment. +4. Update check/publication/build diagnostics and recovery text to identify module, + semantic version, and full tag as available. Preserve existing native exit + classifications and presentation of underlying validation failures. + Implement `publish --expected-module` as a profile-selection comparison using + the shared path normalization, without another declaration resolution. +5. Apply the dependency preparation request cutover and its facade conversions. + Preparation resolves selection without release-note or publication prerequisites. + +**Verification:** CLI profiles select root/nested API requests; explicit empty +lists survive round trips. Product commands observe module CWD and both contexts. +Relative profile lookup remains repository-based and build output module-based. +Missing explicit files fail without enabling checks. Verify nested failure +diagnostics and retain a minimal root profile with no new required fields. +Run CLI profile, command, preparation, and compiled API checks. + +## Stage 11: Implement full-tag CI delivery and prepared-checkout verification + +**Outcome:** The CLI can prepare a complete event tag or reuse a verified +bootstrap checkout, then deliver the selected module. + +**Steps:** + +1. Update `ci-deliver` parsing to accept full `TAG`, required expected commit, + and optional `--prepared`. Validate literal ref syntax and stable terminal + version separately; ordinary commands still accept semantic versions. +2. Implement `TaggedCheckoutRequest.Tag` and `VerifyOnly` in preparation. Share + read-only verification between both modes; default preparation fetches the + exact tag and detaches its expected commit, then verifies. Verify-only checks + matching tag, HEAD, clean repository, and expected commit without fetch or + checkout. Preserve default remote selection and existing failure causes. +3. Load the profile from the prepared source using repository-based path rules. + Compare optional `--expected-module` with its normalized selection before + application dependency preparation; mismatch is a profile-selection error. + Pass its module selection, parsed semantic version, and event `ExpectedTag` + into delivery. Delivery owns committed identity resolution and exact mapping + verification. Keep ordinary `deliver` free of checkout/download preparation. +4. Prepare application dependencies in the selected module only for binary + profiles. Continue reading delivery credentials only for delivery; preparation + and configuration failures retain their existing CLI classifications. +5. Update prebuilt CLI delivery to compare the new receipt and normalized profile + settings, then delegate actual source/asset validation to the facade. + +**Verification:** Standalone CI delivery prepares a nested event tag. Prepared +mode succeeds offline without repeat fetch or checkout and rejects wrong commit, +dirty source, missing/moved tag, and inconsistent profile module. Verify detached +historical delivery, module-targeted dependencies for binaries, and page-only +application-preparation omission. Run preparation and CLI delivery tests. + +## Stage 12: Preserve the small root-module workflow + +**Outcome:** Existing root-only consumers retain a small launcher, profile, and +module-selected CI bootstrap under the current interface. + +**Steps:** + +1. Update `examples/woodpecker/tag-delivery.yml` and the self-bootstrap source + example to use prepared CI delivery after exact event checkout verification. + Keep root module files and default root profile selection. +2. Retain temporary alternate module metadata outside the repository, tagged-source + tool selection, workspace/toolchain controls, compatible Go image selection, + and credential handling. Tool bootstrap's network access remains separate + from offline application compilation. +3. Keep ReleaseKit's own `scripts/release`, root profile, and maintainer procedure + consistent where affected. Root consumers need no module map, extra required + configuration, or additional routine decisions. +4. Update root workflow tests for the receipt/API cutover and prepared mode. + Reuse existing synthetic tool modules and isolated module cache helpers. + +**Verification:** Execute the root launcher/API/profile representative flows and +both maintained root workflow harnesses. Bootstrap and retry select tooling from +the original tagged module after the default branch changes. Confirm subsequent +delivery performs read-only checks without repeating checkout preparation. +Use local remotes/proxies and temporary `GOMODCACHE`, never live CI or credentials. + +## Stage 13: Add a shared multi-module declaration and local launcher example + +**Outcome:** Consumers select modules through small declarations with one maintained +helper shared by local release commands and CI. + +**Steps:** + +1. Add `examples/multi-module/` with root and integration profiles, the specified + TSV mapping, and POSIX shell selection helper. Include a physical-major + directory selection to demonstrate the distinction between module and tag. +2. Have the helper select by local selector or full event tag and return the + physical directory/profile. Share parsing and selection rather than copying + cases into separate launcher and workflow code. Keep unknown selectors and + ambiguous events as configuration errors. +3. Add a small shared launcher that chooses the row, bootstraps the tool from the + selected module's local configuration using temporary alternate module files, + and invokes publication with repository context, `--config`, + `--expected-module`, and semantic version. Module selection comes from the + profile; the expectation verifies table/profile agreement. The library + validates derived release identity. +4. Supply dependency preparation guidance before offline checks and illustrative + sequential core/integration publication when a sibling version must exist. + The launcher does not infer dependency order or repeat the standard suite. + +**Verification:** Run selection and launcher harnesses with local temporary +repositories and isolated dependency proxies. Cover root/nested selection, +physical-major mapping, unknown/ambiguous selection, quoted paths, and profile +agreement. Verify the selected module supplies the tool dependency and publication +receives its semantic version/profile. Shell patterns never become arbitrary +library tag templates. Update example guidance with the implemented format. + +## Stage 14: Bootstrap and deliver mapped module tags in Woodpecker + +**Outcome:** A maintained multi-module workflow uses the same declaration and +tagged module selection for local publication, delivery, and retries. + +**Steps:** + +1. Add a multi-module Woodpecker example under `examples/multi-module/`, with tag + filters for its root and nested selections. Keep the simpler root template. +2. Verify the literal event tag and peeled event commit, detach and check clean + source, then load the mapping/helper from that verified checkout. Select the + physical module and profile before tool bootstrap. Do not derive physical + module location merely by removing the final tag component. +3. Copy the selected module's `go.mod`/`go.sum` to temporary bootstrap metadata + outside the whole checkout; run bootstrap from that module. Build the + ReleaseKit dependency chosen there, then invoke `ci-deliver --prepared` with + repository, selected profile, expected physical module, expected commit, and + full event tag. +4. Exercise page-only and binary declarations through the same workflow. Keep + source verification, dependency preparation, and credential handling with + their established owners. A retry reads the triggering release's mapping, + profile, module files, and selected tool rather than the default branch. + +**Verification:** Workflow harnesses cover nested source-only and binary delivery, +root fallback in the separate simple template, and both physical layouts of a +major-version module. Change default-branch mapping and tool versions after a +tag and verify retry still uses its original selection. Fail inconsistent mapping +through the library's exact tag check. Isolate every synthetic dependency consumer +with test-owned `GOMODCACHE`; use local HTTP fixtures and local Git remotes. + +## Stage 15: Complete consumer documentation and verify the whole cutover + +**Outcome:** The supported interface, examples, migration guidance, and behavioral +evidence describe the complete implemented feature. + +**Steps:** + +1. Update GoDoc, [CLI](../cli.md), [configuration](../config.md), + [consumer guides](../consumers/), [Gitea integration](../integrations/gitea.md), + internal owner documents, examples, and recovery guidance at their canonical + owners. Explain module selection, semantic version versus full tag, declared + versus physical module identity, note/source/license links, path bases, + boundaries, shared-file semantics, preparation, and receipt ownership. +2. Write `docs/roadmap/next-release-notes.md` as the next release's pending notes + and migration guidance. A release version is not selected by this feature; + keep the draft under roadmap ownership until release preparation assigns its + `docs/releases/.md` destination. Include API/profile updates, the + preparation signature and tag field changes, receipt regeneration, CI mapping + and prepared mode, and root-module exclusion of nested fixture module files. + Keep immutable historical release notes intact. +3. Verify ReleaseKit's own root-module release procedure still satisfies its + adopted policy. Consumer guidance explains module-local note adaptation; + this feature does not change the source-push completion point or introduce + live-service adoption/release gates. Correct stale baseline facts in owner + documents touched by the feature, including the declared Go minimum. +4. Audit the acceptance coverage below. Add only missing representative assembled + flows or owner-level cases with a concrete remaining risk. Reuse existing + recovery, cancellation, HTTP conflict, and facade-boundary tests; avoid a + Cartesian product of every module layout, check, target, and failure. +5. Run the normal offline `go test ./...` suite and + `go run ./internal/apicheck` from the repository root. Validate affected local + documentation links/fragments and examples, and run `git diff --check`. + Record the final results and feature completion in the roadmap/plan, then + commit the completed unit. Completion is the implementation and local + evidence; tagging, deployment, live CI, and consumer rollout remain later work. + +**Verification:** Match every acceptance row to concrete test or review evidence, +record the full-suite and compiled API check results, and confirm that the +implemented examples and canonical documentation agree with the current API. + +### Acceptance coverage audit + +| Requirement | Primary stage/evidence owner | +| --- | --- | +| One resolution per operation, committed versus working-tree declarations, major layouts, version/tag distinction | Stages 1, 2, 7; identity tests and composite coordination. | +| Root defaults, own-module declaration, no root declaration required for nested selection | Stages 1, 2, 12; resolver and representative root/nested workflows. | +| Module-local notes; equal versions at one commit; only intended tag; full-tag reuse and recovery | Stages 2, 3; candidate/publication local Git fixtures. | +| Repository-wide guards and progressive failure evidence | Stages 2, 3, 8; facade conversion and operation failure tests. | +| One selected Go suite, vet/compile/module CWD, offline environment reuse | Stage 6; validation and Go-tool tests. | +| Nested boundaries, fixtures, vendor, shared defaults/replacement/empty, committed presence, missing explicit files without checks | Stages 4, 5, 10; scope, checker, and profile round-trip tests. | +| Path deduplication, equal-blob contextual findings, cross-module lookup without expanded inputs, module-relative exclusions | Stages 4, 5; selected-view and reference tests. | +| Existing selective caches, reader cancellation and cleanup attribution | Stages 4, 5; retained regression coverage. | +| Semantic binary versions, module output paths, temporary output outside the whole repository, empty/partial builds | Stage 7; real native consumer and cross-compilation evidence. | +| New-only receipt schema and module/settings/source binding; one local delivery content pass | Stages 8, 9, 11; receipt/prebuilt/tamper fixtures. | +| Distinct hosted pages, slash tags and source links, page-only and binary delivery, unchanged partial/retry outcomes | Stage 8; HTTP fixtures and retained recovery tests. | +| Repository/profile versus module path bases; both product-command contexts; simple root configuration | Stages 10, 12; command/profile/root workflow tests. | +| Exact event checkout, prepared read-only reuse, physical-major mapping, tagged-source retries and tool selection | Stages 11–14; preparation and workflow harnesses. | +| Facade ownership, independent `buildinfo`, documentation and migration guidance, complete offline suite | Stages 2, 7, 10, 15; compiled API checks and final review. | + +No required product decisions remain open. The interface choices above provide +the starting specification; local implementation details may evolve within the +feature roadmap and repository policies. diff --git a/docs/roadmap/module-releases.md b/docs/roadmap/module-releases.md index e1ea7c3..374fa6f 100644 --- a/docs/roadmap/module-releases.md +++ b/docs/roadmap/module-releases.md @@ -10,9 +10,9 @@ ReleaseKit's API and CLI. CommandKit's core and optional integrations provide th consumer case. Each invocation should require only module selection, product settings, and a semantic version, with ReleaseKit owning the common mechanics. -This roadmap describes the target and the work from the current baseline. It -does not select a ReleaseKit release version or prescribe a staged implementation -plan. The decisions recorded below govern the planned scope. +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 @@ -69,212 +69,68 @@ 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. -## Work needed +## Capability requirements -### 1. Establish a shared module and release identity +### Module and release identity -**Rationale:** One resolved identity prevents checks and publication from using -different interpretations of the selected module or tag. +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. -**Target:** Distinct repository directory, module directory, semantic version, -and complete tag are available throughout candidate handling and public evidence. +### Coherent validation scope -**Work:** Add an optional repository-relative module selection to the public -request and profile, with root defaults. Resolve it against the captured -repository and source appropriate to the operation once at the operation entry -point. Check, publication, and delivery use committed module declarations. -Standalone builds use the selected module's working-tree `go.mod`, following -the [declaration-source decision](#declaration-source-by-operation). -Pass the resolved identity through the operation's validation, publication, -build, and delivery collaborators. Standalone operations use the same resolution -logic. Derive tags using Go's standard module conventions, including -major-version directories: a `/v2` module stored at `integrations/ckconfig/v2` -uses `integrations/ckconfig/v2.0.0` for `v2.0.0`. -The same module stored at `integrations/ckconfig` uses that complete tag too. -Support both physical layouts and distinguish the module directory from its -tag prefix. -Carry the resolved identity through facade conversions, internal requests, -callbacks, results, and CLI diagnostics. Keep semantic-version validation -separate from full-tag handling. Exact field names belong in API design. -Keep shared identity resolution separate from each operation's prerequisites. -Populate resolved identity in public evidence as resolution succeeds, including -when a later step fails. +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. -### 2. Apply one validation scope +### Notes, publication, and recovery -**Rationale:** Consumers should select the release unit once and receive -consistent validation across enabled checks. +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. -**Target:** Tests, vet, package compilation, formatting, distribution checks, -file-size checks, Markdown, and product-check context all correspond to the -selected module and its relevant release materials. +### Builds, receipts, and hosted delivery -**Work:** Give the existing shared validation path both repository context and -module scope. Run Go commands in the module directory with the existing -offline and workspace-disabled environment. Select committed file inputs once -under the agreed boundary convention and apply that selection to each content -check. Build one ordered input set and retain the full repository lookup -separately for resolving Markdown destinations and existing committed-file -references. A link to another module may be checked for existence or its -target heading without scanning that module's unrelated documents. +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. -Update module-distribution inspection to examine the selected release's inputs. -For example, an unrelated sibling's filesystem replacement should not fail the -selected module's check. Add shared files through the -[resolved selection rules](#shared-file-validation-inputs), carrying the selection -through the public request and profile and applying it to the shared file inputs. -Keep the optional checks optional and retain their existing individual rules, -error identities, cancellation, and cause propagation apart from the intended -scope change. Apply the boundary and path conventions recorded below. +### CLI and module-selected CI -### 3. Bind notes and publication to the resolved identity +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. -**Rationale:** Different modules can use the same semantic version while -publishing distinct source identities and release notes. +### Complete adoption guidance and behavioral evidence -**Target:** The selected module's committed note identifies its product and -semantic version. Publication and recovery address its complete tag. - -**Work:** Resolve module-local note paths and retain existing title validation -and captured note bytes. Thread the complete tag through local guards, remote -guards, annotated-tag creation, exact-object push, and bounded reconciliation. -Include the module, version, and resolved tag in success and failure evidence -as available, alongside commit, endpoint, phase, state, and tag object. Preserve -the existing publication outcomes and repository checks. Root notes and tags -retain their ordinary forms. - -### 4. Carry module identity through builds and delivery - -**Rationale:** A selected module should mean the same release unit throughout -ReleaseKit's supported operations. - -**Target:** Standalone builds, candidate build checks, direct delivery, and -prebuilt-asset delivery all operate on the selected module. Hosted pages use -its complete tag and module-local note; binaries report its semantic version. - -**Work:** Extend build and delivery requests and profile mapping with the -shared module identity. Resolve main packages and module-owned build paths -from the module directory. Prepare build dependencies there, and preserve -existing offline artifact compilation and version smoke checks. Reuse -operation-local Go settings between validation and subsequent builds when -their environment inputs match. Carry module identity through build results -and receipts so prebuilt delivery verifies the selected module, version, tag -where applicable, candidate commit, settings, and artifact hashes. Keep -ordinary local builds usable without requiring a published tag. - -Use the full tag for tagged-checkout verification, Gitea release lookup and -creation, and source links. Use the semantic version for binary version injection -and module release titles. Select the module-local note and retain existing -page/asset conflict, retry, and partial-delivery behavior. Test source URLs with -slash-containing tags. Distinct module tags can have separate Gitea pages at the -same commit. A page-only profile continues to require no application binary. -Use the new module-bound receipt format for prebuilt delivery. Consumers -regenerate receipts through the updated build operation as part of the clean -cutover described below. -Normalize build settings once for build execution, receipt binding, and -comparison. Receipt loading owns structure and identity validation; delivery -owns the local content-verification pass before hosted requests. Build-time -hashing records produced bytes independently. - -### 5. Support module-aware CI delivery - -**Rationale:** Local operations and tagged-source delivery need the same module, -profile, and version selection. - -**Target:** The maintained consumer workflow accepts root and nested-module tags, -selects the corresponding profile, and delivers only that module's release. -Tool selection follows the tagged module configuration under -[ADR 0004](../adr/0004-module-selected-tooling.md). - -**Work:** Extend tagged-checkout preparation and `ci-deliver` to distinguish the -full event tag from the semantic version. Adapt tag filters, profile selection, -tool bootstrap, and application dependency preparation. Use an explicit -module/profile mapping or equivalent small consumer declaration from the -verified tagged checkout. Resolve the physical module directory and profile -before tool bootstrap, and keep the selection consistent with the derived tag. -Verify the event commit before resolving that mapping and use the tagged -source's selected module files on retries. -Use the same small consumer selection declaration for the launcher and CI. -Bootstrap selects the module and profile; ReleaseKit verifies their consistency -with the derived identity. Reuse the verified checkout after tool bootstrap -with fresh read-only source checks. Standalone `ci-deliver` owns preparation -when it is needed. -For ordinary root tags, use the root profile and module bootstrap defaults. -Consumers using that pattern supply no module/profile mapping declaration. -Preserve temporary bootstrap metadata and existing credential handling. Cover -major-version directory layouts without assuming that trimming the tag always -identifies the physical module directory. Include page-only and binary examples. - -### 6. Make API and CLI adoption small and coherent - -**Rationale:** The shared release operation should replace consumer publication -logic with small per-module declarations. - -**Target:** A shared launcher can select a profile and pass a semantic version; -API consumers express the equivalent operation. Additional checks receive -module context and repository context for explicit composition work. - -**Work:** Map profile selection into the shared request, document relative-path -behavior, and provide module/tag context to configured commands. Retain existing -profile selection through `--config`; a separate CLI override for the module is -not needed to satisfy the initial request. Add a maintained multi-module example -showing root and integration profiles and a small shared launcher. Show dependency -preparation before offline validation and sequential sibling releases when a -dependency version must be published first. Keep product checks focused on -consumer assertions instead of repeating the standard suite. -Preserve the [simple root-module experience](#simple-single-module-experience), -including a small -profile, launcher, and CI workflow with no additional required declarations. - -### 7. Verify and document the complete behavior - -**Rationale:** This changes release identity and validation boundaries, including -the behavior of root modules with nested modules. - -**Target:** Representative public API and CLI workflows establish that the -selected module is validated and only its intended tag is published. - -**Work:** Extend existing behavioral tests using local repositories and -remotes. Cover root defaults; nested-module failure while the root suite -passes; equal versions across modules; major versions with and without -physical major-version directories; full-tag reuse; and failed or unknown -publication with the correct recovery identity. Exercise optional checks with -violations inside and outside the selected scope, parent selection excluding -independent nested modules, and cross-module Markdown references. Cover -omitted, replacement, and empty shared-file lists; optional default files; -missing explicit files; committed-tree lookup; duplicate inputs; and explicit -files in another module. Verify selection errors when optional file checks are -disabled, and that shared-file selection preserves enabled checks and Go -scope. Verify that repository guards still observe changes outside the -selected module and that module selection does not repeat the standard suite. -Reuse existing failure tests where they already protect unchanged behavior. -Add representative nested-module build/version-injection, new-format receipt -ownership and cutover, Gitea page/asset, and CI tag/profile/tool-selection -coverage. Use local HTTP servers for delivery and isolated synthetic module -proxies for bootstrap tests. Verify that retries use the original module -selection and full tag after the default branch changes. Verify a -representative simple root-module API call, profile, launcher, and CI workflow -using the new interface's defaults. Confirm that routine use adds no required -configuration fields, mapping declarations, or consumer decisions. Give -identity derivation, scope selection, and path conversion focused tests at -their owners. Use representative assembled workflows and reuse existing -failure coverage where the underlying behavior remains shared. Verify -preserved empty lists, contextual findings for equal blobs at different paths, -failure identity, and artifact-verification ownership. Cover standalone builds -with modified declarations or new module directories, composite builds using -committed identity, and source verification required for delivery. - -Update GoDoc, CLI/configuration references, check/publication/build/delivery guides, -adoption examples, CI templates, and recovery guidance together. Supply migration -guidance in the next release's documentation, covering API and profile updates, -receipt regeneration, CI mapping, and root-module scope changes, including -exclusion of nested fixture modules from automatic file checks. Document -semantic version versus full tag in note titles and source/licensing links. -ReleaseKit's own maintainer policy continues to describe its root-module release; -consumer guidance explains how -multi-module consumers adapt their policies. Run the normal offline suite and -public API checks for implementation changes; validate documentation links and -examples. Synthetic dependency fixtures use isolated module caches. +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 @@ -459,9 +315,9 @@ 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. -Implementation may proceed in stages; feature completion includes all of these -operations. Omitted module selection uses the root module, and source publication -and asynchronous delivery retain their separate outcomes. +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