* test(#3170): extractOneLinerFromBody must anchor to a summary-shaped heading Regression for #3170: the function matched the first heading's first bold run, so an incidental first heading (rule list, deviation notes) contributed its bold text as the milestone accomplishment. Rows 1/2 fail RED on next; rows 3/4 guard Overview recognition and the #2660 Summary-heading form. * fix(#3170): anchor milestone one-liner extraction to a summary-shaped heading extractOneLinerFromBody matched the first heading's first bold run regardless of section, so an incidental first heading (rule list, deviation notes) contributed its bold text as the milestone accomplishment written into MILESTONES.md. Iterate headings and extract from the first Summary/Overview/ Accomplishments one with a bold run, falling back to null when none exists. The #2660 Summary-heading forms and the frontmatter one-liner precedence are preserved. * docs(#3170): add changeset * test(#3170): align extractOneLinerFromBody unit fixtures with summary-heading contract The core-utils unit fixtures used generic # Title headings encoding the old 'any first heading' contract; the #3170 fix anchors to a Summary/Overview/ Accomplishments heading (the function is summary-specific). Update the heading text to Summary-shaped; the extraction assertions (bold, frontmatter strip, colon-label, CRLF, unicode) are unchanged. * docs(#3170): backfill changeset PR number (3401) --------- Co-authored-by: sim <sim@local>
This commit is contained in:
@@ -502,33 +502,38 @@ describe('extractOneLinerFromBody', () => {
|
||||
assert.strictEqual(coreUtils.extractOneLinerFromBody(''), null);
|
||||
});
|
||||
|
||||
// #3170: extractOneLinerFromBody anchors to a Summary/Overview/Accomplishments
|
||||
// heading (the function is summary-specific — both callers extract a SUMMARY
|
||||
// deliverable one-liner). These fixtures use Summary-shaped headings; the
|
||||
// extraction mechanism under test (heading + bold → bold, frontmatter strip,
|
||||
// colon-label → prose, CRLF, unicode) is unchanged.
|
||||
test('extracts bold text after a heading as one-liner', () => {
|
||||
const content = '# Phase Title\n\n**Implement the feature**\n\nMore details here.\n';
|
||||
const content = '# Phase Summary\n\n**Implement the feature**\n\nMore details here.\n';
|
||||
assert.strictEqual(coreUtils.extractOneLinerFromBody(content), 'Implement the feature');
|
||||
});
|
||||
|
||||
test('returns null when no bold text after heading', () => {
|
||||
const content = '# Phase Title\n\nSome prose without bold.\n';
|
||||
const content = '# Phase Summary\n\nSome prose without bold.\n';
|
||||
assert.strictEqual(coreUtils.extractOneLinerFromBody(content), null);
|
||||
});
|
||||
|
||||
test('strips frontmatter before searching', () => {
|
||||
const content = '---\nstatus: done\n---\n# Title\n\n**One liner here**\n';
|
||||
const content = '---\nstatus: done\n---\n# Summary\n\n**One liner here**\n';
|
||||
assert.strictEqual(coreUtils.extractOneLinerFromBody(content), 'One liner here');
|
||||
});
|
||||
|
||||
test('when bold ends with colon, returns text after the bold', () => {
|
||||
const content = '# Title\n\n**Objective:** Complete the work\n';
|
||||
const content = '# Summary\n\n**Objective:** Complete the work\n';
|
||||
assert.strictEqual(coreUtils.extractOneLinerFromBody(content), 'Complete the work');
|
||||
});
|
||||
|
||||
test('CRLF line endings are normalized', () => {
|
||||
const content = '# Title\r\n\r\n**Bold line**\r\nmore\r\n';
|
||||
const content = '# Summary\r\n\r\n**Bold line**\r\nmore\r\n';
|
||||
assert.strictEqual(coreUtils.extractOneLinerFromBody(content), 'Bold line');
|
||||
});
|
||||
|
||||
test('adversarial: unicode in bold text', () => {
|
||||
const content = '# Title\n\n**中文 one-liner**\n\nMore.\n';
|
||||
const content = '# Summary\n\n**中文 one-liner**\n\nMore.\n';
|
||||
assert.strictEqual(coreUtils.extractOneLinerFromBody(content), '中文 one-liner');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user