# Github Release

> Use when releasing this repository from the CLI by promoting develop to main with a fast-forward push, grading the release as patch/minor/major by what installed projects actually pay, computing the next version from the latest tag, and publishing a GitHub release with agent-written notes. No release PR, no release-drafter.

- Skill: `0x0w1/github-release` (Agent Skill)
- Install (CLI): `npx skillmds@latest add 0x0w1/github-release`
- Raw SKILL.md: https://api.skillmd.com/api/skills/0x0w1/github-release/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: 0x0w1 (https://skillmd.com/u/0x0w1)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/0x0w1/github-release

---


# GitHub Release

Use this repository skill for release execution.

## Release Model

- A release promotes the current `origin/develop` to `main` with a fast-forward push: `git push origin develop:main`. There is no release PR and no `release/*` branch.
- `develop` must already contain every intended release change, squash-merged through `develop-task-flow`.
- The bump is graded against this project's version rubric, not against a rule inside this skill. See Version Rubric.
- The next version is computed from the latest `vX.Y.Z` tag using the graded bump type. See Version Format.
- The release tag and GitHub release are created from the CLI with `git tag` and `gh release create`.
- Release notes are written by the agent from the commits in `<previous tag>..<new tag>`, categorized by conventional commit prefix.

## GitHub Profile

Before any `gh` command, resolve the host from `JIG_GITHUB_HOST`, local `jig.githubHost`, then `github.com`, and resolve the profile from `JIG_GITHUB_PROFILE`, then local `jig.githubProfile`. If a profile is configured, read its credential with `gh auth token --hostname <host> --user <profile>` without printing it and run every `gh` command with that credential through `GH_TOKEN` (`github.com` or `*.ghe.com`) or `GH_ENTERPRISE_TOKEN` (other hosts). Verify `gh api user --jq .login` matches the profile. Do not use `gh auth switch`; fall back to the globally active account only when neither the environment nor local config selects a profile.

## Version Rubric

The grading rubric is not in this skill. It is a project-owned file, so every project grades by its own axis. The `version-rubric` skill owns that file.

Resolve the rubric path in this order:

1. `JIG_VERSION_RUBRIC` environment variable (session-only override).
2. `git config --local --get jig.versionRubric` (repository override).
3. `.jig/versioning.md` (the convention).

Apply it like this:

- Grade with the rubric's `## Decision Order`: ask its questions in order and **stop at the first match**. That ordering is fixed; a rubric cannot change it.
- Check the graded bump against the rubric's `## Grade Definitions` before computing the version, and quote the deciding question in the report.
- Apply `## Hard Rules` after the ordered questions. A rubric without that section has no escalation rule.
- A missing optional section (`## Hard Rules`, `## Interface Paths`, `## Release Notes`, `## Version Format`, `## Pre-Release Checks`) means that rule does not apply.
- Rubrics written before the contract switched to English carry Korean titles, and they stay valid. Accept either spelling for every section: `## 판정 순서`, `## 등급 정의`, `## 강경 규칙`, `## 인터페이스 경로`, `## 릴리즈 노트`, `## 버전 형식`, `## 릴리즈 전 검증`, and `> 기준:` for `> Basis:`. Read the file as it is; never retitle it during a release.
- Read sections beyond the contract as grading context; a project may list what counts as its public interface there.
- Report the rubric path, its source, and whether it records the adopted default or a project-specific rubric.
- Never edit the rubric file from this skill.

### Recorded Task Grades

`develop-task-flow` grades each task as it is squash-merged and records the verdict as a `Release-Grade` trailer. Read those first: they were decided with the diff in hand, which this step no longer has.

```bash
git log <previous>..HEAD --no-merges --format='%h %(trailers:key=Release-Grade,valueonly)'
```

- The release floor is the highest grade recorded in the range, ordered `patch` < `minor` < `major`. Name the commit that set it in the report.
- Grade any commit with no trailer from its subject and body, then fold that verdict into the floor. A range with no trailers at all grades exactly as it did before.
- The floor is a starting point, not the verdict. Apply the rubric once more to the range as a whole: a combination of tasks can cost more than any one of them did alone, and `## Hard Rules` still runs against the composed notes in step 6.
- Never settle the release below the floor. Raising it is a normal outcome; lowering it discards evidence that is no longer available.

