diff --git a/docs/release.md b/docs/release.md index 1d4d4a2..dcd0da5 100644 --- a/docs/release.md +++ b/docs/release.md @@ -1,28 +1,26 @@ # 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. -After source publication, deliver the hosted Gitea release page as described -below. Report source publication and hosted delivery separately. +publishes source-only Go module tags from `main` to `origin`, followed by a +page-only Gitea release. Successful publication of the intended tag, with its +source commit available on `main`, completes the source release. Report hosted +delivery separately. 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: +Use the latest Go installation available locally for the release tool and its +child commands. Put it first on `PATH` and keep it selected throughout: ```sh export GOTOOLCHAIN=local go version ``` -For a minor release, advance Promptkit's consumer minimum to the initial stable -release of that Go series before committing the candidate: +For a minor release, normally advance the consumer minimum to the initial +stable patch of that Go series: ```sh release_go_version=$(go env GOVERSION) @@ -31,151 +29,97 @@ release_go_series=${release_go_series%.*} go mod edit "-go=${release_go_series}.0" ``` -For example, Go 1.27.1 normally results in `go 1.27.0`. Keep a higher patch -minimum if a dependency or identified correctness fix requires it. For a patch -release, leave the consumer minimum unchanged; using a newer validation -toolchain does not itself raise that minimum. If the candidate needs a higher -minimum, prepare a minor release instead. See the -[consumer-minimum policy](policy/release.md#consumer-minimum-and-release-toolchain). - -Prepare module caches before validation; this may update `go.sum` and belongs -before the candidate commit: +Retain a higher patch minimum when required by a dependency or identified fix. +For a patch release, preserve the existing minimum. Explain minimum increases +under the [versioning policy](policy/release.md#versioning-and-compatibility). +Prepare dependency caches before committing the candidate: ```sh -GOTOOLCHAIN=local go mod download +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: +compatibility impact or upgrade instructions. End the note with: ```markdown [COPYRIGHT](https://forge.maximumdirect.net/base-layer/promptkit/src/tag/vX.Y.Z/COPYRIGHT) | [LICENSE](https://forge.maximumdirect.net/base-layer/promptkit/src/tag/vX.Y.Z/LICENSE) | [ATTRIBUTION](https://forge.maximumdirect.net/base-layer/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. Hosted delivery reuses this complete note without a separate summary. -Promptkit publishes no binaries, attachments, or checksum manifests. +Substitute the selected version and check the paths against the candidate; +future tag URLs need not resolve during preparation. Follow the +[OSS policy](policy/oss.md). Historical notes and tags remain unchanged. -For hosted delivery, supply a Gitea API token with access to publish releases -through `RELEASEKIT_GITEA_TOKEN` or the ignored local file -`.releasekit/gitea-token`, with owner-only permissions for the file. A nonblank -environment value takes precedence. ReleaseKit trims surrounding whitespace -from file contents. Keep the token out of commits and shared logs. The profile -rejects that exact token path if -committed; it does not scan other files or Git history. Source publication uses -Git authentication and neither reads nor requires the delivery token. +Supply delivery credentials through `RELEASEKIT_GITEA_TOKEN` or the ignored +local file `.releasekit/gitea-token`, with owner-only file permissions. A +nonblank environment value takes precedence. Source publication neither reads +nor requires this token. The [profile](../releasekit.json) selects the token +path for committed-file protection; keep credentials out of commits and logs. -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. +Retire completed roadmaps, preserve unfinished work, and repair affected links. +Review and commit the candidate on `main`, including any module updates, then +push `main` to `origin` before publishing its tag. ## 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://forge.maximumdirect.net/base-layer/releasekit/src/tag/v0.7.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. It also checks that the configured local -token path is not committed. ReleaseKit 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 launcher uses `go tool` to build or reuse the module-selected ReleaseKit +executable in Go's cache, using the selected local toolchain. ReleaseKit runs +the [profile's checks](../releasekit.json) once, verifies publication state, and +publishes only the intended tag. Preserve its native exit status and diagnostic. +Successful publication needs no separate remote read-back or CI wait. -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. +For optional local diagnosis, use `./scripts/releasekit.sh check VERSION`. +It is not a required step before publication. The upstream +[candidate-check guide](https://forge.maximumdirect.net/base-layer/releasekit/src/tag/v0.7.0/docs/consumers/check.md) +and [CLI contract](https://forge.maximumdirect.net/base-layer/releasekit/src/tag/v0.7.0/docs/cli.md) +own shared checks and exit-status definitions. ## Deliver The Hosted Release -After source publication succeeds, keep a clean checkout at the published tag's -commit and run: +After source publication, keep a clean checkout at the published tag's commit: ```sh ./scripts/releasekit.sh deliver vMAJOR.MINOR.PATCH ``` -The profile selects Gitea at `https://forge.maximumdirect.net`, owner -`base-layer`, repository `promptkit`. With no build targets, ReleaseKit creates -or accepts a stable, non-draft release page containing the complete committed -note and licensing footer. There is no binary build, attachment upload, or -candidate revalidation. Delivery does not publish another tag or wait for CI. - -ReleaseKit performs its authenticated, read-only repository preflight during -delivery; no separate preflight is required before source publication. Missing -credentials or an unavailable hosted service leave the source release complete. - -Delivery returns status 0 for completion, 1 for an operational failure, -conflict, or partial delivery, 2 for invalid configuration or credential/access -errors, and 3 for an unresolved hosted write. Report the hosted URL on success -and retain the diagnostic and delivery state on failure. See the upstream -[delivery guide](https://forge.maximumdirect.net/base-layer/releasekit/src/tag/v0.7.0/docs/consumers/delivery.md) -for the full result contract. +The profile selects page-only Gitea delivery for this repository. The hosted +body is the complete checked-in note, including its licensing footer. There are +no binary assets, checksum manifests, candidate revalidation, or CI waits. +ReleaseKit checks delivery credentials during delivery, not as a publication +gate. Report the hosted URL on success; delivery failure leaves the source +release complete. For a later retry, use a clean checkout of the original tag with its recorded -module files and make the token available locally. For example, in a separate -checkout with the tag available: +module files and supply the token there. In a separate checkout, for example: ```sh git switch --detach vMAJOR.MINOR.PATCH ./scripts/releasekit.sh deliver vMAJOR.MINOR.PATCH ``` -The launcher builds the tool selected by that checkout. Matching hosted content -is accepted; conflicting content is not overwritten. Resolve an unknown hosted -write before retrying. Retry delivery with the same immutable version rather -than rerunning `publish` or moving a tag. Corrections to published source or -content require a new appropriate version. These steps apply to tags containing +Resolve uncertain hosted writes before retrying the same immutable version. +Matching content is accepted; conflicts are not overwritten. Do not rerun +`publish` or move tags to repair delivery. Follow the upstream +[delivery guide](https://forge.maximumdirect.net/base-layer/releasekit/src/tag/v0.7.0/docs/consumers/delivery.md) +for result interpretation and recovery. These commands apply to tags containing this delivery configuration; older releases retain their original workflows. ## Failure Recovery -This section covers source publication. Hosted-delivery recovery is described -[above](#deliver-the-hosted-release); its failure does not undo source publication. +For source-publication failures, use ReleaseKit's status and diagnostic to +distinguish a candidate defect from a publication conflict. Correct and commit +candidate defects, push `main`, and rerun publication as appropriate. A failure +after local tag creation may leave a ref even when its object ID is unavailable. -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. - -If local tag creation or verification fails, inspect the reported local ref: -it may remain even when ReleaseKit could not establish its object ID. Apply -the authoritative-state checks below before removing a retained tag. - -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://forge.maximumdirect.net/base-layer/releasekit/src/tag/v0.7.0/docs/release.md#resolve-failures). - -CLI diagnostics mask HTTP(S) credentials. If the displayed endpoint is -redacted, use the actual endpoint captured for that attempt, with authentication -supplied locally; do not copy the redacted display as a transport URL or expose -credentials in shared logs. +Status 3 means the push outcome remains unknown. Preserve the captured endpoint, +version, and tag object from that attempt; do not retry or remove the local tag +until the authoritative outcome is resolved. Diagnostics mask HTTP(S) credentials, +so use the actual captured endpoint rather than a redacted display. Follow the +upstream [failure-recovery procedure](https://forge.maximumdirect.net/base-layer/releasekit/src/tag/v0.7.0/docs/release.md#resolve-failures): ```sh releasekit_endpoint='COPY_CAPTURED_ENDPOINT' @@ -184,16 +128,8 @@ test "$(git ls-remote --get-url -- "$releasekit_endpoint")" = "$releasekit_endpo 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. +An exact tag-object match confirms publication. Absence is established only if +both checks succeed and the tag is missing; a failed check leaves the outcome +unknown. Remove an unpublished local tag only after confirming authoritative +absence. Never move or replace a published tag or hosted page. Corrections to +published source or content require a new appropriate version.