Take every themed list in an entry, not the first one (#585)

* Take every themed list in an entry, not the first one

A long changelog entry is grouped into themed lists behind cf-group labels, and
the extractor stopped at the first one. skill-v4.0.0 shipped 6 of its 19
bullets that way, and v4.1.0 would have shipped 6 of 21.

This is the same shape as the bounded-search fix one commit earlier: the
extractor treated "found a list" as "found the notes". It now collects every
cf-items list inside the entry's own article and joins them, so grouping an
entry for readability cannot silently truncate its release notes.

Written with AI assistance (Claude Code).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Name the malformed case separately

An entry that opens a cf-items list and never closes it inside its article
matched nothing, and the failure said the entry had no list of its own. That is
a different repair, and the message sent you looking for the wrong thing.

Written with AI assistance (Claude Code).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Paul Bakaus
2026-08-14 01:28:36 -04:00
committed by GitHub
co-authored by Claude Opus 5
parent 2c33196c51
commit c8f476b330
+16 -7
View File
@@ -173,14 +173,23 @@ if (headerIdx === -1) {
// went out carrying v4.0.0's notes that way, and nothing failed. A mismatch
// now stops the release instead of publishing another version's words.
const articleEnd = changelogHtml.indexOf('</article>', headerIdx);
const listStart = changelogHtml.indexOf('<ul class="cf-items">', headerIdx);
const listEnd = changelogHtml.indexOf('</ul>', listStart);
if (listStart === -1 || listEnd === -1) fail('Changelog entry markup is malformed.');
if (articleEnd !== -1 && listStart > articleEnd) {
fail(`The changelog entry for "${cfg.changelogLabel}${version}" has no <ul class="cf-items"> of its own. `
+ 'Its bullets are in a list this script cannot read, and the next entry\'s notes would ship instead.');
if (articleEnd === -1) fail('Changelog entry markup is malformed.');
// EVERY list in the entry, not the first. A long release is grouped into
// themed <ul>s behind cf-group labels, and taking only the first published one
// theme and silently dropped the rest.
const entryScope = changelogHtml.slice(headerIdx, articleEnd);
const lists = entryScope.match(/<ul class="cf-items">[\s\S]*?<\/ul>/g);
if (!lists || !lists.length) {
// An unclosed list and a missing one are different repairs, so they get
// different messages. Reporting "no list" for markup that plainly has one
// sends you looking for the wrong thing.
const opened = entryScope.includes('<ul class="cf-items">');
fail(opened
? `The changelog entry for "${cfg.changelogLabel}${version}" opens a <ul class="cf-items"> that is never closed inside its <article>. Fix the markup.`
: `The changelog entry for "${cfg.changelogLabel}${version}" has no <ul class="cf-items"> of its own. `
+ 'Its bullets are in a list this script cannot read, and no notes would ship.');
}
const entryHtml = changelogHtml.slice(listStart, listEnd + '</ul>'.length);
const entryHtml = lists.join('\n');
const notes = htmlToMarkdown(entryHtml);
ok('extracted');