Skip to content

Commit f75d72d

Browse files
committed
fix: link first challenge
1 parent 0ee579e commit f75d72d

6 files changed

Lines changed: 301 additions & 6 deletions

File tree

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import { readFileSync } from "node:fs";
2+
import { join } from "node:path";
3+
4+
import type { Metadata } from "next";
5+
import Link from "next/link";
6+
7+
import { AppShell } from "@/components/layout/AppShell";
8+
import { Badge } from "@/components/ui/Badge";
9+
10+
const challengeDir = "challenges/review/001-sympy-point2d-ai-patch";
11+
const diff = readFileSync(join(process.cwd(), challengeDir, "ai-pr.diff"), "utf8");
12+
13+
export const metadata: Metadata = {
14+
title: "Review 001: SymPy Point2D AI Patch | AgentCode",
15+
description: "Review a real SWE-bench/SymPy AI patch and decide whether it can be merged."
16+
};
17+
18+
export default function FirstReviewChallengePage() {
19+
return (
20+
<AppShell>
21+
<header className="topbar">
22+
<div className="topbar-inner">
23+
<Link className="brand" href="/">
24+
<span className="brand-mark">AC</span>
25+
<strong>AgentCode</strong>
26+
</Link>
27+
<nav className="nav" aria-label="Challenge navigation">
28+
<Link href="/">题库</Link>
29+
<a className="active" href="#review">
30+
第一题
31+
</a>
32+
<a href="#diff">AI Diff</a>
33+
<a href="#rubric">Rubric</a>
34+
</nav>
35+
<div className="actions">
36+
<Link className="button button-outline" href="/">
37+
返回题库
38+
</Link>
39+
</div>
40+
</div>
41+
</header>
42+
43+
<main className="page challenge-page">
44+
<div className="notice">
45+
<span>
46+
<strong>真实来源改编</strong> SymPy issue + SWE-bench / PatchDiff 中的 AI 错误补丁案例。
47+
</span>
48+
<span className="mono">Review 001</span>
49+
</div>
50+
51+
<section className="challenge-header card">
52+
<div className="challenge-kicker">
53+
<span className="id">001</span>
54+
<Badge tone="review">Review</Badge>
55+
<Badge tone="mid">Mid</Badge>
56+
</div>
57+
<h1>这个 AI 修复能合并吗?</h1>
58+
<p>
59+
你正在审核一个 AI agent 生成的补丁。补丁声称修复 SymPy 中 `Point2D` 在 `evaluate(False)`
60+
下误报 `Imaginary coordinates are not permitted` 的问题。
61+
</p>
62+
<div className="source-grid">
63+
<a href="https://github.com/sympy/sympy/issues/22684" rel="noreferrer" target="_blank">
64+
SymPy Issue
65+
</a>
66+
<a href="https://github.com/sympy/sympy/pull/22714" rel="noreferrer" target="_blank">
67+
Correct PR
68+
</a>
69+
<a href="https://arxiv.org/abs/2503.15223" rel="noreferrer" target="_blank">
70+
PatchDiff Paper
71+
</a>
72+
</div>
73+
</section>
74+
75+
<div className="challenge-layout">
76+
<article className="challenge-main">
77+
<section className="challenge-section card" id="review">
78+
<div className="card-head">
79+
<h2>你的任务</h2>
80+
</div>
81+
<div className="section-body">
82+
<p>
83+
阅读下面的 AI PR diff,判断它是否可以 merge。如果不能,需要指出具体问题、影响和修复建议。
84+
</p>
85+
<div className="review-template">
86+
<pre>{`Can merge? Yes / No
87+
88+
Finding 1:
89+
- Severity:
90+
- Problem:
91+
- Why it matters:
92+
- Suggested fix:
93+
94+
Finding 2:
95+
...`}</pre>
96+
</div>
97+
</div>
98+
</section>
99+
100+
<section className="challenge-section card" id="diff">
101+
<div className="card-head">
102+
<h2>AI PR Diff</h2>
103+
<span className="mono">ai-pr.diff</span>
104+
</div>
105+
<pre className="diff-block">{diff}</pre>
106+
</section>
107+
</article>
108+
109+
<aside className="challenge-side">
110+
<section className="card">
111+
<div className="card-head">
112+
<h2>背景</h2>
113+
</div>
114+
<div className="section-body compact">
115+
<p>
116+
SymPy `Point` / `Point2D` 不允许创建带有虚数坐标的点。真实 bug 是:
117+
在 `evaluate(False)` 下,即使输入没有虚数,也可能错误抛出异常。
118+
</p>
119+
<p>
120+
你要审核的是 AI 补丁,不是上游最终合并的正确修复。
121+
</p>
122+
</div>
123+
</section>
124+
125+
<section className="card" id="rubric">
126+
<div className="card-head">
127+
<h2>评分重点</h2>
128+
</div>
129+
<div className="rubric-list">
130+
<div className="rubric-item">
131+
<span>Merge 判断</span>
132+
<strong>30%</strong>
133+
</div>
134+
<div className="rubric-item">
135+
<span>回归风险</span>
136+
<strong>35%</strong>
137+
</div>
138+
<div className="rubric-item">
139+
<span>语义边界</span>
140+
<strong>15%</strong>
141+
</div>
142+
<div className="rubric-item">
143+
<span>测试质量</span>
144+
<strong>10%</strong>
145+
</div>
146+
<div className="rubric-item">
147+
<span>修复建议</span>
148+
<strong>10%</strong>
149+
</div>
150+
</div>
151+
</section>
152+
</aside>
153+
</div>
154+
</main>
155+
</AppShell>
156+
);
157+
}

