Files
ReleaseKit/docs/roadmap/implementation.md

37 KiB
Raw Blame History

ReleaseKit audit implementation plan

Status: All implementation stages complete. Baseline: e4be7fa (2026-10-06). The audit records the evidence, product goals, and selected direction. This document owns implementation order and completion criteria for that work.

How to execute this plan

Implement one numbered stage per prompt, in order. Each stage includes its production change, relevant tests, and current-contract documentation. Leave the repository compiling and its checks passing at each stage boundary. Record completed stages here with a concise validation result; report the commit identifier in the stage completion response. Read development guidance and its applicable policies at the start of each stage.

Use the agent policy, architecture policy, testing policy, and documentation policy. Discover current symbols through the codebase graph, then inspect their callers and tests before editing. The paths below locate the baseline; internal names may evolve during the work. Use ordinary functions and existing internal packages where their ownership fits. Public named types remain facade-owned with explicit internal conversions.

For each stage, run focused behavioral tests for its changed responsibilities. Then run the existing repository checks from the root:

GOTOOLCHAIN=local GOPROXY=off GOSUMDB=off go test -mod=readonly -count=1 ./...
GOTOOLCHAIN=local GOPROXY=off GOSUMDB=off go run ./internal/apicheck

Prepare dependencies before these offline checks when needed. Review changed GoDoc, examples, local documentation links and fragments, and git diff --check. Reuse successful checks for unchanged content. Commit each completed stage under the agent policy. These implementation checks serve the development workflow.

Decisions for this sprint

These choices resolve the audit's design alternatives for implementation:

  • Candidate validation runs the standard offline Go suite once, then optional product checks, then selected-target build verification. Rename the Go callback to AdditionalChecks; JSON retains checks with additive semantics.
  • ReleaseKit uses the available compatible Go toolchain, internal baseline CPU settings, and shared build flags. It controls incidental flags and persistent Go settings while preserving operational configuration such as caches.
  • Deliver accepts a build declaration and owns temporary build output, checksums, uploads, and cleanup. An explicit prebuilt path retains original artifacts for retries and supports separated build/delivery environments.
  • Delivery asset categories are disjoint observations: matching, uploaded, known pending, conflicting, and uncertain. Existing overall delivery states and content-preservation rules remain authoritative.
  • A versioned source-installed command is the initial shared CI entry point. Add ci-deliver for explicit CI checkout and dependency preparation followed by the same facade delivery operation. Ordinary deliver remains suitable for an already prepared checkout. CI images remain an operational option.
  • Shared artifact rules and Go execution settings have small internal owners. Application profiles continue to declare product facts and additional checks.

The callback and delivery request changes are deliberate pre-release API changes. Update all in-repository callers and their canonical documentation in the corresponding stage. The initial release note should describe the final interfaces and migration impact when that release is prepared.

The sprint preserves the existing source transaction, successful-tag-push completion point, bounded recovery, content-aware retries, standalone Build, and lightweight buildinfo. Build observations and private receipts retain their existing source-eligibility meaning. Toolchain-dependent byte differences remain acceptable. Build identity remains an observation of the checked source and produced files under the existing contracts. Live deployment and sibling repository migrations remain separate adoption work in the product roadmap.

Stage 1 — Keep ambiguous-push recovery on the captured endpoint

Covers: F2. Primary owners: internal/git/tag.go, internal/git/remote.go, internal/publish/publish.go and their tests.

  1. Before Endpoint.QueryTag performs its remote read, reuse verifyScopedURLs with the captured endpoint and command-scoped configuration. Verify that the captured URL still resolves to itself. Use the existing reconciliation context and timeout for both verification and the remote read.
  2. Treat verification failure as unreadable authoritative state. Preserve error identity through wrapping so reconcilePush reports unknown, retains the local tag, and preserves the original push failure for diagnosis.
  3. Keep the captured endpoint as recovery's authority. The local resolution check precedes the existing single remote tag query. Preserve exact tag-object and peeled-commit comparison and successful push as the completion point.
  4. Update relevant recovery GoDoc and internal guidance to explain the automatic URL-resolution check. Keep the manual recovery runbook consistent.

