diff --git a/.agents/skills/qv-agent-stack-sync/SKILL.md b/.agents/skills/qv-agent-stack-sync/SKILL.md index 6e9702face..a63a3a69b3 100644 --- a/.agents/skills/qv-agent-stack-sync/SKILL.md +++ b/.agents/skills/qv-agent-stack-sync/SKILL.md @@ -90,7 +90,8 @@ Requires explicit user confirmation of the plan (versions + which packages). Then for each `needs_release` package in dependency order, follow [references/prepare-cascade.md](references/prepare-cascade.md): 1. Create org `release--` from `main` if missing. -2. Prep version bump + dep ranges + changelog (`qv-sdk-changelog --package=`) + NOTICE. +2. Prep version bump + dep ranges, then `qv-sdk-changelog --package=` + (follow that skill; do not call the generator as a shortcut) + NOTICE. 3. Open **draft** release PR → `release--`. 4. Open **draft** backmerge PR → `main` (`[skiplog]`, cherry-pick `-x`) in the same session. 5. Skip packages marked blocked; report them clearly. @@ -104,8 +105,16 @@ releases chain `qv-sdk-inference-version` + docs Step 8 from `qv-sdk-changelog`. 1. Confirm lower dependencies are on npm (`npm view`). 2. Fresh-install verification (below). -3. Mark the draft release PR ready for review (and keep backmerge draft until release merges, or ready it alongside — prefer ready both when release is ready to merge). -4. Remind: human merges; human triggers publish; then promote the next upper package. +3. Re-run NOTICE for this package so JS can resolve. If install still fails, + restore the JS block from `HEAD`. +4. Mark the draft release PR ready for review (and keep backmerge draft until + release merges, or ready it alongside — prefer ready both when release is + ready to merge). +5. Remind: human merges; human triggers publish; then promote the next upper + package. + +The `release--*` line is the cut. Do not cherry-pick later `main` onto it. +Backmerge keeps `main` in sync with the cut. ## File updates (when preparing releases) @@ -179,6 +188,8 @@ Always end with: - [ ] OpenClaw included in the cascade - [ ] `@qvac/inference` released ahead of an SDK release that moves major.minor - [ ] Draft release **and** draft backmerge opened together per package +- [ ] Release head is `chore/--changelog`, not `release-*` +- [ ] `qv-sdk-changelog` completed for each hop (published-tag audit included) - [ ] Blocked plugins (e.g. AI SDK mismatch) not force-released - [ ] No publish / workflow_dispatch for npm - [ ] Org-branch heads preferred (`tetherto/qvac`) diff --git a/.agents/skills/qv-agent-stack-sync/references/prepare-cascade.md b/.agents/skills/qv-agent-stack-sync/references/prepare-cascade.md index ceb5e91828..c2dc8db2b9 100644 --- a/.agents/skills/qv-agent-stack-sync/references/prepare-cascade.md +++ b/.agents/skills/qv-agent-stack-sync/references/prepare-cascade.md @@ -17,36 +17,37 @@ Reuse if it exists. Do not force-push. ### 2. Head + metadata ```bash -git checkout -b release/- ORG_REMOTE/release-- +git checkout -b chore/--changelog ORG_REMOTE/release-- ``` +Head must not start with `release-` (Merge Guard runs on the pushed ref). Full +naming: `qv-sdk-pr-create` → "Release PR branch naming". + 1. Bump `package.json` (and `openclaw.plugin.json` when present). 2. Apply planned dep / peer ranges. -3. Changelog + NOTICE: - -```bash -node scripts/sdk/generate-changelog-sdk-pod.cjs --package= -``` - -Author `CHANGELOG_LLM.md`, prettier-check, rebuild aggregate, announcement-post (gitignored), NOTICE. Path map: `scripts/sdk/package-paths.cjs`. - -4. `--package=sdk` only: `qv-sdk-inference-version` + docs Step 8 from `qv-sdk-changelog`. It - writes the range from a published engine version, so the `inference` release merges and - publishes before the SDK draft is promoted. +3. Follow `qv-sdk-changelog` for this `--package` (lockstep `--base-commit`, + published-tag audit, LLM, prettier, NOTICE). Do not call the generator as a + shortcut. +4. `--package=sdk` only: `qv-sdk-inference-version` + docs Step 8 from + `qv-sdk-changelog`. It writes the range from a published engine version, so + the `inference` release merges and publishes before the SDK draft is promoted. -Commit `chore[notask]: release @qvac/ ` (use `chore[bc|notask]:` when breaking). Push to `ORG_REMOTE`. +Commit `chore[notask]: release @qvac/ ` — no `[bc]` on the title. +Push to `ORG_REMOTE`. ### 3. Draft release PR ```bash gh pr create --repo tetherto/qvac --draft \ --base release-- \ - --head release/- \ + --head chore/--changelog \ --title "chore[notask]: release @qvac/ " \ --body "..." ``` -SDK pod template. Note future dep versions if lower npm is not live. Publish is human-gated. +SDK pod template. Body API / Models / Breaking copied from +`changelog//`. Note future dep versions if lower npm is not live. +Publish is human-gated. ### 4. Draft backmerge PR diff --git a/.agents/skills/qv-notice-generate/SKILL.md b/.agents/skills/qv-notice-generate/SKILL.md index 655d4b7b55..9670c4db6c 100644 --- a/.agents/skills/qv-notice-generate/SKILL.md +++ b/.agents/skills/qv-notice-generate/SKILL.md @@ -40,7 +40,10 @@ System requirements for Python scanning: 1. Ask which package to generate NOTICE for (or `--all` for all packages) 2. Source `.env` in the shell 3. Run the generator script — this writes NOTICE files directly -4. Only use `--dry-run` if the user explicitly asks for it +4. If the JS scan logs `npm install failed` (or the JS section went to zero + deps while `HEAD` had a JS section), restore that JS block from `HEAD`. + Keep successful model-scan additions. Do not commit a wiped JS section. +5. Only use `--dry-run` if the user explicitly asks for it **Do NOT commit changes.** The user will review and commit manually. diff --git a/.agents/skills/qv-sdk-changelog/SKILL.md b/.agents/skills/qv-sdk-changelog/SKILL.md index 4cb7d44484..ec9d3343a1 100644 --- a/.agents/skills/qv-sdk-changelog/SKILL.md +++ b/.agents/skills/qv-sdk-changelog/SKILL.md @@ -30,13 +30,22 @@ If the user doesn't specify, ask which SDK pod package they want to generate a c Package slugs match git tags (`sdk`, `inference`, `cli`, `ai-sdk-provider`, `opencode-plugin`, `openclaw-plugin`, …). Directory resolution (including `plugins/*`) is in `scripts/sdk/package-paths.cjs`. -**`sdk` and `inference` are separate releases that share a major and minor.** Moving to a -new major.minor is two changelogs and two releases, engine first: `--package=inference` -for `release-inference-`, then `--package=sdk` for `release-sdk-`. Engine -commits are scanned into the SDK changelog too (`CHANGELOG_EXTRA_SCAN_DIRS` in -`scripts/sdk/package-paths.cjs`), so the engine's user-facing changes appear in the SDK -release notes as well — the SDK is where consumers read them. A patch on either side is -one release of its own. +**`sdk` and `inference` are lockstep on major.minor.** Two changelogs, two +releases, engine first: `--package=inference` for `release-inference-`, +then `--package=sdk` for `release-sdk-`. Both notes for the same `x.y.z` +share one **display floor**: the last lockstep version already shipped (patch or +`.0`). `--base-commit` is that version's backmerge on main so the new notes do +not repeat it. Use the same floor on both packages; splitting them (inference +from the previous `.0`, SDK from a later patch) duplicates patch notes and +makes the files disagree. + +`--base-commit` is only the generate range, not the full set of notes. See +Step 2 when that floor is a patch. + +The SDK is the consumer-facing full notes. `--package=sdk` also scans +`packages/inference` (`CHANGELOG_EXTRA_SCAN_DIRS` in +`scripts/sdk/package-paths.cjs`). The inference changelog is the engine-only +slice of that same set. A patch on either side is one release of its own. **Working branch (when cutting from a release line):** use `chore/--changelog` (e.g. `chore/sdk-0.17.0-changelog`). Do **not** @@ -61,30 +70,50 @@ The script fetches from `upstream` first, falling back to `origin`. The generator enforces both checks and exits non-zero on failure. -Run `git tag --list "-v*" --sort=-v:refname` to check for existing version tags. +**Nested worktrees:** `unset GIT_DIR GIT_WORK_TREE` before any git or changelog +command, or the generator runs against the parent repo. -- If tags exist: the script auto-detects the release type from `package.json` version: - - **Minor/major release** (version ends in `.0`, e.g. `0.9.0`): uses the latest `.0` tag as base (e.g. `sdk-v0.8.0`), skipping patch tags - - **Patch release** (version ends in non-zero patch, e.g. `0.8.4`): uses the absolute latest tag as base (e.g. `sdk-v0.8.3`) -- If no tags: ask the user for `--base-commit` and `--base-version` (migration scenario) +**Pick `--base-commit`, then pass it.** Do not run the generator unflagged and +hope auto-detect is right. -**Why this matters:** patches ship on separate release branches and get backmerged into main. -Using the latest patch tag as base for a minor release would miss all PRs that landed on main -between the previous minor release and the last backmerge. The correct base for a minor release -is the previous minor's `.0` tag. +- **Lockstep `sdk` + `inference`:** always pass `--base-commit` / `--base-version` + — the last lockstep ship's backmerge on main, same floor on both packages. + Never tag auto-detect: `inference-v*` is often not an ancestor of `main`, and + a minor auto-detects the previous `.0` (repeats already-shipped patch notes). + When that floor is a `.0`, generate is enough. When it is a **patch**, generate + from the patch backmerge, then union main-only work from the previous lockstep + `.0` backmerge → that patch backmerge: first-parent merges touching + `packages/inference` or `packages/sdk`, minus `[skiplog]`, minus PR numbers + already in `packages/sdk/changelog//CHANGELOG.md`. Hand-add to both + changelogs (`CHANGELOG.md` and `breaking.md` / `models.md` / `api.md` when the + PR tag requires them). `--update-root-changelog` only after that. + +```bash +git log --first-parent --format='%s' .. +# keep subjects whose merge diff touches packages/inference or packages/sdk +``` + +- **Standalone** (cli, plugins, anything not lockstep): omit the flags. The + generator auto-detects (minor → previous `.0`, patch → previous tag). A + previous `.0` still includes main-only work in the patch window; drop PR + numbers already in `changelog//` if they re-list. If no tags exist, + ask for `--base-commit` and `--base-version`. + +`--base-commit` is only the generate range. The published-tag audit after +generate is the consumer delta, for every package. ### Step 3: Generate Raw Changelog -All SDK pod packages use the same command: +Lockstep (`sdk` / `inference`) always passes the floor from Step 2: ```bash -node scripts/sdk/generate-changelog-sdk-pod.cjs --package= +node scripts/sdk/generate-changelog-sdk-pod.cjs --package= --base-commit= --base-version= ``` -With migration flags: +Standalone packages can omit the flags (auto-detect): ```bash -node scripts/sdk/generate-changelog-sdk-pod.cjs --package= --base-commit= --base-version= +node scripts/sdk/generate-changelog-sdk-pod.cjs --package= ``` The script automatically excludes: @@ -99,7 +128,15 @@ The script automatically excludes: For `[mod]` PRs, the script extracts the `Added`/`Updated`/`Removed` model lists from the PR body and renders them as **indented continuation lines beneath the bullet** in `CHANGELOG.md` (each section on its own line — never inline as one -giant row). The same filtered lists are written to `models.md`. +giant row). It also writes `models.md`. + +`CHANGELOG.md` inline lines may stay at `MAX_INLINE_MODELS` (5) plus +`(and N more)`. **`models.md` is the full added/removed set** — never truncated. +PR bodies are often incomplete; if the published-tag audit disagrees, replace +`models.md` from the export/constant diff, not from the PR body. + +If this package's public API *is* those exported constants, removed names are +breaking: they go in `breaking.md` even when the PR was only `[mod]`. The extractor applies two policies (in this order): @@ -125,40 +162,76 @@ After both filters, each section is trimmed to `MAX_INLINE_MODELS` (currently If after filtering a section is empty, it's omitted. If all sections are empty the bullet emits with no continuation lines. -When writing the human-readable `CHANGELOG_LLM.md` (Step 4), apply the same -"no informational value" rule manually: skip backmerges, automated bumps, and any -entry whose subject would just repeat what a previous release already said. For -the Models section, mirror the script's policy — keep it concise in the body -(highlight the most notable adds/removes) and defer the full constant list to -the `### Added` / `### Removed` blocks at the bottom. +### After generate: published-tag audit (mandatory) + +`git log ..HEAD` is the generate range. It is not the consumer delta. + +For **every** SDK pod package, after the raw files exist: + +```bash +DIR=$(node -e "console.log(require('./scripts/sdk/package-paths.cjs').getPackageDir(''))") +LAST=$(git tag --list "-v*" --sort=-v:refname | head -1) +git diff "$LAST" HEAD -- "$DIR/package.json" +``` + +Diff this package's public surface the same way: `exports`, serve/HTTP routes, +exported constants/catalog. Every user-facing add, remove, or rename in that +diff must appear in `api.md`, `breaking.md`, and/or `models.md`. Hand-add. +`--update-root-changelog` only — do not re-run a full generate. New public +exports under an older umbrella PR still get their own `api.md` example. + +Fail-stop until the notes match the tree. Then write `CHANGELOG_LLM.md`. ### Step 4: Generate CHANGELOG_LLM.md (mandatory) Always run this step. Do not ask the user — it's part of the skill. -After raw changelog files exist, generate the human-readable version at -`packages//changelog//CHANGELOG_LLM.md`. +Author `CHANGELOG_LLM.md` from `changelog//` **after** the published-tag +audit, not from `git log`. Title and NPM line are this package (`@qvac/`), +not always sdk. -See [references/changelog-llm-format.md](references/changelog-llm-format.md) for the format guide. +See [references/changelog-llm-format.md](references/changelog-llm-format.md). -After writing the file, re-run the raw generator (or rebuild the root aggregate) so -`packages//CHANGELOG.md` picks up the new `CHANGELOG_LLM.md` (the aggregator -prefers it over `CHANGELOG.md`). Easiest way: re-run the script from Step 3 — it's idempotent. +Skip backmerges, automated bumps, and entries that only repeat a previous +release. Models body stays concise; the full constant lists live in `models.md` +and in the LLM `### Added` / `### Removed` blocks. + +After writing the file, rebuild the root aggregate so +`packages//CHANGELOG.md` picks up `CHANGELOG_LLM.md` (the aggregator +prefers it over `CHANGELOG.md`): + +```bash +node scripts/sdk/generate-changelog-sdk-pod.cjs --package= --update-root-changelog +``` + +Do **not** re-run a full generate after the published-tag hand edits — that +overwrites `api.md` / `breaking.md` / `models.md`. **Format the generated markdown (mandatory).** `CHANGELOG_LLM.md` is authored by hand here, so it is the file most likely to carry markdown formatting issues that a committed-file format check would later reject. Every SDK pod package uses prettier -(`format` = `prettier --check .`, `format:fix` = `prettier --write .`). Run the check -scoped to the changelog output so any issue surfaces now: +(`format` = `prettier --check .`, `format:fix` = `prettier --write .`) with +`.prettierrc` set to `"prettier-config-holepunch"`. **Never `--no-config`.** CI +(`[inference] format`, `[sdk] format`, …) loads holepunch; `--no-config` or a +different parser (quote style, trailing commas) is the usual red we hit. + +`bunx prettier` fails with `Cannot find package 'prettier-config-holepunch'` +when that package is not resolvable, then either skips or formats with a +fallback CI rejects. **Never `--no-config`.** Do not `bun install` in a package +whose range names an unpublished lockstep dep (e.g. sdk waiting on inference) — +run `bunx` from a sibling that already has `node_modules`. ```bash -cd packages/ -bunx prettier --check "changelog/**/*.md" "CHANGELOG.md" +DIR=$(node -e "console.log(require('./scripts/sdk/package-paths.cjs').getPackageDir(''))") +bunx prettier --check "$DIR/changelog//**/*.md" "$DIR/CHANGELOG.md" ``` -If it reports problems, fix them — `bunx prettier --write` on the same paths, or hand-edit — -and re-run the check until it passes clean. Do this before moving on so the release commit -carries only prettier-clean markdown. +Scope those globs to **this package**. Do not run `changelog/**/*.md` from the +repo root or another package cwd — that walks every historical version folder. + +If it reports problems, fix them — `bunx prettier --write` on the same paths, or +`bun run format:fix` — and re-run the check until it passes clean. Do this before +moving on so the release commit carries only prettier-clean markdown. **Downstream rendering note:** the docs site reads `CHANGELOG_LLM.md` **verbatim** and inlines it under a `### @qvac/` subsection of the @@ -192,9 +265,8 @@ Layout: - `:qvac: SDK :rocket: NPM Public release` header. - NPM, GitHub release, and full-changelog tree links. - `:warning: Breaking Changes` section with link to `breaking.md` — emitted - only when `breaking.md` exists in the version folder (i.e. at least one PR - carries the `[bc]` tag). Detected by file presence, not by parsing - CHANGELOG.md. + when `breaking.md` exists (including hand-added catalog-as-API removals). + File presence, not `[bc]` tags and not CHANGELOG.md. - Footer: `Thanks to everyone on QVAC team :green_heart: :qvac: :green_heart:`. If the post needs hand-tuning (e.g. a custom note for a specific release), @@ -210,6 +282,11 @@ source .env node .agents/skills/qv-notice-generate/scripts/generate-notice.js ``` +If JS `npm install` fails (unpublished lockstep dep, registry miss), **do not +commit** a NOTICE whose JS section is empty. Restore the JS block from `HEAD` +and keep any successful model-scan additions. Models-only packages still update +model attributions against the last published NOTICE. + Do NOT commit the announcement post (gitignored) and let the user review the rest before committing. @@ -318,8 +395,8 @@ See `docs/website/docs-workflow.md` for the full pipeline reference. | Flag | Required | Description | | ------------------------------- | -------- | ------------------------------------------------------------------ | | `--package` | Yes | Package name (e.g., `sdk`) | -| `--base-commit` | No | Initial commit SHA for migration (overrides tag lookup) | -| `--base-version` | No | Version label for base commit (display only) | +| `--base-commit` | Lockstep | Generate-range start. Required for `sdk`/`inference`; overrides tag auto-detect | +| `--base-version` | Lockstep | Display label for that floor | | `--release-type` | No | `minor` or `patch` (auto-detected from package.json version) | | `--dry-run` | No | Preview output without writing files | | `--update-root-changelog` | No | Rebuild only the root aggregate `packages//CHANGELOG.md` | @@ -331,9 +408,9 @@ See `docs/website/docs-workflow.md` for the full pipeline reference. Generates changelog files in `packages//changelog//`: - `CHANGELOG.md` - Main changelog -- `breaking.md` - Breaking changes detail (if `[bc]` PRs) -- `api.md` - API changes detail (if `[api]` PRs) -- `models.md` - Model changes (if `[mod]` PRs) +- `breaking.md` - Breaking changes (`[bc]` PRs and catalog-as-API removals) +- `api.md` - API changes (`[api]` PRs and published-tag export/route diffs) +- `models.md` - Model changes (full set; `[mod]` PRs and constant diffs) - `CHANGELOG_LLM.md` - Human-readable version (always generated, see Step 4) - `announcement-post.txt` - Slack copy-paste post (always generated, see Step 5, **gitignored** — never commit) @@ -363,6 +440,32 @@ Examples: - `sdk-v0.8.1` (patch — used as base for next patch release) - `rag-v2.0.0` +## Repeated footguns + +These have gone red on more than one SDK-pod changelog PR. Fix them before +push, and keep this list to things that are cheap to prevent: + +- **Prettier is holepunch, not stock.** `.prettierrc` is `"prettier-config-holepunch"`. + Never `--no-config`. Resolve holepunch from a package that can install; do not + `bun install` against an unpublished lockstep dep. Quote style and trailing + commas on `CHANGELOG_LLM.md` are the usual fail. +- **Lockstep: pass the floor.** Never run the generator unflagged for `sdk` / + `inference`. Same `--base-commit` on both. When that floor is a patch, union + the Step 2 main-only window. SDK is the consumer set; inference is the engine + slice. +- **`inference-v*` is often not on `main`.** Use the backmerge SHA, not the tag. +- **Nested worktrees inherit `GIT_DIR`.** `unset GIT_DIR GIT_WORK_TREE` before + generate/commit/cherry-pick, or you operate on the parent repo. +- **Push the org remote** (`upstream` when that is `tetherto/qvac`), not the + contributor fork. `git push` with no remote follows `origin`. +- **Do not skip SDK Pod Checks.** Workspace red vs published red is a real + signal; `[skip-sdk-pod-checks]` is not the changelog fix. +- **Notes vs last published tag, not only `git log`.** After generate, audit + exports / routes / constants against `-v*` (highest shipped). `git log` + `..HEAD` misses work that is already an ancestor of `--base-commit`. +- **NOTICE JS wipe.** A failed `npm install` must not replace the JS section + with zero deps. Restore JS from `HEAD`; keep successful model-scan adds. + ## Quality Checklist Before completing: @@ -371,18 +474,24 @@ Before completing: - [ ] Working head (if branched for the release PR) is `chore/--changelog`, not `release-*` - [ ] Clone is not shallow (`git rev-parse --is-shallow-repository` → `false`) - [ ] Base reference resolved (tag or `--base-commit`) and is an ancestor of `HEAD` +- [ ] For lockstep `sdk` + `inference`: both generated with the **same** `--base-commit` / `--base-version` (last lockstep display floor); never unflagged auto-detect; SDK changelog includes the engine slice +- [ ] When that floor is a patch: main-only window unioned in on both changelogs +- [ ] `GIT_DIR` / `GIT_WORK_TREE` unset (or pointed at this worktree) so generate/git did not run in a parent repo - [ ] PRs scoped to package path only - [ ] Changelog files written to correct version directory -- [ ] CHANGELOG_LLM.md generated (mandatory) and follows format guide -- [ ] Generated markdown is prettier-clean (`prettier --check` on the changelog output passes) +- [ ] CHANGELOG_LLM.md authored from `changelog//` after the published-tag audit (this package's name on the title/NPM line) +- [ ] Generated markdown is prettier-clean with **prettier-config-holepunch** resolved (never `--no-config`; do not `bun install` against unpublished lockstep deps) - [ ] announcement-post.txt generated (mandatory, gitignored) -- [ ] NOTICE file updated for the target package +- [ ] Published-tag audit done: last `-v*` vs HEAD public surface under `getPackageDir()` matches `api.md` / `breaking.md` / `models.md` +- [ ] `models.md` is the full added/removed set (inline `CHANGELOG.md` may still use `(and N more)`); catalog-as-API removals are in `breaking.md` +- [ ] NOTICE updated; JS section not emptied by a failed install - [ ] When `--package=sdk`: `qv-sdk-inference-version` run (engine version published, sdk version and `@qvac/inference` range sharing a major.minor, sdk-python regenerated), python `generate.py --check` passing - [ ] When `--package=sdk`: site docs generated via `release-version.ts`, `npm run build` passed, and `git status` shows only `reference/api/**`, `reference/release-notes/**`, `src/lib/versions.ts` (and `public/_redirects` on **minor** releases — the managed latest-series alias block) as committable docs changes (byproducts gitignored) - [ ] Root CHANGELOG.md rebuilt from all version folders (and picks up CHANGELOG_LLM.md) - [ ] Versions sorted in descending semver order - [ ] No duplicated versions - [ ] Root file is deterministic (fully regenerated) +- [ ] Org remote (`upstream` when that is tetherto/qvac) is the push target, not the fork ## References diff --git a/.agents/skills/qv-sdk-changelog/references/changelog-llm-format.md b/.agents/skills/qv-sdk-changelog/references/changelog-llm-format.md index 0484520611..c389b82362 100644 --- a/.agents/skills/qv-sdk-changelog/references/changelog-llm-format.md +++ b/.agents/skills/qv-sdk-changelog/references/changelog-llm-format.md @@ -29,9 +29,9 @@ Create `{PACKAGE_ROOT}/changelog/{VERSION}/CHANGELOG_LLM.md` with these guidelin ### Format Requirements -1. **Title**: `# QVAC SDK v{VERSION} Release Notes` +1. **Title**: `# QVAC v{VERSION} Release Notes` — this package, not always SDK. -2. **NPM Link**: Add `📦 **NPM:** https://www.npmjs.com/package/@qvac/sdk/v/{VERSION}` right after the title. This is the **only** place an emoji is allowed in the document (see the no-emoji rule below). +2. **NPM Link**: `📦 **NPM:** https://www.npmjs.com/package/@qvac//v/{VERSION}` right after the title. This is the **only** place an emoji is allowed in the document (see the no-emoji rule below). 3. **Introduction**: Write a brief 2-3 sentence summary of what this release brings diff --git a/.agents/skills/qv-sdk-pr-create/SKILL.md b/.agents/skills/qv-sdk-pr-create/SKILL.md index 90a8a03a8f..17cd6acbc2 100644 --- a/.agents/skills/qv-sdk-pr-create/SKILL.md +++ b/.agents/skills/qv-sdk-pr-create/SKILL.md @@ -54,6 +54,14 @@ Consequences for release changelog / metadata PRs: `backmerge/release--` heads are fine — they do not match the `release-*` push trigger. +**Release changelog PRs** (metadata + notes onto `release--x.y.z`): + +- Title is `chore:` (optional `[mod]` when the cut is catalog-only). Do not put + `[bc]` on the release title; breaking lives in `breaking.md`. +- Body API / Models / Breaking sections are copied from + `changelog//`, not from an earlier hop or the generator + summary. Delete a section only when that file is absent. + ## Workflow 1. Identify base and current branch — note whether the base is `main` or a `release--` branch. For release PRs, apply **Release PR branch naming** above (base three-part; head not `release-*`) @@ -93,6 +101,7 @@ Infer first, ask only if uncertain: - `[bc]`: removed/changed existing public API signatures - `[mod]`: changes to model constant definitions - ASK only if change scope is ambiguous +- **Release changelog PRs** (base `release-*`, diff is notes / NOTICE / version / generated docs): title is `chore:` (optional `[mod]`). Do not copy `[bc]` / `[api]` from the notes into the title. Body API / Models / Breaking still copy `changelog//`. **Testing section:** - If test files modified → "Unit tests added/updated for X" @@ -270,7 +279,7 @@ Before outputting the PR description, verify: - [ ] "What problem" describes user impact, not implementation - [ ] "How it solves" is high-level approach, not line-by-line - [ ] Unused sections are deleted -- [ ] `[bc]` tag has BEFORE/AFTER code examples +- [ ] `[bc]` tag has BEFORE/AFTER code examples (feature PRs). Release changelog PRs: no `[bc]` on the title; Breaking section copies `breaking.md` when that file exists - [ ] `[api]` tag has usage example - [ ] `[mod]` tag has Added/Removed models list - [ ] Description is concise - bullet points, no fluff @@ -280,6 +289,7 @@ Before outputting the PR description, verify: - [ ] For sdk releases with generated docs, `git status` shows only `reference/api/**`, `reference/release-notes/**`, and `src/lib/versions.ts` as committable docs changes — disposable byproducts (`api-data.json`, `out/`, `.next/`, `dist/`, etc.) are gitignored - [ ] If base is `release--`, the dual-PR flow ran (or `--no-backmerge` was set), and both PR URLs are reported - [ ] Release PRs: base is three-part `release--x.y.z`; org head is `chore/--changelog` (or other non-`release-*` name) +- [ ] Release changelog PRs: title is `chore:` (no `[bc]`); body API / Models / Breaking match `changelog//` - [ ] Head was pushed to the org remote when write access allows; fork path only used as fallback (with `fork-ci` re-approval called out) - [ ] PR is Ready for review when baseline CI is expected (not left as Draft unintentionally)