From c333f08eb47ccd45c2121f47b5fe03be6032c7fc Mon Sep 17 00:00:00 2001 From: repo-worker-code-k Date: Sat, 7 Nov 2026 20:20:04 -0600 Subject: [PATCH] fix(aggregator): preserve distinct provider display names --- pm-stack/aggregator/src/provider-display.ts | 12 +++++--- .../aggregator/test/provider-display.test.ts | 29 +++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/pm-stack/aggregator/src/provider-display.ts b/pm-stack/aggregator/src/provider-display.ts index a5c5b9713..1d98617a6 100644 --- a/pm-stack/aggregator/src/provider-display.ts +++ b/pm-stack/aggregator/src/provider-display.ts @@ -2,7 +2,8 @@ // // Rule 0 (#1823, Drew 2026-11-07): a leading underscore is a // config/source-level ownership marker (fleet-built providers carry -// it: _claude, _antigravity, ...). Display surfaces strip it — the +// it: _claude, _antigravity, ...). Display surfaces strip it unless +// that would collide with another provider in the rendered set — the // canonical id keeps it everywhere else. // // Rule (dashboard only, markup only): a provider whose name ends in @@ -35,13 +36,16 @@ function providerHead(name: string): string { * same set. */ export function providerDisplayNames(names: Iterable): Map { - const list = [...names].map((name) => { + const originals = [...names]; + const originalSet = new Set(originals); + const list = originals.map((name) => { const head = providerHead(name); - return head.startsWith("_") ? head.slice(1) + name.slice(head.length) : name; + if (!head.startsWith("_")) return name; + const stripped = head.slice(1) + name.slice(head.length); + return originalSet.has(stripped) ? name : stripped; }); const heads = new Set(list.map(providerHead)); const out = new Map(); - const originals = [...names]; for (let i = 0; i < list.length; i++) { const name = list[i]; const original = originals[i]; diff --git a/pm-stack/aggregator/test/provider-display.test.ts b/pm-stack/aggregator/test/provider-display.test.ts index d96be4ac9..34455d14e 100644 --- a/pm-stack/aggregator/test/provider-display.test.ts +++ b/pm-stack/aggregator/test/provider-display.test.ts @@ -35,6 +35,35 @@ describe("providerDisplayNames (#6125)", () => { expect([...names.keys()].sort()).toEqual(["_antigravity.claude-gpt", "_antigravity.gemini", "_claude", "meta"]); }); + test("reads one-shot iterables exactly once and preserves their input keys", () => { + const inputs = ["_claude", "meta", "_antigravity.gemini"]; + function* providers() { + yield* inputs; + } + + const expected: [string, string][] = [ + ["_claude", "claude"], + ["meta", "meta"], + ["_antigravity.gemini", "antigravity.gemini"], + ]; + expect([...providerDisplayNames(providers())]).toEqual(expected); + + const keys = new Map(inputs.map((name) => [name, true] as const)).keys(); + expect([...providerDisplayNames(keys)]).toEqual(expected); + }); + + test("keeps the ownership marker when stripping it would collide with a plain provider", () => { + const names = providerDisplayNames(["_claude", "claude"]); + expect(names.get("_claude")).toBe("_claude"); + expect(names.get("claude")).toBe("claude"); + }); + + test("keeps dotted renamed providers distinguishable from their plain sibling", () => { + const names = providerDisplayNames(["_antigravity.gemini", "antigravity.gemini"]); + expect(names.get("_antigravity.gemini")).toBe("_antigravity.gemini"); + expect(names.get("antigravity.gemini")).toBe("antigravity.gemini"); + }); + test("non-direct names are untouched", () => { const names = providerDisplayNames(["mistral", "openai.main", "cline-pass", "direct"]); expect(names.get("mistral")).toBe("mistral");