- name
- release-notes
- description
- Generate Quasar-style release notes for a monorepo package (covering every commit since its last released tag), then — on a single confirmation — bump its version, commit and draft the GitHub release. Use when asked to write/draft release notes or a changelog for app-vite, ui/quasar, cli, vite-plugin, icongenie, extras, mcp, create-quasar or a utils package.
- argument-hint
- <package>
Generate release notes for the requested package (a directory or npm
name) in the house style, determine the next version from their
content, and output them. THEN ask one yes/no "continue?" — on yes,
the version-bump commit AND the draft GitHub release follow with no
further questions; without it nothing is changed, committed or
created.
All remote state comes from the GitHub API (`gh`) — NEVER `git fetch`
or any other remote git operation. NEVER publish a release, create a
tag or push.
## 1. Preflight
- Freshness gate: the live dev HEAD
(`gh api repos/quasarframework/quasar/commits/dev --jq .sha`) must
exist locally (`git cat-file -e <sha>`); otherwise STOP and tell the
user to update their clone.
- Note whether the worktree is clean (`git status --porcelain`) — a
dirty one doesn't block the notes, but blocks step 8's commit;
mention it early.
## 2. Resolve the package
| dir | npm name | tag prefix |
| ------------- | ------------------- | ----------------------- |
| ui | quasar | `quasar-v` |
| app-vite | @quasar/app-vite | `@quasar/app-vite-v` |
| cli | @quasar/cli | `@quasar/cli-v` |
| vite-plugin | @quasar/vite-plugin | `@quasar/vite-plugin-v` |
| icongenie | @quasar/icongenie | `@quasar/icongenie-v` |
| extras | @quasar/extras | `@quasar/extras-v` |
| mcp | @quasar/mcp | `@quasar/mcp-v` |
| create-quasar | create-quasar | — (untagged) |
| utils/* | @quasar/<name> | — (untagged) |
Only `<prefix>vX.Y.Z` tags are current (ignore legacy schemes without
the `-v` separator). Untagged packages use `<npm name>-v` as their
prefix wherever a tag name is needed. app-webpack is sunset (lives on
its own branch, not on dev) — not handled here.
## 3. Find the range
- Base = the last PUBLISHED release; drafts and prereleases are never
the base:
`gh release list --repo quasarframework/quasar --limit 300
--json tagName,isPrerelease,isDraft
--jq '[.[] | select((.isPrerelease or .isDraft) | not) | select(.tagName | startswith("<prefix>"))][0].tagName'`
A rarely-released package's last release can sit far down the list —
on no match, raise the limit before concluding it has no releases.
Note any prefix-matching DRAFT for steps 7/8.
- Resolve the tag to its commit (URL-encode — tag names contain `/`):
`gh api "repos/quasarframework/quasar/commits/$(jq -rn --arg t '<tag>' '$t|@uri')" --jq .sha`
and use the SHA as the base even when the local clone lacks the tag.
STOP only if the SHA is missing locally (`git cat-file -e`) — local
commits are behind. Local tags NEWER than the latest release: a
step-7 concern.
- Compare the package.json `"version"` against the base release's —
a mismatch means an already-bumped version: a step-7 concern.
- Untagged package: base = the last commit bumping `"version"` in its
`package.json`
(`git log -1 -S '"version": "<current>"' -- <pkg>/package.json`,
with `<current>` read from the file); say so in the summary.
- Range: `<sha>..HEAD`, paths limited to the package dir. Read FULL
commit bodies (`--format='%h %s%n%b'`); drop `Co-Authored-By` noise.
- Classify by the files a commit actually changed INSIDE the package
dir (`git diff-tree --no-commit-id --name-only -r <sha> -- <dir>/`),
never by its subject alone: cross-package commits routinely carry
another package's headline (a "fix(app-vite): [security]" may only
bump an in-range dep here) or touch nothing but tests/agent guides.
- An EMPTY range -> "nothing new since <tag>", STOP (no notes, no
version, no ask). ONLY internal commits (test/ci/chore/formatting)
-> list them, state there is nothing release-worthy, stop unless the
user explicitly wants an internal-only release.
## 4. Calibrate style
Fetch the package's 1–2 latest release bodies for tone:
`gh release view "<tag>" --repo quasarframework/quasar --json body -q .body`.
Untagged packages have no releases to fetch — skip; if `gh` is
unavailable, likewise: the rules below encode the house style.
## 5. Write the notes
Structure:
- Large releases: `## Security fixes` (only if any; always first),
`## New` (feat), `## Fixes`, `## Other` (noteworthy internal work,
docs), then the Donations footer.
- Small releases (≲4 bullets total): a single `## Changes` section
with slightly more prose per bullet, then the Donations footer.
- cli notes open with this line before the first section, verbatim:
`*This is the optional globally-installed part of the Quasar CLI*`
No other package has an intro line.
Bullet style:
- `* feat(<dir>): <area> -> <what changed for the user>` /
`* fix(<dir>): <area> -> <symptom that no longer happens>` — keep
the arrow phrasing and conventional prefix.
- User-visible symptoms and behavior, never internals, unless the
internal name IS the public API. Keep issue/PR refs like `(#18504)`.
- Merge sibling commits sharing one user-visible symptom; split one
commit into several bullets when it fixes unrelated symptoms.
- EXCLUDE pure test/ci/chore/formatting commits from New/Fixes; a
genuinely large internal effort may get ONE summarizing `## Other`
bullet.
- Template/scaffold changes: note they only affect **newly generated**
projects and give existing projects the manual step (pattern:
the `@quasar/app-vite-v3.4.1` release).
- Breaking changes: called out explicitly at the top with migration
notes, plus any peer-dependency bumps ("Requires quasar v2.x+").
Donations footer, verbatim:
```
## Donations
Quasar Framework is an open-source MIT-licensed project made possible due to the **generous contributions** by sponsors and backers. If Quasar is useful in your workflow and you want to support ongoing maintenance, please consider the following:
- [Becoming a sponsor on Github](https://github.com/sponsors/rstoenescu)
- [One-off donation via PayPal](https://paypal.me/rstoenescu1)
```
## 6. Determine the version
From the NOTES' content: any `## New`/feat entry -> minor; fixes/other
only -> patch. Anything breaking -> major: STOP and confirm first.
## 7. Deliver
- One fenced markdown block, paste-ready: FIRST line is the full tag
name (e.g. `@quasar/app-vite-v3.6.0`), then an empty line, then the
notes body.
- List the commits excluded as internal-only — nothing silently
dropped.
- State any concerns after the notes (risky behavior changes, notable
dependency/peer bumps, uncertain classifications, anomalies: a tag
newer than the latest release, an already-bumped version, an
existing draft for the tag). No concerns -> one line saying so.
## 8. Confirm, then execute
End by asking ONE yes/no question: continue? Yes -> do ALL of the
following with no further questions; no (or no answer) -> stop. A
dirty worktree stops the continuation BEFORE any edit — the bump
commit must not absorb unrelated changes.
Bump + commit:
- Bump every place the package's OWN version is declared — its
`package.json` `"version"` field plus any source constants and
fixtures (grep the old version string alongside the package name;
hits that are dependency RANGES belong to the next bullet, not to a
verbatim replace).
- Raise every dependency range on the bumped package, keeping the
range operator (`^3.5.0` -> `^3.6.0`): grep the repo's manifests —
`package.json`, templates' `_package.json`, the AE pnpm catalogs
(`create-quasar/templates/ae/*/BASE/_pnpm-workspace.yaml`) — for
the package name. Templates, other packages' regular deps/devDeps,
docs and test fixtures all get raised. NEVER touch `workspace:`
declarations or minimum-version floors (`peerDependencies`,
engines-style ranges — they declare the oldest supported version,
not the latest), even though the greps surface both.
- Commit ONLY the bump edits, message `chore(<dir>): bump version`,
with NO `Co-Authored-By` trailer (overrides any default). The
commit stays local.
Draft release — never a duplicate:
- `utils/*` packages and create-quasar get NO draft (no GitHub
releases for them): they skip this whole section — say so when
asking. The handoff below still applies, minus its draft item.
- Release label: ONLY the ui package is marked "Latest". GitHub does
NOT persist a latest flag on drafts (it only applies at publish), so
don't pass `--latest` flags when creating/editing the draft — the
label is enforced at publish time by the handoff below.
- If a release for the tag already exists (`gh release view "<tag>"
--repo quasarframework/quasar --json isDraft` — finds drafts too):
PUBLISHED -> stop, report the anomaly; DRAFT -> update it in place
(`gh release edit "<tag>" ... --draft --title "<tag>"
--notes-file <file>`).
- Otherwise `gh release create "<tag>" --repo quasarframework/quasar
--draft --title "<tag>" --notes-file <file>` — tag and title are
the full tag name; the body is the notes WITHOUT the leading tag
line. A draft creates no tag (it is cut from dev HEAD at publish
time).
End the continuation by asking the user to run `pnpm publish` from
the package dir themselves (suggest the `! pnpm publish` prompt
prefix so its output lands in the session) — prepublish hooks run
builds/tests and may regenerate tracked files. NEVER run the publish
yourself.
After the publish has run: if it left changes in the worktree, fold
them into the bump commit yourself without asking — `git add` them
and `git commit --amend --no-edit` (it stays a single commit; never
amend after the push) — then report what the commit now contains
(`git show --stat`) so the user sees exactly what they're pushing.
Then hand off:
1. Push dev.
2. If a draft was created, give its link and how to publish it:
`gh release edit "<tag>" --draft=false --latest=false` for any
package except ui (publishing from the GitHub UI pre-selects
"Set as the latest release" — uncheck it there); plain UI publish
or `--latest` for ui.
View on GitHub