Release-management (spec)

June 2, 2026 · View on GitHub

Status

Proposed. No release-* skill code yet. This document defines the runtime contract the future skills must satisfy. The lifecycle they execute against is in process.md; the family overview is in README.md. The pattern matches Mentoring, spec lands first so the contract, state-change boundaries, and adopter knobs are reviewable independently from skill code.

This spec is binding on future PRs that add release-* skill code. A skill PR that violates a cross-cutting commitment below is a review-blocker, not a style nit.

Cross-cutting commitments

Every skill in this family inherits the four boundaries below. They are non-negotiable.

Boundary 1: Agent never holds the RM's signing key

The agent does not load, hold in memory, proxy, or invoke the Release Manager's GPG private key, the GPG passphrase, the hardware-token PIN, or any equivalent credential. Skills that need a signature emit a paste-ready command sequence; the RM runs every gpg --detach-sign, git tag -s, or token-backed operation on their own machine, as themselves.

This mirrors security-cve-allocate: the skill emits the Vulnogram URL + paste-ready JSON, the human submits the record. It satisfies RFC-AI-0004 Principle 1.

Practical consequences:

  • No skill in this family stores, requests, or reads from GPG_PASSPHRASE, a passphrase file, a smartcard reader, or a key-server private endpoint.
  • The adopter contract § signing declares the key fingerprint the RM is expected to use; the skill verifies the public counterpart appears in the project's KEYS and refuses to advance if it does not. It never sees the private side.
  • Verification skills (release-verify-rc) use gpg --verify <artefact>.asc <artefact> against the project's KEYS file as their only signature operation. They never sign.
  • Signing happens on hardware the RM personally controls. ASF policy requires the release-signing private key to live only on hardware the committer has physical possession of and full administrative control over; it MUST NOT be placed on, or used from, ASF-owned infrastructure (release-policy.html). The skill states this in its hand-off text; it cannot enforce it.

Boundary 2: Agent never publishes the release

The two operations that constitute publication are:

  • svn mv https://dist.apache.org/repos/dist/dev/<project>/<rc> https://dist.apache.org/repos/dist/release/<project>/<version> (Step 10).
  • The [ANNOUNCE] email send to announce@apache.org and the site-bump PR merge (Step 11).

Neither is performed by the agent. release-promote emits the svn command set; the RM runs it under their own ASF credentials. release-announce-draft emits the email body and opens (not merges) the site-bump PR; the RM sends, a committer merges.

This boundary holds even with full per-skill permission grants. A permission to run svn against dist.apache.org does not grant permission to run the promotion svn move; that step is identified by destination path (dist/release/) and is on a hard skill-side denylist, not a permission denylist. Removing it requires editing the skill, not the permission set.

Boundary 3: Agent never sends mail to dev@, users@, announce@

Drafting skills (release-vote-draft, release-announce-draft, release-vote-tally for the [RESULT] reply) emit email bodies as markdown blocks the RM copies into their mail client. No skill in the family is wired to an outbound SMTP path, an MCP send-mail endpoint, or a CLI that posts to mailing lists. This holds even when the adopter ships a send-mail MCP for other skill families (e.g. security-issue-import drafting reporter replies); the release-management skill must explicitly not enumerate that capability.

The boundary is read-side too: skills may read mail archives (PonyMail) to tally votes, but a read-mail capability for the project's PonyMail archive does not extend to a write-mail capability anywhere.

Boundary 4: Agent never auto-flips state labels

The planning issue's status label (see process.md § Label reference) is moved by the RM, not the skill. Every skill proposes the next label transition in its output (e.g. release-vote-tally proposes vote-passed or rc-rolled); the RM applies it on the issue. This mirrors the security family's discipline that security-issue-triage opens a discussion comment, never flips the label.

Rationale: labels are the lifecycle's audit trail. A label flip the RM cannot defend after the fact is worse than a slow flip.

Per-skill specifications

Each spec below names: scope, triggers, inputs, outputs, state- change boundary specifics, hand-off conditions, and adopter knobs the skill reads.

release-prepare

Mode: Drafting. Steps owned: 1, 2, 14.

Scope. Drafts the planning issue, the prep PR (version bump + changelog + NOTICE/LICENSE), and the post-release -SNAPSHOT bump PR.

