---
path: /isis/model-merging
surface: admin
domain: isis
auth: signed-in (admin)
source: apps/oshun/admin/src/app/isis/model-merging/page.tsx
status: drafted
last_walked: '—'
---

# Isis ops · Model merging

## Purpose

Operator picks merge components, sets weights, sees an A/B preview against a
fixture set; on save the bridge emits a provenance bundle (parent hashes,
ratios, ratifier signature). Backed by `@isis/lora-training-surface` (§24.5).

## Entry points

- Direct URL — `/isis/model-merging`
- External runbooks / deep links
- Not in canonical IA — no sidebar entry

## Layout regions

Page does NOT wrap in `AdminShell`. Resolves a `MergeContext`
(`{ operatorId, candidateComponents, availableFixtureSets }`) via `binding`
(`bindMergeContextLoader`) and renders `<ModelMergingPanel {...ctx} />`. When
binding is unset, defaults to `operator-anon` with empty component / fixture-set
lists.

- **ModelMergingPanel** — `<main>` with a three-column grid (320px candidates /
  1fr center / 320px provenance):
  - **Candidates aside** (`aria-label="Candidates"`):
    - `<ul data-testid="candidates-list">` with one `<li>` per
      `candidateComponent`
    - Per row: checkbox `data-action="toggle-pick"` plus weight input when
      picked
  - **Center pane** — preview / A-B against fixture set; merge id input
  - **Provenance aside (right)** — built when `picked.length >= 2` and
    `fixtureSetId` is set via `buildProvenanceBundle(request)` (parent hashes,
    ratios, ratifier signature). Otherwise validation runs via
    `validateMergeRequest(request)` and any error is surfaced

## States

- [ ] Anonymous → global middleware redirects
- [ ] Binding unset → `operator-anon`, no candidates, no fixture sets;
      provenance never builds
- [ ] No components picked → `validateMergeRequest` runs but does not surface a
      bundle
- [ ] Single component picked → `validationError` likely populated (must merge
      ≥ 2)
- [ ] ≥ 2 components picked + fixture set chosen → `provenance` built; visible
      in the right aside
- [ ] Provenance build throws → `validationError` shows the message caught from
      `Error.message`
- [ ] Empty `availableFixtureSets` → `fixtureSetId` initialized to `''`;
      provenance never builds until a fixture set exists

## Interactions

- [ ] **Candidate checkbox** (`data-action="toggle-pick"`)
  - Function: `togglePick(c)` adds/removes from `picked`
- [ ] **Weight input** (per picked component)
  - Function: `setWeight(modelHash, weight)` updates ratio
- [ ] **Fixture set selector** — choice from `availableFixtureSets`
- [ ] **Merge id input** — string; defaults to `'merge-draft'`
- [ ] **Provenance bundle viewer** — readonly display of the
      `MergeProvenanceBundle` (parent hashes, ratios, ratifier signature)

## Data & contracts

- **Reads**: `binding()` returns
  `MergeContext = { operatorId, candidateComponents, availableFixtureSets }`
- **Writes**: no BFF write visible at page level. Saving a merge presumably
  happens via a downstream endpoint not in this panel
- **Realtime**: _None._
- **Auth/role check**: only the global middleware

## Cross-references

- Shell: `shell/02-routing-layouts.md`
- Sibling Isis routes: `isis-lora-training.md` (sources merge components),
  `isis-runpod-endpoints.md` (executes inference)
- Related canonical workspace: `../workspaces/content/models.md` (promoted
  merges land in model registry); `../workspaces/safety/rights.md` (provenance
  bundles are inspected there)
- Library: `@isis/lora-training-surface` — `buildProvenanceBundle`,
  `validateMergeRequest`, `MergeComponent`, `MergeRequest`,
  `MergeProvenanceBundle`
- Component source:
  `apps/oshun/admin/src/app/isis/model-merging/ModelMergingPanel.tsx`

## Open questions / known gaps

- [ ] No save / persist action visible in the panel; document the downstream
      endpoint that consumes the provenance bundle
- [ ] No session / scope check at the page level — operator id comes from
      `loadMergeContext`, falling back to `operator-anon` when unbound
- [ ] Document the fixture-set production source (CI eval suite? curated set?)
      for `availableFixtureSets`