src/app/globals.css

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,14 @@ a {
155155
}
156156

157157
.button {
158+
align-items: center;
158159
border-radius: 7px;
160+
display: inline-flex;
159161
font-weight: 600;
162+
justify-content: center;
160163
min-height: 36px;
161164
padding: 0 13px;
165+
text-decoration: none;
162166
}
163167

164168
.button-primary {
@@ -391,6 +395,18 @@ h1 {
391395
margin-bottom: 6px;
392396
}
393397

398+
.challenge-title-link {
399+
color: var(--text);
400+
display: block;
401+
font-weight: 600;
402+
margin-bottom: 6px;
403+
text-decoration: none;
404+
}
405+
406+
.challenge-title-link:hover {
407+
color: var(--blue);
408+
}
409+
394410
.title-cell span:not(.mobile-label) {
395411
color: var(--muted);
396412
display: block;
@@ -557,10 +573,114 @@ h1 {
557573
display: none;
558574
}
559575

576+
.challenge-page {
577+
display: grid;
578+
gap: 18px;
579+
}
580+
581+
.challenge-header {
582+
padding: 22px;
583+
}
584+
585+
.challenge-kicker {
586+
align-items: center;
587+
display: flex;
588+
flex-wrap: wrap;
589+
gap: 8px;
590+
margin-bottom: 12px;
591+
}
592+
593+
.challenge-header h1 {
594+
font-size: clamp(28px, 3vw, 38px);
595+
}
596+
597+
.challenge-header p {
598+
color: var(--text-soft);
599+
font-size: 16px;
600+
line-height: 1.7;
601+
margin: 14px 0 0;
602+
max-width: 860px;
603+
}
604+
605+
.source-grid {
606+
display: flex;
607+
flex-wrap: wrap;
608+
gap: 10px;
609+
margin-top: 18px;
610+
}
611+
612+
.source-grid a {
613+
background: var(--surface-soft);
614+
border: 1px solid var(--line);
615+
border-radius: 7px;
616+
color: var(--blue);
617+
font-size: 13px;
618+
font-weight: 600;
619+
padding: 8px 10px;
620+
text-decoration: none;
621+
}
622+
623+
.challenge-layout {
624+
align-items: start;
625+
display: grid;
626+
gap: 18px;
627+
grid-template-columns: minmax(0, 1fr) 330px;
628+
}
629+
630+
.challenge-main,
631+
.challenge-side {
632+
display: grid;
633+
gap: 18px;
634+
}
635+
636+
.section-body {
637+
color: var(--text-soft);
638+
display: grid;
639+
gap: 12px;
640+
font-size: 14px;
641+
line-height: 1.7;
642+
padding: 16px;
643+
}
644+
645+
.section-body p {
646+
margin: 0;
647+
}
648+
649+
.section-body.compact {
650+
gap: 10px;
651+
}
652+
653+
.review-template,
654+
.diff-block {
655+
background: #24201b;
656+
color: #fff7e8;
657+
font-family: var(--mono);
658+
font-size: 12px;
659+
line-height: 1.7;
660+
overflow-x: auto;
661+
}
662+
663+
.review-template {
664+
border-radius: 8px;
665+
padding: 14px;
666+
}
667+
668+
.review-template pre {
669+
margin: 0;
670+
}
671+
672+
.diff-block {
673+
border: 0;
674+
margin: 0;
675+
padding: 16px;
676+
white-space: pre;
677+
}
678+
560679
@media (max-width: 980px) {
561680
.topbar-inner,
562681
.hero-main,
563-
.layout {
682+
.layout,
683+
.challenge-layout {
564684
grid-template-columns: 1fr;
565685
}
566686

src/components/problems/PracticeHome.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"use client";
22

3+
import Link from "next/link";
34
import { useState } from "react";
45

56
import { TopNav } from "@/components/layout/TopNav";
@@ -10,12 +11,12 @@ import { ProblemList } from "@/components/problems/ProblemList";
1011
import { ProblemStatsStrip } from "@/components/problems/ProblemStatsStrip";
1112
import { ProblemToolbar } from "@/components/problems/ProblemToolbar";
1213
import { TopicSidebar } from "@/components/problems/TopicSidebar";
13-
import { Button } from "@/components/ui/Button";
1414
import { challenges, practiceStats } from "@/lib/mock-data/problems";
1515

1616
export function PracticeHome() {
1717
const [language, setLanguage] = useState<Language>("zh");
1818
const labels = copy[language];
19+
const firstChallengeHref = challenges[0]?.href ?? "#";
1920

2021
return (
2122
<>
@@ -35,10 +36,17 @@ export function PracticeHome() {
3536
<h1>{labels.headline}</h1>
3637
<p className="lede">{labels.lede}</p>
3738
<div className="hero-actions">
38-
<Button type="button">{labels.startTask}</Button>
39-
<Button type="button" variant="outline">
39+
<Link className="button button-primary" href={firstChallengeHref}>
40+
{labels.startTask}
41+
</Link>
42+
<a
43+
className="button button-outline"
44+
href="https://github.com/study8677/agentcode/blob/main/plan.md"
45+
rel="noreferrer"
46+
target="_blank"
47+
>
4048
{labels.viewRoadmap}
41-
</Button>
49+
</a>
4250
</div>
4351
</div>
4452

src/components/problems/ProblemRow.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import Link from "next/link";
2+
13
import { Badge } from "@/components/ui/Badge";
24
import type { Language } from "@/components/problems/copy";
35
import type { Challenge } from "@/lib/types/problem";
@@ -46,7 +48,13 @@ export function ProblemRow({ challenge, labels, language }: ProblemRowProps) {
4648
</td>
4749
<td className="title-cell">
4850
<span className="mobile-label">{labels.tableTitle}</span>
49-
<strong>{challenge.title[language]}</strong>
51+
{challenge.href ? (
52+
<Link className="challenge-title-link" href={challenge.href}>
53+
{challenge.title[language]}
54+
</Link>
55+
) : (
56+
<strong>{challenge.title[language]}</strong>
57+
)}
5058
<span>{challenge.summary[language]}</span>
5159
</td>
5260
<td>

src/lib/mock-data/problems.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const practiceStats: PracticeStats = {
1111
export const challenges: Challenge[] = [
1212
{
1313
id: "001",
14+
href: "/challenges/review/001-sympy-point2d-ai-patch",
1415
title: {
1516
zh: "SymPy Point2D AI 补丁审查",
1617
en: "Review a SymPy Point2D AI patch"

src/lib/types/problem.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export type LocalizedText = {
1313

1414
export type Challenge = {
1515
id: string;
16+
href?: string;
1617
title: LocalizedText;
1718
summary: LocalizedText;
1819
mode: ChallengeMode;

0 commit comments

Comments
 (0)