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
22 changes: 16 additions & 6 deletions .cursor/commands/issue-close.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Optional text after the command (same line). Examples:
- **`bump minor`** or **`minor`** — bump **minor**.
- **`bump major`** or **`major`** — bump **major**.
- **Free text** — if it clearly asks to release or bump the version, infer `patch`, `minor`, or `major` from wording (e.g. "bugfix release" → patch); if unclear, ask once.
- **`nohistory`** or **`skip history`** — skip the `HISTORY.md` update step (step 3) for this run.
- **`log "..."`** or **`note "..."`** — use the quoted text verbatim as the `HISTORY.md` bullet summary (otherwise the GitHub issue title is used).

Other optional notes still apply: branch name, PR title, draft PR, skip issue doc update, commit all changes, etc.

Expand All @@ -26,24 +28,32 @@ Other optional notes still apply: branch name, PR title, draft PR, skip issue do
- Do this **before** updating issue markdown and **before** commit / push / PR so the new version is in the tree that gets merged.
- If the project has no bumpable `pyproject.toml` version, skip and say so; continue with the remaining steps.

3. **Issue tracking in the repo** (see project rules under `.issueflows/01-current-issues`)
3. **Update `HISTORY.md`** (opt-out via `nohistory`)
- Read `.cursor/skills/issueflow-history-update/SKILL.md` and follow it.
- Default summary for the new bullet is the GitHub issue title; override with `log "..."` / `note "..."` from the command input.
- If step 2 did **not** bump the version, append a bullet to the existing `## [Unreleased]` section: `- <summary>. (#<N>)`.
- If step 2 **did** bump the version, promote `## [Unreleased]` to `## [<new_version>] - <YYYY-MM-DD>`, prepend a fresh empty `## [Unreleased]` above it, and put the new bullet inside the just-closed release section.
- If `HISTORY.md` does not exist at the project root, skip this step with a short note and continue. Never create it here.
- Show the proposed diff and confirm once before writing. If declined, leave `HISTORY.md` untouched and move on.

4. **Issue tracking in the repo** (see project rules under `.issueflows/01-current-issues`)
- Update the status file for this issue: clear checklist, remaining work, and use `- [x] Done` only when fully resolved.
- If the issue is fully resolved, move its markdown files from `.issueflows/01-current-issues` to `.issueflows/03-solved-issues`. If partially resolved, move to `.issueflows/02-partly-solved-issues`.

4. **Commit and fix merge conflicts**
5. **Commit and fix merge conflicts**
- Before staging, run `git status` to list all modified/untracked files. If any changes are **not relevant** to this issue, tell the user which ones and ask whether to include them in this commit or leave them for later. Do not silently drop or include unrelated changes.
- Unless told to commit all, stage the right files (avoid unrelated changes). Include `pyproject.toml` (and `uv.lock` if it changed) when a version bump ran.
- Unless told to commit all, stage the right files (avoid unrelated changes). Include `pyproject.toml` (and `uv.lock` if it changed) when a version bump ran. Include `HISTORY.md` when step 3 updated it.
- Write a commit message that states what changed and why in normal sentences.
- Sync with the default branch before pushing: run `git fetch --prune` then `git pull --ff-only` from the default branch (e.g. `main`) merged into the issue branch (or rebase, per project preference). Use `--ff-only` so unrelated work never gets merged in silently; if it refuses, stop and ask how to reconcile. Check for and fix merge conflicts.

5. **Push**
6. **Push**
- Push your branch to `origin` (or the remote you use).

6. **Pull request**
7. **Pull request**
- Open a PR against the default branch (e.g. `main`).
- Describe the change, how to test it, and link the GitHub issue (e.g. `Closes #123` or `Refs #123` in the PR body).

7. **After review**
8. **After review**
- Address feedback, push updates, and merge when approved and CI is green.
- Remind the user that the working copy is still on the issue branch, not the default. Suggest `git switch <default>` before starting unrelated work so new changes don't accidentally land on the issue branch.
- Once the PR is merged, run **`/issue-cleanup`** to switch back to the default branch, `git pull --ff-only`, `git fetch --prune`, and delete local branches whose commits are already in the default branch (single consolidated confirm). `/issue-close` no longer does post-merge cleanup itself.
Expand Down
2 changes: 2 additions & 0 deletions .cursor/commands/issue-yolo.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ For anything non-trivial, use the individual commands so you get confirmation ch
Same as `/issue-init` (issue number, URL, or empty to infer from the branch). Optional extra tokens are forwarded to the downstream commands:

- `bump` / `patch` / `minor` / `major` — forwarded to `/issue-close` for the version bump.
- `nohistory` / `skip history` — forwarded to `/issue-close` to skip the `HISTORY.md` update step.
- `log "..."` / `note "..."` — forwarded to `/issue-close` as the `HISTORY.md` bullet summary.
- `draft` — open a draft PR in `/issue-close`.
- Free-form notes — used as the plan/commit context.

