← All craftbooks

Changelog Cut

Ship and releaseevalv1.0.0released 2026-06-05workflow: build-loop

Cut a new versioned section into a Keep a Changelog / CHANGELOG.md style file for a release — moving entries out of the Unreleased section into a dated, semver-stamped version block under the standard Added / Changed / Deprecated / Removed / Fixed / Security headings, with a fresh empty Unreleased section left behind. A developer gathers the unreleased entries and reconciles them against actual merged changes before a copywriter normalizes them into terse, consistent changelog lines and stamps the version block. Use this whenever you 'cut a release', 'update the changelog', or roll the Unreleased section into a tagged version while keeping the file append-only and machine-comparable.

Steps

Entry step: gather. Each step names the specialist role it wants; the full working prompt is expandable.

  1. Gather unreleased entriesdeveloperentry

    reconcile the Unreleased section against actual merged changes

    Show working prompt
    1. Locate the changelog file (CHANGELOG.md or similar) and read its existing format — Keep a Changelog headings (Added, Changed, Deprecated, Removed, Fixed, Security) are the default; match whatever the file already uses. 2. Read the current Unreleased section and reconcile it against the real merged changes since the last version block (git log / merged PRs) — add anything user-facing that is missing, and remove or merge duplicates. 3. Determine the new version number per semver: bump MAJOR for breaking changes, MINOR for new backward-compatible features, PATCH for fixes only; note the reasoning. 4. Map each entry to the correct heading (Removed and Security are not Changed). 5. Good looks like: a reconciled, categorized list of every unreleased user-facing change, the chosen version number with a one-line semver justification, and the release date. Write an acceptance-criteria checklist ('version follows semver given the change set', 'every entry sits under the correct standard heading', 'Unreleased reconciles with merged changes', 'existing version blocks untouched') plus the inventory to the notes file via write_task_note AND to notes/gather.md.
  2. Cut the version blockcopywriter

    normalize entries and stamp the dated version section

    Show working prompt
    1. Open notes/gather.md and rewrite the changelog so the reconciled entries form a new version block headed '## [VERSION] - YYYY-MM-DD' inserted directly above the previous version block. 2. Under that block, emit only the non-empty standard headings, each with terse, parallel one-line bullets in the imperative ('Add…', 'Fix…') — one change per bullet, no implementation chatter. 3. Leave a fresh, empty '## [Unreleased]' section at the top with the standard heading placeholders. 4. Do NOT alter any pre-existing version block, the file header, or the comparison-link footer except to add the new version's link if the file uses them. 5. Preserve issue/PR references if the file's convention includes them. 6. Good looks like: a clean, append-only CHANGELOG.md where the new dated version block is correct semver, Unreleased is empty, and the file still parses as Keep a Changelog. Write the updated changelog to CHANGELOG.md.
  3. Evaluatereviewer

    Grade the deliverable against every acceptance criterion. All pass → finish; any fail → loop back and fix the gap.

    Show working prompt
    Open CHANGELOG.md and check it against the acceptance criteria in notes/gather.md, PASS/FAIL each. Confirm: (a) a new '## [VERSION] - DATE' block exists with a valid date and a semver-correct version for the change set; (b) every gathered entry appears once under the correct standard heading and empty headings are omitted; (c) a fresh empty Unreleased section sits at the top; (d) all previous version blocks and the file header/footer are unchanged; (e) bullets are terse and parallel with one change each; (f) the file still reads as a valid Keep a Changelog document. Any FAIL routes back to the write phase.
    
    Then route — this is the whole point of the loop:
    
    - **Every criterion PASSES →** call `advance_task_step({ ref, stepId: "evaluate", next: "finish" })`.
    - **Any criterion FAILS →** write the specific gaps to notes, then call `advance_task_step({ ref, stepId: "evaluate", next: "write" })` to loop back. The builder fixes exactly those gaps.
    
    Never route to `finish` while any criterion is unmet. The build phase's completion gate already blocked a grossly-incomplete deliverable; your job is the judgment an automated check cannot make (does it actually work, read well, look right). After ~3 unproductive loops, stop and report DONE_WITH_CONCERNS so the user can step in.
  4. Finishdeveloper

    All acceptance criteria met. Stamp a short summary and report DONE.

    Show working prompt
    Every acceptance criterion passed. Write a one-paragraph DONE summary to task notes via `write_task_note`: what was built, the deliverable path(s), and a one-line confirmation that each criterion is met. Then report DONE.

Triggers

Phrases that suggest this craftbook to a crew.

Source

View this craftbook on GitHub · MIT license