From c5eb38a381fce2ac64576aba44c90b2cc34d5e49 Mon Sep 17 00:00:00 2001 From: Paul Bakaus Date: Fri, 31 Jul 2026 17:21:29 -0700 Subject: [PATCH] Fix wrapped design characteristics Join indented Markdown bullet continuations and keep them out of Overview philosophy text. AI assistance: Codex reproduced the issue, implemented the fix, and added regression coverage under maintainer authorization. --- skill/scripts/lib/design-parser.mjs | 15 +++++++-------- tests/design-parser.test.mjs | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/skill/scripts/lib/design-parser.mjs b/skill/scripts/lib/design-parser.mjs index a4b9e9483..5e2f2c286 100644 --- a/skill/scripts/lib/design-parser.mjs +++ b/skill/scripts/lib/design-parser.mjs @@ -330,17 +330,16 @@ function extractOverview(section) { if (!section) return null; const text = section.lines.join('\n'); const northStar = text.match(/\*\*Creative North Star:\s*"([^"]+)"\*\*/); - const keyChars = []; const keyCharMatch = text.match(/\*\*Key Characteristics:\*\*\s*\n([\s\S]+?)(?:\n##|\n###|$)/); - if (keyCharMatch) { - for (const line of keyCharMatch[1].split('\n')) { - const m = line.match(/^\s*[-*]\s+(.+)$/); - if (m) keyChars.push(stripBold(m[1].trim())); - } - } + const keyChars = keyCharMatch + ? collectBullets(keyCharMatch[1].split('\n')).map((bullet) => stripBold(bullet.trim())) + : []; + const prose = keyCharMatch + ? text.slice(0, keyCharMatch.index) + text.slice(keyCharMatch.index + keyCharMatch[0].length) + : text; // Philosophy paragraphs: everything that isn't a rule header or key-char block - const paragraphs = collectParagraphs(section.lines).filter( + const paragraphs = collectParagraphs(prose.split('\n')).filter( (p) => !p.startsWith('**Creative North Star') && !p.startsWith('**Key Characteristics') diff --git a/tests/design-parser.test.mjs b/tests/design-parser.test.mjs index 16986cab1..053f8dd48 100644 --- a/tests/design-parser.test.mjs +++ b/tests/design-parser.test.mjs @@ -143,3 +143,28 @@ Prose. assert.equal(model.frontmatter.rounded['"2xl"'], undefined); }); }); + +describe('parseDesignMd overview branch', () => { + it('joins wrapped Key Characteristics bullets without leaking continuations into philosophy', () => { + const md = `# Design System: Example + +## Overview + +**Creative North Star: "Structured clarity"** + +**Key Characteristics:** + +- Status remains understandable without relying on color + alone. +- Navigation controls remain visible when the viewport becomes + narrow. +`; + const overview = parseDesignMd(md).overview; + + assert.deepEqual(overview.keyCharacteristics, [ + 'Status remains understandable without relying on color alone.', + 'Navigation controls remain visible when the viewport becomes narrow.', + ]); + assert.deepEqual(overview.philosophy, []); + }); +});