Expand Down
84 changes: 84 additions & 0 deletions .cursor/skills/issueflow-history-update/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
name: issueflow-history-update
description: >-
Keep HISTORY.md (or equivalent changelog) up to date when landing an issue:
append a bullet to [Unreleased], or promote [Unreleased] to a new [x.y.z]
release section when a version bump happened. Invoked from /issue-close.
disable-model-invocation: true
---

# issue-flow — history update

Use this skill to update the project's changelog file (default **`HISTORY.md`**, overridable via `ISSUEFLOW_HISTORY_FILE` in `.env`) as part of `/issue-close`. It never runs on its own schedule; it is driven by the "update HISTORY" step in `.cursor/commands/issue-close.md`.

## When to use

- `/issue-close` is landing an issue and the project has a changelog file in the repo root.
- The user did **not** pass `nohistory` / `skip history` on the command line.

## Preconditions

1. The changelog file (`HISTORY.md`) exists at the **project root**. If it does not, **skip** this step, print "no `HISTORY.md` — skipping changelog update" and continue the rest of `/issue-close`. Never create the file from this skill.
2. The file is in **Keep a Changelog** shape: a top-level `## [Unreleased]` heading, with released versions below as `## [x.y.z] - YYYY-MM-DD` headings. If the shape does not match, **stop and report the mismatch** instead of guessing — let the user fix the file or pass `nohistory`.
3. UTF-8 read/write with explicit encoding.

## Inputs from `/issue-close`

| From | Used for |
|---|---|
| Issue number `N` | Reference suffix on the new bullet, e.g. `(#42)`. |
| Issue title (from `.issueflows/01-current-issues/issue<N>_original.md`) | Default bullet summary. |
| `log "..."` / `note "..."` input token | Override the bullet summary verbatim. |
| Version-bump outcome (from step 2 of `/issue-close`) | Decides **append** vs **promote** (see below). |

## Operation modes

### A. No version bump — append to `[Unreleased]`

1. Read `HISTORY.md`. Locate the first `## [Unreleased]` heading. The block ends at the next `## [` heading (or EOF).
2. Compose the new bullet:

```
- <summary>. (#<N>)
```

Summary = `log "..."` override if provided, else the issue title with sentence case, trailing period trimmed before the `.` we add.
3. Append the bullet to the end of the Unreleased bullet list. Preserve existing formatting (blank lines, list markers). Do not reorder existing entries.
4. Show the user the proposed diff of `HISTORY.md` and confirm once before writing.

### B. Version bump happened — promote `[Unreleased]` to a new release section

Only runs when step 2 of `/issue-close` actually changed `pyproject.toml` to a new version `NEW_VERSION`.

1. Determine `NEW_VERSION` (e.g. read from `pyproject.toml`, or from the `uv version` command output). Determine `TODAY` as `YYYY-MM-DD` in the user's local timezone.
2. Read `HISTORY.md`. Find `## [Unreleased]`.
3. Compose the new bullet (same shape as mode A). If `[Unreleased]` was empty when the bump happened, still create the new release section with this bullet inside it — a version bump implies a release, and the focus issue's bullet is always meaningful.
4. Rename the existing heading from `## [Unreleased]` to `## [<NEW_VERSION>] - <TODAY>` and add the new bullet at the end of that section's bullet list.
5. Prepend a fresh, empty `## [Unreleased]` section above the just-closed release, with one blank line separating them:

```markdown
## [Unreleased]

## [NEW_VERSION] - TODAY

- …existing bullets from before the promote…
- <new bullet for this issue> (#N)
```

6. Show the user the proposed diff and confirm once before writing.

## Staging

When `/issue-close` reaches its commit step:

- Stage `HISTORY.md` alongside the issue's other changes.
- If a version bump also ran, `HISTORY.md` is staged in the same commit as `pyproject.toml` (and `uv.lock` if it changed).

## Constraints

- Read/write only `HISTORY.md` at the project root. Do not touch any other file from this skill.
- Never create `HISTORY.md` from scratch — scaffolding a starter changelog is out of scope for `issue-flow init` / `update`.
- If the user passed `nohistory` (or `skip history`) to `/issue-close`, don't run this skill at all.
- If the confirm prompt in mode A or mode B is declined, leave `HISTORY.md` untouched and print a short "skipped changelog update" note. The rest of `/issue-close` continues normally.
- Preserve existing formatting conventions (bullet style, sentence case, trailing punctuation). Match the style of the nearest existing entries when in doubt.
- The new bullet's `(#<N>)` suffix is always GitHub issue `#N`, matching the focus issue's number in `.issueflows/01-current-issues/issue<N>_original.md`.
21 changes: 14 additions & 7 deletions .cursor/skills/issueflow-issue-close/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,32 @@ If the user included text after `/issue-close` that requests a version bump:

When a bump applies: read `.cursor/skills/issueflow-version-bump/SKILL.md`, run the bump from the **project root** **after** the sanity check and **before** issue-folder updates and **before** commit / push / PR.

## Changelog update tokens (command input)

