mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-29 12:55:16 -07:00
feat(changelog): add nested bullet format for release notes
- Prompt now requests short top-level bullets with nested change/benefit/action sub-bullets in release-notes mode - CHANGELOG mode keeps single-line bullets unchanged - Tests assert new prompt constraints are present
This commit is contained in:
@@ -35,6 +35,7 @@ How fragments turn into a release:
|
|||||||
|
|
||||||
- At release time, `bun run changelog:build` (and `bun run changelog:prerelease-notes`) pipes every pending fragment through `claude -p` to merge related items, drop noise, and rewrite into a clean user-facing release body. Write fragments as raw, informative notes — don't worry about polished prose, deduping across PRs, or line-by-line phrasing. The polish step handles all of that.
|
- At release time, `bun run changelog:build` (and `bun run changelog:prerelease-notes`) pipes every pending fragment through `claude -p` to merge related items, drop noise, and rewrite into a clean user-facing release body. Write fragments as raw, informative notes — don't worry about polished prose, deduping across PRs, or line-by-line phrasing. The polish step handles all of that.
|
||||||
- The polish step treats pending fragments as the final release outcome, not prerelease history. If a feature is added and then renamed or fixed before the stable cut, ship the final feature bullet instead of separate prerelease-only breaking/fix entries.
|
- The polish step treats pending fragments as the final release outcome, not prerelease history. If a feature is added and then renamed or fixed before the stable cut, ship the final feature bullet instead of separate prerelease-only breaking/fix entries.
|
||||||
|
- GitHub release notes and prerelease notes use short top-level items with nested bullets for the change, user benefit, and any useful action note. The stable `CHANGELOG.md` can stay in compact single-line bullets.
|
||||||
- `internal` fragments stay in `CHANGELOG.md` (inside a collapsed `<details>` block) but are dropped from the GitHub release notes entirely.
|
- `internal` fragments stay in `CHANGELOG.md` (inside a collapsed `<details>` block) but are dropped from the GitHub release notes entirely.
|
||||||
- The polished `CHANGELOG.md` and `release/release-notes.md` are committed and reviewed before tagging — edit the Markdown by hand if Claude misses something.
|
- The polished `CHANGELOG.md` and `release/release-notes.md` are committed and reviewed before tagging — edit the Markdown by hand if Claude misses something.
|
||||||
|
|
||||||
|
|||||||
@@ -3,3 +3,4 @@ area: release
|
|||||||
|
|
||||||
- Release-note polishing treats pending fragments and reviewed prerelease notes as a cumulative final outcome, collapsing prerelease-only fixes or breakages into the final user-facing change.
|
- Release-note polishing treats pending fragments and reviewed prerelease notes as a cumulative final outcome, collapsing prerelease-only fixes or breakages into the final user-facing change.
|
||||||
- Prerelease note generation reuses existing reviewed notes and merges only new fragment material, and `make clean` preserves `release/prerelease-notes.md`.
|
- Prerelease note generation reuses existing reviewed notes and merges only new fragment material, and `make clean` preserves `release/prerelease-notes.md`.
|
||||||
|
- Release-note polishing now asks Claude to write short, nested highlight bullets so longer changes are easier to scan.
|
||||||
|
|||||||
@@ -43,6 +43,14 @@ function fragmentTypesInPrompt(input: string): string[] {
|
|||||||
.map((line) => line.slice('type: '.length).trim());
|
.map((line) => line.slice('type: '.length).trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function assertReleaseNotesPromptRequestsNestedBullets(input: string): void {
|
||||||
|
assert.match(input, /In MODE: release-notes, use short top-level change bullets/);
|
||||||
|
assert.match(input, /Nested bullets should cover the change, user benefit, and any user action/);
|
||||||
|
assert.match(input, /Do not require the exact nested labels/);
|
||||||
|
assert.match(input, /Keep nested bullets short, concrete, and readable by non-technical users/);
|
||||||
|
assert.match(input, /Avoid paragraph-style release-note bullets/);
|
||||||
|
}
|
||||||
|
|
||||||
function defaultPolishedBody(input: string): string {
|
function defaultPolishedBody(input: string): string {
|
||||||
const mode = modeFromPrompt(input);
|
const mode = modeFromPrompt(input);
|
||||||
const types = fragmentTypesInPrompt(input);
|
const types = fragmentTypesInPrompt(input);
|
||||||
@@ -437,6 +445,12 @@ test('writeChangelogArtifacts prompts Claude to summarize the final stable outco
|
|||||||
/Multiple fixes within the same prerelease cycle should collapse into one current-state bullet/,
|
/Multiple fixes within the same prerelease cycle should collapse into one current-state bullet/,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const releaseNotesPrompt = stub.calls.find(
|
||||||
|
(call) => modeFromPrompt(call.input) === 'release-notes',
|
||||||
|
);
|
||||||
|
assert.ok(releaseNotesPrompt, 'expected a release-notes Claude invocation');
|
||||||
|
assertReleaseNotesPromptRequestsNestedBullets(releaseNotesPrompt.input);
|
||||||
} finally {
|
} finally {
|
||||||
fs.rmSync(workspace, { recursive: true, force: true });
|
fs.rmSync(workspace, { recursive: true, force: true });
|
||||||
}
|
}
|
||||||
@@ -706,6 +720,7 @@ test('writePrereleaseNotesForVersion prompts Claude to revise stale prerelease b
|
|||||||
prompt,
|
prompt,
|
||||||
/Multiple fixes within the same prerelease cycle should collapse into one current-state bullet/,
|
/Multiple fixes within the same prerelease cycle should collapse into one current-state bullet/,
|
||||||
);
|
);
|
||||||
|
assertReleaseNotesPromptRequestsNestedBullets(prompt);
|
||||||
} finally {
|
} finally {
|
||||||
fs.rmSync(workspace, { recursive: true, force: true });
|
fs.rmSync(workspace, { recursive: true, force: true });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -260,14 +260,18 @@ You will receive a list of FRAGMENT entries below. Each fragment has metadata (t
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
Do not include the Internal section at all in MODE: release-notes; internal fragments will not be present in the input for that mode.
|
Do not include the Internal section at all in MODE: release-notes; internal fragments will not be present in the input for that mode.
|
||||||
4. Each bullet should:
|
4. Each top-level change item should:
|
||||||
- Lead with a short feature/area name in title case followed by a colon, e.g. "Playlist browser:", "Windows overlay:", "Stats dashboard:". Pick the name from the fragment's bullet content, not the raw 'area:' slug.
|
- Lead with a short feature/area name in title case. Pick the name from the fragment's bullet content, not the raw 'area:' slug.
|
||||||
- Be written in user-facing language. Drop implementation jargon, internal class names, file paths, and PR numbers.
|
- Be written in user-facing language. Drop implementation jargon, internal class names, file paths, and PR numbers.
|
||||||
- Be merged with related bullets when possible. If five fragments all touch Windows overlay z-order/focus/restore, write one or two bullets that summarize the overall improvement instead of five.
|
- Be merged with related bullets when possible. If five fragments all touch Windows overlay z-order/focus/restore, write one or two bullets that summarize the overall improvement instead of five.
|
||||||
- Drop bullets that only describe PR housekeeping, CodeRabbit follow-ups, or test-only changes that don't affect users.
|
- Drop bullets that only describe PR housekeeping, CodeRabbit follow-ups, or test-only changes that don't affect users.
|
||||||
- Preserve the substance of breaking changes that remain breaking after applying the Release Outcome Rules. Do not soften or omit them.
|
- Preserve the substance of breaking changes that remain breaking after applying the Release Outcome Rules. Do not soften or omit them.
|
||||||
5. Do not invent features. Every bullet must be grounded in the input fragments.
|
5. In MODE: changelog, each item may be a conventional single-level bullet, e.g. "- Playlist Browser: Adds faster saved-show browsing."
|
||||||
6. Do not include the version heading (## v...) — that wrapper is added by the caller.
|
6. In MODE: release-notes, use short top-level change bullets with two or three nested bullets when an item needs explanation.
|
||||||
|
Nested bullets should cover the change, user benefit, and any user action or compatibility note when useful. Do not require the exact nested labels; natural phrasing is fine. Omit the action bullet when no action is needed.
|
||||||
|
Keep nested bullets short, concrete, and readable by non-technical users. Avoid paragraph-style release-note bullets.
|
||||||
|
7. Do not invent features. Every bullet must be grounded in the input fragments.
|
||||||
|
8. Do not include the version heading (## v...) — that wrapper is added by the caller.
|
||||||
|
|
||||||
The input begins below.
|
The input begins below.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user