Triggers.

  1. RM runs /release-prepare <version> to open the planning issue.
  2. RM runs /release-prepare prep <version> to draft the prep PR after the planning issue is open and Step 1's scope is locked.
  3. RM runs /release-prepare post <version> after Step 11 to bump the development branch.

Inputs.

  • <project-config>/release-trains.md, train identity for the target version.
  • Merged-PR set between the previous release tag and the current HEAD, fetched via gh pr list filtered by the configured base branch.
  • <project-config>/release-management-config.md, Category-X dependency list to refuse on (per ASF licensing-howto).
  • The previous release's NOTICE and LICENSE files for diff.

Outputs.

  • A planning-issue body (markdown), labelled release-planning.
  • A prep PR (separate invocation), labelled prep-pr-open.
  • A post-release bump PR (third invocation), unlabelled.

State-change boundary. The skill opens the planning issue and opens the PRs as drafts. The RM marks them ready and merges. The skill never marks ready, never merges, never closes.

Hand-off conditions.

  • A Category-X dependency appears in the prep diff → hand off to the RM with the dependency list; skill refuses to advance.
  • The merged-PR set is empty (no changes since previous release) → hand off; the RM decides whether to skip the release.
  • A NOTICE diff includes a removed attribution that the remaining file does not justify (still-vendored third-party code, missing notice) → hand off.

Adopter knobs.

KeyPurpose
release_planning_issue_templateMarkdown template path under <project-config>/.
release_branch_baseDefault base branch for the prep PR (main, master, <release-train>-stable).
category_x_dependenciesPinned list of Category-X identifiers; skill refuses if any appear.
version_manifest_filesFiles the version bump touches (e.g. pom.xml, pyproject.toml).

release-keys-sync

Mode: Drafting. Steps owned: 3.

Scope. Draft the diff that adds the RM's public key to the project's KEYS file under dist/release/<project>/KEYS, emit the svn commit sequence, remind the RM to upload to a public keyserver, and validate that the key meets the ASF strength floor (RSA at least 2048-bit, or an equivalently strong algorithm).

Triggers.

  • RM runs /release-keys-sync during release prep; the skill detects whether the configured RM key fingerprint is already in KEYS and is a no-op if so.

Inputs.

  • <project-config>/release-management-config.md, rm_key_fingerprint.
  • Current KEYS file from dist/release/<project>/KEYS.
  • RM's public key block (fetched from a keyserver keys.openpgp.org / keyserver.ubuntu.com by fingerprint; fingerprint is the only input the agent uses).

Outputs.

  • A markdown diff showing the KEYS block to append.
  • A paste-ready svn checkout + edit + svn commit command sequence the RM executes under their ASF credentials.

State-change boundary. No commit, no key fetch into a held keyring. The skill formats the public-key block; the RM commits. The skill never operates on the private key half.

Hand-off conditions.

  • The fingerprint configured in <project-config>/release-management-config.md does not exist on the keyserver → hand off; the RM uploads it first or corrects the configured fingerprint.
  • The configured fingerprint is already in KEYS but for a different uid (key rolled) → hand off; the RM decides whether to replace or append.
  • The configured key is weaker than the ASF floor (an RSA key below 2048-bit) → hand off; the RM generates a conforming key before the release proceeds.

Adopter knobs.

KeyPurpose
keys_file_urlhttps://dist.apache.org/repos/dist/release/<project>/KEYS (overridable for non-ASF adopters).
keyserverDefault keys.openpgp.org; overridable per project.
rm_key_fingerprintSet per-RM (often in .apache-magpie-overrides/user.md, not project config).

release-rc-cut

Mode: Drafting. Steps owned: 4, 5.

Scope. Emit the paste-ready command sequence to tag the RC, build artefacts, sign each artefact, generate checksums, and stage to the adopter's distribution backend (default svn import to dist/dev/<project>/<version>-rcN/; alternatives resolved from release_dist_backend per process.md § Adopter backends).

Triggers.

  • RM runs /release-rc-cut <version> rc<N> after the prep PR is merged.

Inputs.

  • <project-config>/release-build.md, build invocation, digest set (sha512, optionally sha256), binary-exclude list.
  • Current HEAD of the configured release branch.
  • The RC number (from the trigger).

