Skip to content
ExamsLibraryFor agentsConnect your agent

Code tells and leftovers

intermediate·8 min·Markdown for agents

What this lesson teaches

Clean the over-defended, over-commented residue agents leave in UI code, and catch the dev tools, routes, logs and secrets that must never ship.

  1. 1The pass, in order
  2. 2Leftovers and leaks

An agent wrote this component. It compiles, the tests pass, and the page works. Tap every line that gives away who wrote it.

Tap every line that reads as generated 0 of 7 found
components/InvoiceListV2.tsx
import { useEffect, useState } from "react"; useEffect(() => {fetch("/api/invoices").then((result) => setData(result))}, []);}

Tap any detail that a model would produce by default. Each find is numbered and explained here.

Seven code tells in sixteen lines. The default fix for almost all of them is deletion.

Nobody flags generated code for one bad line. They recognize the accumulation: a comment narrating every statement, a try-catch around code that can't throw, a fallback to an empty array, a helper that already exists two files over.

There is a reason. Models learned from places where code that runs in isolation wins, so they over-defend, over-comment and over-scaffold. Everything that keeps a snippet alive on its own makes it noise inside a real codebase. These are .

The pass, in order

Scan for comments, then defense, then types, names, structure, logging, tests and scope. Delete first; rewrite only where behavior must survive.

Comments. One test: does it say something the code can't? A constraint, a unit, a tradeoff, the bug it works around: keep. Narration (// increment the counter), notes to a reviewer (// Updated to use the new API), section dividers, commented-out code: delete.

Defensive theater.

  • Null checks against states the types already rule out. Fix the type once.
  • Catch, log, rethrow. Empty catches. catch (e) { console.error(e) } that carries on as if nothing happened.
  • The is the most dangerous item on the list. catch { return [] } turns a broken API into "No invoices yet". Tests stay green while the main path is broken.

When removing a cast, catch or fallback forces a choice, choose the loud failure (a thrown error, a failed build, a visible error state) over the quiet wrong answer.

Types and names. as any, @ts-ignore and a ! that silences instead of fixes: the compiler error was information. data, result, item say nothing; unpaidInvoices does. fetchDataV2, EnhancedButton, utils-new.ts: replace the old thing and take its name.

Structure. One-call wrappers, an options object with one caller, an interface with one implementation, a duplicate helper the model didn't search for, TODO: implement error handling.

Logs and tests. console.log("here") and ✅ Successfully initialized! are debug leftovers. Never delete, skip or weaken a test to make it pass, and be wary of a test that recomputes the implementation's own math: it passes when both are wrong.

✕ Before

// Fetch the data
fetch("/api/invoices")
  .then((res) => res.json())
  .then((result) =>
    setData(result))
  .catch(() => setData([]));

✓ After

const res =
  await fetch("/api/invoices");
if (!res.ok)
  throw new Error(
    `Invoices ${res.status}`);
setInvoices(await res.json());
Match the room. A codebase that is dense with comments by convention isn't slop; rewriting it to your taste is a drive-by change.

Keep the diff to what the task needed, and propose unrelated cleanup separately.

Leftovers and leaks

The second half is worse, because none of it shows up as a bug. The app works. It just ships an inspector panel to every visitor, lets search engines index /lab, and prints the session to the console.

Tap what must not ship 0 of 6 found
.env.production
app/layout.tsx
import { Leva } from "leva";
app/lab/page.tsx
lib/auth.ts
app/api/invoices/[id]/route.ts
export async function DELETE(req, { params }) {await db.invoice.delete({ where: { id: params.id } });}
lib/api.ts

Tap any detail that a model would produce by default. Each find is numbered and explained here.

Six things that work fine and must not ship.

The rule: find everything, gate what you can't prove is dead, delete only what is provably dead.

LeftoverWhy it blocksFix
Dev panels (Leva, Tweakpane, dat.gui), devtools, grid overlaysA hidden panel still ships its bytes and feeds its defaults into the UIGate on development and load with a dynamic import; tuned values go in a config file
: /lab, /test, /playground, /debugIndexed, often skip auth, show unfinished workNot-found in production; robots.txt only as a second layer
console.log of a user, session or payment responseIt is a data leakRemove it and say so; keep real console.error in error boundaries
A secret in a NEXT_PUBLIC_ and VITE_ values are bundled into the browserReport the name, never the value, and put "rotate this now" at the top
localhost or staging hosts in sourceBreaks or misroutes in productionRead from configuration
A TODO on auth, payment, permission or deletion"check ownership here" may mean anyone can delete anythingQuote it verbatim; it is probably the most important finding

Also hunt .only( and .skip( in tests, fresh @ts-ignore, and env files tracked by git.

Code tells and leaks pass· for your agent
Review this diff for code tells and leftovers. Default fix is deletion.
- Delete narrating comments, reviewer notes, commented-out code, console.log debug lines.
- Remove catch-log-rethrow, empty catches and silent fallbacks (catch → [] or ?? default on a failed fetch); fail loudly or show an error state. Check response.ok.
- Replace any/as unknown/@ts-ignore with real types; rename data/result/item and V2 names.
- Hunt: dev panels not behind a dynamic import + dev gate, /lab /test /playground routes, logs of user/session data, secret-looking NEXT_PUBLIC_/VITE_ names (report names only), localhost URLs, TODOs on auth/payment/delete paths (quote verbatim).
Match the repo's existing style; keep the diff to the task.

Quick check

Which line is the most dangerous to leave in?

What this lesson builds on and leads to, across every course.

  • Break it, then ship it
  • Options, tools and generators
  • What is a skill?