- **`nohistory`** or **`skip history`** → skip step 3 entirely.
- **`log "..."`** or **`note "..."`** → override the bullet summary verbatim. Otherwise the GitHub issue title is used.

## Instructions

1. **Sanity check** — Run the project test suite (e.g. `uv run pytest`) and any checks the repo relies on. Skim the diff; avoid bundling unrelated changes.

2. **Optional version bump** — If the user asked for a bump (see above), follow `.cursor/skills/issueflow-version-bump/SKILL.md` and run `uv version --bump <patch|minor|major>`. If there is no bumpable `pyproject.toml`, skip and continue.

3. **Issue tracking** — Under `.issueflows/01-current-issues/`, update the status file: remaining work, checklists, and **`- [x] Done`** only when the issue is fully resolved. If fully resolved, move that issue's markdown files (`issue<n>_*`) to `.issueflows/03-solved-issues/`. If partially resolved, move to `.issueflows/02-partly-solved-issues/`. Follow any stricter rules in `.cursor/rules/issueflow-rules.mdc` if present.
3. **Update `HISTORY.md`** — Unless the user passed `nohistory`, follow `.cursor/skills/issueflow-history-update/SKILL.md`. If step 2 did not bump the version, append a bullet to the `## [Unreleased]` section. If step 2 bumped the version, promote `## [Unreleased]` to `## [<new_version>] - <YYYY-MM-DD>` and open a fresh empty `## [Unreleased]` above it. Show the diff and confirm once before writing. Skip with a note if `HISTORY.md` does not exist at the project root.

4. **Issue tracking** — Under `.issueflows/01-current-issues/`, update the status file: remaining work, checklists, and **`- [x] Done`** only when the issue is fully resolved. If fully resolved, move that issue's markdown files (`issue<n>_*`) to `.issueflows/03-solved-issues/`. If partially resolved, move to `.issueflows/02-partly-solved-issues/`. Follow any stricter rules in `.cursor/rules/issueflow-rules.mdc` if present.

4. **Commit** — First check `git status`; if there are unrelated uncommitted changes, surface them and ask the user whether to include them — do not auto-include or drop silently. Then stage intentionally (include `pyproject.toml` and `uv.lock` if changed after a bump); write a commit message in full sentences describing what changed and why.
5. **Commit** — First check `git status`; if there are unrelated uncommitted changes, surface them and ask the user whether to include them — do not auto-include or drop silently. Then stage intentionally (include `pyproject.toml` and `uv.lock` if changed after a bump, and `HISTORY.md` if step 3 updated it); write a commit message in full sentences describing what changed and why.

5. **Branch hygiene before push** — Run `git fetch --prune`, then sync with the default branch using `git pull --ff-only` (rebase or merge per project preference). Use `--ff-only` so unrelated history never gets pulled in silently; if it refuses, stop and ask how to reconcile. Resolve merge conflicts before pushing.
6. **Branch hygiene before push** — Run `git fetch --prune`, then sync with the default branch using `git pull --ff-only` (rebase or merge per project preference). Use `--ff-only` so unrelated history never gets pulled in silently; if it refuses, stop and ask how to reconcile. Resolve merge conflicts before pushing.

6. **Push** — Push to the remote the project uses (typically `origin`).
7. **Push** — Push to the remote the project uses (typically `origin`).

7. **Pull request** — Open (or update) a PR against the default branch. Body should explain the change, how to test, and link the GitHub issue (`Closes #n` / `Refs #n`).
8. **Pull request** — Open (or update) a PR against the default branch. Body should explain the change, how to test, and link the GitHub issue (`Closes #n` / `Refs #n`).

8. **After review** — Remind the user the working copy is still on the issue branch (not the default). Suggest `git switch <default>` before starting unrelated work. Tell them to run **`/issue-cleanup`** once the PR is merged so the standard post-merge cleanup runs (switch to default, `git pull --ff-only`, `git fetch --prune`, `git branch -d` on merged local branches under a single consolidated confirm).
9. **After review** — Remind the user the working copy is still on the issue branch (not the default). Suggest `git switch <default>` before starting unrelated work. Tell them to run **`/issue-cleanup`** once the PR is merged so the standard post-merge cleanup runs (switch to default, `git pull --ff-only`, `git fetch --prune`, `git branch -d` on merged local branches under a single consolidated confirm).

9. **Output** — Summarize commit, push result, PR URL, and next step (`/issue-cleanup` after merge, or "blocked on …" if stuck).
10. **Output** — Summarize commit, push result, PR URL, and next step (`/issue-cleanup` after merge, or "blocked on …" if stuck).

## Constraints

Expand Down
7 changes: 7 additions & 0 deletions .issueflows/03-solved-issues/issue15_original.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Issue #15: update history when making changes worthy of mentioning

Source: https://github.com/jepegit/issue-flow/issues/15

## Original issue text

It would be nice if issue-flow could help in updating HISTORY.md or similar file. It could be either as a part of `/issue-close` or a new slash command.
Loading
Loading