diff --git a/src/resources/extensions/gsd/tests/visualizer-data.test.ts b/src/resources/extensions/gsd/tests/visualizer-data.test.ts index 3aec834e1..85f740db7 100644 --- a/src/resources/extensions/gsd/tests/visualizer-data.test.ts +++ b/src/resources/extensions/gsd/tests/visualizer-data.test.ts @@ -165,6 +165,17 @@ assertTrue( "VisualizerData has changelog field", ); +// completedAt must be coerced to String() to handle YAML Date objects (issue #644) +assertTrue( + dataSrc.includes("String(summary.frontmatter.completed_at"), + "completedAt assignment coerces to String() for YAML Date safety", +); + +assertTrue( + dataSrc.includes("String(b.completedAt") && dataSrc.includes("String(a.completedAt"), + "changelog sort coerces completedAt to String() for YAML Date safety", +); + // Verify overlay source exists and imports data module const overlayPath = join(__dirname, "..", "visualizer-overlay.ts"); const overlaySrc = readFileSync(overlayPath, "utf-8"); diff --git a/src/resources/extensions/gsd/visualizer-data.ts b/src/resources/extensions/gsd/visualizer-data.ts index 5abf82e01..3e0c75182 100644 --- a/src/resources/extensions/gsd/visualizer-data.ts +++ b/src/resources/extensions/gsd/visualizer-data.ts @@ -379,7 +379,7 @@ async function loadChangelog(basePath: string, milestones: VisualizerMilestone[] path: f.path, description: f.description, })), - completedAt: summary.frontmatter.completed_at ?? '', + completedAt: String(summary.frontmatter.completed_at ?? ''), }; changelogCache.set(cacheKey, { mtime, entry }); @@ -388,7 +388,7 @@ async function loadChangelog(basePath: string, milestones: VisualizerMilestone[] } // Sort by completedAt descending - entries.sort((a, b) => (b.completedAt || '').localeCompare(a.completedAt || '')); + entries.sort((a, b) => String(b.completedAt || '').localeCompare(String(a.completedAt || ''))); return { entries }; }