A single class can appear twice as a subclass of the same class
(e.g. `class (Foo a, Foo b) => Bar a b` produces two SuperclassEdges
with target Foo). The reverse-index push happens per-edge, which is
the right granularity for chain reasoning, but the side-panel list
was rendering each entry verbatim and so duplicated subclass names.
Add a per-render dedup set keyed on the subclass's qid so each
subclass shows up at most once.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
})
.join('');
const subEntries = subclassesByClass.get(cid) || [];
+ // Dedupe by subclass qid: a single class can list the same
+ // superclass twice in ciSuperclasses (e.g. `class (Foo a, Foo b)
+ // => Bar a b` produces two SuperclassEdges with the same target),
+ // which would otherwise show as duplicate rows here.
+ const seenSubs = new Set();
const subs = subEntries.length === 0 ? '<dd><em>none</em></dd>' :
subEntries
.map(({subclass}) => {
const sid = qid(subclass.ciName);
+ if (seenSubs.has(sid)) return '';
+ seenSubs.add(sid);
return `<dd><a href="#" data-action="navigate-class" data-id="${escapeAttr(sid)}">` +
`${escape(subclass.ciName.qnName)}</a></dd>`;
})