### Interface Path Floor

When the rubric has an `## Interface Paths` table, compute a second floor from the changed paths:

```bash
git diff --name-only <previous>..HEAD
```

- Each changed path takes the floor of the **first row it matches**; rows are read top to bottom. The path floor is the highest floor any changed path took. A path matching no row contributes nothing.
- Report the floor and the path that set it, so the reader can see which interface the range touched.
- **This floor is advisory, unlike a recorded task grade.** Paths say what changed, never how. Releasing below it is allowed and must state the reason in the report — for example, that the only change under a public path was a comment. Releasing above it needs no justification.
- A rubric with no such table skips this step entirely; do not invent globs for a project that did not write any.

When the rubric is missing or unusable:

- **Missing file**: run the `version-rubric` skill to settle it, then continue the release. Do not stop the release for this.
- **`version-rubric` not installed**: grade with the fallback below, say so in the report, and continue.
- **Contract broken** (neither spelling of the decision-order or grade-definition section is present, or fewer than three ordered questions): stop and point at `version-rubric`. Grading with a broken rubric silently is worse than stopping.

The fallback rubric, used only in the two cases above. It matches the default `version-rubric` writes, so a project grades the same whether or not that skill is installed:

1. Is this a fix inside what the project already does? → `patch`
2. Can people do something new, or did a generation turn over, while everything they already do keeps working? → `minor`
3. Did the value on offer widen, shrink, or change, or must a human step in to keep using it? → `major`

With these escalation rules, applied after the ordered questions:

> A change that raises no error but behaves differently is `major`. Its size does not matter.

> A skill or prompt instruction that changes when the agent speaks is at least `minor`.

## Version Format

Defaults, each overridable by the rubric's `## Version Format` section:

- The version must match `^v[0-9]+\.[0-9]+\.[0-9]+$`.
- `patch`: `vX.Y.Z` → `vX.Y.(Z+1)`; `minor`: → `vX.(Y+1).0`; `major`: → `v(X+1).0.0`.
- While the major version is `0`, a `major` grade raises the minor position instead: `v0.Y.Z` → `v0.(Y+1).0`. Grade exactly as after 1.0 and state the verdict in the report, so the rule is exercised before it becomes binding.
- An explicit `vX.Y.Z` from the user overrides the computed version.

## Release Notes

- `## Changes`, then one section per commit type present in the range, each only when it has items, separated by horizontal rules.
- Section titles derive from the commit prefix: `feat` → `### 🚀 Enhancements`, `fix` → `### 🐛 Fixes`, `chore` → `### 🧰 Chores`. Any other prefix becomes its own section named after it (`docs:` → `### 📚 Documentation`). Never fold an unlisted prefix into chores.
- The rubric's `## Release Notes` section overrides section order and titles.
- One `- <commit subject without type prefix>` line per commit.
- `### Summary`: user-perspective bullet items written from the commit subjects and bodies, release-note ready, with technical terms in backticks. Write them in the language the repository already uses for its release notes and commit bodies, defaulting to English.
- The `Release-Grade` trailer is grading input, not prose. Keep it out of every note section.
- `### Migration`: only when downstream projects must take action that re-running an update does not cover.

## Migration Blocks

The `### Migration` section is not prose. It is the input an updating agent executes, so it is written as marker-delimited blocks:

```md
### Migration

<!-- jig:start migration-auto -->
- `rm -f .github/workflows/drafter.yaml`
- Move `.agents/skills/github-sync/` to `.agents/skills/jig-github-sync/` when it exists
<!-- jig:end migration-auto -->

<!-- jig:start migration-manual -->
- Decide whether `develop` keeps its required status checks; jig no longer sets them.
<!-- jig:end migration-manual -->
```

- `migration-auto`: mechanical steps an agent finishes unattended. Every item must be **idempotent** and be either a single command or an unambiguous file operation. A target that is already absent counts as done.
- `migration-manual`: steps needing a human judgement, a choice, or an irreversible action. `jig-update` presents these and does not run them without approval.
- When in doubt, an item is `manual`. Either block may be omitted; omit the whole section when neither applies.
- **A marker counts only when it is the entire line**, matching `^<!-- jig:(start|end) migration-(auto|manual) -->$`. Release notes routinely name these markers in prose, so a mention inside backticks or mid-sentence is text, not a marker. Keep marker lines flush left with nothing else on them, and always close a block with its matching end marker.
- A rubric may key an escalation rule off these blocks; jig's own rubric grades any `migration-manual` block as `major`. When applying such a rule, count line-anchored markers only.

