Repository navigation
Description
Describe the bug
duplicate_composition_id reports an error on the multi-instance sub-composition pattern
that sub-compositions.md documents. Everything else in the pipeline handles that pattern
correctly, so the only thing standing in the way is the lint rule.
Reported as:
lint
duplicate_composition_idfalse-positive: repeating the same sub-composition N times
in one host (data-composition-src, samedata-composition-idper sub-compositions.md
'Per-Instance Variables') trips this rule as an error, even though
render/validate/inspect/snapshot all handle it correctly (confirmed via snapshot). Pattern:
word-per-instance captions, e.g.compositions/word-caption.htmlmounted 8x with different
data-variable-valueson one track. Rule has no exemption for elements carrying
data-composition-src.
The documented pattern it rejects
skills/hyperframes-core/references/sub-compositions.md:220 — "Per-Instance Variables":
<div
data-composition-id="data-chart"
data-composition-src="compositions/data-chart.html"
data-variable-values='{"title":"Q4 Revenue","accent":"#66d9ef"}'
...
></div>The host can render the same sub-composition multiple times with different
data-variable-valuesto produce per-instance variations.
Doing exactly that produces N elements sharing one data-composition-id, which is what the
rule errors on.
Root cause
packages/lint/src/rules/composition.ts:268 buckets every element by data-composition-id
and reports any bucket with two or more members:
for (const tag of tags) {
if (isInsideInertTemplate(tag, tags)) continue;
const compositionId = readDecodedAttr(tag.raw, "data-composition-id");
if (!compositionId || compositionId.trim().length === 0) continue;
...
}
...
if (matchingTags.length < 2) continue;The rule has no awareness of data-composition-src — zero references to it in the rule
body. It cannot tell a composition root (where the id must be unique) from a mount of a
sub-composition (where repeating the id is the documented way to get per-instance
variations).
The rule's own message and fixHint show what it was built for — a <meta> tag carrying the
same id as the root <div>:
"Keep data-composition-id on exactly one element, the composition root. Remove it from
metadata or duplicate hosts, especially a<meta>tag carrying the same
data-composition-id as the root<div>, which causes a silent duplicate-id collision."
That is a real collision worth catching. Repeated mounts are not the same thing, and the
runtime already treats them differently: assignRuntimeCompositionIds rewrites repeated
mounts to id__hf1, id__hf2, and so on, precisely so they can coexist.
Suggested fix
Only consider elements that are not sub-composition mounts when looking for duplicates —
i.e. skip any tag carrying data-composition-src, the same way the rule already skips tags
inside an inert <template>.
That keeps the meta-versus-root collision the rule exists for, and stops it contradicting the
documented per-instance pattern.
Regression tests worth having: the documented pattern (same id, multiple
data-composition-src mounts, differing data-variable-values) must be clean, and the
original <meta>-versus-root collision must still error.
Severity note
This is an error, so it blocks check. A user following our own documentation gets a
failing gate and no correct way to satisfy it short of abandoning the pattern.
Environment
hyperframes 0.8.6
Affected packages/lint/src/rules/composition.ts:268
Docs skills/hyperframes-core/references/sub-compositions.md:220
Activity