Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
4c26bf2
feat(seer): Replace the level line with an autofix step indicator
jshchnz Jul 20, 2026
1f84721
feat(seer): Treat the merged PR as the pipeline's fifth step
jshchnz Jul 20, 2026
7245e12
fix(seer): Fill the step indicator in fifths so PR-opened isn't full
jshchnz Jul 20, 2026
ffcdb73
ref(seer): Drop the step icon beside the progress ring
jshchnz Jul 20, 2026
2219d21
ref(seer): Tuck the analysis + vitals line under the card title
jshchnz Jul 20, 2026
5a8bfdc
ref(seer): Vitals under the title, analysis toggle at the card's tail
jshchnz Jul 20, 2026
40184c0
fix(seer): Center the progress ring on the title block and size it up
jshchnz Jul 20, 2026
7fb057a
feat(seer): Full-row analysis toggle, linked project badge
jshchnz Jul 20, 2026
032ee7d
feat(seer): Count the steps left to a fix inside the progress ring
jshchnz Jul 20, 2026
0445ada
feat(seer): Inline file differ on overview cards for small fixes
jshchnz Jul 20, 2026
79ad752
feat(seer): Project selector on the Autofix overview
jshchnz Jul 20, 2026
656dbf0
ref(seer): Drop the Workflow runs / Runs demo header buttons
jshchnz Jul 20, 2026
b3a20cb
ref(seer): Adopt the standard top-bar chrome, drop width caps
jshchnz Jul 20, 2026
9f8b49b
fix(seer): Keep long paths from clipping the diff pill tooltip
jshchnz Jul 20, 2026
f4e2b36
feat(seer): Stage-hue ramp on the progress ring
jshchnz Jul 20, 2026
cda2a0d
feat(seer): Traffic-light countdown ramp on the progress ring
jshchnz Jul 20, 2026
3513b8f
fix(seer): Ramp the ring by urgency as the fix nears
jshchnz Jul 20, 2026
544242e
fix(seer): Match card typography to the issues feed and details pages
jshchnz Jul 21, 2026
7f3d2b2
fix(seer): Return the ring to the deepening accent-purple ramp
jshchnz Jul 21, 2026
08df9dc
ref(seer): Remove the quick-filter stat cards
jshchnz Jul 21, 2026
8c34696
feat(seer): Deep-link focus mode via ?id=<issueId>
jshchnz Jul 21, 2026
1f77665
ref(seer): Remove the fixability tag from overview cards
jshchnz Jul 21, 2026
1488b21
feat(seer): Promote Next steps to its own body block on the card face
jshchnz Jul 21, 2026
81a2c6f
fix(seer): Quiet the Next-steps block
jshchnz Jul 21, 2026
1728dfc
fix(seer): Size the card CTAs like the rest of the app's controls
jshchnz Jul 21, 2026
f6efff5
fix(seer): Keep 'have Seer generate the fix' out of Next steps
jshchnz Jul 21, 2026
af62a1d
fix(seer): Cap Next steps at three bullets
jshchnz Jul 21, 2026
f7bbc66
ref(seer): Rename the analysis toggle to More details
jshchnz Jul 21, 2026
d4c89a4
ref(seer): Reset the cursor on filter changes, consolidate the spec
jshchnz Jul 21, 2026
02e82fa
feat(seer): Linear-style collapsible sticky status groups
jshchnz Jul 21, 2026
504162b
feat(seer): Subtle bulk expand/collapse for the status groups
jshchnz Jul 21, 2026
defe950
fix(seer): Double-chevron icon on the bulk group toggle
jshchnz Jul 21, 2026
c815b59
ref(seer): Rework overview cards around a single narrative flow
jshchnz Jul 21, 2026
b0ba4e6
feat(seer): Add a table view toggle to the overview
mtopo27 Jul 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion static/app/views/autofixIssuesDemo/useAutofixIssues.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,16 @@ export interface AutofixIssue extends Issue {

interface UseAutofixIssuesParams {
cursor?: string;
// Gates the issues request; pass page-filters readiness so the initial
// fetch waits for the restored project selection. Defaults to true.
enabled?: boolean;
// Fetch exactly these group ids instead of searching the stream. The
// endpoint ignores every other query component in this mode, so a
// deep-linked issue resolves even outside the list's filters/pagination.
groupIds?: string[];
// Project ids to scope the issue stream to (page-filters selection: [] is
// "My Projects", [-1] is all). Defaults to all accessible projects.
projects?: number[];
query?: string;
// One-shot questions asked about each run (repeatable `question` param,
// capped at 5 by the endpoint). Defaults to this page's demo set.
Expand All @@ -161,6 +171,9 @@ interface UseAutofixIssuesResult {
export function useAutofixIssues({
query,
cursor,
enabled = true,
groupIds: pinnedGroupIds,
projects,
questions = DEMO_QUESTIONS,
runsQuery: runsQueryFilter = RUNS_QUERY,
}: UseAutofixIssuesParams): UseAutofixIssuesResult {
Expand All @@ -173,7 +186,10 @@ export function useAutofixIssues({
query: {
query: withRequiredFilter(query ?? ''),
cursor,
project: -1,
group: pinnedGroupIds,
// In group-id mode the page-filters project selection must not hide
// the deep-linked issue — the backend still enforces access.
project: pinnedGroupIds ? -1 : (projects ?? -1),
statsPeriod: '90d',
// Explicit endpoint default: last-seen desc selects the issues still
// actively occurring as the candidate pool; callers order the loaded
Expand All @@ -183,6 +199,7 @@ export function useAutofixIssues({
},
staleTime: 30_000,
}),
enabled,
select: selectJsonWithHeaders,
});

Expand Down
42 changes: 4 additions & 38 deletions static/app/views/seerWorkflows/overview/attentionBadge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,40 +93,6 @@ export function getAttentionReason(row: OverviewRow): AttentionReason | null {
return null;
}

// Actionable tiers ordered by urgency-to-a-human: blocked-on-you first, then
// nearest-to-shipping, with the low-confidence retry last.
const ATTENTION_TRIAGE_RANK: Record<AttentionReason, number> = {
awaiting_input: 0,
review_pr: 1,
code_changes_ready: 2,
solution_ready: 3,
errored: 4,
};

/**
* Queue position for the overview's triage sort: everything a human can act on
* (ranked by urgency), then rows whose state is still loading (parked in the
* middle so they don't leap from the top when they resolve), then Seer-is-
* working, then diagnosed-only, with merged wins sinking to the bottom as an
* archive shelf. Lower sorts first.
*/
export function getTriageRank(row: OverviewRow, attention: AttentionReason | null) {
if (attention !== null) {
return ATTENTION_TRIAGE_RANK[attention];
}
if (row.statePending) {
return 5;
}
if (row.isProcessing) {
return 6;
}
if (row.prMerged) {
return 8;
}
// Diagnosed-only: informational, optional next step.
return 7;
}

const AccentLinkButton = styled(LinkButton)`
background: ${p => p.theme.tokens.background.accent};
border-color: ${p => p.theme.tokens.border.accent};
Expand Down Expand Up @@ -163,7 +129,7 @@ export function AttentionBadge({
if (reason === 'code_changes_ready') {
return (
<Tooltip title={meta.description} skipWrapper>
<AccentLinkButton size="zero" icon={<meta.Icon />} to={to}>
<AccentLinkButton size="sm" icon={<meta.Icon />} to={to}>
{meta.label}
</AccentLinkButton>
</Tooltip>
Expand All @@ -172,7 +138,7 @@ export function AttentionBadge({
if (reason === 'solution_ready') {
return (
<Tooltip title={meta.description} skipWrapper>
<SuccessLinkButton size="zero" icon={<meta.Icon />} to={to}>
<SuccessLinkButton size="sm" icon={<meta.Icon />} to={to}>
{meta.label}
</SuccessLinkButton>
</Tooltip>
Expand All @@ -181,7 +147,7 @@ export function AttentionBadge({
if (reason === 'errored') {
return (
<Tooltip title={meta.description} skipWrapper>
<MutedLinkButton size="zero" icon={<meta.Icon />} to={to}>
<MutedLinkButton size="sm" icon={<meta.Icon />} to={to}>
{meta.label}
</MutedLinkButton>
</Tooltip>
Expand All @@ -190,7 +156,7 @@ export function AttentionBadge({

return (
<Tooltip title={meta.description} skipWrapper>
<LinkButton size="zero" variant={meta.variant} icon={<meta.Icon />} to={to}>
<LinkButton size="sm" variant={meta.variant} icon={<meta.Icon />} to={to}>
{meta.label}
</LinkButton>
</Tooltip>
Expand Down
43 changes: 33 additions & 10 deletions static/app/views/seerWorkflows/overview/buildOverviewRows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,24 @@ function deriveRunStatus(state: ExplorerAutofixState | null): AutofixRunStatus {
}
}

function extractPatchStats(state: ExplorerAutofixState | null): PatchStats | undefined {
// A diff qualifies for the on-card differ only when it is genuinely small:
// few files, few changed lines, and bounded hunk context so a fix with huge
// surrounding context can't blow the card up.
const INLINE_DIFF_MAX_FILES = 2;
const INLINE_DIFF_MAX_CHANGED_LINES = 25;
const INLINE_DIFF_MAX_RENDERED_LINES = 60;

function extractPatchInfo(state: ExplorerAutofixState | null): {
inlinePatches?: OverviewRow['inlinePatches'];
patchStats?: PatchStats;
} {
const section = getOrderedAutofixSections(state).find(isCodeChangesSection);
if (!section) {
return undefined;
return {};
}
const artifact = getAutofixArtifactFromSection(section);
if (!isCodeChangesArtifact(artifact)) {
return undefined;
return {};
}
// Disambiguate paths with the repo name only when the diff spans repos.
const multiRepo = new Set(artifact.map(filePatch => filePatch.repo_name)).size > 1;
Expand All @@ -90,11 +100,26 @@ function extractPatchStats(state: ExplorerAutofixState | null): PatchStats | und
}))
// Most-changed files first, so a capped tooltip shows what matters.
.sort((a, b) => b.added + b.removed - (a.added + a.removed));
const added = artifact.reduce((sum, filePatch) => sum + filePatch.patch.added, 0);
const removed = artifact.reduce((sum, filePatch) => sum + filePatch.patch.removed, 0);
const renderedLines = artifact.reduce(
(sum, filePatch) =>
sum + filePatch.patch.hunks.reduce((lines, hunk) => lines + hunk.lines.length, 0),
0
);
const inlineEligible =
artifact.length <= INLINE_DIFF_MAX_FILES &&
added + removed <= INLINE_DIFF_MAX_CHANGED_LINES &&
renderedLines > 0 &&
renderedLines <= INLINE_DIFF_MAX_RENDERED_LINES;
return {
fileList,
files: artifact.length,
added: artifact.reduce((sum, filePatch) => sum + filePatch.patch.added, 0),
removed: artifact.reduce((sum, filePatch) => sum + filePatch.patch.removed, 0),
patchStats: {fileList, files: artifact.length, added, removed},
inlinePatches: inlineEligible
? artifact.map(filePatch => ({
patch: filePatch.patch,
repoName: multiRepo ? filePatch.repo_name : undefined,
}))
: undefined,
};
}

Expand Down Expand Up @@ -201,7 +226,6 @@ function buildAnalysis(outputs: RunQuestion[] | undefined): {
entries.push({
key: config.key,
label: config.label,
placement: config.placement,
answer,
});
});
Expand All @@ -223,7 +247,6 @@ function buildOverviewRow(issue: AutofixIssue): OverviewRow {
eventCount: Number.isFinite(eventCount) ? eventCount : 0,
userCount: issue.userCount,
lastSeen: issue.lastSeen,
fixabilityScore: issue.seerFixabilityScore,
lastActivityAt:
state?.updated_at ??
issue.run?.lastTriggeredAt ??
Expand All @@ -237,7 +260,7 @@ function buildOverviewRow(issue: AutofixIssue): OverviewRow {
trigger: mapRunSourceToTrigger(issue.run?.source ?? null),
rawSource: issue.run?.source ?? null,
analysis,
patchStats: extractPatchStats(state),
...extractPatchInfo(state),
pendingQuestion: extractPendingQuestion(state),
...extractPr(state),
};
Expand Down
Loading
Loading