DEV Community

Jordan Huang
Jordan Huang

Posted on

More Generated Code Is Not Less Debt: A Myth FAQ

Did that model patch really close your ticket? I doubt it, and here is why.

Cheap generation changed only the cost of typing. It did not change ownership, review, or blast radius.

I keep hearing the same five confident claims. They sound modern, and they hide old debt.

This FAQ offers a corrected mental model. Steal the receipt checklist before you merge.

The claim I want to kill

Here is the slogan I hear in standups. "The model wrote it, so we shipped it."

That sentence skips design, tests, and blast radius. Generation is inventory, not repayment.

Want a better question on every pull request? Who owns this code at 2 a.m.?

How to use this FAQ

Read each myth as a repeated claim. Then collect cheap evidence in the repo.

Then apply the corrected model. Then fill a debt receipt on the branch.

I treat the receipt as a merge artifact, not a diary. If git lacks the name, nobody owns the failure.

Myth 1: More generated code means less debt

The claim

"We added twelve files in twenty minutes. The backlog should shrink after that."

Why it spreads

Typing used to be the bottleneck. Now it is not, and motion feels like retirement.

Lines are not closed tickets. Inventory can grow while the board looks green.

Evidence you can collect

Count production files added. Count tests added. Count owners named in the diff.

If owners are missing, the debt grew. Speed does not argue with missing names.

# proposal: run from the repo root, not a published benchmark
git diff --name-only origin/main...HEAD | tee /tmp/changed.txt
echo "changed_files=$(wc -l < /tmp/changed.txt)"
rg -n "TODO|FIXME|XXX" $(cat /tmp/changed.txt) || true
Enter fullscreen mode Exit fullscreen mode

Corrected model

Generation increases inventory that still needs care. Inventory needs an owner and a test path.

A ticket closes when residual risk is accepted. It does not close when tokens stop.

Myth 2: A model explanation replaces a design record

The claim

"The chat already explained the architecture. Why write any of it down?"

Why it spreads

The transcript feels complete in the moment. It is also ephemeral and unsearchable.

Chats vanish when tools change. New hires cannot grep a vanished thread.

Evidence you can collect

Ask for one durable artifact in git. A decision. An invariant. A rejected alternative.

If the PR has none, you have folklore. Folklore is debt with nicer grammar.

<!-- proposal: drop this block into DEBT_RECEIPT.md -->
## Decision
- Problem:
- Choice:
- Rejected alternatives:
- Invariant we will not break:
- Owner:
Enter fullscreen mode Exit fullscreen mode

Corrected model

Explanation is a draft of understanding. Design is a recorded constraint in the repo.

If it is not in git, it is not a decision. Can you point at the file?

Myth 3: Regenerating later is cheaper than documenting now

The claim

"We can always ask the model again next quarter. Documentation is extra work."

Why it spreads

Regeneration looks free in the current session. Context reconstruction is not free later.

Next quarter the prompt is gone. Production shape has drifted under the same names.

Evidence you can collect

Time a cold regenerate on one module. Then time a change against written invariants.

Treat that as a local check only. I am not publishing numbers from your repo.

Label the result as a thought experiment. Do not paste it into a slide as proof.

Corrected model

Documentation is compression while context is warm. Regeneration is decompression with loss.

Pay the compression cost on the same branch. Future you cannot replay this chat.

Myth 4: Tests the model wrote are tests you own

The claim

"It added pytest files, so we are covered. Look, the session finished green."

Why it spreads

Green output soothes tired reviewers. Generated tests often assert the implementation.

They freeze today's bugs as specification. That is debt wearing a checkmark.

Evidence you can collect

Read each new test name out loud. Ask what a user would notice on failure.

If the test only mirrors internals, it is a snapshot. Snapshots rot without an owner.

# proposal: filename tripwire, not coverage, not executed against your CI here
from pathlib import Path
import sys

changed = Path("/tmp/changed.txt").read_text().splitlines()
prod = [p for p in changed if p.endswith(".py") and "test" not in Path(p).name]
tests = [p for p in changed if p.endswith(".py") and "test" in Path(p).name]

print(f"prod_py={len(prod)} test_py={len(tests)}")
if prod and not tests:
    print("FAIL: production python changed without test files")
    sys.exit(1)
