Skip to main content

warp-release-notes

Use when drafting GitHub release notes for a Warp feature or bugfix release from Towncrier fragments or a tagged final changelog.

Source facts

Repository
NVIDIA/warp
Last source activity
September 10, 2026 at 19:40
Detected SKILL.md language
English
Stars
7,255
Forks
674

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
7 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
warp-release-notes
description
Use when drafting GitHub release notes for a Warp feature or bugfix release from Towncrier fragments or a tagged final changelog.
license
Apache-2.0
# Release Notes Draft Generates a markdown draft of the impending Warp release's GitHub release notes, written in GitHub Flavored Markdown. Auto-detects feature vs bugfix release from the version, picks the correct prior tag for diffing, and produces a digestible user-facing summary that the release manager edits and posts to the release page. **Output:** a single markdown report, filed according to the destination chosen in Phase 1: - **Secret gist** (default when `gh` is available and authenticated): stable filename `warp-<version-string>-release-notes.md`, stable description `Warp <version-string> Release Notes Draft`. Later runs against the same version revise the same gist in place; prior versions are preserved in the gist's git history. - **Local markdown file** (fallback when `gh` unavailable, or opt-in when `gh` available): dated path at `$(pwd)/warp-<version-string>-release-notes-<YYYY-MM-DD>.md`. Not auto-committed; the user reviews, edits, and copy-pastes into the GitHub release form. **Inputs:** the positional argument is a branch name (resolved as `upstream/<name>` → `origin/<name>` → local), a tag (e.g. `v1.13.0`), or omitted (defaults to `HEAD`). Version string comes from `VERSION.md` at the resolved head, or parsed from the tag name. ## Phase 1 — Resolve target and previous release 1. **Resolve the head ref.** With no argument, head = `HEAD`. With an argument, try in order: `upstream/<arg>`, `origin/<arg>`, `<arg>` (local branch or tag). Use the first that resolves via `git rev-parse --verify <candidate>`. Record both the symbolic ref and the resolved SHA. If nothing resolves, abort with the candidate list shown. 2. **Read the version string.** If the argument was a tag matching `v<X>.<Y>.<Z>...`, parse the version directly from the tag (strip the leading `v`). Otherwise read `VERSION.md` at the head: ```bash git show <head-ref>:VERSION.md ``` Strip whitespace; this is the raw version string (e.g. `1.13.0rc3`, `1.13.0`, `1.13.1`). 3. **Parse `(major, minor, patch)`** from the leading numeric portion; discard pre-release suffixes (`rc1`, `dev0`, `.post1`). Release notes are written for the eventual release, so `1.13.0rc3` becomes target version `1.13.0`. 4. **Classify release type.** `patch == 0` → **feature release** (full notes); `patch > 0` → **bugfix release** (slim notes). 5. **Determine the previous release tag** (the diff base) using integer math on the parsed tuple: - **Feature release (`X.Y.0`):** highest `vX.<Y-1>.*` tag. If `minor == 0`, fall back to highest `v<X-1>.*`. ```bash git tag --list 'v<major>.<minor-1>.*' --sort=-v:refname ``` - **Bugfix release (`X.Y.Z`, `Z > 0`):** highest `vX.Y.<Z'>` where `Z' < Z`. Enumerate and filter: ```bash git tag --list 'v<major>.<minor>.*' --sort=-v:refname ``` 6. **Probe the head for an existing tag.** If `git tag --points-at <head-ref>` returns a tag matching the target version (e.g. `v1.13.0`), the tag exists but the GitHub release isn't published yet. Note this in the confirmation message; CHANGELOG URLs can use the tag. 7. **Count commits in the range** using the **same cherry-pick-filtered range the contributor helper uses** (so the scope shown to the user matches the work that will be analyzed): ```bash git log --no-merges --oneline --cherry-pick --right-only <prev-tag>...<head-ref> | wc -l ``` Note the `...` (symmetric difference) and `--cherry-pick --right-only` flags: these drop commits whose patch-id has an equivalent on the prior release. This matters when the previous tag is on a bugfix branch rather than an ancestor of the head — without filtering, the proposal can overstate scope by hundreds of commits, and the user confirms a misleading count. If zero after filtering, abort. 8. **Probe `gh` and look up matching gists.** Run `gh --version && gh auth status`. If either fails, force destination to `local` and skip the rest. Otherwise run `gh gist list --limit 1000` and filter rows whose description exactly matches `Warp <version-string> Release Notes Draft`. Record the matching gist IDs and count (0, 1, N ≥ 2) for Phase 2. Display URLs are `https://gist.github.com/<id>`. ## Phase 2 — Confirm scope and destination with user Print a single proposal block and **wait for explicit user confirmation**. Mandatory pause; do not proceed to Phase 3 until the user replies. Lead with the scope line: > Drafting **<feature|bugfix>** release notes for Warp **<version-string>**. > - Head: `<head-ref>` @ `<short-sha>` <(tag `<tag>` exists at this SHA)> > - Previous release: `<prev-tag>` @ `<short-sha>` > - Commits in range: `<N>` Append the output block matching the current `gh` / match state: **`gh` unavailable:** > Output: local markdown file at `<cwd>/warp-<version-string>-release-notes-<today>.md` (`gh` not available). Confirm, or specify different refs? **`gh` available, 0 matches:** > Output: (a) new secret gist [default], (b) local markdown file in cwd. Confirm refs + pick. **`gh` available, 1 match:** > Output: (a) revise existing gist `<url>` [default], (b) new secret gist, (c) local markdown file in cwd. Confirm refs + pick. **`gh` available, N matches (N ≥ 2):** > Multiple existing gists share the stable title: > 1. `<url-1>` — updated `<time-1>` > 2. `<url-2>` — updated `<time-2>` > ... > > Output: (a) revise gist by number, (b) new secret gist, (c) local markdown file in cwd. Confirm refs + pick. Translate the reply into one destination token (`local`, `new-gist`, `revise-gist:<id>`). Letters `(a)`/`(b)`/`(c)` are positional within the prompt shown; for the N-match branch a numeric reply (e.g. "revise 2") selects from the listed gists. New refs in the reply re-run Phase 1. ## Phase 3 — Gather inputs ### 3a — Current release view Read `changelog/README.md` and enumerate fragments from the selected ref, not the caller's working tree: ```bash git show <head-ref>:changelog/README.md git ls-tree -r --name-only <head-ref> -- changelog ``` Exclude `changelog/README.md`. Record every fragment's path, identifier, category, optional counter, and full content. Choose one authoritative current-release view: - If Phase 1 found a matching target tag at `<head-ref>`, extract the exact `## [<target-version>]` section from that tag's `CHANGELOG.md`. Its ordering is final and authoritative; do not rebuild, sort, or rewrite it. - Otherwise render the selected ref's fragments with pinned Towncrier in a temporary detached worktree: ```bash notes_worktree=$(mktemp -d) git worktree add --detach "$notes_worktree" <head-ref> trap 'git worktree remove --force "$notes_worktree" 2>/dev/null || true' EXIT draft_status=0 (cd "$notes_worktree" && uvx --from towncrier==25.8.0 towncrier build \ --draft --version <target-version> --date "$(date +%F)") || draft_status=$? git worktree remove --force "$notes_worktree" trap - EXIT test "$draft_status" -eq 0 ``` Extract only `## [<target-version>]` from the draft. Do not fall back to a released section in `CHANGELOG.md` when fragments are absent. Collect bullets per subsection (`### Added`, `### Removed`, `### Deprecated`, `### Changed`, `### Fixed`, `### Documentation`). For each bullet, capture full raw text, section, GH refs, source fragment paths when available, experimental flag, and breaking flag. Read `<head-ref>:CHANGELOG.md` separately for prior release history, including deprecation lookups; it is not the pending source. ### 3b — Commit list and contributor attribution Resolve `<skill-dir>` to the directory containing the currently loaded `SKILL.md` for this skill (for example, `<repo>/.claude/skills/warp-release-notes` or `<repo>/.codex/skills/warp-release-notes`). Do not hardcode `.claude` or `.codex`; the skill content must work from either tree. Build a temporary changelog view for contributor attribution. For a tagged release, use the tag's complete `CHANGELOG.md`. Before tagging, prepend the rendered target section from 3a to the historical `CHANGELOG.md` at `<head-ref>`: ```bash # Tagged release: git show <target-tag>:CHANGELOG.md > /tmp/warp-<version-string>-changelog.md # Untagged release (rendered_release_section was captured in 3a): { printf '%s\n\n' "$rendered_release_section"; \ git show <head-ref>:CHANGELOG.md; \ } > /tmp/warp-<version-string>-changelog.md uv run "<skill-dir>/scripts/list_contributors.py" \ --base <prev-tag> \ --head <head-ref> \ --changelog /tmp/warp-<version-string>-changelog.md \ --target-version <target-version> ``` Delete `/tmp/warp-<version-string>-changelog.md` after the script returns. The script emits `commits[]` with GH refs from messages, numeric fragment filenames, and legacy `CHANGELOG.md` additions. It emits `contributors[]` with `commit_count`, `gh_login`, `classification`, `pr_summary`, `changelog_sections`, `already_shipped`, `prior_commit_count`, `is_first_time_contributor`, and `nvidia_low_commit_count`. See `references/contributor-attribution.md` for definitions and thresholds. Two robustness filters run by default: a cherry-pick filter (drops commits whose patch-id appears in `<prev-tag>`, common when fixes land on bugfix branches before main) and CHANGELOG-section attribution (sets `already_shipped`). See `references/contributor-attribution.md` for the rationale. Capture the JSON. Phase 5d auto-renders only `classification == "external"` AND `already_shipped == False` contributors; the `nvidia_low_commit_count` and `is_first_time_contributor` flags surface candidates for manual decision in the Phase 6 chat summary, not in the rendered Acknowledgments section. ### 3c — Past-release calibration (optional) For tone calibration, fetch one recent release body of matching type via `gh release view <tag> --repo NVIDIA/warp --json body --jq .body`. Mirror structure and register; do not copy content. ## Phase 4 — Plan grouping and inspect implementations (feature releases only) Bugfix releases skip Phase 4 and proceed to Phase 5 (include a one-sentence intro in Phase 5a). Read `references/style-rules.md`, `references/feature-investigation.md`, and `references/feature-release-template.md` before writing. 1. **Identify the lead feature** — the single most exciting capability in the release. Gets its own `### …` block at the top of `## New features` with a code example. Prefer items that unlock previously-impossible workflows (new artifact, file format, cross-language boundary) over new parameters. Honor the lead the user named at invocation. 2. **Plan theme groups.** Bucket remaining `### Added` / `### Changed` entries into 3–6 themes that reflect what users *do* with the features. Common shapes: "Tile programming enhancements", "JAX integration", "`warp.fem` enhancements", "Compilation and tooling", "Performance improvements", "Language enhancements", "New examples". 3. **Order by impact.** Lead feature first, then themes by user-facing impact. `## Bug fixes` near the end, omitted if no fix warrants a highlight. 4. **Tag experimental items.** Any bullet flagged `**Experimental**` in 3a gets a `> [!IMPORTANT]` admonition under its `### …` heading. 5. **Inspect implementations for caveats, artifacts, and in-tree examples.** Apply the protocol in `references/feature-investigation.md` to the lead feature and to every `### …` block you plan to write. The protocol surfaces (a) "not yet supported" / TODO limits buried in the implementation, (b) on-disk or wire artifacts beyond the obvious file (sidecar directories, compute-arch pinning, version metadata), (c) existing in-tree examples worth linking (`warp/examples/**`, `warp/tests/**`), and (d) cross-language requirements (any feature crossing Python ↔ C++ ↔ JAX needs a snippet on each side, not just Python). Skipping this step is the difference between "looks like a release announcement" and "lets me start using the feature." ## Phase 5 — Draft sections ### 5a — Intro paragraph Open the body with a 2-3 sentence paragraph that names the shape of the release. Lead with the unlock, not API names. Feature-release intros name the lead feature first, then 1-2 supporting themes. Bugfix-release intros are one sentence: `Warp v<version> is a bugfix release following v<prev>.` plus a changelog pointer. ### 5b — Sections Fill in `references/feature-release-template.md` (feature release) or `references/bugfix-release-template.md` (bugfix release). Both templates carry per-section instructions inline. **Code examples are the default**: every `### …` block describing a new public API or behavioral change ships with a runnable Python snippet unless the change is a single-parameter tidy-up. Snippets must NOT call `wp.init()` (Warp initializes implicitly). Breaking changes in `## Bug fixes` or `## Changes` ship with **before/after** snippets, not prose. When a snippet has a `print(...)`, run it via `uv run /tmp/release_notes_example_<name>.py` and embed the **real** captured output. Render single-line output as a trailing `# comment`; render multi-line or structured output as a separate fenced ```text block following the Python block (see `references/style-rules.md` "Rendering output"). Required when the output IS the feature (memory tracker, diagnostics, dtype promotion). Use `> [!NOTE]` / `> [!IMPORTANT]` / `> [!CAUTION]` admonitions, never ad-hoc `**Note:**` or quoted-bold forms. See `references/style-rules.md`. ### 5c — Announcements This section appears in both feature and bugfix release notes (deprecations carry forward across releases until they actually land). It announces **CHANGES** in this release: removals, deprecations, platform-support shifts, release-cadence shifts. It does NOT restate unchanged policy. If a sub-section has no actual change to announce in this release, drop the sub-section. If no sub-section applies, drop the entire `## Announcements` section. Pull from: 1. **Rendered current `### Removed`.** Each entry is a candidate `### Removals in this release` bullet. Apply the tone rules in `references/style-rules.md` "Tone for removals and deprecations": neutral migration step tied to the user's outcome, no scolding about prior deprecation warnings. 2. **Rendered current `### Deprecated`.** Each entry is a candidate `### Upcoming removals` bullet. Only state a specific removal version when a primary source commits to it (entry text, runtime `DeprecationWarning` emit string, docstring, design doc, or maintainer statement). Without a primary source, use the neutral framing "will be removed in a future feature release per the standard deprecation timeline." See `references/style-rules.md` "Forward-looking claims". 3. **CHANGELOG `### Deprecated` from previous releases** that explicitly named this release as the removal version. These deprecations have now landed; promote them under `### Removals in this release`.
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub