Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
## Changelog

<!-- CRITICAL: This section is the source of truth for CHANGELOG.md.
generate-changelog.sh extracts these categorized bullets verbatim
generate-changelog.py extracts these categorized bullets verbatim
into the release changelog. Write carefully. This IS the changelog.

AUDIENCE: Users and operators. Write from their perspective.
Expand Down
6 changes: 3 additions & 3 deletions RELEASES-RATIONALE.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ on both sides with different content. Always branch from `origin/main` and cherr

Branch naming `release/v<version>` or `release/v<version>-<slug>` (e.g. `release/v0.1.0`,
`release/v0.2.0-python-checks`) makes release branches sortable and unambiguous when multiple cuts are in flight. The
`v<version>` prefix is required: `scripts/generate-changelog.sh` extracts the version from the branch name. Slug is
`v<version>` prefix is required: `scripts/generate-changelog.py` extracts the version from the branch name. Slug is
kebab-case, short, descriptive.

## PR body conventions
Expand Down Expand Up @@ -121,7 +121,7 @@ prior squash, it's a false positive (no action). Otherwise cherry-pick the commi

### Generated, never hand-written

`scripts/generate-changelog.sh` (with `cliff.toml`) is the only sanctioned way to update `CHANGELOG.md`. The script runs
`scripts/generate-changelog.py` (with `cliff.toml`) is the only sanctioned way to update `CHANGELOG.md`. The script runs
`git-cliff` to prepend a versioned entry for commits since the last tag, then walks each squash-merged PR's body to
extract the `## Changelog → ### Added / Changed / Fixed / Documentation` subsections, replacing the auto-generated
bullets with the curated PR-body content (with author and PR-link attribution).
Expand Down Expand Up @@ -212,7 +212,7 @@ Scrub-before-submit (author in `/tmp/`, scrub there, submit via `--body-file`) a
edit, scrub again". Every fix lands locally and the public PR sees only clean text. The auto-format hook skips `/tmp/`
paths so the body keeps its authored shape and no soft-wrapping is injected.

For a `CHANGELOG.md` finding, fix the upstream PR body (which `generate-changelog.sh` re-fetches every run) and
For a `CHANGELOG.md` finding, fix the upstream PR body (which `generate-changelog.py` re-fetches every run) and
regenerate. Hand-editing `CHANGELOG.md` directly produces drift the next regeneration overwrites.

