From 22b26a271ea1d73f51d15e36017f0b21ba68694c Mon Sep 17 00:00:00 2001 From: mpstaton Date: Sat, 9 May 2026 16:35:32 -0500 Subject: [PATCH] fix(sources-footer): use canonical [N]: form per Lossless citation spec Previous fix used [N] without the colon. Lossless-Citation-Spec.md mandates the colon for reference-section identifiers (cite-wide reminders/spec line 68: "always use a `: ` after the citation identifier"). Cite-wide's parser accepts both shapes, but the colon form is canonical and what other Lossless tooling expects to see in checked-in files. Verified the parser flow against cite-wide: - REFDEF_NUM_RE (llmCitationParserService.ts:91) matches both `[N]` and `[N]:` - reformatRefDefBodyAsMarkdownLink (line 547) skips wrapping when the body already contains a markdown link, so `[N]: [Title](URL)` passes through untouched into the hex-conversion stage. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/services/directoryTemplateService.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/services/directoryTemplateService.ts b/src/services/directoryTemplateService.ts index adb3b1b..a8fa786 100644 --- a/src/services/directoryTemplateService.ts +++ b/src/services/directoryTemplateService.ts @@ -63,14 +63,17 @@ function wrapThinkBlocks(text: string): string { function buildSourcesFooter(sources: PerplexitySource[]): string { if (!sources.length) return ''; - // Format matches cite-wide's REFDEF_NUM_RE (`[N] `) so the - // existing "convert to hex citations" command can process this footer. - // See cite-wide/src/services/llmCitationParserService.ts. + // Canonical Lossless reference-section format per + // cite-wide/context-v/reminders/Lossless-Citation-Spec.md: + // "always use a `: ` after the citation identifier". + // cite-wide's parser (REFDEF_NUM_RE, line 91 of llmCitationParserService.ts) + // accepts both `[N]` and `[N]:` thanks to the `(:?)` group, but the colon + // form matches the spec, so emit it. const lines = sources.map((s, i) => { const n = i + 1; const title = (typeof s.title === 'string' && s.title) ? s.title : (s.url ?? 'Source'); const url = s.url ?? ''; - return url ? `[${n.toString()}] [${title}](${url})` : `[${n.toString()}] ${title}`; + return url ? `[${n.toString()}]: [${title}](${url})` : `[${n.toString()}]: ${title}`; }); return '\n\n## Sources\n\n' + lines.join('\n') + '\n'; }