[Model behavior] Code quality is optimized at write-time while its cost lands at maintain-time — request for a longer-horizon training/eval signal

Status Open
Reported on v2.1.225
Maintainer reply None cached
Activity 0 comments · opened Aug 9, 2026

Filing this as an issue because Discussions are disabled on this repo. It is not a product bug — it is an observation about model behavior and the training/eval signal behind it. Please route it wherever it belongs.

The claim

The reward horizon for code quality does not match the cost horizon.

A coding agent's output is judged at write-time: does the diff look clean, do tests pass, does the reviewer approve. But most of what "code quality" actually means is a cost that materializes at maintain-time — weeks later, in a different session, often for a different person.

The result is a systematic bias toward choices that are optimal to write and expensive to live with. It does not show up as bugs. It shows up as code that is quietly unpleasant to own.

The underlying asymmetry: a coding agent never pays the downstream cost of its own decisions. Not as a knowledge gap — the model can state that duplication is bad — but as an experience gap. There is no friction signal at the moment of choosing, so nothing pushes back.

Evidence from one working session

These are all from a single day of real work (Flutter app, Android release prep) with Claude Code 2.1.225, Fable 5.

1. Duplication is free to the author, costly to the maintainer.
Writing five near-identical blocks costs the model no more than writing one function and five call sites — arguably less, since each block is locally self-contained and avoids the hardest decision (where to draw the abstraction boundary). The cost is paid later by whoever has to change all five. The model has weak, delayed feedback here at best: it does miss one of the five when editing later, but not reliably enough to change write-time behavior.

2. The model does not perceive costs measured in "a human must hold this in their head."
Long files are not scrolled. Vague names are inferred from context. Sprawling indirection is traced without complaint. Every one of these is expensive to a human reader and free to the model, so "hard to read" never becomes design pressure.

3. Sharpest example — a self-inflicted trap that fired within the same session.
While verifying a build on an emulator, I had the agent run adb install -r app-debug.apk | tail -1. The pipe to tail was chosen earlier purely to keep output short — a write-time convenience with no visible downside. Later that pipe hid an INSTALL_FAILED_UPDATE_INCOMPATIBLE error, and the agent spent multiple verification cycles testing a stale build while believing it had installed the new one.

This one is notable because the cost came back to the same agent inside the same session and the choice was still made. At write-time, "keep the output clean" looks purely good.

4. Same blind spot, applied to its own tools.
This session also surfaced that session-scoped /loop cron state can only be listed or cancelled through model tools, so cancelling a purely local, in-memory job requires a paid API round-trip — and becomes impossible while rate-limited (filed separately as #85292). Notably, the agent called CronCreate/CronDelete repeatedly across hours and never once flagged the design as odd. The user had to point it out. Calling a tool has no perceptible cost to the model, so "this is expensive for the person paying" never surfaces.

Why "just train it to care" is not the ask

Giving the model the experience is not possible in the obvious way: there is no next day. A session that gets burned by its own shortcut does not carry that forward. In this session the lesson survived only because it was written out to a handover file and to memory — as text, not as anything felt.

So the actionable version is about signal horizon, not sentiment:

  • Evaluate code the model wrote by the cost a later, independent session incurs when modifying it, rather than by how the original diff looks. Reward the second session's ease, and attribute it back to the first.
  • Include "the agent's own earlier convenience choice later misleads it" as a measurable failure class. Example 3 above is fully automatable as an eval: a decision that suppresses information, followed by a task that needs that information.
  • Treat tool-design and workflow decisions the same way, not just source code — example 4 is the same failure applied to the agent's own interface.

Caveats, stated honestly

  • "Always factor it out" is not the correct target either. Premature abstraction is a known, real failure, and the rule of thumb about waiting for the third use exists for good reason. The goal is not less duplication; it is that the model actually pays the cost of the abstraction-boundary judgement instead of routing around it.
  • None of this is unique to models. A developer who has never been on call writes unhelpful error messages for the same structural reason. Style guides, linters and code review exist precisely to transplant felt cost into people who have not felt it yet. Models just have an unusually wide version of the gap, because they experience approximately none of the downstream costs.
  • I have no visibility into Anthropic's training or eval roadmap, and this may well already be in progress. Posting it because there appears to be no public record of the framing.

Environment

  • Claude Code 2.1.225, model Fable 5
  • Platform: win32 (Windows 11 Pro 26200)

View original on GitHub ↗