From 8a7a09bd22e1d23a36abafde5997f83b5b54cb0e Mon Sep 17 00:00:00 2001 From: Rahul Krishna Date: Sat, 27 Jun 2026 16:55:28 -0400 Subject: [PATCH 1/2] chore: add release-announcer agent playbook (CLAUDE.md) The release workflow auto-posts a machine-generated announcement (raw changelog-builder output) to the repo and org Discussions. It mis-categorizes PRs, includes chore(release) noise, and buries breaking changes. Add .github/release-announcer/CLAUDE.md: instructions for an agent run that reads the latest release, reads the auto-posted Discussion body, reconstructs what actually changed from the CHANGELOG/PRs/diff, and rewrites the Discussion(s) into a clear, user-facing announcement (breaking changes first, plain-language highlights, upgrade steps). Includes a rewritten-by marker so it never re-announces, and read-only/no-fabrication/no-attribution guardrails. Force-added: CLAUDE.md is excluded by a global gitignore, but this one is a shared, committed automation playbook. --- .github/release-announcer/CLAUDE.md | 104 ++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 .github/release-announcer/CLAUDE.md diff --git a/.github/release-announcer/CLAUDE.md b/.github/release-announcer/CLAUDE.md new file mode 100644 index 00000000..6bfcbff0 --- /dev/null +++ b/.github/release-announcer/CLAUDE.md @@ -0,0 +1,104 @@ +# Release Announcer + +You are an agent run with this directory as your working context. Your single job: **after a +release, rewrite the auto-generated GitHub Discussion announcement into a clear, accurate, +user-facing message that explains what _actually_ changed.** + +## Why this exists + +The `Python uv Release` workflow (`.github/workflows/release.yml`) fires on a `v*.*.*` tag and, via +`softprops/action-gh-release` + `mikepenz/release-changelog-builder-action`, auto-posts an +announcement to: + +- the **repo** Discussions, category **Announcements** (`codellm-devkit/python-sdk`), and +- the **org** Discussions, category **Announcements** (`codellm-devkit/.github`), titled + `python-sdk vX.Y.Z`. + +That body is mechanical: it lists raw PR titles grouped by conventional-commit prefix. It is +routinely wrong or noisy — it mis-categorizes PRs (a `feat(typescript)` landing under "🐛 Fixes"), +includes `chore(release)` entries, and **buries breaking changes**. Users deserve better. + +## How this is triggered + +This file is the agent's instructions, not a trigger by itself. Wire one of: + +- a **scheduled cloud agent / cron** whose working directory is `.github/release-announcer/`, or +- a **post-release job** in `release.yml` that runs Claude Code with this directory as cwd after + "Publish Release on GitHub" succeeds. + +Either way, the agent reads this CLAUDE.md and executes the procedure below. + +## Procedure + +Run from the repo root (the commands assume the `gh` CLI is authenticated). + +### 1. Identify the release to announce +```bash +gh release view --json tagName,name,publishedAt,body +``` +Take the newest tag (`vX.Y.Z`). If you have already rewritten its discussion (see the marker in +step 5), stop — do not re-announce. + +### 2. Find the auto-posted announcement discussion(s) +Repo discussion in the Announcements category whose title is the tag: +```bash +gh api graphql -f query=' +{ repository(owner:"codellm-devkit", name:"python-sdk") { + discussions(first:10, orderBy:{field:CREATED_AT, direction:DESC}) { + nodes { id number title url category{name} body } } } }' +``` +Match `category.name == "Announcements"` and `title == "vX.Y.Z"`. Keep its `id` (a node ID, needed +to update) and read its `body` — that is the raw text to replace. The org mirror lives in +`codellm-devkit/.github` (title `python-sdk vX.Y.Z`); update it too if reachable. + +### 3. Establish what ACTUALLY changed +Do not trust the auto-grouping. Reconstruct the truth from sources: +```bash +sed -n '/## \[v X.Y.Z\]/,/## \[/p' CHANGELOG.md # the human-written entry for this version +gh pr view --json title,body,labels,files # for each PR referenced in the raw body +git diff ..vX.Y.Z -- # when a PR's intent is unclear +``` +For each change, classify by its **real** nature and record the **user impact**: +- **Breaking** — removed/renamed public API, changed defaults, dependency majors that change + behavior. Capture the concrete migration step. +- **Feature** — new public capability users can call. +- **Fix** — corrected behavior. +- **Dependency / internal** — bumps and CI; keep only if user-visible. +Drop pure noise: `chore(release)`, internal CI-only PRs, refactors with no surface change. + +### 4. Compose the improved announcement +Write Markdown that leads with meaning, not commit subjects: +- One-paragraph **TL;DR**: what shipped and why a user cares. +- **⚠️ Breaking changes** first (only if any), each with a copy-pasteable migration step. +- **Highlights** (features) in plain language — what it does, not the PR title. +- **Fixes** worth knowing. +- **Upgrade**: `pip install -U "cldk==X.Y.Z"` (and the `cldk[neo4j]` extra if relevant). +- Links: the GitHub release, the full `CHANGELOG.md` entry, and key PRs/issues. +Verify every dependency version against `pyproject.toml` (`[project.dependencies]` and +`[tool.backend-versions]`). + +### 5. Update the discussion(s) +Replace the body in place (preserve the title). Prepend a hidden marker so future runs skip it: +```bash +gh api graphql -f query=' +mutation($id:ID!, $body:String!) { + updateDiscussion(input:{discussionId:$id, body:$body}) { discussion { url } } }' \ + -f id="" -f body=" +" +``` +Mirror the same body to the org discussion in `codellm-devkit/.github` when reachable. The +`` marker is how step 1 detects an already-rewritten +release. + +## Guardrails + +- **Accuracy over polish.** Every claim must trace to the CHANGELOG, a PR, or the diff. Never invent + features or benefits. If unsure what a change does, read the diff before writing about it. +- **Name breaking changes as breaking**, up top, with migration steps. (Example — v1.4.0: the + `use_codeql` option and the `CodeQL*` exception classes were removed because codeanalyzer-python + 0.3.0 dropped CodeQL for PyCG; call-graph results can differ.) +- **Don't re-announce.** Honor the `rewritten-by` marker. +- **Edit, never duplicate.** Update the existing discussion; do not open a new one. +- **No attribution.** Do not add AI/assistant/tool credit anywhere in the announcement; match the + repo's writing conventions. +- **Read-only on code.** This task only reads the repo and edits Discussions — it makes no commits. From f2e059a283491d1767d4ae2f22d4e1cb2073a5a1 Mon Sep 17 00:00:00 2001 From: Rahul Krishna Date: Sat, 27 Jun 2026 16:58:53 -0400 Subject: [PATCH 2/2] chore: add root CLAUDE.md to tidy up release announcements Replace the .github/release-announcer playbook with a simple instruction in the repo's root CLAUDE.md: when working in the repo, check whether the latest release's auto-posted Announcements discussion still has the raw, machine-generated body and, if so, rewrite it in place into a clear user-facing announcement (breaking changes first, plain highlights, upgrade line), grounded in CHANGELOG.md and the PRs. A marker prevents redoing it. CLAUDE.md is excluded by a global gitignore, so it is force-added here as an intentionally committed, shared file. --- .github/release-announcer/CLAUDE.md | 104 ---------------------------- CLAUDE.md | 28 ++++++++ 2 files changed, 28 insertions(+), 104 deletions(-) delete mode 100644 .github/release-announcer/CLAUDE.md create mode 100644 CLAUDE.md diff --git a/.github/release-announcer/CLAUDE.md b/.github/release-announcer/CLAUDE.md deleted file mode 100644 index 6bfcbff0..00000000 --- a/.github/release-announcer/CLAUDE.md +++ /dev/null @@ -1,104 +0,0 @@ -# Release Announcer - -You are an agent run with this directory as your working context. Your single job: **after a -release, rewrite the auto-generated GitHub Discussion announcement into a clear, accurate, -user-facing message that explains what _actually_ changed.** - -## Why this exists - -The `Python uv Release` workflow (`.github/workflows/release.yml`) fires on a `v*.*.*` tag and, via -`softprops/action-gh-release` + `mikepenz/release-changelog-builder-action`, auto-posts an -announcement to: - -- the **repo** Discussions, category **Announcements** (`codellm-devkit/python-sdk`), and -- the **org** Discussions, category **Announcements** (`codellm-devkit/.github`), titled - `python-sdk vX.Y.Z`. - -That body is mechanical: it lists raw PR titles grouped by conventional-commit prefix. It is -routinely wrong or noisy — it mis-categorizes PRs (a `feat(typescript)` landing under "🐛 Fixes"), -includes `chore(release)` entries, and **buries breaking changes**. Users deserve better. - -## How this is triggered - -This file is the agent's instructions, not a trigger by itself. Wire one of: - -- a **scheduled cloud agent / cron** whose working directory is `.github/release-announcer/`, or -- a **post-release job** in `release.yml` that runs Claude Code with this directory as cwd after - "Publish Release on GitHub" succeeds. - -Either way, the agent reads this CLAUDE.md and executes the procedure below. - -## Procedure - -Run from the repo root (the commands assume the `gh` CLI is authenticated). - -### 1. Identify the release to announce -```bash -gh release view --json tagName,name,publishedAt,body -``` -Take the newest tag (`vX.Y.Z`). If you have already rewritten its discussion (see the marker in -step 5), stop — do not re-announce. - -### 2. Find the auto-posted announcement discussion(s) -Repo discussion in the Announcements category whose title is the tag: -```bash -gh api graphql -f query=' -{ repository(owner:"codellm-devkit", name:"python-sdk") { - discussions(first:10, orderBy:{field:CREATED_AT, direction:DESC}) { - nodes { id number title url category{name} body } } } }' -``` -Match `category.name == "Announcements"` and `title == "vX.Y.Z"`. Keep its `id` (a node ID, needed -to update) and read its `body` — that is the raw text to replace. The org mirror lives in -`codellm-devkit/.github` (title `python-sdk vX.Y.Z`); update it too if reachable. - -### 3. Establish what ACTUALLY changed -Do not trust the auto-grouping. Reconstruct the truth from sources: -```bash -sed -n '/## \[v X.Y.Z\]/,/## \[/p' CHANGELOG.md # the human-written entry for this version -gh pr view --json title,body,labels,files # for each PR referenced in the raw body -git diff ..vX.Y.Z -- # when a PR's intent is unclear -``` -For each change, classify by its **real** nature and record the **user impact**: -- **Breaking** — removed/renamed public API, changed defaults, dependency majors that change - behavior. Capture the concrete migration step. -- **Feature** — new public capability users can call. -- **Fix** — corrected behavior. -- **Dependency / internal** — bumps and CI; keep only if user-visible. -Drop pure noise: `chore(release)`, internal CI-only PRs, refactors with no surface change. - -### 4. Compose the improved announcement -Write Markdown that leads with meaning, not commit subjects: -- One-paragraph **TL;DR**: what shipped and why a user cares. -- **⚠️ Breaking changes** first (only if any), each with a copy-pasteable migration step. -- **Highlights** (features) in plain language — what it does, not the PR title. -- **Fixes** worth knowing. -- **Upgrade**: `pip install -U "cldk==X.Y.Z"` (and the `cldk[neo4j]` extra if relevant). -- Links: the GitHub release, the full `CHANGELOG.md` entry, and key PRs/issues. -Verify every dependency version against `pyproject.toml` (`[project.dependencies]` and -`[tool.backend-versions]`). - -### 5. Update the discussion(s) -Replace the body in place (preserve the title). Prepend a hidden marker so future runs skip it: -```bash -gh api graphql -f query=' -mutation($id:ID!, $body:String!) { - updateDiscussion(input:{discussionId:$id, body:$body}) { discussion { url } } }' \ - -f id="" -f body=" -" -``` -Mirror the same body to the org discussion in `codellm-devkit/.github` when reachable. The -`` marker is how step 1 detects an already-rewritten -release. - -## Guardrails - -- **Accuracy over polish.** Every claim must trace to the CHANGELOG, a PR, or the diff. Never invent - features or benefits. If unsure what a change does, read the diff before writing about it. -- **Name breaking changes as breaking**, up top, with migration steps. (Example — v1.4.0: the - `use_codeql` option and the `CodeQL*` exception classes were removed because codeanalyzer-python - 0.3.0 dropped CodeQL for PyCG; call-graph results can differ.) -- **Don't re-announce.** Honor the `rewritten-by` marker. -- **Edit, never duplicate.** Update the existing discussion; do not open a new one. -- **No attribution.** Do not add AI/assistant/tool credit anywhere in the announcement; match the - repo's writing conventions. -- **Read-only on code.** This task only reads the repo and edits Discussions — it makes no commits. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..6c30d3f4 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,28 @@ +# CLAUDE.md + +Agent guidance for `codellm-devkit/python-sdk`. + +## Tidy up the release announcement + +Every `vX.Y.Z` tag makes the release workflow (`.github/workflows/release.yml`) auto-post an +announcement to the **Announcements** discussion (this repo, and the org mirror in +`codellm-devkit/.github`). That body is machine-generated from PR titles — it mis-categorizes +changes, includes `chore(release)` noise, and buries breaking changes. + +When you're working in this repo, check whether the latest release's announcement still needs +cleanup, and if so, fix it: + +1. **Find it.** `gh release view --json tagName,publishedAt`; then list recent discussions via + `gh api graphql` (repository → discussions), match category `Announcements` and title `vX.Y.Z`. + Keep the discussion node `id` and read its `body`. +2. **Skip if already done.** If the body starts with `` (or already reads as a + clear, human-written announcement), do nothing. +3. **Otherwise rewrite it** into a clear, user-facing announcement, grounded in `CHANGELOG.md` and + the referenced PRs/diff (not the auto-grouping — verify each change; never invent anything): + - **breaking changes first**, each with a one-line migration step; + - plain-language highlights (what it does, not the PR title); + - upgrade line: `pip install -U "cldk==X.Y.Z"`; + - links to the GitHub release and `CHANGELOG.md`. +4. **Update in place.** Edit the discussion body with the GraphQL `updateDiscussion` mutation + (don't open a new one), prepend ``, and mirror the same body to the org + discussion. This task only reads code and edits Discussions — it makes no commits.