Completion evidence: Extend the existing local Git publication fixtures with F2's lost-acknowledgment reproduction: actually publish the tag, install a URL rewrite to an empty bare repository, then report a push error. Recovery must return unknown and preserve the tag/error; direct inspection of the original remote must find the intended object. Existing unchanged-endpoint success, absence, conflict, and unreadable-recovery tests continue to pass. Test the behavior through publication; avoid a second copy of the full recovery matrix.

Completed: Recovery now verifies the captured URL before its one tag query. The rewrite reproduction returns unknown, preserves the local tag and both errors, and confirms the object on the original remote. Focused publication tests, the full offline suite, API boundary checks, and documentation whitespace checks pass.

Stage 2 — Own effective Go settings for validation and builds

Covers: F1, F3, Go-environment portion of F8. Primary owners: internal/candidate/check.go, internal/build/build.go, internal/process/, and a small new internal/gotool package.

  1. Put effective Go-environment construction and common invocation behavior in internal/gotool. Reuse the existing subprocess boundary for context, working directory, output, and error handling. Support native validation and static target builds as distinct modes of the same implementation.
  2. Account for both the process environment and values from Go's persistent environment file. Resolve effective Go configuration with the installed Go command under local toolchain selection and a controlled GOFLAGS. Ensure configuration discovery itself tolerates the ambient settings being replaced; an experiment override used only for discovery must not become the build default. Carry effective operational settings into child environments, then use GOENV=off there so removed settings cannot reappear from the persistent file. Retain ordinary process variables and effective cache, module-cache, temporary, tool-location, and native C-tool settings. Keep informational go env output separate from configuration when constructing child environments.
  3. Own GOFLAGS, GOWORK, GOTOOLCHAIN, module-network settings, target selection, experiment selection, and architecture-feature settings. Standard validation uses go test -mod=readonly -count=1 ./..., host OS/architecture, GOWORK=off, GOTOOLCHAIN=local, GOPROXY=off, GONOPROXY=none, and GOSUMDB=off. Resolve the Go host target independently of ambient cross-build settings. Native tests retain native Go cgo behavior and explicit native C-tool configuration; release builds retain CGO_ENABLED=0.
  4. Clear ambient experiments and architecture tuning for the child so the selected Go toolchain supplies ordinary baseline defaults. Handle the Go feature variables for supported toolchains, including GOAMD64, GOARM, GOARM64, GO386, GOMIPS, GOMIPS64, GOPPC64, GORISCV64, and GOWASM. Clearing must take effect for persisted values as well. Retain the existing release flags, linker injection, target selection, and native version smoke check. Keep these settings internal; the profile needs no new tuning fields.
  5. Route default validation, build toolchain/host queries, target compilation, and native smoke-build compilation through the shared owner. Preserve useful compiler diagnostics and cancellation. Custom product commands retain their explicitly selected arguments and environment overlays.
  6. Update the build and check consumer guides and relevant GoDoc with the supported behavior: shared baseline settings and the available compatible toolchain. Exact internal environment construction belongs in internal docs.

Completion evidence: A genuinely failing fixture test still fails with GOFLAGS=-run=^$ supplied through either the process or a temporary Go env file. An ambient cross-target setting still results in host-native validation. Extend existing build fixtures to demonstrate that ambient/persisted GOAMD64=v2 and experiment settings do not alter the selected baseline build settings. Inspect build metadata where useful; identical binary bytes are unnecessary evidence. Use a temporary configured cache to demonstrate that persistent cache choices survive. Preserve existing version injection, empty-target, cancellation, and partial-build behavior. Fixtures use temporary Go configuration and never edit the developer's persistent settings.

Completed: Shared Go configuration now drives default validation, toolchain/host queries, target builds, and the native smoke build. Failing validation fixtures prove process and persistent GOFLAGS cannot suppress a real test and that cross-target settings still run tests on the host. Build metadata confirms ambient and persistent tuning are cleared, and a temporary persistent cache is used. Focused tests, the full offline suite, API boundary checks, and documentation whitespace checks pass.

Stage 3 — Make product checks additive