## Safety Rules

- Do not force push.
- Do not bypass git hooks: never pass `--no-verify` to `git push`.
- If `git push origin develop:main` would not fast-forward, stop and report that `main` has commits `develop` lacks; never resolve this by force-pushing. The usual cause is a hotfix that landed on `main` without returning to `develop` — `hotfix-flow` step 8 restores the invariant with `git merge main` into `develop`.
- Do not release while the worktree has uncommitted changes to tracked files.
- Do not create a tag that already exists locally or on `origin`.
- Do not release while local `develop` differs from `origin/develop`.
- Do not delete branches.
- The release must only promote already-merged `develop` state; complete pending work through `develop-task-flow` first.
- Show the release note draft to the user before publishing, unless the user already asked for the release to be executed end to end.
- Preserve unrelated user changes.

## Develop-First Gate

- If the release request includes unfinished implementation, config, docs, generated `dist`, or workflow changes, stop release execution.
- Complete those changes first with `develop-task-flow`: create a `feature/*`, `fix/*`, or `chore/*` branch from `origin/develop`, squash-merge it into `develop`, and push `develop`.
- Resume release only after `origin/develop` contains every intended change.
- If the user has not explicitly asked to release, stop after `develop` is pushed.

## Release Procedure

1. Inspect state:
   - `git status --short --branch`
   - `git fetch origin --prune`
   - verify local `develop` matches `origin/develop`
2. Determine the previous version: latest `vX.Y.Z` tag reachable from `origin/main` (`git describe --tags --abbrev=0 origin/main`).
3. Resolve and read the version rubric, then grade the release against it before computing anything. Start from the grades recorded by `develop-task-flow` per Recorded Task Grades, read the subjects and bodies of any commit that carries none, compute the path floor per Interface Path Floor when the rubric has that table, and review both floors against the rubric for the range as a whole. Handle a missing, uninstalled, or broken rubric per Version Rubric.
   - If the graded bump is higher than the one the user requested, say so with the specific reason and ask before continuing. The user's choice wins if they repeat it; record the graded verdict in the report either way.
   - If the graded bump is lower, use the requested one; a user may always release higher than required.
4. Verify `origin/develop` already contains every intended release change. If not, stop and run the Develop-First Gate.
5. Compose the release notes from `git log <previous>..HEAD --no-merges` per Release Notes. Do this **before** promoting or tagging, because the notes can still change the version.
6. Re-check the bump against the composed notes when the rubric has a `## Hard Rules` section that keys off them, counting **line-anchored markers only** (`grep -cE '^<!-- jig:start migration-manual -->$'`; a bare substring search also matches prose that names the marker):
   - an opened block with no matching end marker is a defect; fix the notes before publishing
   - if the rule raises the grade from step 3, go back to step 3 and resolve it with the user. Never weaken the notes to fit a version.
7. Compute the new version from the settled bump type per Version Format, or validate the explicit version. It must not exist as a tag or release.
8. Run the repository's pre-release validation: the commands in the rubric's `## Pre-Release Checks` section when present, otherwise the validation or test command the repository already uses. Skip and report when there is none.
9. Promote: `git push origin develop:main`. This must fast-forward; if rejected, stop and report.
10. Tag the released commit: `git tag <version> <develop sha>` then `git push origin <version>`.
11. Publish: `gh release create <version> --title "<version> 🌈" --notes-file <draft file>`.
12. Verify the release and tag exist (`gh release view <version>`).

## Final Report

Keep reports short and include:

- Current repo and branch
- Previous and new version
- Rubric path, source, and kind (adopted default or project-specific)
- Recorded task-grade floor and the commit that set it, or that the range carried no trailers
- Interface path floor and the path that set it, or that the rubric has no `## Interface Paths` table; when the release lands below it, the reason
- Graded bump versus the requested bump, with the rubric question that decided it
- `develop` to `main` promotion result
- Tag and release status
- Release note summary
- Commands that could not run and why
- User next actions, if any

