ConstructiCat Logo
CodeBust.
Browse section ▾

Prompt-Residue Comments.

Comments that are artifacts of the generation conversation — restated prompts, step-by-step narration, chat asides, and placeholder elisions like `// ... rest of the code here` — committed into source instead of real documentation.

##Signs and Symptoms

A reviewer spots Prompt-Residue Comments when the comments document the conversation that produced the code rather than the code itself. Four tells, often co-occurring:

  • Restated prompt — a comment that paraphrases the request verbatim (// Function to add two numbers) above a function literally named add.
  • Step narration — line-by-line play-by-play of obvious operations (// Step 1: loop over the array, // increment i by 1 above i++).
  • Chat asides — second-person, present-tense remarks aimed at you, the prompter (// As requested, here is the updated handler, // Sure! Here's the fix, // Note: replace with your actual API key).
  • Elision / placeholder residue// ... rest of the code here, // keep your existing logic, // your code here, // TODO: implement error handling left in committed source.
// Function to add two numbers and return the result   <- restates the prompt
function add(a: number, b: number): number {
  // Step 1: add the two numbers                        <- narrates the obvious
  const sum = a + b;
  return sum; // return the sum
}

// As requested, here is the updated handler            <- chat aside to "you"
export async function handler(req: Req, res: Res) {
  // ... keep your existing validation logic here ...   <- elision: real code dropped
  // TODO: implement error handling                     <- placeholder shipped as-is
  const user = await db.users.find(req.params.id);
  res.json(user);
}

The elision line is the dangerous one: it reads as documentation but is actually an instruction to a human to paste code that the model omitted — apply the block verbatim and the existing validation silently disappears. OX Security found "Comments Everywhere" in 90–100% of AI-generated code in its 300+ repo study, describing them as markers that "look helpful but mainly support the AI itself, cluttering repositories."

##Reasons for the Problem

Why models emit it

  • Next-token mimicry of tutorial corpora. The training mix is saturated with blog posts, StackOverflow answers, and docs where every line is explained for a learner. The model reproduces that didactic register — narration and restated intent — because it is the statistically likely continuation, not because the surrounding repo needs it.
  • Chat register bleed / sycophancy. RLHF tunes assistants to be explanatory and agreeable in the chat channel. That conversational, second-person tone leaks into the code channel, producing "As requested…" and "Note: you should…" asides that make no sense once the code is detached from the conversation.
  • Reasoning narrated as comments. Models externalize their plan ("Step 1… Step 2…") as inline comments — chain-of-thought leakage frozen into the file.
  • Elision is a chat affordance, misapplied. In a chat reply, // ... rest unchanged ... is a polite way to avoid re-printing a file. When that reply is pasted or auto-applied to a real file, the affordance becomes literal residue — and literal data loss.
  • No repo context, so it restates the prompt. Lacking the ticket, the domain, and the real "why," the model has nothing true to say in a comment, so it falls back to paraphrasing the only thing it has: your prompt. OX characterizes the comments as "internal markers to navigate context limits… dependence on short-term memory rather than true understanding."

Why it hurts

  • Review load. Every narration line is noise a human must read past. OX's framing: AI "codes like a junior dev" at machine speed, and human review "cannot scale to match AI's output" — residue comments make each diff more expensive to review precisely when there are more diffs.
  • Correctness / data loss. Elision placeholders (// ...existing code...) cause real code to be dropped when blocks are applied blindly.
  • Comment rot. Restated-prompt comments duplicate the code's intent in prose; the prose drifts as the code changes, leaving actively misleading documentation — Fowler's classic Comments-as-deodorant smell.
  • Hidden incompleteness. // TODO: implement error handling is the model signaling it worked at the edge of its competence; shipped as-is, it is unfinished logic disguised as a tracked task.
  • Security tells. // replace with your actual API key typically sits beside a hardcoded placeholder credential — the residue marks exactly the line a scanner (and an attacker) cares about.

##Treatment

Prompting / generation tactics

  • Constrain the register: "Output the complete file. Never abbreviate with // ..., // rest of the code, or // existing code. Do not narrate steps — comment only non-obvious rationale (the why). No conversational asides; this goes straight into a repo."
  • Ask for a unified diff rather than a prose-wrapped snippet, so omissions are explicit and applyable instead of hand-waved with an elision comment.
  • Require the model to run the formatter and your lint config (e.g. no-warning-comments with custom terms) and report the result — closing the "validate with the linter" loop catches placeholder/TODO residue automatically.
  • Add a pre-commit / CI grep gate for residue markers (rest of the code, your code here, existing code, As requested, Step \d) and treat elision markers as a hard blocker, since they often mean code was silently dropped.

The refactor

Delete chat asides and narration outright. Where a comment merely restates what the code does, that is the signal to make the code self-documenting — apply Extract Function and Rename so the name carries the intent, then keep only comments that explain a non-obvious why (Fowler: Remove comments that are deodorant for bad names).

// before — prompt residue
// Create a function that validates an email address using a regex
function validateEmail(input) {
  // check if the input matches the email pattern
  const re = /^[^@]+@[^@]+\.[^@]+$/;
  // return true or false
  return re.test(input);
}
// after — name carries intent; the only comment explains the non-obvious why
const EMAIL_RE = /^[^@]+@[^@]+\.[^@]+$/; // intentionally loose: we only catch typos pre-send, not RFC 5322
const isValidEmail = (input: string): boolean => EMAIL_RE.test(input);

For elision residue, never apply the block as written — diff it against the current file and restore what the model dropped. For // TODO: implement …, either finish the logic or convert it into a tracked issue and fail the build on the placeholder term so it cannot ship as-is.

##Detected by

  • ESLint no-warning-commentsFlags TODO/FIXME/XXX and custom configurable terms — set `terms` to catch placeholder residue like "your code here" or "rest of the code"
  • SonarQube / SonarSource S125Sections of code should not be commented out — flags elided/leftover commented-out blocks
  • SonarQube / SonarSource S1135Track uses of "TODO" tags — surfaces placeholder TODO residue shipped as code
  • SonarQube / SonarSource S1134Track uses of "FIXME" tags