From f98396b412c63ff5069e7f6ecad21cab39b29de1 Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Sun, 23 Aug 2026 13:16:17 -0700 Subject: [PATCH] Pin skill-miss dedup across independent diagnostics collectors The startup path runs the skill-miss summary through seven independent call sites, each with its own PluginLoadDiagnostics collector. Add a test confirming formatPluginWarningsSummary still dedupes correctly when warnings originate from multiple separate collectors, guarding the invariant as more collectors are added to the chain. --- src/plugins/diagnostics.test.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/plugins/diagnostics.test.ts b/src/plugins/diagnostics.test.ts index 3fae61fe1..86f02fd41 100644 --- a/src/plugins/diagnostics.test.ts +++ b/src/plugins/diagnostics.test.ts @@ -68,6 +68,29 @@ describe("formatPluginWarningsSummary", () => { expect(summary).toBe("plugins: 3 skills missing: brand-identity, style, philosophy"); }); + test("dedupes a skill across warnings from independent collectors, not just within one", () => { + // The startup path runs several separate PluginLoadDiagnostics collectors + // (discovery, tool-plugins, trust, verify, add-path, profile resolution), + // each with its own warnings array. If a future collector starts + // reporting the same "skill missing" shape as another, whatever merges + // their warnings before summarizing must still collapse to one entry per + // skill — formatPluginWarningsSummary itself must not care which + // collector instance a warning came from. + const discoveryDiag = createPluginLoadDiagnostics(); + discoveryDiag.warnings.push( + 'agent a: skill "style" referenced but not found in skill search path', + ); + const profileResolutionDiag = createPluginLoadDiagnostics(); + profileResolutionDiag.warnings.push( + 'agent b: skill "style" referenced but not found in skill search path', + 'agent b: skill "philosophy" referenced but not found in skill search path', + ); + + const merged = [...discoveryDiag.warnings, ...profileResolutionDiag.warnings]; + const summary = formatPluginWarningsSummary(merged); + expect(summary).toBe("plugins: 2 skills missing: style, philosophy"); + }); + test("mixed-warning count also counts distinct skills", () => { const summary = formatPluginWarningsSummary([ 'agent a: skill "style" referenced but not found in skill search path',