Covers: F4 and ReleaseKit's own F1 exposure. Primary owners: check.go, publish.go, internal/candidate/, CLI profile mapping and fixtures.

  1. Rename ReleaseRequest.Validate to AdditionalChecks func(context.Context, Candidate) error and update the corresponding internal request and facade conversions. The callback keeps the existing candidate-value ownership and error-wrapping behavior.
  2. Make candidate.Validate always run the shared offline suite first. On success, invoke AdditionalChecks once when supplied. Run selected-target build verification after these checks through the existing orchestration. A failure or cancellation ends the sequence and preserves its cause.
  3. Retain checks in JSON as ordered additional commands. Map the CLI's RunChecks callback to AdditionalChecks. Keep the existing argument-vector and per-command environment semantics.
  4. Remove repeated standard-suite commands from releasekit.json and example profiles. Preserve additional checks that address actual product behavior. Update in-repository callback callers and fixtures to provide small valid Go modules with an effective default suite. A callback fixture must exercise its intended callback behavior after that suite succeeds.
  5. Update facade GoDoc, docs/config.md, docs/cli.md, check/publish consumer guides, examples, and affected internal documentation. Explain migration: rename the callback and remove standard-suite invocations from custom checks.

Completion evidence: Through the public facade, prove that a failed standard suite prevents the additional callback and publication, that an additional failure prevents publication while preserving error identity, and that a successful publication runs the standard suite and additional checks once for its captured candidate. Reuse existing mutation/recheck tests with the new callback. One CLI profile test covers ordered extra commands. Keep callback unit coverage and end-to-end suite-count coverage at distinct boundaries.

Completed: AdditionalChecks now runs after the standard offline suite in the public check and publish flows; selected builds remain after both. The CLI keeps ordered JSON checks as additional commands, and the bundled profiles no longer repeat the standard suite. Facade tests prove suite failure stops checks and publication, additional-check errors retain identity, and successful publication runs both once for its captured candidate. CLI coverage verifies ordered checks. The full offline suite, API boundary check, and documentation whitespace checks pass.

Stage 4 — Consolidate artifact identity and declaration rules

Covers: artifact portion of F8. Primary owners: internal/build/, internal/delivery/assets.go, cmd/releasekit/internal/cli/receipt.go.

  1. Add a small internal artifact-contract owner for target normalization, filename-component validation, artifact names, and the expected declaration for a build. Choose internal/artifact for these shared pure rules.
  2. Move the existing rules from builder, receipt, and delivery into that owner. Preserve accepted inputs, target order/deduplication, filenames, manifest naming, and validation meaning. Keep build execution in internal/build, hosted-content checks in delivery/Gitea, and receipt JSON/path handling in the CLI adapter.
  3. Use ordinary conversions at facade and receipt boundaries. Preserve facade-owned public types and the current private receipt format. Consolidate repeated declaration comparisons while retaining boundary-specific checks for repository, commit, version, file location, and actual file contents.
  4. Update the internal package inventory. Keep exact public build/result contracts in GoDoc and private receipt lifecycle in its existing owner.

Completion evidence: Existing build-to-receipt-to-delivery tests retain behavior for normalized targets, filenames, altered files, mismatched identity, and manifests. Add only missing coverage for disagreement between these boundaries. The API/dependency checker confirms that the shared internal owner has not leaked through exported signatures or runtime dependencies.

Completed: internal/artifact now owns target normalization, filename components, binary declarations, and checksum-manifest naming. The builder, receipt adapter, and delivery validation share those rules while retaining their build, receipt-path/file, and hosted-content responsibilities. Existing coverage plus a mismatched delivery declaration check preserve cross-boundary behavior. Focused tests, the full offline suite, API boundary checks, and documentation whitespace checks pass.

Stage 5 — Make delivery outcomes disjoint and actionable

Covers: F7. Primary owners: internal/gitea/upload.go, delivery result GoDoc, CLI delivery reporting, and their tests.

  1. Define the five collections as current observations for each reported asset. Matching means existing matching content; Uploaded means confirmed upload during this invocation; Pending means known missing work; Conflicting means a detected conflict; Uncertain means unresolved state. Each asset appears in at most one collection in a returned result.
  2. In every upload/reconciliation branch, remove an asset from Pending when moving it to matching, uploaded, conflicting, or uncertain. In particular, fix failed reconciliation reads, conflicts, and unresolved writes. Later known-missing assets can remain pending when an earlier upload stops work.
  3. Preserve the existing overall delivery states and their handling of remote writes. Early failures can return incomplete asset information. Category exclusivity establishes no claim that every declaration has been observed.
  4. Keep concise state-based recovery guidance in one CLI formatter: correct local/preflight failures before retrying; retry partial delivery after fixing its cause; resolve uncertain remote state before retrying; investigate conflicting content and use a new version when source or published contents require correction. Mention retained original artifacts when a rebuild would conflict. Go callers use the documented overall state and asset categories.
  5. Update delivery GoDoc, docs/cli.md, the delivery consumer guide and Gitea integration documentation. Keep diagnostics available alongside the summary.

