<!-- GENERATED by scripts/build-llms.mjs from llms/retrieval.md — do not edit this file. -->

# `lr-provenance-panel`

- **Import** `import '@aceshooting/lyra-ui/components/lr-provenance-panel.js';` (stable tag alias; registers the tag)
- **Class** `LyraProvenancePanel`, also available unregistered from `@aceshooting/lyra-ui/components/retrieval/provenance-panel/provenance-panel.class.js`
- **Family** `components/retrieval/` — see `llms/index.md` for its siblings
- **Status** `stable` since `4.0.0` — see the maturity and deprecation policy in `llms/shared.md`
- **Release history** [CHANGELOG.md](../../CHANGELOG.md); family-wide breaking-change summaries: [llms-full.txt](../../llms-full.txt)
- **Deprecations** none
- **Optional peers** none
- **Themeable via** 7 parts, 1 custom property — see this component's own `@csspart`/`@cssprop` list below
- **Library-wide behavior** (events, form association, `locale`/`strings`, tokens, TS types): `llms/shared.md`

---

## `lr-provenance-panel`

The grounding breakdown for one answer: a sectioned disclosure panel (Entities / Relationships /
Communities / Text chunks) composing this family's own pieces. The chat ↔ graph ↔ document glue
component. Pure projection + event conduit: no fetching, no graph/viewer imports, no persistence.

Malformed type rows are ignored during lookup, preserving valid later matching records and the
existing immutable collection ownership.

**Properties:**

- `provenance: LyraProvenance | null = null` (attribute: false) — `LyraProvenance { entities?:
LyraEntity[]; relationships?: { path: LyraPathElement[] }[]; communities?: LyraCommunity[]; chunks?:
LyraChunk[] }`; each present array renders through the matching sibling component (`lr-entity-
chip` row, one `lr-path-strip` per relationship, `lr-community-card`, `lr-chunk-inspector`);
  `null` or every section empty renders the overall empty state. Non-array nested collections are
  treated as empty; malformed relationship records and blank/later-duplicate entity, community, or
  chunk ids are omitted without hiding valid neighboring records
- `types: LyraNodeTypeStyle[] = []` (attribute: false) — forwarded to the Entities section's chips
- `thresholds: { high: number; medium: number } = { high: 0.75, medium: 0.5 }` (attribute: false) —
  forwarded to the Text chunks section's `lr-chunk-inspector`
- `label?: string` — fallback name for the stable overall group; omission uses the localized panel
  label. A non-empty host `aria-label`
  makes the host the sole overall owner; an explicitly empty host label stays empty

**Events:** `lr-toggle` (`detail: { section, expanded }`, a section header was toggled —
`section` is `'entities' | 'relationships' | 'communities' | 'chunks'`). Because the panel is a
conduit, every affordance it renders also reaches a listener on the panel itself, and all are
part of its typed event map: `lr-entity-select` (`detail: { entityId }`, from an entity chip),
`lr-entity-activate` (`detail: { entityId, occurrenceIndex? }`, from a community card member or
path-strip node — the only name either one emits, and the only one carrying `occurrenceIndex`),
`lr-entity-open` (`detail: { entityId }`, an entity chip double-click or
Space), `lr-drill` (`detail: { communityId }`, a community card's title, drill button, or overflow chip), and
`lr-relation-activate` (`detail: { relation, sourceNodeId?, targetNodeId?, occurrenceIndex }`, a relationship path-strip
edge), plus `lr-chunk-open` (`detail: { chunkId, sourceId, anchor? }`) and `lr-expand`
(`detail: { chunkId, expanded }`) from the chunk inspector.

**Slots:** none.

**CSS parts:** `base`, `section`, `header` (a section's disclosure `<button>`), `count` (a section's
item-count badge), `body` (`hidden` while collapsed), `entity-row` (the wrapping row of entity chips
inside the entities section), `empty` (shown when every section is empty).

**Themeable custom properties:** `--lr-provenance-panel-entity-justify` (default `flex-start`) —
main-axis packing of the entity-chip row; `center` centers every line, the wrapped final one
included. Justifying `::part(body)` cannot do this, because the row fills the body's inline size.
Plus shared tokens.

**Optional peer deps:** none.

```html
<lr-provenance-panel></lr-provenance-panel>
<script>
  document.querySelector("lr-provenance-panel").provenance = {
    entities: [{ id: "e1", label: "Ada Lovelace", type: "person" }],
    chunks: [
      { id: "c1", text: "Revenue grew 12%…", score: 0.91, sourceId: "doc-1" },
    ],
  };
</script>
```

**Known gotchas:**

- Composes `lr-entity-chip`, `lr-path-strip`, `lr-community-card`, and `lr-chunk-inspector`
  directly rather than reimplementing their rendering — events from those inner components (e.g.
  `lr-entity-activate`, `lr-chunk-open`) still bubble/compose up through this panel's light DOM
  for the host to handle in one place.

---
