diff --git a/frontend/packages/swarm-ui/src/App.tsx b/frontend/packages/swarm-ui/src/App.tsx
index 854f5169..65d47afe 100644
--- a/frontend/packages/swarm-ui/src/App.tsx
+++ b/frontend/packages/swarm-ui/src/App.tsx
@@ -6,7 +6,6 @@ import { AgentsPage } from './pages/AgentsPage.js';
import { ComponentsPage } from './pages/ComponentsPage.js';
import { JobsPage } from './pages/JobsPage.js';
import { HivesPage } from './pages/HivesPage.js';
-import { IssueReportPage } from './pages/IssueReportPage.js';
import { Panel } from './ui/panel/Panel.js';
function NotFound() {
@@ -24,7 +23,6 @@ export function App() {
-
diff --git a/frontend/packages/swarm-ui/src/pages/IssueReportPage.css b/frontend/packages/swarm-ui/src/pages/IssueReportPage.css
deleted file mode 100644
index 1419727d..00000000
--- a/frontend/packages/swarm-ui/src/pages/IssueReportPage.css
+++ /dev/null
@@ -1,43 +0,0 @@
-/* — the repo-picker + hide-blocked toggle sit in one
- row (mirrors CreateAgentForm's row/wrap pattern: flex-wrap so narrow
- viewports stack instead of overflowing), the label chips get their
- own row below since the set is open-ended and shouldn't fight the
- controls row for width. Sort buttons live inside the table's own
- `
` cells (Table.tsx's `header` now accepts real markup for
- exactly this) so they inherit the table's header styling for free —
- only the pointer cursor + no-underline reset is this page's to own. */
-.issue-report-controls {
- display: flex;
- flex-wrap: wrap;
- align-items: flex-end;
- gap: 1.25em;
- margin-bottom: 1em;
-}
-.issue-report-toggle {
- display: flex;
- align-items: center;
- gap: 0.4em;
- cursor: pointer;
-}
-.issue-report-labels {
- display: flex;
- flex-wrap: wrap;
- gap: 0.6em;
- margin-bottom: 1em;
-}
-.issue-report-label-chip {
- display: flex;
- align-items: center;
- gap: 0.35em;
- cursor: pointer;
- color: var(--muted);
-}
-.issue-report-sort-btn {
- background: none;
- border: none;
- padding: 0;
- margin: 0;
- font: inherit;
- color: inherit;
- cursor: pointer;
-}
diff --git a/frontend/packages/swarm-ui/src/pages/IssueReportPage.tsx b/frontend/packages/swarm-ui/src/pages/IssueReportPage.tsx
deleted file mode 100644
index dc7a352c..00000000
--- a/frontend/packages/swarm-ui/src/pages/IssueReportPage.tsx
+++ /dev/null
@@ -1,318 +0,0 @@
-// — mara's custom issue report: browse open issues
-// across every repo that has one, sortable/filterable her own way, with
-// "hide blocked (open dependency)" as the headline filter and a rank
-// column for how many other open issues depend on each one. Backed by
-// swarm-controller's `GET /api/repos` (dropdown source, only repos with
-// an open issue), `GET /api/issue-report` (default — every repo
-// combined) and `GET /api/repos/{org}/{repo}/issue-report` (once a
-// specific repo is picked) — `blocked` and `depended_on_by_count` both
-// arrive pre-resolved per row, so nothing here does its own
-// dependency-graph walk.
-//
-// Sorting and the label/hide-blocked filters are client-side over
-// whatever's currently loaded — only the repo selection re-fetches.
-// Default sort is `depended_on_by_count` descending: mara's own framing
-// ("i would also like to rank them by how many issues depend on them")
-// reads as the report's headline ordering, not just one more column.
-//
-// No `RefreshIntervalPicker`/auto-poll like the roster pages — this
-// reads as a "generate a report" action rather than a live status view
-// (mara: a "generating report" spinner sub-5s is fine, doesn't need to
-// be instant), so it fetches once per repo-selection change instead of
-// polling.
-import { useEffect, useMemo, useState } from 'preact/hooks';
-import { ApiErrorPanel } from '@hive/shared/api-error-panel.js';
-import { readApiError, type ProblemDetails } from '@hive/shared/api-error.js';
-import { Badge } from '@hive/shared/badge.js';
-import { Panel } from '../ui/panel/Panel.js';
-import { SelectField } from '../ui/select-field/SelectField.js';
-import { Table, type TableColumn } from '../ui/table/Table.js';
-import './IssueReportPage.css';
-
-interface IssueReportRow {
- repo: string;
- number: number;
- title: string;
- labels: string[];
- // `string[]`, not a single `assignee` — forge's own `assignee` field is
- // the legacy single-value one; `assignees` is the real multi-assignee
- // list, and this repo actually uses multiple (caught against an
- // earlier draft of this row shape that had it singular).
- assignees: string[];
- html_url: string | null;
- blocked: boolean;
- depended_on_by_count: number;
-}
-
-type SortKey = 'repo' | 'number' | 'title' | 'assignees' | 'blocked' | 'depended_on_by_count';
-type SortDir = 'asc' | 'desc';
-
-// Sentinel `