Completion evidence: Update the existing reconciliation-read-failure test that currently expects overlap. Extend existing upload tests to cover conflict, missing-after-ambiguous-upload, matching-after-lost-acknowledgment, and later pending assets. Assert category exclusivity and meaningful overall state at the upload boundary. CLI tests verify recovery meaning and exit classification without freezing full diagnostic wording.

Completed: Delivery asset categories now contain disjoint current observations, with later known-missing assets retained when an earlier upload stops work. CLI failures include state-based recovery guidance, while GoDoc and the delivery and Gitea guides describe category meaning and incomplete early observations. Upload and CLI tests cover reconciliation outcomes, recovery classification, and category exclusivity. The full offline suite, API boundary check, and documentation whitespace checks pass.

Stage 6 — Give the facade ownership of build-and-deliver

Covers: F5. Primary owners: delivery.go, internal/delivery/, internal/build/, and existing temporary-directory helpers.

  1. Change DeliveryRequest.Build to *BuildSpec. Add Prebuilt *BuildResult and Output io.Writer. Build requests managed builds; Prebuilt supplies an existing result. Supplying both is an invalid request because the operation needs one artifact source. With neither, or with an empty selected target set, ordinary delivery is page-only. Preserve the existing handling of empty prebuilt results.
  2. Implement the reusable orchestration inside internal/delivery; the public facade performs conversions. Verify version, product, local tag/HEAD agreement, checkout cleanliness, and the committed release note before compilation. Preserve historical lightweight-tag and detached-HEAD support.
  3. For nonempty Build, create temporary output outside the worktree using the existing helper, invoke the shared builder, and feed its result into the existing asset validation/delivery path. Defer cleanup for success, failure, and cancellation. Return diagnostic progress through Output; managed temporary paths have no caller-owned lifetime.
  4. Before hosted writes, retain the tagged-source eligibility check and the build-result, file-digest, and manifest checks. A checkout change during the build must fail eligibility. Use the same captured tag commit to read the note and validate the build. Reuse the existing builders and delivery client.
  5. Prebuilt retains caller-owned files and existing source/identity/content checks. Its build result declares its targets as today. The CLI continues comparing receipts with the selected profile. This path supports original bytes across retries; callers own retention and cleanup.
  6. Keep pre-remote build/preflight failures DeliveryNotAttempted. Preserve candidate identity when known, wrapped error causes, cancellation, and the current mapping of hosted failures and partial progress.
  7. Update all Go callers for the request shape. As an intermediate step, map the CLI's current already-built result to Prebuilt; Stage 7 removes that duplicate orchestration. Update delivery GoDoc and the consumer guide with the normal Build path and the explicit Prebuilt lifecycle.

Completion evidence: Add facade-level tests using a real small Go consumer and a local HTTP server for managed binary delivery and page-only delivery. Prove invalid tagged source fails before Go compilation or hosted writes, build failure prevents hosted writes, and managed temporary output is cleaned on success and failure. Extend existing mutation/cancellation coverage where needed. Preserve prebuilt retry, digest conflict, note conflict, and source eligibility coverage. Confirm the two facades' dependency boundaries.

Completed: Deliver now owns optional managed builds, page-only requests, and explicit prebuilt artifact delivery behind the public facade. Managed output uses temporary storage outside the checkout and is cleaned after success, failure, and cancellation; source and note checks precede compilation, and eligibility is rechecked before hosted writes. Prebuilt files remain caller-owned. Consumer and internal package guides describe these paths. Facade-level consumer and HTTP tests cover managed upload, page-only delivery, preflight and build failures, checkout mutation, cleanup, cancellation, and prebuilt ownership. The full offline suite, API boundary check, and documentation whitespace checks pass.

Stage 7 — Route ordinary CLI delivery through the facade