Outputs.

  • A four-section markdown block: (1) git tag -s command, (2) build command, (3) gpg --detach-sign for each expected artefact, (4) sha512sum > artefact.sha512 for each artefact.
  • A second markdown block with the backend-shaped staging command sequence. For svnpubsub (ASF default): svn import into dist/dev/<project>/<version>-rcN/. For github-releases: gh release create <version>-rcN --draft plus gh release upload <version>-rcN <artefact> per artefact. For s3: aws s3 cp --recursive <local> s3://<bucket>/<version>-rcN/. For self-hosted: the command template at release_publish_command_template rendered with <version> and <rcN> substituted.

The checksum commands emit .sha512 (and .sha256 where the adopter's release-build.md requests it) only; MD5 and SHA-1 are prohibited for new releases. Signatures are detached .asc files (gpg --detach-sign --armor), never a binary .sig. Both prohibitions hold per release-distribution § sigs-and-sums.

State-change boundary. The skill writes nothing to disk and runs nothing locally. The RM runs every command on their own machine, with their own key, in their own checkout, with their own ASF credentials.

Hand-off conditions.

  • The RC tag already exists on the remote → hand off; the RM decides whether to delete (rare) or bump RC.
  • The build command in <project-config>/release-build.md exits non-zero in the RM's run, the skill never sees this directly; the RM reports failure back, and the skill records it on the planning issue.

Adopter knobs. Inherits <project-config>/release-build.md verbatim, see the projects/_template/release-build.md scaffold.

release-verify-rc

Mode: Triage / Pairing. Steps owned: 6.

Scope. Read-only verification of a staged RC. Designed to run in two contexts: (1) the RM's pre-flight self-check before posting the [VOTE] thread, and (2) any voter's Pairing-mode dev loop before posting +1.

Triggers.

  • RM or committer runs /release-verify-rc <version>-rcN against a staged RC URL.

Inputs.

  • The staging URL (from the trigger).
  • <project-config>/release-build.md, expected artefact list, digest set, binary-exclude rules, RAT (license-header) configuration path.
  • The project's KEYS file from dist/release/<project>/KEYS.

Outputs.

  • A pass/fail report per check (signatures, checksums, license headers via Apache RAT, NOTICE / LICENSE presence + diff vs previous release, no prohibited binaries, version-string consistency).
  • A summary classification: PASS, PASS-WITH-WARNINGS, FAIL.

The report is a mechanical aid, not a vote. A PASS does not discharge a voter's own ASF obligation to download, build, and test the candidate on their own hardware before posting a binding +1; the skill states this in the report header.

State-change boundary. Read-only. The skill posts no comments unless explicitly invoked with --post-to <planning-issue>, in which case it proposes a comment for the RM's confirmation before posting.

Hand-off conditions.

  • A signature fails to verify against the project's KEYS, the skill reports FAIL and refuses to mark the check ambiguous. The RM rolls a new RC.
  • A binary appears that the binary-exclude list neither permits nor names, the skill reports FAIL and points at the file; the RM decides whether to exclude or pull the binary.

Adopter knobs. Inherits <project-config>/release-build.md.

release-vote-draft

Mode: Drafting. Steps owned: 7.

Scope. Draft the [VOTE] email body to dev@<project> from the planning issue's metadata.

Expedited releases. A vote window shorter than the ASF 72h baseline is permitted only in exceptional circumstances (e.g. a critical security fix). When vote_window_hours is below 72, the skill requires an explanation of why the release is expedited in the [VOTE] body and flags the RM's obligation to report the deviation in the project's next board report, per release-policy.html § release approval. The skill never silently drafts a sub-72h [VOTE].

Triggers.

  • RM runs /release-vote-draft <version>-rcN after the RC is staged and release-verify-rc reports PASS.

Inputs.

  • Planning issue body.
  • Staging URL, tag URL, KEYS URL, changelog URL.
  • <project-config>/release-management-config.md, vote-window length (overrides the release-policy.html § release approval baseline if the project demands a longer window; the baseline is the floor, never the ceiling).
  • <project-config>/canned-responses.md, [VOTE] body template if the project has one; otherwise the skill uses a default template that mirrors the release-policy.html § release approval reference body.

Outputs.

  • A markdown block containing the [VOTE] subject line and body.
  • A second markdown block for the planning-issue comment summarising the vote-open state (proposed, not auto-posted).

State-change boundary. No mail send. No issue comment without explicit RM confirmation.

Hand-off conditions.

  • release-verify-rc did not run, or ran with FAIL, skill refuses to draft the [VOTE] and hands off; the RM either passes verification first or explicitly overrides (--skip-verify-check, logged on the planning issue).

Adopter knobs.

KeyPurpose
vote_window_hoursHours the vote remains open; floor per ASF policy.
vote_subject_templateSubject-line template ([VOTE] Release <project> <version>-rcN).
vote_dev_listMailing list (dev@<project>.apache.org).

release-vote-tally

Mode: Triage. Steps owned: 9.

Scope. After the approval window closes, fetch the approval signal from the adopter's release_approval_mechanism backend, classify each reply / approval as +1 / 0 / -1, classify each approver as binding or non-binding against the configured roster, propose the result body (mailing-list [RESULT] [VOTE] or backend-equivalent).

Fractional votes. A fractional vote (+0.9, +0.5) is not ambiguous: it is determinately non-binding per ASF voting convention. The skill classifies it as non-binding directly and does not mark it AMBIGUOUS. The skill also counts only the explicit +1 replies it parses from the thread; it never attributes an implicit +1 to the Release Manager.

Triggers.

  • RM runs /release-vote-tally <version>-rcN after the configured approval window (vote_window_hours for dev-list-vote, approval_window_hours for non-list mechanisms) has elapsed.

Inputs.

  • Approval signal: mail thread (dev-list-vote), Discussion thread + reactions (github-discussion), PR review approvals (pr-approval), or signed off-band roster file (maintainer-roster). Backend resolved from release_approval_mechanism.
  • Approver roster: <project-config>/pmc-roster.md for ASF (the release_approver_roster_path default), or <project-config>/release-approvers.md (or adopter-named path) for non-ASF. Both files share the same schema.
  • <project-config>/release-management-config.md, vote-pass rule (baseline for dev-list-vote: release-policy.html § release approval three binding +1 minimum, more binding +1 than -1; project override permitted only to strengthen, never to weaken; for non-list mechanisms, the backend-specific rule keys (approval_pr_min_approvals etc.) play the same role).

Outputs.

  • Per-reply classification table: from-address, binding flag, vote value, ambiguous flag, raw vote line.
  • Tally summary: binding +1 count, binding -1 count, non-binding counts, ambiguous count, pass/fail per the configured rule.
  • A [RESULT] [VOTE] email body (markdown block).
  • The proposed next label (vote-passed or rc-rolled).

State-change boundary. No mail send. No label flip. The classification is the agent's; the decision is the RM's.

Hand-off conditions.

  • An ambiguous vote (+1 with one caveat, +1 if X is added), the skill marks AMBIGUOUS, needs RM call and refuses to count. The RM resolves by replying to the voter on the thread; the skill re-runs after the resolution lands. (A fractional vote is not ambiguous, it is classified non-binding directly, see the Fractional votes note above.)
  • A binding voter cannot be resolved against pmc-roster.md, the skill flags and hands off; the RM updates the roster or corrects the from-address.

Adopter knobs.

KeyPurpose
mail_archiveArchive backend; default ponymail.
mail_archive_url_templateURL template the skill uses to fetch the thread.
vote_pass_rule_overridesOptional stricter rule (e.g. require five binding +1); never weakens the ASF baseline.
result_subject_templateSubject line for [RESULT] [VOTE] ([RESULT] [VOTE] Release <project> <version>-rcN).

release-promote

Mode: Drafting. Steps owned: 10.

Scope. Emit the backend-shaped promotion command set after a passing vote. For svnpubsub (ASF): svn mv dist/dev → dist/release plus commit message. For github-releases: gh release edit <version> --draft=false. For s3: aws s3 mv --recursive s3://<bucket>/<version>-rcN/ s3://<bucket>/<version>/. For self-hosted: the promote half of release_publish_command_template.

Triggers.

  • RM runs /release-promote <version>-rcN after release-vote-tally has reported vote-passed.

Inputs.

  • Staging URL (dist/dev/<project>/<version>-rcN/).
  • Target URL (dist/release/<project>/<version>/).
  • The [RESULT] [VOTE] archive URL (for the commit message).
  • <project-config>/release-management-config.md, release_dist_url_template.

Outputs.

  • A markdown block with the svn command sequence (svn mv, svn commit -m, expected mirror-propagation note).
  • A proposed next label: promoted.

The mirror-propagation note also records the earliest time the download page may be updated and the [ANNOUNCE] sent: ASF policy requires at least one hour after the promote commit (release-policy.html).

State-change boundary. This skill is the Boundary 2 demonstration. The agent does not run the svn mv. The promotion target URL is identified by dist/release/ prefix and is on a hard skill-side denylist; removing it requires a skill PR.

Hand-off conditions.

  • The planning issue does not carry vote-passed, skill refuses to advance; the RM either reruns release-vote-tally or explains the override on the planning issue.
  • The target URL already contains the version (e.g. a previous promote attempt half-landed), skill refuses and hands off; the RM resolves with ASF infra.
  • The RM is a committer but not on the PMC roster, the dist/release/ tree is PMC-write-only by default (release-policy.html); the skill emits an "ask a PMC member to publish" hand-off instead of the svn mv command set.

release-announce-draft

Mode: Drafting. Steps owned: 11.

Scope. Draft the announcement artefact and the site-bump PR on the configured site repo. The announcement artefact shape depends on release_announce_backend: [ANNOUNCE] email body for announce-list (ASF default), GitHub Release page body for github-release-notes, blog-post markdown for site-post, webhook message body for discord-channel. The site-bump PR is emitted only when site_repo is configured.

Triggers.

  • RM runs /release-announce-draft <version> after the promote step is confirmed (planning issue carries promoted).

Inputs.

  • Planning issue body.
  • The dist/release/<project>/<version>/ URL.
  • The previous release's announcement body, fetched from the announce@apache.org archive, for tone and format consistency.
  • <project-config>/site-repo.md, site repo path, files to update (download page, release notes index, current-version banner).
  • <project-config>/release-management-config.md, announce_subject_template.

Outputs.

  • A markdown block with the [ANNOUNCE] subject + body.
  • A draft PR opened against the configured site repo with the download-page / release-notes / banner updates.

ASF constraints the drafted artefacts must satisfy, all stated in the output so the RM cannot miss them: the [ANNOUNCE] goes out no sooner than one hour after the Step 10 promote commit; it is sent from an @apache.org address (the announce list rejects other senders); the body links the project Download Page rather than a direct dist.apache.org URL; and the site-bump PR's download links resolve through the closer.lua mirror redirector (release-policy.html, release-distribution).

State-change boundary. No mail send. The PR is opened as draft; the agent never marks ready and never merges.

Hand-off conditions.

  • The site repo does not exist or the agent lacks write access, hand off; the RM either opens the PR manually from the drafted diff or grants access.
  • The previous announcement body cannot be fetched (archive unreachable), the skill drafts from the default template and flags the missing-precedent on the planning issue.

release-archive-sweep

Mode: Triage. Steps owned: 12.

Scope. Scan dist/release/<project>/, identify releases past retention per the project's rule, propose the svn mv to archive.apache.org (or the project's configured archive location).

