{
  "jimothyPipeline": 1,
  "name": "Release notes from a tag",
  "description": "Writes release notes from the commits since the previous tag and publishes them to the GitHub release.",
  "icon": "rocket",
  "color": "#f97316",
  "repo": {
    "mode": "inplace",
    "localPath": "",
    "baseBranch": "main"
  },
  "concurrency": 1,
  "variables": {
    "product": "Acme, a reporting tool for finance teams. Readers are admins at customer companies."
  },
  "steps": [
    {
      "id": "log",
      "name": "Commits since last tag",
      "type": "shell",
      "description": "Fetches tags and lists the commits between the previous tag and this one.",
      "timeoutMinutes": 3,
      "command": "git fetch -q --tags origin && tag={{issue.title}} && if prev=$(git describe --tags --abbrev=0 \"$tag^\" 2>/dev/null); then echo \"Changes from $prev to $tag\"; git log --no-merges --pretty='- %s (%h)' \"$prev..$tag\"; else echo \"First release: $tag\"; git log --no-merges --pretty='- %s (%h)' \"$tag\" | head -300; fi"
    },
    {
      "id": "draft",
      "name": "Write release notes",
      "type": "agent",
      "description": "Groups the changes for users and leaves out internal work.",
      "harnessId": "anthropic-api",
      "model": "claude-sonnet-5",
      "dependsOn": [
        "log"
      ],
      "timeoutMinutes": 5,
      "systemPrompt": "You write release notes for {{vars.product}} Plain, specific, no hype.",
      "prompt": "{{steps.log.output | truncate:30000}}\n\nWrite the release notes for {{issue.title}} in Markdown with these sections, leaving out any that are empty: ## Breaking changes (with what to do), ## New, ## Improved, ## Fixed. Describe each change by what users can now do or what no longer goes wrong, with the commit hash in brackets. Leave out refactors, tests, CI, dependency bumps and internal tooling.{{#if steps.approve.output}}\n\nYour previous draft was rejected with this feedback. Rewrite it:\n{{steps.approve.output}}{{/if}}"
    },
    {
      "id": "approve",
      "name": "Approve notes",
      "type": "approval",
      "description": "Shows you the notes. Reject with a comment and they are rewritten.",
      "dependsOn": [
        "draft"
      ],
      "loopBackTo": "draft",
      "maxLoops": 3,
      "approvalMessage": "Publish these notes to the {{issue.title}} release?\n\n---\n\n{{steps.draft.output}}"
    },
    {
      "id": "publish",
      "name": "Publish to GitHub",
      "type": "shell",
      "description": "Updates the GitHub release for the tag, or creates it.",
      "dependsOn": [
        "approve"
      ],
      "timeoutMinutes": 3,
      "command": "if gh release view {{issue.title}} >/dev/null 2>&1; then gh release edit {{issue.title}} --notes {{steps.draft.output}}; else gh release create {{issue.title}} --title {{issue.title}} --notes {{steps.draft.output}}; fi && gh release view {{issue.title}} --json url --jq .url"
    }
  ]
}