Covers: the CLI portion of F5. Primary owners: cmd/releasekit/main.go, CLI receipt adapters, CLI tests and documentation.

  1. Change ordinary runDelivery to pass the configured BuildSpec and output writer directly to Deliver. Remove its temporary-directory and standalone build coordination. Keep profile parsing, credential lookup, presentation, and exit-code selection in the CLI.
  2. Retain build --output and deliver --assets. The latter loads and verifies the private receipt, compares it with the selected profile, and supplies Prebuilt. Keep stale-receipt invalidation and standalone build behavior.
  3. Share the final CLI-to-facade delivery adapter so the CI entry point in Stage 9 can use it after preparation. Keep ordinary deliver free of dependency downloading and checkout mutation.
  4. Update CLI/configuration guidance and examples to make one deliver invocation the normal path. Describe split build/delivery for retained bytes and credential separation. Preserve exit statuses 0, 1, 2, and 3.

Completion evidence: CLI tests cover source-only and binary profiles, preflight failure before compilation, token/profile errors, and the explicit receipt path. Reuse Stage 6 for domain failure coverage. Confirm the maintained ordinary command exercises the facade-owned lifecycle and reports F7's results.

Completed: Ordinary deliver now passes configured builds and progress output directly to the public facade; the CLI retains profile, credential, receipt, presentation, and exit-status handling. --assets still validates the private receipt and supplies caller-owned artifacts. CLI tests cover page-only and binary profiles, preflight rejection before build progress, retained prebuilt artifacts, retry observations, and temporary-output cleanup. The binary workflow and consumer guidance use one deliver invocation by default and explain the separate build/--assets path. The full offline suite, API boundary check, and documentation whitespace checks pass.

Stage 8 — Add reusable CI preparation operations

Covers: preparation ownership in F6. Primary owners: a new root preparation.go, internal/git/, internal/gotool/, and a small internal preparation coordinator.

  1. Add facade-owned TaggedCheckoutRequest with RepositoryDir, Version, Remote, and ExpectedCommit strings, and PrepareTaggedCheckout(context.Context, TaggedCheckoutRequest) error. An empty remote selects origin. This is an explicit preparation operation for disposable CI checkouts; ordinary delivery keeps its current behavior.
  2. Validate the version and required expected commit before mutation. Fetch the selected tag from the selected remote with an explicit tag refspec, verify that its peeled commit equals the expected CI commit, detach checkout at that commit, and verify HEAD agreement. Use the existing Git subprocess boundary and preserve Git errors. Use ordinary checkout/fetch behavior; conflicting local changes or tags are reported for the operator to resolve.
  3. Add PrepareBuildDependencies(context.Context, string) error, taking the repository directory. Internally run go mod download with the available compatible local Go toolchain and workspace discovery disabled. Preparation uses the caller's dependency-access settings, including proxy/private-module configuration and caches. This operation is explicitly network-capable. Keep offline test/build environments from Stage 2 distinct from preparation.
  4. Keep both operations behind the root facade with internal implementations. These two additions serve the concrete shared CI workflow and Go consumers with the same preparation needs. Keep their API small: CI-provider variables, JSON profile loading, credentials, and output formatting stay in adapters.
  5. Add GoDoc and a short preparation section to the delivery consumer guide; update the internal package inventory. State filesystem/network effects and cancellation behavior. Preparation does not publish a tag or hosted content.

Completion evidence: Local Git fixtures verify expected-commit agreement, wrong-tag rejection before checkout, detached checkout, and ordinary local conflict behavior. A subprocess-boundary test verifies dependency preparation uses the repository and preparation environment and propagates failure and cancellation. Keep default tests offline with a local module cache or a small Go-command fixture; no live module server is needed.

Completed: The root facade now exposes PrepareTaggedCheckout and PrepareBuildDependencies. Checkout preparation fetches an explicit tag refspec, compares the peeled commit with the expected full object ID, and detaches only after a match; tests cover default and selected remotes, wrong commits, conflicting local edits and tags, and input rejection before fetch. Dependency preparation runs go mod download with workspace discovery off and the local Go toolchain, preserving caller proxy, private-module, and cache settings; subprocess fixtures verify repository selection, failure details, and cancellation without network access. GoDoc, the delivery consumer guide, and the internal inventory describe effects and ownership. The full offline suite, API boundary check, and documentation whitespace checks pass.

Stage 9 — Add the shared CI delivery command