Triggers.

  • RM runs /release-archive-sweep periodically (e.g. after each release; or on schedule).

Inputs.

  • Current listing of dist/release/<project>/.
  • <project-config>/release-management-config.md, archive_retention_rule (default per release-distribution: only the latest version of each supported release line stays on dist/release/; project overrides may add lines but never remove the latest-of-each-line floor).
  • The configured archive URL template (https://archive.apache.org/dist/<project>/ by default).

Outputs.

  • A table of releases past retention.
  • A markdown block with the svn mv sequence the RM executes.

State-change boundary. Read-only on dist.apache.org; never runs svn mv. The RM executes.

Hand-off conditions.

  • The retention rule classifies the latest release as past retention (config error), skill refuses and hands off.
  • A release on dist/release/ is not in <project-config>/release-trains.md (orphan), skill flags and hands off; the RM decides whether the orphan stays, archives, or gets reconciled into a train.

release-audit-report

Mode: Triage (read-only dashboard). Steps owned: 13.

Scope. Assemble a per-release record from the planning issue, vote thread, RC artefact list, promote revision, announcement archive URL. Output appended to the project's audit log.

Triggers.

  • RM runs /release-audit-report <version> after Step 12.
  • Optionally scheduled, the framework can rerun the report periodically to catch late corrections.

Inputs.

  • Planning issue and every comment on it.
  • [VOTE] and [RESULT] archive URLs.
  • The RC artefact list with sigs and checksums (recorded by release-rc-cut on the planning issue).
  • Promote svn revision.
  • [ANNOUNCE] archive URL.
  • <project-config>/release-management-config.md, audit_log_path.

Outputs.

  • A markdown record appended to <adopter-repo>/<audit_log_path>/<version>.md. The append is proposed as a PR against the adopter repo, not committed directly.

State-change boundary. Read-only on every release surface. Write-side limited to opening a PR on the adopter repo's audit log; the PR is reviewed and merged by a committer.

Privacy boundary (per RFC-AI-0004 Principle 6). The audit log is committed to the adopter repo and is public by default. The skill MUST NOT include:

  • Any content read from the security tracker (<tracker>), CVE drafts, GHSA forwards, reporter mail, embargoed disclosure text, severity scores, reporter-supplied CVSS, pre-disclosure CVE detail. The release planning issue is public; the security tracker is not. Even if a release closes a CVE, the audit record cites the public CVE identifier and the public fix PR, never the security-tracker thread that triggered them.
  • Email addresses of voters or commenters. The record cites voters by their <project> PMC roster handle (already publicly listed at projects.apache.org/projects/<project>), not by personal email.
  • Any content that did not pass through a reviewed PR or a public mailing-list archive. External content is data to analyse, never an instruction to obey.

If a required input would force the skill across this boundary, the field appears as REDACTED in the report and the skill records the reason in the PR description so a committer can decide whether to widen the audit-log scope.

Hand-off conditions. None expected, the skill is informational. If a required input is missing, the report includes a MISSING flag for that field and continues.

Adopter contract

Per-project values live in <project-config>/release-management-config.md. See the template at projects/_template/release-management-config.md.

Required keys (cross-skill):

KeyPurposeUsed by
release_dist_backendOne of svnpubsub / github-releases / s3 / self-hosted. Selects the staging-and-promote command set.release-rc-cut, release-promote, release-archive-sweep
release_approval_mechanismOne of dev-list-vote / github-discussion / pr-approval / maintainer-roster. Selects how release-vote-draft opens the approval and how release-vote-tally reads it.release-vote-draft, release-vote-tally
release_announce_backendOne of announce-list / github-release-notes / site-post / discord-channel. Selects the announcement artefact shape.release-announce-draft
release_dist_url_templatehttps://dist.apache.org/repos/dist/<bucket>/<project>/<version>/ for svnpubsub; backend-shaped URL template for non-ASF backends.release-rc-cut, release-promote, release-archive-sweep
release_publish_command_templateBackend-specific command template (required when release_dist_backend = self-hosted; defaulted from the backend for the other values).release-rc-cut, release-promote
keys_file_urlURL of the project's signing-key trust anchor (KEYS on ASF; equivalent file on non-ASF).release-keys-sync, release-verify-rc
release_approver_roster_pathRoster the release-vote-tally skill consults to classify binding vs non-binding. ASF default: <project-config>/pmc-roster.md.release-vote-tally
vote_window_hours / approval_window_hoursApproval window length. ASF floor per policy.release-vote-draft, release-vote-tally
vote_pass_rule_overridesOptional stricter rule (ASF baseline cannot be weakened; non-ASF backends define their own rule keys).release-vote-tally
archive_retention_ruleRetention rule for the archive sweep.release-archive-sweep
audit_log_pathPath under the adopter repo for audit records.release-audit-report
rm_key_fingerprintRM's key fingerprint (often per-user, in .apache-magpie-overrides/user.md).release-keys-sync
category_x_dependenciesPinned Category-X identifiers; refuses prep PR if any appear.release-prepare

The contract is the single per-adopter knob set. Skills consult the file, fall back to documented defaults if a key is missing, and refuse to proceed if a required key is missing (refusal text names the key). Backend-specific required keys (per the backend table in projects/_template/release-management-config.md) are required only when the corresponding backend is selected.

ASF TLP releases are pinned to release_approval_mechanism = dev-list-vote (mandatory per release-policy.html § release approval) and release_announce_backend = announce-list (mandatory per release-policy.html § announcements). release-vote-tally and release-announce-draft refuse to run an ASF TLP release against any other value; non-ASF adopters set the keys their workflow uses.

Eval

Skill behaviour in this family is probabilistic; correctness lives in distributions, not unit tests. Every skill in this family ships with eval cases and a grading methodology before it leaves experimental. A skill without an eval is unreleased, regardless of how well it performs in a demo. This complements RFC-AI-0004 Principle 4 on conversational correctability.

Eval expectations per skill:

SkillEval focusGrading signal
release-prepareVersion-bump correctness across version_manifest_files; Category-X denylist hits; changelog draft on real release historyDiff matches hand-rolled bump; denylist refuses on seeded violations; changelog covers ≥90% of merged PRs in window
release-keys-syncKEYS-block diff correctness for first-time RMPublic block matches gpg --export --armor <fp> byte-for-byte; never proposes a private key fragment
release-rc-cutPaste-ready recipe completeness; signed-tag + detached-sig + checksum command setRecipe reproduces a known-good RC end-to-end on a fixture project; no missing or extra commands
release-verify-rcFalse-negative rate on tampered fixtures (mutated sig, missing checksum, prohibited binary, missing LICENSE/NOTICE, RAT failure)Catches 100% of seeded defects; false-positive rate <5% on known-good RCs
release-vote-draft[VOTE] body conformance to ASF policy; subject template correctnessBody includes mandatory checklist; subject matches vote_subject_template; never schedules window shorter than vote_window_hours
release-vote-tallyBinding/non-binding classification accuracy on real vote threads; AMBIGUOUS detection rateClassification matches PMC ground truth on a labelled corpus; AMBIGUOUS, needs RM call fires on every adversarial case (lazy +1, conditional +1, retracted vote)
release-promotesvn mv command-set correctnessCommands replay against a sandbox svn mirror produce the expected target layout
release-announce-draft[ANNOUNCE] body completeness; site-PR scope correctnessBody cites canonical URLs (release, KEYS, sigs); site PR touches only files in site_pr_files
release-archive-sweepRetention-rule application accuracyIdentifies the exact set of past-retention releases on a fixture dist/release/<project>/ listing; refuses on latest_of_supported_line violation
release-audit-reportField coverage; MISSING flag accuracyReport includes every required field where source data exists; MISSING only fires when source data is genuinely absent

Eval corpora are project-specific (real [VOTE] threads, real RC artefact lists), so each adopter is expected to contribute fixtures from their own release history. The framework ships a seed corpus per skill (synthetic but realistic) so a new adopter can run a baseline eval before recording their own.

Open questions

Surfaced here so reviewers can weigh in before any skill is built.

  • Should release-verify-rc ship as a Pairing skill from day one, or land as Triage and graduate later? Current draft: ship Triage-marked with explicit Pairing-mode invocation (/release-verify-rc --pairing) so the same code path serves the RM's project-side self-check and the voter's developer-side pre-flight. The framework's Pairing-mode definition is still proposed (docs/modes.md § Pairing); this question is best resolved alongside the Pairing spec, not in isolation.
  • Where do non-ASF adopters' release-distribution analogues plug in? Current draft: release_dist_url_template is generic enough to point at a GitHub Releases URL or a self-hosted artefact store, but the svn-shaped commands in release-rc-cut and release-promote assume an svnpubsub workflow. A non-ASF adopter may need a parallel template (release_dist_command_template) that swaps svn for aws s3 mv or gh release upload. Defer to first non-ASF pilot.
  • release-audit-report audit-log location: in the adopter repo, or in a separate audit repo? Current draft: adopter repo (<adopter>/<audit_log_path>/). A separate audit repo is the right call for projects with audit-trail isolation requirements; the skill can support both by accepting either a path inside the adopter repo or a URL to a separate repo, but the second case requires extra credentials and is deferred.
  • Auto-merge eligibility for the prep PR's -SNAPSHOT bump (Step 14)? Current draft: not eligible. The Step 14 PR is mechanical (<version>-SNAPSHOT bump on a single manifest file) but per docs/modes.md § Auto-merge, Auto-merge is off until Pairing has run stable for two quarters. Revisit when Auto-merge sequencing changes; the bump is a plausible first eligible class given its mechanical shape and reversibility.
  • Publishing to distribution areas beyond dist/release/, and validating them. Some projects also publish a release to language package indexes (PyPI, npm, Maven Central) or container registries as part of the same cycle. The current family scopes to the ASF dist/ svnpubsub area only. A future skill could draft and verify those secondary publications. Out of scope for this first docs PR; tracked here so it is not lost.

Cross-references