ADR 0064: Automate Draft Release Proposals Without Releasing
Status: Accepted
Date: 2026-08-01
Context
ADR 0063 gave new STAGE commits machine-readable change types but deferred release automation until its authority and update boundaries were explicit.
STAGE releases synchronize a plugin package version, website package metadata, method-version references when applicable, compatibility guidance, a changelog, and a required evidence-bearing release record. An automated version guess cannot decide whether those materials are complete, whether a change alters the method version, or whether the plugin is ready to refresh and publish.
Release Please can separately prepare a release pull request and create a tag or GitHub Release. The first operation reduces recurring version and changelog work. The second is a release action and must remain human-owned.
Decision
Run a pinned Release Please v5 workflow only after STAGE quality gate
succeeds for main, with manual dispatch available for recovery. Configure it
to open or update a draft release pull request and explicitly skip GitHub
release and tag creation.
For a quality-triggered run, the workflow also confirms that the successfully
verified revision still heads main. If main has advanced, that run does
not prepare a proposal; the quality run for the newer revision becomes the
next opportunity. Manual dispatch always operates on the current main.
The automated proposal may update only:
.release-please-manifest.json;- root
package.jsonandpackage-lock.jsonrelease mirrors; plugin/.codex-plugin/plugin.json, which remains the plugin package version;website/package.json; andCHANGELOG.mdfrom accepted Conventional Commits.
The root package version and Release Please manifest are automation mirrors, not independent release identities. Repository tests keep them synchronized with the plugin and website versions.
Every generated proposal starts as a draft. Before marking it ready, a human must:
- reconcile the existing
Unreleasedchangelog material with the proposed version section; - refresh
website/package-lock.jsonfrom the proposed website version; - decide whether
SPEC.mdmethod major/minor changes; - update all current-version, compatibility, adoption, and evaluation references;
- add
docs/releases/<version>.mdwith evidence and limitations; - run the full release gate and direct package validators; and
- approve the version and complete diff.
Merging the completed proposal does not create a tag, GitHub Release, plugin publication, public source publication, or package refresh. The maintainer creates the annotated tag and any GitHub Release explicitly after inspecting the merged revision, then performs the existing plugin refresh and fresh-task verification.
The workflow uses only repository-content and pull-request write permissions
and skips labels to avoid issue permission. It prefers an optional scoped
STAGE_RELEASE_PLEASE_TOKEN; without that secret it falls back to
GITHUB_TOKEN. GitHub does not start new workflows for pull requests created
with GITHUB_TOKEN, so the first human completion commit must establish the PR
quality run before merge.
For pre-1.0 releases, breaking changes propose a minor rather than major bump. The proposal remains editable and rejectable; commit syntax never grants release approval.
Consequences
- Conventional Commit metadata now has a bounded automated consumer.
- Repeated version and changelog preparation becomes reviewable draft work without automating publication.
- Release proposals deliberately begin incomplete and fail closed on the existing version, release-record, and documentation contracts until a human completes them.
- The default Actions token keeps credential scope narrow but does not trigger the initial pull-request checks. A future scoped token or GitHub App may remove that limitation without widening release authority.
- Existing pre-adoption
Unreleasedmaterial remains human-curated; automation begins at the Conventional Commit adoption boundary.