Covers: the shared command portion of F6. Primary owners: CLI parsing/routing, CLI command tests, docs/cli.md, and docs/config.md.

  1. Add:

    releasekit ci-deliver [--repo DIR] [--config FILE] [--remote NAME] --commit OID VERSION
    

    Options precede the version, consistent with existing commands. Repository and profile defaults match deliver; remote defaults to origin. The explicit command authorizes preparation of the selected CI checkout.

  2. Call PrepareTaggedCheckout, then load the profile from that checked-out source, then validate the selected delivery configuration and credentials. When the profile selects binaries, call PrepareBuildDependencies. Finish through Stage 7's ordinary delivery adapter and Deliver. Page-only profiles skip application dependency preparation and binary work. Read custom profile paths under the existing CLI path rules.

  3. Keep the provider adapter declarative: Woodpecker supplies CI_WORKSPACE, CI_COMMIT_SHA, and CI_COMMIT_TAG as command arguments. The library and ordinary CLI operations remain independent of Woodpecker environment names. Preparation failures return 1; argument/profile/credential errors return 2; final delivery uses the existing success/failure/unknown status mapping.

  4. Update command usage, docs/cli.md, and configuration guidance for the new entry point, its preparation effects, profile-loading order, and exit codes. Keep ordinary deliver documented as operating on prepared source.

Completion evidence: Exercise the command with local Git/HTTP fixtures for source-only and binary delivery. Prove the profile is read after checkout, a wrong CI commit fails before application builds or hosted writes, and a source-only module with unavailable dependencies still reaches page delivery. Reuse facade tests for the individual preparation and delivery operations.

Completed: ci-deliver now prepares the tagged checkout against the provider-supplied commit, loads the profile from that checkout, validates its delivery settings and credential, downloads dependencies only for selected binary targets, and finishes through the existing delivery facade. Local Git/HTTP fixtures cover source-only and binary delivery, relative custom profile loading, commit mismatch before Go or hosted requests, and unavailable source-only dependencies. CLI and configuration guidance describe preparation, provider arguments, effects, and exit statuses. The full offline suite, API boundary check, and documentation whitespace checks pass.

Stage 10 — Consolidate and exercise maintained CI templates

Covers: installation, workflow duplication, and artifact-testing in F6. Primary owners: examples/woodpecker/, CLI workflow tests, installation instructions, and the product roadmap.

  1. Select versioned source execution as the default bootstrap: go run gitea.maximumdirect.net/eric/ReleaseKit/cmd/releasekit@PIN ci-deliver .... PIN is an immutable ReleaseKit revision or published version. Applications choose a compatible Go/Git image and provision the delivery token. The shared command owns checkout checks, conditional dependency preparation, and delivery. The normal Go caches suffice; optional CI cache mounts remain deployment configuration. Document go install ...@PIN for a locally retained executable and one upgrade procedure based on changing the selected version.
  2. Consolidate source-only and binary Woodpecker templates into one maintained examples/woodpecker/tag-delivery.yml, with the product profile selecting page-only or binary behavior. Remove the two superseded templates and repair their links. Retain the distinct first-release bootstrap in releasekit-source-delivery.yml, since ReleaseKit's own first source release must build its tool from the tagged source. Simplify it around the shared command where this preserves that bootstrap.
  3. Replace tests that reconstruct the workflow commands with checks tied to the maintained artifact. Use a small extractor for the template's one command block and execute it with controlled CI variables, local Git/HTTP fixtures, and a Go bootstrap shim that maps the pinned remote tool invocation to the CLI built from the test checkout. Validate the module/command/version arguments in the shim. Apply the template's matrix substitutions and Woodpecker dollar escaping before shell execution. Keep the template subset simple enough for a small test helper; a general YAML runner is unnecessary.
  4. Document bootstrap requirements, token provision, compatible Go selection, optional caches, dependency preparation, and the version upgrade procedure. Align releasekit.md's remaining adoption work with source installation; identify live deployment and the real immutable pin as remaining work.

Completion evidence: Execute the actual maintained command block for both source-only and binary fixture delivery. A repeated invocation preserves matching remote content. The bootstrap shim proves template wiring, not published-module availability. Record that distinction and retain real installation/live Woodpecker verification as deployment work.

