From 150b2187a2f8e8911a9523172bd735691039823b Mon Sep 17 00:00:00 2001 From: clawedassistant26 <307253840+clawedassistant26@users.noreply.github.com> Date: Sun, 26 Jul 2026 06:18:11 +0000 Subject: [PATCH] fix(prd): stop a `-->` in the idea closing the seed comment early `renderPrd` embeds the idea verbatim in a hidden `` marker. An idea containing `-->` closes that comment at its own terminator, so the rest of the idea and the template's real closer render as visible text at the top of the Problem section. Repro on main: `moshcode prd "ship a parser for --> arrows in specs"` writes arrows in specs --> _Describe the user/business problem, and why it matters now._ Neutralise the terminator in the marker only (`-->`), which is invisible inside the comment. Ideas without `-->` render byte-identically. Two regression tests added; both fail on unpatched src. Full suite 149/149. --- src/prd.mjs | 9 ++++++++- test/prd.test.mjs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/prd.mjs b/src/prd.mjs index c6c22d9..76bcbda 100644 --- a/src/prd.mjs +++ b/src/prd.mjs @@ -108,9 +108,16 @@ How the goals will be measured. `; } +// The seed marker is a hidden HTML comment, so a `-->` inside the idea would +// close it early and render the rest of the idea (plus the real closer) as +// visible text at the top of the Problem section. Neutralise the terminator. +function commentSafe(text) { + return String(text).replace(/--+>/g, (run) => `${run.slice(0, -1)}>`); +} + /** A numbered PRD body (prd/NNNN-slug.md), seeded from an idea. */ export function renderPrd({ id, title, idea, author }) { - const seed = idea && idea !== title ? `\n` : ""; + const seed = idea && idea !== title ? `\n` : ""; return `--- openprd: "${OPENPRD.version}" id: "${id}" diff --git a/test/prd.test.mjs b/test/prd.test.mjs index 6fc7abf..2c66dde 100644 --- a/test/prd.test.mjs +++ b/test/prd.test.mjs @@ -77,3 +77,34 @@ test("regenerateIndex escapes a pipe in a title so the row keeps its columns", ( fs.rmSync(root, { recursive: true, force: true }); } }); + +test("renderPrd keeps a `-->` in the idea from closing the seed comment", () => { + const idea = "add a dark mode toggle and then some more idea text"; + const body = renderPrd({ id: "0007", title: "Add a dark mode toggle", idea, author: "you@example.com" }); + + const lines = body.split(/\r?\n/); + const at = lines.findIndex((l) => l.startsWith("/g).length, 1, `seed comment closes early: ${seedLine}`); + assert.ok(seedLine.endsWith(" and then some more idea text -->"), seedLine); + assert.ok(seedLine.includes(" arrows in specs", root); + + const lines = fs.readFileSync(file, "utf8").split(/\r?\n/); + const at = lines.findIndex((l) => l.startsWith("/g).length, 1, `seed comment closes early: ${lines[at]}`); + assert.match(lines[at + 1], /^_Describe the user\/business problem/); + } finally { + fs.rmSync(root, { recursive: true, force: true }); + } +});