# Release Procedure This runbook implements the [release policy](policy/release.md). Promptkit publishes source-only Go module tags from `main` to `origin`. A successful push of the selected annotated tag, after its source commit is available on `main`, completes the release. Do not wait for CI or Go module availability. ## Prepare The Candidate Required tools are Git, Go with race-detector support, POSIX shell, and Python 3. Work from the repository root with push access to `origin`. Use the latest Go installation available locally for the release tool, the candidate validation, and the maintained examples. Make it the active `go` command and record its version. Set Promptkit's consumer minimum to the initial stable release of that Go series before committing the candidate: ```sh export GOTOOLCHAIN=local go version release_go_version=$(go env GOVERSION) release_go_series=${release_go_version#go} release_go_series=${release_go_series%.*} go mod edit "-go=${release_go_series}.0" ``` For example, Go 1.26.8 normally results in `go 1.26.0`. Keep a higher patch minimum if a dependency or correctness fix requires it. Prepare module caches before validation; this may update `go.sum` and belongs before the candidate commit: ```sh GOTOOLCHAIN=local go mod download ``` Choose an unused stable version and create `docs/releases/.md` with a title containing `Promptkit` and that exact version, a short summary, and any relevant compatibility impact or upgrade instructions. No fixed section headings are required. Describe a raised Go minimum and its compatibility impact under the [versioning policy](policy/release.md#versioning-and-compatibility). End each new note with the licensing footer below, using the selected version: ```markdown [COPYRIGHT](https://gitea.maximumdirect.net/eric/promptkit/src/tag/vX.Y.Z/COPYRIGHT) | [LICENSE](https://gitea.maximumdirect.net/eric/promptkit/src/tag/vX.Y.Z/LICENSE) | [ATTRIBUTION](https://gitea.maximumdirect.net/eric/promptkit/src/tag/vX.Y.Z/docs/oss/attribution.md) ``` Check the footer paths against the candidate; the future tag need not resolve remotely during preparation. Follow the [OSS policy](policy/oss.md) for these links. Promptkit publishes no binaries, hosted download page, or other asynchronous deliverables. Retire completed roadmaps while preserving deferred work and repairing incoming links. Review the intended changes through the ordinary development workflow, commit the candidate on `main`, and push `main` to `origin` before publication. Preparation may update module metadata; the release bootstrap and validation preserve the committed candidate. ## Validate And Publish For an optional local diagnostic of a committed candidate, run: ```sh ./scripts/releasekit.sh check vMAJOR.MINOR.PATCH ``` This is not a required step before publication. The upstream [candidate-check contract](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/v0.2.0/docs/consumers/check.md) describes its requirements. Run the single publication command with the chosen version: ```sh ./scripts/release.sh vMAJOR.MINOR.PATCH ``` The familiar wrapper delegates to the native ReleaseKit executable selected in `go.mod`. The committed [profile](../releasekit.json) selects the race-enabled Go suite, full vet, committed Go formatting, local Markdown links, workspace and filesystem replacement inspection, and semantic checks for the three maintained offline consumer examples. ReleaseKit also verifies the committed candidate and publication state, then publishes only the selected tag. Its checks run once for this candidate; do not repeat them as a separate sign-off. The native command returns status 0 for confirmed publication, 1 for a known validation or publication failure, 2 for invalid input or profile, and 3 when the push outcome remains unknown. Successful publication needs no remote read-back, CI wait, or installation check. Provider probes and inference calls are not part of validation. ## Catalog Profile Compatibility The [release policy](policy/release.md#catalog-profile-compatibility) owns the catalog compatibility boundary. This heading preserves older incoming links. ## Failure Recovery For status 1, use the diagnostic to distinguish a validation failure from a known publication conflict. Correct and commit candidate defects, push `main`, and rerun publication with an unused version when appropriate. Status 2 means the invocation or profile must be corrected. For status 3, do not retry or remove the local tag until the remote outcome is resolved. ReleaseKit reports the attempted version, tag object, and recovery state, including the captured publication endpoint when available. Use that endpoint—not merely the current `origin` URL—to query the exact tag; follow the upstream [failure-recovery procedure](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/v0.2.0/docs/release.md#resolve-failures): ```sh releasekit_endpoint='COPY_CAPTURED_ENDPOINT' releasekit_version='vX.Y.Z' test "$(git ls-remote --get-url -- "$releasekit_endpoint")" = "$releasekit_endpoint" && git ls-remote --refs -- "$releasekit_endpoint" "refs/tags/$releasekit_version" ``` Compare the returned object ID with the reported tag object. An exact match confirms publication. A missing ref confirms absence only when the endpoint identity check and query both succeed. If either check fails, the outcome remains unknown; correct the transport configuration and resolve it before retrying. Only after authoritative absence is confirmed may an unpublished local tag be removed before correcting the candidate or retrying. Never move, overwrite, or delete a published tag. ## Policy Changes Update the policy and this procedure together when changing release governance. Consumers own their dependency-availability and release checks; their readiness does not delay completion of a Promptkit release.