Completed: Source-only and binary consumer delivery now share one profile-driven tag-delivery.yml using versioned go run ... ci-deliver; the duplicated templates were removed. ReleaseKit's separate first-source workflow still builds its CLI from tagged source and then uses ci-deliver. CLI workflow tests extract and execute the maintained command blocks with matrix substitution, Woodpecker dollar escaping, local Git/HTTP fixtures, and a Go bootstrap shim. Both profiles deliver successfully twice, preserving matching pages and binary assets. The shim validates command wiring but does not prove published-module availability. Consumer and maintainer guidance now covers bootstrap requirements, credentials, Go compatibility, caches, dependency preparation, and pin upgrades. Real pins and live integration remain deployment work. The full offline suite, API boundary check, and documentation whitespace checks pass.

Stage 11 — Validate representative adoption and close the sprint

Covers: audit-wide acceptance and adoption evidence. Primary owners: existing external-consumer fixtures, consumer guidance, this plan, and the remaining-work section of releasekit.md.

  1. Exercise a source-only consumer with one meaningful extra check and a binary consumer using buildinfo, selected targets, and Gitea delivery. Reuse and extend the fixtures from prior stages. Verify publication through local Git remotes and delivery through local HTTP fixtures as separate operations.
  2. Review available sibling projects named by the product roadmap read-only. Use PromptKit and Narratio as the source-only and binary representatives. Record a concise migration assessment: retained product settings/checks, release code and repeated tests that can be deleted, runtime-version adaptation, and required policy or procedure changes. Label projected deletions as estimates. If a sibling checkout is unavailable, use the audit evidence and label its verification date. Keep implementation tests self-contained in ReleaseKit.
  3. Assess the final user workflow against the audit: standard tests once, additional checks declared once, one ordinary delivery invocation, one versioned CI entry point, clear recovery, and shared artifact/build rules. Address implementation gaps within their existing stage scope before closing the sprint. Record any new product decision as such.
  4. Reconcile GoDoc, CLI/configuration references, consumer guides, maintained examples, internal inventory, and the product roadmap with implemented behavior. Keep the audit's original evidence historical. Record completion here and link to the remaining adoption/deployment work.
  5. Run the standard offline suite and API checks on the final implementation. Run them with the minimum supported Go 1.25 toolchain when available in the implementation environment; otherwise record that verification limitation explicitly. Minimum-version verification is evidence about the existing module requirement, rather than a new permanent release matrix.
  6. Leave source publication, real installation verification, credentials, workflow activation, live service checks, and changes in sibling repositories for their deployment/adoption tasks. Follow the maintainer release procedure when a release is separately requested. Keep ReleaseKit's own deliverables source-only under the current release policy.

Completion evidence: A concise final record identifies the passing checks, representative workflows, projected adoption savings, implemented API/profile migration, and remaining deployment work. Every F1–F8 finding has an implemented resolution and appropriately scoped evidence. Review and commit the final changes with a clean worktree.

Completed: The source-only consumer publication fixture runs one meaningful compatibility check against its committed note and module, then confirms the annotated tag on a local Git remote. A separate binary consumer fixture builds buildinfo binaries for selected Linux targets, checks native version output, and delivers both binaries plus SHA256SUMS to a local HTTP Gitea fixture. PromptKit and Narratio were reviewed read-only on 2026-10-06; the product roadmap records retained settings, runtime and policy/procedure adaptations, and projected deletion ranges. No sibling repositories were changed.

The final documentation review reconciled GoDoc, CLI/configuration references, consumer guidance, Woodpecker examples, the internal inventory, and product roadmap. The pre-release API migration is Validate to AdditionalChecks and DeliveryRequest.Build to *BuildSpec, with Prebuilt for retained artifacts; JSON checks remains the ordered additional-check setting. No new product decision was required. The completed stages address F1–F8; real source publication, an immutable tool pin, credentials, workflow activation, and live Gitea/Woodpecker verification remain deployment work.

The full offline suite and API boundary check pass with Go 1.25.0. Go formatting, documentation whitespace, and changed local-link checks pass.

Open Questions

No unresolved product choice is required to implement these stages. The selected approaches and rationale are recorded in the audit's design choices. Real deployment pins, credentials, service availability, and per-application migration scheduling are inputs to subsequent deployment/adoption work. They are separate from the implementation acceptance criteria above.