print("PASS: at least one test file in the diff")
Enter fullscreen mode Exit fullscreen mode

This script is a tripwire on names. It is not a quality argument.

Corrected model

You own a test when you can explain the failure. You also own keeping it honest.

If nobody can defend the assertion, delete it or rewrite it. Coverage theater is still debt.

Myth 5: Free model access means review can wait

The claim

"We will review after it lands. The box already ran the patch."

Why it spreads

Remote runs feel official under time pressure. They are still a sketch of reality.

A free coding box is scratch space. It is not your merge gate, and you know that.

Evidence you can collect

Compare the box to CI in writing. Language version. Dependencies. Secret policy. Network rules.

If they differ, the green run is folklore. Why merge folklore into main tonight?

Corrected model

Review is where ownership gets a name. Delay it, and debt compounds on default branch.

Run cheap exploration early. Keep the human gate anyway. Exploration is not acceptance.

A labeled walkthrough (unexecuted)

Suppose a PR adds billing/prorate.py. The model also adds tests/test_prorate.py.

Looks done, right? Open the test before you cheer.

If it only checks a helper return value, users can still be billed twice. The receipt must state the user-visible check.

# proposal: shape of a behavior test, not a real billing suite
def test_proration_does_not_double_charge_on_plan_change():
    """User-visible: monthly charge stays a single line item."""
    invoice = prorate(old_plan="pro", new_plan="team", days_used=10)
    assert invoice.line_items_named("subscription") == 1
    assert invoice.total > 0
Enter fullscreen mode Exit fullscreen mode

I did not run this against a billing system. Copy the shape, not the domain.

The tripwire would pass because a test file exists. The receipt should still fail until the user-visible check is named.

A workflow that uses a free model box without lying

I want a boring loop. Explore, receipt, human gate. Nothing fancier.

MonkeyCode offers free model access and a free server option. That pair is useful for the explore step, not the merge step.

Disclosure: This article was prepared as part of MonkeyCode's product outreach.

Here is the loop I recommend. Treat every step as a template, not a war story.

  1. Draft the change with a free model session.
  2. Run the inventory commands on a free server.
  3. Fill DEBT_RECEIPT.md on the same branch.
  4. Let CI be the only green that matters.
  5. Merge only with a named owner and residual debt.
# DEBT_RECEIPT.md (proposal)

## Scope
- User-visible behavior:
- Files touched:

## Ownership
- Primary owner:
- Backup:
- On-call path:

## Verification
- CI job that must stay green:
- Manual check we still owe:

## Residual debt
- What we did not do:
- Why that is acceptable until:
Enter fullscreen mode Exit fullscreen mode

The free server can execute grep and the Python tripwire. It cannot accept residual risk for you.

Do not paste secrets into that box. Put the policy in the receipt, never the secret.

Decision table

Use this table before you close the ticket. Empty cells mean stop.

Signal Looks like progress Actual question
Many new files Speed Who owns each file?
Chat explanation Clarity Which invariant landed in git?
Model-written tests Coverage What user behavior fails?
Green on a free box Confidence Does CI match that box?
"We can regenerate" Optionality What context will be missing?

If you cannot fill a cell, the ticket stays open. Painful. Honest. Better than a silent 2 a.m. page.

Limitations

This receipt is a heuristic. It will miss semantic debt and bad names that look fine.

The tripwire only looks at filenames. Rename a test and it goes quiet.

Free model output varies across sessions. Do not pin process quality to one chat.

I am not giving quotas, hardware, model names, or runtime promises. Those claims go stale. Read current product docs before you plan capacity.

This article does not claim production benchmarks. Run the commands on your own repo.

Generated tests can still be good. The myth is ownership by default, not the existence of pytest.

Who should not use this

Skip this if you already have a formal architecture review. You do not need a lighter ritual.

Skip this if policy forbids hosted models. Stay on local tools and internal CI.

Skip this if the change is a one-line config. A receipt would be ceremony, not signal.

Skip this if you cannot name an owner. Fix staffing before you automate folklore.

What I want you to remember

Generation is cheap typing. Debt is unpaid understanding sitting in main.

Ask who owns the blast radius. Then write that name into git.

If you already have a free model box, run the tripwire there first. Then argue about the ticket, not the autocomplete.

Top comments (0)