## Branch protection
Expand Down
6 changes: 3 additions & 3 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Engineering docs (`docs/plans/`, `docs/solutions/`, `docs/brainstorms/`, `docs/r
isn't `release/*`.

**Branch naming**: `release/v<version>` or `release/v<version>-<slug>` (e.g. `release/v0.1.0`,
`release/v0.2.0-python-checks`). The `v<version>` prefix is required: `scripts/generate-changelog.sh` extracts the
`release/v0.2.0-python-checks`). The `v<version>` prefix is required: `scripts/generate-changelog.py` extracts the
version from the branch name.

```bash
Expand Down Expand Up @@ -121,7 +121,7 @@ git add src/skill_install/skill.json && \
git commit -m "chore(skill): refresh fixture for v0.2.0" || true

# 8. Generate CHANGELOG.md (auto-detects version from branch name; CI enforces this).
./scripts/generate-changelog.sh
./scripts/generate-changelog.py

# 9. Scrub CHANGELOG.md via Vale + LanguageTool + unslop. See § Prose scrubbing.
# Fix findings on upstream PR bodies, never by hand-editing CHANGELOG.md. When clean:
Expand Down Expand Up @@ -257,7 +257,7 @@ lt_check /tmp/body.md

# 6. Apply the cleaned version.
gh pr edit <num> --body-file /tmp/body.md # for PR body edits
# ./scripts/generate-changelog.sh # for CHANGELOG.md (re-runs the PR-body fetch from GitHub)
# ./scripts/generate-changelog.py # for CHANGELOG.md (re-runs the PR-body fetch from GitHub)
```

For a `CHANGELOG.md` finding, fix the upstream PR body and regenerate. Hand-editing `CHANGELOG.md` directly produces
Expand Down
44 changes: 22 additions & 22 deletions docs/plans/2026-04-02-002-feat-release-infrastructure-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ files and channels, and this plan closes every gap.

- `~/.claude/skills/rust-tool-release/SKILL.md` — canonical release standard
- `~/.claude/skills/rust-tool-release/scripts/generate-completions.sh` — generates `completions/` directory
- `~/.claude/skills/rust-tool-release/scripts/generate-changelog.sh` — generates `CHANGELOG.md` from git-cliff + PR body
- `~/.claude/skills/rust-tool-release/scripts/generate-changelog.py` — generates `CHANGELOG.md` from git-cliff + PR body
expansion
- `~/dev/bird/RELEASING.md` — reference RELEASING.md
- `~/dev/bird/README.md` — reference README with all 5 install channels
Expand All @@ -68,7 +68,7 @@ files and channels, and this plan closes every gap.
this.
- **Generate completions locally, commit to repo**: Per `rust-tool-release` standard, completions are
platform-independent text files committed to `completions/`. Not generated in CI.
- **CHANGELOG via generate-changelog.sh**: Uses git-cliff + PR body `## Changelog` section expansion. This is the
- **CHANGELOG via generate-changelog.py**: Uses git-cliff + PR body `## Changelog` section expansion. This is the
standard tooling, not manual editing.
- **Release branch from main, not dev**: Per the release branch pattern, `guard-main-docs.yml` blocks docs paths. The
release branch cherry-picks non-docs commits from dev.
Expand All @@ -82,7 +82,7 @@ files and channels, and this plan closes every gap.

### Deferred to Implementation

- **Exact CHANGELOG content**: `generate-changelog.sh` will produce the content from PR bodies. The quality depends on
- **Exact CHANGELOG content**: `generate-changelog.py` will produce the content from PR bodies. The quality depends on
how well the PR `## Changelog` sections were written.

## Implementation Units
Expand Down Expand Up @@ -135,8 +135,8 @@ Unblocks the release archive step.

**Dependencies:** None

**Status:** Shipped as `RELEASES.md` (canonical template renamed from `RELEASING.md` — see bird commit
`da19ad5 docs: rename RELEASING.md to RELEASES.md and align with canonical template`).
**Status:** Shipped as `RELEASES.md` (canonical template renamed from `RELEASING.md` — see bird commit `da19ad5 docs:
rename RELEASING.md to RELEASES.md and align with canonical template`).

**Files:**

Expand Down Expand Up @@ -169,9 +169,9 @@ Unblocks the release archive step.

**Dependencies:** None

**Status:** Shipped with 4 of 5 channels (Homebrew, `cargo install`, `cargo binstall`, pre-built binaries from
GitHub Releases). "From source" (`git clone && cargo build --release`) is omitted — trivial for Rust users and implicit.
If strict 5-channel coverage is required, add a one-line bullet in a follow-up.
**Status:** Shipped with 4 of 5 channels (Homebrew, `cargo install`, `cargo binstall`, pre-built binaries from GitHub
Releases). "From source" (`git clone && cargo build --release`) is omitted — trivial for Rust users and implicit. If
strict 5-channel coverage is required, add a one-line bullet in a follow-up.

**Files:**

Expand Down Expand Up @@ -271,7 +271,7 @@ If strict 5-channel coverage is required, add a one-line bullet in a follow-up.

- [x] **Unit 6: Generate CHANGELOG.md for v0.1.0 (on release branch)**

**Goal:** Populate CHANGELOG.md with v0.1.0 release notes using `generate-changelog.sh`.
**Goal:** Populate CHANGELOG.md with v0.1.0 release notes using `generate-changelog.py`.

**Requirements:** R3, R7

Expand All @@ -286,7 +286,7 @@ If strict 5-channel coverage is required, add a one-line bullet in a follow-up.
- This happens on the release branch during release prep, NOT on dev
- Create `release/v0.1.0` from `origin/main`
- Cherry-pick non-docs commits from dev
- Run `~/.claude/skills/rust-tool-release/scripts/generate-changelog.sh`
- Run `~/.claude/skills/rust-tool-release/scripts/generate-changelog.py`
- The script auto-detects version from branch name
- Commit CHANGELOG.md as part of the release PR to main
- After PR merges: `git tag v0.1.0 && git push origin main --tags`
Expand All @@ -297,7 +297,7 @@ If strict 5-channel coverage is required, add a one-line bullet in a follow-up.

**Test scenarios:**

- Happy path: `generate-changelog.sh` produces a CHANGELOG.md with a `## [0.1.0]` section
- Happy path: `generate-changelog.py` produces a CHANGELOG.md with a `## [0.1.0]` section
- Happy path: CHANGELOG.md content includes PR links and author attribution
- Error path: script fails if `cliff.toml` is misconfigured — verify `[remote.github]` section exists

Expand All @@ -318,12 +318,12 @@ If strict 5-channel coverage is required, add a one-line bullet in a follow-up.

## Risks & Dependencies

| Risk | Mitigation |
| --- | --- |
| `generate-completions.sh` doesn't support the crate/bin name split | Crate ships a single `anc` bin; run the script once against `anc` |
| `generate-changelog.sh` produces empty output (squash-merge history) | The script uses git-cliff on cherry-picked commits (which are individual conventional commits), not squash-merged ones |
| Homebrew formula pre-seed conflicts with first real release | Use `v0.0.0` placeholder per documented pattern |
| `cargo publish` fails on first run (Trusted Publishing not configured) | First publish must be manual with `CARGO_REGISTRY_TOKEN` |
| Risk | Mitigation |
| ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `generate-completions.sh` doesn't support the crate/bin name split | Crate ships a single `anc` bin; run the script once against `anc` |
| `generate-changelog.py` produces empty output (squash-merge history) | The script uses git-cliff on cherry-picked commits (which are individual conventional commits), not squash-merged ones |
| Homebrew formula pre-seed conflicts with first real release | Use `v0.0.0` placeholder per documented pattern |
| `cargo publish` fails on first run (Trusted Publishing not configured) | First publish must be manual with `CARGO_REGISTRY_TOKEN` |

## Sources & References

Expand All @@ -346,8 +346,8 @@ Plan audited against repo state. Resolved: Units 1, 2, 3. Remaining: Units 4, 5,
- Unit 5 (stale branch cleanup) — NOT done; 6 stale `origin/*` branches remain (enumerated in Unit 5 body).
- Unit 6 (CHANGELOG v0.1.0) — NOT done; `CHANGELOG.md` is a 1-line header. No `v0.1.0` tag exists.

Next action: Unit 4 (Homebrew formula pre-seed) is the smallest independent piece. Unit 6 blocks the actual release
and must happen on a `release/v0.1.0` branch, not on `dev`. Unit 5 is trivial housekeeping.
Next action: Unit 4 (Homebrew formula pre-seed) is the smallest independent piece. Unit 6 blocks the actual release and
must happen on a `release/v0.1.0` branch, not on `dev`. Unit 5 is trivial housekeeping.

### 2026-04-16

Expand Down Expand Up @@ -384,13 +384,13 @@ All 6 units complete. v0.1.0 released successfully through the full pipeline:

- Release branch cherry-picked 13 commits from dev, excluding guarded docs/plans/ paths
- Cargo.toml already at 0.1.0, completions already fresh -- no bump or regen needed
- CHANGELOG.md generated via generate-changelog.sh with PR body expansion
- CHANGELOG.md generated via generate-changelog.py with PR body expansion
- PR #18 merged to main, all 9 CI checks passed
- Alpha v0.1.0-alpha.1 published manually to establish crate on crates.io
- Trusted Publishing configured, then annotated tag pushed
- release.yml: 5-target build, TP publish, non-draft release, Homebrew dispatch all succeeded
- homebrew-tap: formula update PR, bottle builds (3 platforms), publish, finalize-release all succeeded
- make_latest flipped to true. All channels live.

Post-release: two CE todos filed for monorepo discovery (006) and multi-language support (007),
discovered during RC testing against bird, xr, and markitdown.
Post-release: two CE todos filed for monorepo discovery (006) and multi-language support (007), discovered during RC
testing against bird, xr, and markitdown.
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ None applicable — this is repo-internal release choreography.
**Approach:**

- Resolve Q-CLI1 first (MINOR vs PATCH). Recommendation MINOR (`v0.2.0`).
- Run `scripts/generate-changelog.sh` if the project uses it for changelog generation, otherwise hand-edit per the
- Run `scripts/generate-changelog.py` if the project uses it for changelog generation, otherwise hand-edit per the
existing CHANGELOG voice.
- The version-string-on-`dev` note: `Cargo.toml` shows `version = "0.1.0"` even though tags `v0.1.1`/`v0.1.2`/`v0.1.3`
exist. This is consistent with prior release branches doing the bump on the `release/*` branch rather than `dev`.
Expand Down Expand Up @@ -641,7 +641,7 @@ Run in order. The first three steps are HARD GATES — do not advance past a fai
1. ☐ Cut `release/launch` from `dev` HEAD: `git switch -c release/launch dev`.
2. ☐ On `release/launch`: bump `Cargo.toml` version `0.1.0 → 0.2.0`; `cargo build` regenerates `Cargo.lock`; commit as
`chore: bump version to 0.2.0` per the established pattern (`a1b3bfd` for v0.1.3).
3. ☐ Generate CHANGELOG entry for `v0.2.0`: `scripts/generate-changelog.sh` (or `git cliff --tag v0.2.0 --unreleased`
3. ☐ Generate CHANGELOG entry for `v0.2.0`: `scripts/generate-changelog.py` (or `git cliff --tag v0.2.0 --unreleased`
per `cliff.toml`); commit as `docs(changelog): v0.2.0`.
4. ☐ Open PR `release/launch` → `main` titled `release: v0.2.0` (mirror `release: v0.1.3 (#28)`). Body uses
`.github/pull_request_template.md` cascade per global CLAUDE.md.
Expand Down
2 changes: 1 addition & 1 deletion docs/plans/2026-05-07-001-feat-v0.4.0-spec-sync-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ CLI version, and prepare the PR body's `## Changelog` section.

- Prior coverage-matrix regen commits (search `git log --oneline -- coverage/matrix.json` for the shape).
- Existing CHANGELOG entries — `## [Unreleased]` block accepts the verbatim `## Changelog` body via
`generate-changelog.sh` at release time. Do not hand-edit `CHANGELOG.md`.
`generate-changelog.py` at release time. Do not hand-edit `CHANGELOG.md`.

**Test scenarios:**

Expand Down
Loading
Loading