Skip to content

Run-history table can silently collide rows for the same repoFullName tracked across different forge hosts #7080

Description

@JSONbored

Context

packages/loopover-miner/lib/run-state.js stores run state keyed by (api_base_url, repo_full_name)
specifically because, per its own migration comment (run-state.js:42), "two forge hosts serving a
same-named owner/repo must not share one 'current state' row." listRunStates() (run-state.js:125-134)
returns apiBaseUrl on every row for exactly this reason.

apps/loopover-miner-ui/vite-run-state-api.ts's hand-written RunStateModule type
(vite-run-state-api.ts:13-16) narrows the row shape to { repoFullName; state; updatedAt }, omitting
apiBaseUrl from the type the rest of the app is built against (the field is still present on the
wire since JSON.stringify serializes the real object regardless of this local type). Client-side,
apps/loopover-miner-ui/src/lib/run-history.ts's RunStateRow type and isRunStateRow validator
likewise only recognize repoFullName, state, and updatedAtapiBaseUrl is dropped entirely
from what the UI is typed to see or display. apps/loopover-miner-ui/src/routes/run-history.tsx's
RunStateTable then keys each row with <TableRow key={row.repoFullName}> (run-history.tsx:92) and
renders only repoFullName in the "Repository" column (run-history.tsx:93) — nothing in the row
distinguishes two forges tracking the same owner/repo.

If the same miner instance ever tracks owner/repo on two different forge hosts (e.g. github.com
and a self-hosted GHE instance — the exact scenario the store's own schema comment calls out), the
run-history table receives two JSON rows with an identical repoFullName but different apiBaseUrl.
React's reconciliation on the duplicate key means one of the two rows is silently dropped/misrendered
instead of both being shown, and even if both rendered, there is no visible way to tell them apart —
they'd show identical "Repository" text with no forge-host indicator.

Requirements

  • apps/loopover-miner-ui/vite-run-state-api.ts's RunStateModule row type must include apiBaseUrl: string,
    matching listRunStates()'s real return shape.
  • apps/loopover-miner-ui/src/lib/run-history.ts's RunStateRow type and isRunStateRow validator
    must include and validate apiBaseUrl: string.
  • apps/loopover-miner-ui/src/routes/run-history.tsx's RunStateTable must key each row on a
    composite of apiBaseUrl + repoFullName (not repoFullName alone), so two rows sharing a
    repoFullName across different forges never collide.
  • The "Repository" column must visibly disambiguate rows sharing a repoFullName across different
    apiBaseUrl values (e.g. showing the forge host alongside the repo name) so an operator can tell
    them apart, not just avoid a React key collision.
  • No change to packages/loopover-miner/lib/run-state.js or the /api/run-state route's response
    shape — the server already returns the needed field; this is a client-side type/render fix.

Deliverables

  • RunStateModule / RunStateRow types include apiBaseUrl
  • isRunStateRow validates apiBaseUrl
  • Table row key is a composite of apiBaseUrl + repoFullName
  • The rendered row visibly disambiguates same-named repos across different forge hosts
  • Regression test: two rows with the same repoFullName and different apiBaseUrl both render as distinct rows

Test Coverage Requirements

apps/** is listed under ignore: in codecov.yml, so this app is not gated by Codecov's 99% patch
check — but the local npm run test:coverage invariant bar still applies, and the regression test
above is required. This changes the rendered "Repository" column, so a before/after screenshot is
required per this repo's UI-PR convention.

Expected Outcome

The run-history table can never silently drop or conflate a repo tracked under two different forge
hosts — every row is uniquely keyed and visibly distinguishable, matching the guarantee the store's
own schema was built to provide.

Links & Resources

packages/loopover-miner/lib/run-state.js (schema comment at line 42, listRunStates at 125-134),
apps/loopover-miner-ui/vite-run-state-api.ts (lines 13-16),
apps/loopover-miner-ui/src/lib/run-history.ts,
apps/loopover-miner-ui/src/routes/run-history.tsx (lines 86-103).

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.help wantedExtra attention is neededvisualUI/web visual work — owner-led, NOT for Gittensor contributors (extensions excepted)

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions