fix : ai slop

This commit is contained in:
2026-09-01 20:54:54 +07:00 Unverified
parent 10e3bf987f
commit e3345e1d66
12 changed files with 27 additions and 27 deletions
+11 -11
View File
@@ -17,17 +17,17 @@ Stand outside the change and ask whether it should exist at all, then verify it
Run these in order. Do not skip ahead. Run these in order. Do not skip ahead.
### 1. Intent — what is this actually trying to do? ### 1. Intent - what is this actually trying to do?
- State the goal in one sentence, in your own words. If you cannot, the artifact is underspecified — say so and stop. - State the goal in one sentence, in your own words. If you cannot, the artifact is underspecified - say so and stop.
- Ask: **is there a simpler, smaller, or more elegant way to achieve the same goal?** Consider: - Ask: **is there a simpler, smaller, or more elegant way to achieve the same goal?** Consider:
- Doing nothing (is the problem real / load-bearing?). - Doing nothing (is the problem real / load-bearing?).
- Using something that already exists in the codebase instead of adding new surface. - Using something that already exists in the codebase instead of adding new surface.
- A smaller change that solves 90% of the goal with 10% of the risk. - A smaller change that solves 90% of the goal with 10% of the risk.
- Solving it at a different layer (config vs code, framework vs app, build vs runtime). - Solving it at a different layer (config vs code, framework vs app, build vs runtime).
- If a better alternative exists, name it explicitly with rationale. This is the most valuable thing you can output — surface it before the line-by-line review. - If a better alternative exists, name it explicitly with rationale. This is the most valuable thing you can output - surface it before the line-by-line review.
### 2. Trace — walk the actual code path ### 2. Trace - walk the actual code path
- For each behavior the change claims, trace the path end-to-end through the real code, not just the lines in the diff: - For each behavior the change claims, trace the path end-to-end through the real code, not just the lines in the diff:
- Entry point → call sites → branches taken → state mutated → exit / return / side effect. - Entry point → call sites → branches taken → state mutated → exit / return / side effect.
@@ -35,7 +35,7 @@ Run these in order. Do not skip ahead.
- For a plan or design doc: trace the proposed flow against the existing system. Where does it touch reality? What does it assume that isn't true? - For a plan or design doc: trace the proposed flow against the existing system. Where does it touch reality? What does it assume that isn't true?
- Note every place the trace surprises you (unexpected branch, dead code reached, state you didn't know existed). Surprises are signal. - Note every place the trace surprises you (unexpected branch, dead code reached, state you didn't know existed). Surprises are signal.
### 3. Verify — does it actually do what it claims? ### 3. Verify - does it actually do what it claims?
For each claim the change/plan makes, answer: For each claim the change/plan makes, answer:
@@ -48,18 +48,18 @@ For each claim the change/plan makes, answer:
Output one tight section per finding. Order by severity (blocker → major → nit). For each: Output one tight section per finding. Order by severity (blocker → major → nit). For each:
- **Finding** — one sentence, specific. Cite `file:line` when applicable. - **Finding** - one sentence, specific. Cite `file:line` when applicable.
- **Why it matters** — the consequence, not the principle. - **Why it matters** - the consequence, not the principle.
- **Evidence** — the trace step or input that exposes it. - **Evidence** - the trace step or input that exposes it.
- **Suggested change** — concrete, minimal. - **Suggested change** - concrete, minimal.
Close with a one-line verdict: ship / fix-then-ship / rework / reject — with the single biggest reason. Close with a one-line verdict: ship / fix-then-ship / rework / reject - with the single biggest reason.
## Operating rules ## Operating rules
- **No rubber-stamps.** "LGTM" is not an output. If you genuinely find nothing, say what you traced and what you checked, so the user can judge whether your review covered the surface they cared about. - **No rubber-stamps.** "LGTM" is not an output. If you genuinely find nothing, say what you traced and what you checked, so the user can judge whether your review covered the surface they cared about.
- **Cite or it didn't happen.** Every claim about the code references a specific path, file, or line. No vague "this might break under load." - **Cite or it didn't happen.** Every claim about the code references a specific path, file, or line. No vague "this might break under load."
- **Distinguish claim from verification.** "The PR says X" and "I traced X and confirmed / refuted it" are different — keep them separate in the output. - **Distinguish claim from verification.** "The PR says X" and "I traced X and confirmed / refuted it" are different - keep them separate in the output.
- **One simpler-alternative pass is mandatory.** Even on small changes, spend one breath asking if the whole thing is necessary. Skip only if the user explicitly says "don't question scope." - **One simpler-alternative pass is mandatory.** Even on small changes, spend one breath asking if the whole thing is necessary. Skip only if the user explicitly says "don't question scope."
- **Don't pad with style nits when there's a structural problem.** If step 1 or step 2 surfaces a real issue, lead with it; defer nits or drop them. - **Don't pad with style nits when there's a structural problem.** If step 1 or step 2 surfaces a real issue, lead with it; defer nits or drop them.
- **No flattery, no hedging.** "This is a great PR but..." adds nothing. State the finding. - **No flattery, no hedging.** "This is a great PR but..." adds nothing. State the finding.
+2 -2
View File
@@ -2,8 +2,8 @@
# This is NOT the Next.js you know # This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices. This version has breaking changes - APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices.
This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean. This block is written and re-added by `next dev` - verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean.
<!-- END:nextjs-agent-rules --> <!-- END:nextjs-agent-rules -->
+1 -1
View File
@@ -11,7 +11,7 @@ export async function generateMetadata({ params }: { params: Params }): Promise<
await connection(); await connection();
const { character, page } = await params; const { character, page } = await params;
const guide = await getCachedPublicGuide(character); const guide = await getCachedPublicGuide(character);
return guide ? { title: `${page} — ${guide.name} — คู่มือ`, description: guide.overview } : { title: "ไม่พบไกด์" }; return guide ? { title: `${page} - ${guide.name} - คู่มือ`, description: guide.overview } : { title: "ไม่พบไกด์" };
} }
export default async function GuideSectionPage({ params }: { params: Params }) { export default async function GuideSectionPage({ params }: { params: Params }) {
+1 -1
View File
@@ -15,7 +15,7 @@ export async function generateMetadata({
await connection(); await connection();
const guide = await getCachedPublicGuide((await params).character); const guide = await getCachedPublicGuide((await params).character);
return guide return guide
? { title: `${guide.name} — คู่มือ`, description: guide.overview } ? { title: `${guide.name} - คู่มือ`, description: guide.overview }
: { title: "ไม่พบไกด์" }; : { title: "ไม่พบไกด์" };
} }
@@ -227,7 +227,7 @@ export async function GET(
<div style={{ display: "flex", fontSize: 17, fontWeight: 700 }}>{stat.label}</div> <div style={{ display: "flex", fontSize: 17, fontWeight: 700 }}>{stat.label}</div>
<div style={{ display: "flex", width: "100%", borderTop: "1px solid #34343d" }} /> <div style={{ display: "flex", width: "100%", borderTop: "1px solid #34343d" }} />
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 4, fontSize: 14, lineHeight: 1.45 }}> <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 4, fontSize: 14, lineHeight: 1.45 }}>
{stat.values.length ? stat.values.map((value, index) => <span key={`${value}-${index}`} style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 5, color: statPriorityColor(index), whiteSpace: "normal", wordBreak: "break-word" }}>{recommendedStatAsset(value) ? <img src={recommendedStatAsset(value)!} alt="" width={18} height={18} style={{ objectFit: "contain" }} /> : null}{statLabel(value)}</span>) : "—"} {stat.values.length ? stat.values.map((value, index) => <span key={`${value}-${index}`} style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 5, color: statPriorityColor(index), whiteSpace: "normal", wordBreak: "break-word" }}>{recommendedStatAsset(value) ? <img src={recommendedStatAsset(value)!} alt="" width={18} height={18} style={{ objectFit: "contain" }} /> : null}{statLabel(value)}</span>) : "-"}
</div> </div>
</div> </div>
))} ))}
+1 -1
View File
@@ -4,7 +4,7 @@ import {
ogImageSize, ogImageSize,
} from "@/lib/og-image"; } from "@/lib/og-image";
export const alt = "Buzz Guide — คู่มือเกนชินสาธารณะที่เตรียมไว้ให้คุณ"; export const alt = "Buzz Guide - คู่มือเกนชินสาธารณะที่เตรียมไว้ให้คุณ";
export const size = ogImageSize; export const size = ogImageSize;
export const contentType = ogImageContentType; export const contentType = ogImageContentType;
+2 -2
View File
@@ -272,7 +272,7 @@ function DataSourceEditor({
<datalist id={`fields-${source.id}`}> <datalist id={`fields-${source.id}`}>
{source.fields.filter((candidate) => candidate.key !== field.key).map((candidate) => <option key={candidate.key} value={candidate.key}>{candidate.label}</option>)} {source.fields.filter((candidate) => candidate.key !== field.key).map((candidate) => <option key={candidate.key} value={candidate.key}>{candidate.label}</option>)}
</datalist> </datalist>
{cell?.error ? <FieldError>สูตรนี้ยังคำนวณไม่ได้: ตรวจสอบชื่อฟิลด์และตัวหาร</FieldError> : <FieldDescription>ตัวอย่างผลลัพธ์: <span className="font-mono text-foreground">{cell?.display ?? "—"}</span></FieldDescription>} {cell?.error ? <FieldError>สูตรนี้ยังคำนวณไม่ได้: ตรวจสอบชื่อฟิลด์และตัวหาร</FieldError> : <FieldDescription>ตัวอย่างผลลัพธ์: <span className="font-mono text-foreground">{cell?.display ?? "-"}</span></FieldDescription>}
</Field> </Field>
); );
})} })}
@@ -280,7 +280,7 @@ function DataSourceEditor({
<div className="overflow-hidden rounded-lg border"> <div className="overflow-hidden rounded-lg border">
<Table> <Table>
<TableHeader><TableRow>{source.fields.slice(0, 3).map((field) => <TableHead key={field.key}>{field.label}</TableHead>)}<TableHead className="w-12" /></TableRow></TableHeader> <TableHeader><TableRow>{source.fields.slice(0, 3).map((field) => <TableHead key={field.key}>{field.label}</TableHead>)}<TableHead className="w-12" /></TableRow></TableHeader>
<TableBody>{source.rows.slice(0, 10).map((row) => <TableRow key={row.id}>{source.fields.slice(0, 3).map((field) => <TableCell key={field.key} className="max-w-28 truncate">{row.values[field.key] ?? previewRow?.cells[field.key]?.display ?? "—"}</TableCell>)}<TableCell><Button size="xs" variant="ghost" onClick={() => setRowId(row.id)}>แก้ไข</Button></TableCell></TableRow>)}</TableBody> <TableBody>{source.rows.slice(0, 10).map((row) => <TableRow key={row.id}>{source.fields.slice(0, 3).map((field) => <TableCell key={field.key} className="max-w-28 truncate">{row.values[field.key] ?? previewRow?.cells[field.key]?.display ?? "-"}</TableCell>)}<TableCell><Button size="xs" variant="ghost" onClick={() => setRowId(row.id)}>แก้ไข</Button></TableCell></TableRow>)}</TableBody>
</Table> </Table>
</div> </div>
<Button <Button
+2 -2
View File
@@ -84,7 +84,7 @@ function displayCell(
field: string, field: string,
): string { ): string {
const cell = evaluated.rows.find((row) => row.id === rowId)?.cells[field]; const cell = evaluated.rows.find((row) => row.id === rowId)?.cells[field];
return cell && !cell.error && cell.display != null ? cell.display : "—"; return cell && !cell.error && cell.display != null ? cell.display : "-";
} }
export function collectGuideSections( export function collectGuideSections(
@@ -538,7 +538,7 @@ function RankingBlock({
#{index + 1} #{index + 1}
</span> </span>
<div className="min-w-0"> <div className="min-w-0">
{detail && detail !== "—" ? ( {detail && detail !== "-" ? (
<TermDetail label={label} detail={detail} /> <TermDetail label={label} detail={detail} />
) : ( ) : (
<span className="font-medium">{label}</span> <span className="font-medium">{label}</span>
+2 -2
View File
@@ -437,7 +437,7 @@ function ArtifactSection({ guide }: { guide: PublicGuide }) {
<div className="relative size-14 overflow-hidden rounded-xl border bg-muted sm:size-20"> <div className="relative size-14 overflow-hidden rounded-xl border bg-muted sm:size-20">
{catalogTalent?.iconUrl ? <Image src={catalogTalent.iconUrl} alt={talentName} fill className="object-contain" /> : <span className="grid size-full place-items-center font-semibold">{talent.type}</span>} {catalogTalent?.iconUrl ? <Image src={catalogTalent.iconUrl} alt={talentName} fill className="object-contain" /> : <span className="grid size-full place-items-center font-semibold">{talent.type}</span>}
</div> </div>
<Badge variant="secondary">{talent.level ? `เลเวล ${talent.level}+` : "—"}</Badge> <Badge variant="secondary">{talent.level ? `เลเวล ${talent.level}+` : "-"}</Badge>
<p className="text-xs font-medium sm:text-sm">{talentName}</p> <p className="text-xs font-medium sm:text-sm">{talentName}</p>
<p className="text-[11px] text-muted-foreground sm:text-xs">{talentTypeLabel(talent.type)}</p> <p className="text-[11px] text-muted-foreground sm:text-xs">{talentTypeLabel(talent.type)}</p>
</div> </div>
@@ -506,7 +506,7 @@ function ArtifactStat({ iconSrc, label, values }: { iconSrc: string; label: stri
? values.map((value, index) => ( ? values.map((value, index) => (
<ArtifactStatValue key={`${value}-${index}`} value={value} index={index} /> <ArtifactStatValue key={`${value}-${index}`} value={value} index={index} />
)) ))
: <span>—</span>} : <span>-</span>}
</div> </div>
</div> </div>
); );
+1 -1
View File
@@ -134,7 +134,7 @@ function snapshot(pageSlug: string): PageSnapshot | null {
sortOrder: 0, sortOrder: 0,
config: { config: {
eyebrow: "คู่มือตัวละคร", eyebrow: "คู่มือตัวละคร",
title: "แอสตรา — ผู้กำหนดจังหวะสนามรบ", title: "แอสตรา - ผู้กำหนดจังหวะสนามรบ",
subtitle: "ตัวสนับสนุนที่เพิ่มพลังให้ทีมผ่านการจัดลำดับสกิล", subtitle: "ตัวสนับสนุนที่เพิ่มพลังให้ทีมผ่านการจัดลำดับสกิล",
summary: summary:
"ตัวอย่างนี้แสดงว่าคู่มือสามารถอ่านง่ายบนมือถือและยังรองรับข้อมูลคำนวณที่ตรวจสอบได้", "ตัวอย่างนี้แสดงว่าคู่มือสามารถอ่านง่ายบนมือถือและยังรองรับข้อมูลคำนวณที่ตรวจสอบได้",
+1 -1
View File
@@ -89,7 +89,7 @@ export function createEditorBlock(
callout: { title: "ข้อควรรู้", body: "เพิ่มรายละเอียด", tone: "info" }, callout: { title: "ข้อควรรู้", body: "เพิ่มรายละเอียด", tone: "info" },
"stat-cards": { "stat-cards": {
title: "ค่าสำคัญ", title: "ค่าสำคัญ",
items: [{ id: nestedId(), label: "ค่า", value: "—" }], items: [{ id: nestedId(), label: "ค่า", value: "-" }],
}, },
"key-value": { "key-value": {
items: [{ id: nestedId(), label: "หัวข้อ", value: "รายละเอียด" }], items: [{ id: nestedId(), label: "หัวข้อ", value: "รายละเอียด" }],
+2 -2
View File
@@ -160,8 +160,8 @@ export const builtInTemplates: readonly TemplateBlueprint[] = [
config: { config: {
title: "เป้าหมายค่าสถานะ", title: "เป้าหมายค่าสถานะ",
items: [ items: [
{ id: "@id:stat-1", label: "ค่าสำคัญ", value: "—" }, { id: "@id:stat-1", label: "ค่าสำคัญ", value: "-" },
{ id: "@id:stat-2", label: "ค่ารอง", value: "—" }, { id: "@id:stat-2", label: "ค่ารอง", value: "-" },
], ],
}, },
}, },