[KongchangAI]
· 4 min read· 2,067 words

Five AI Anti-Patterns Before a Free Host Sees Code

Five AI Anti-Patterns Before a Free Host Sees Code

The hidden risk in AI code review isn't a too-soft model—it's treating chat "agreement" as a release gate.

The article argues that AI models tend to nod along in code reviews, and the real problem isn't the model but a workflow that mistakes "agreement" for review. The author identifies five anti-patterns—nodding-along reviews, schema roulette, secret leakage, host role drift, and theatre testing—all occurring before code is uploaded to a free host, the stage where discovery is cheapest but speed hides the risk. The core claim: the contract file is the only gate; the green checkmark in chat doesn't count. The contract is a version-controlled set of files containing schema, rejection cases, and host role, paired with a standard-library-only local checker where a nonzero exit blocks upload. The author also insists that failure cases must be human-written, and free hosts should be labeled scratch with user-data storage forbidden.

rss source: Five Anti-Patterns Before a Free Host Sees Code

The developer community has recently been discussing a topic: AI models are too quick to nod along in code reviews. Some blame the models for being too soft, but the real culprit is the workflow—treating "agreement" as a review.

I've boiled this class of problems down to five anti-patterns, all of which occur at one critical moment: before code is uploaded to a free host. It's the stage where the cost of finding problems is lowest, yet it's also the stage that speed tends to obscure.

The core claim is just one sentence: the contract file is the only gate; the green checkmark in the chat window is not.

Why "nodding-along reviews" are dangerous

I don't trust a chat model that only nods. I trust a contract file that errors out when it fails.

Free drafts are cheap, and cheap agreement is expensive. A temporary host can display a page, but that doesn't mean it's accountable for your data. When a model restates your plan in prettier wording, you feel reviewed, but nothing has actually been falsified.

The problem isn't the model itself. The reason is that what you're asking the model for is confidence, not counterexamples. A model biased toward saying yes will happily take the bait, and your deadline will mistake politeness for evidence.

Replacement approach: ask the model for three inputs that should make the code fail, and save those inputs before it praises you.

Anti-Pattern 1: The Nodding-Along Review

Symptom: The model restates your plan in cleaner words. You feel reviewed, but nothing has been falsified.

Root cause: You're asking the model for confidence, not counterexamples. The deadline makes you treat politeness as evidence.

Replacement: Ask for three inputs that should make the code fail, and save them before any praise. Would you accept a review from a person who only says "looks good"?

Anti-Pattern 2: Schema Roulette

Symptom: Field names drift between similar runs. One time it's userId, the next time it's a bare id. The client can only parse whatever shape arrived last night.

Root cause: The prompt describes a feeling, not a locked schema. Retries create a "sense of progress," and drift gets masked.

Replacement: Fix the required keys and reject unknown fields. Local checks fail when required keys are missing. Don't rewrite the client in chat to fix drift.

What a response schema is: In the context of APIs or data exchange, a schema is an explicit declaration—it specifies which keys a response object must contain, what type each key is, and whether extra fields are allowed. It's a different thing from the natural-language description in a prompt: a prompt saying "return user info" is just intent, while a schema locks that intent down with constraints like {"required": ["userId", "email"], "additionalProperties": false}. Without a schema, each sampling by the model can produce a different shape, and both userId and id get treated as valid answers. The article's call to "reject unknown fields" is exactly strict mode in schema validation: any undeclared key causes a failure rather than being silently ignored. That way drift is exposed locally at the first opportunity, instead of flowing out to the client.

Anti-Pattern 3: Secret Leakage

Symptom: Tokens, cookies, or customer data rows show up in prompts. That same text may later land in host logs. Can you pull the secret back out of the history?

Root cause: Because it's free, the temporary path feels private. But free access can still retain prompts or logs. A free server is a convenience, not a vault.

Replacement: Redact before writing the prompt. Keep real credentials in a local env file. Refuse to push when a secret-like pattern is detected.

Why free paths still leave logs: Many people assume a temporary host is "disposable," so pasting a token into a prompt doesn't matter. In reality, any HTTP layer may log—reverse proxies, CDNs, and hosting platform debug logs can all write request bodies to disk verbatim. Once an API key, cookie, or customer data row enters those logs alongside a prompt, you've lost control over it and can't guarantee it will be cleared on schedule. The article's call to "redact before writing the prompt" and keep real credentials in a local env file is essentially about physically separating secrets from request traffic. Combined with regex scanning over scan_paths, you can intercept suspected secrets before submission, rather than waiting for them to appear in public logs.

Anti-Pattern 4: Host Role Drift

Symptom: A free server starts out as a short-term demo, and a week later it holds the only copy of the state. No commit records this quiet role change.

Root cause: An online page makes you feel you really own the data. But free options can be suspended, reset, or vanish at any time. If that host forgot your data tonight, what would break?

Replacement: Write down the host's role, marked as scratch or durable. Block deployment when scratch would store user data. Role upgrades must go through a human commit.

The difference between scratch and system-of-record: A scratch host is a temporary draft environment that can be reset, suspended, or deleted at any time, and the data in it doesn't count; a system-of-record is the authoritative data source, and losing it causes real incidents. The danger of role drift is that a free host that starts as scratch can, over time, quietly become the sole holder of state without any commit recording the upgrade. The article's rule is: write explicitly into the contract file whether the host is scratch or durable, block deployment outright when a scratch is asked to store user data, and require any role upgrade to be traced via a human commit. That way "what this machine is allowed to remember" goes from a default behavior to an explicit decision.

Anti-Pattern 5: Theatre Testing

Symptom: A test asserts a happy string the model just wrote, passing on the same tree that generated them. Where are empty inputs, huge inputs, wrongly typed inputs?

Root cause: The model grades the story it just told. You want speed, so adversarial cases slip away. The contract never listed those cases.

Replacement: Before implementation, you write the failing cases. The model can still draft the handling code, but it can't be the sole author of the tests.

Replacement Workflow

Even if the chat feels finished, work in this order:

  1. Write the schema file, listing required keys
  2. Write the cases file, containing the rejection inputs you invented
  3. Write the host file, marking role and scan paths
  4. Run the local checker, fix every error
  5. Only then let the model draft the handler
  6. Run the checker again before uploading
  7. Use the free server only when the role is scratch

The contract itself is a small set of files kept in git. It lists required keys, rejection cases, forbidden scan items, and states whether the host is scratch or durable. This is a proposal, not a personal benchmark—the samples haven't been executed on a real host. Mark them as unrun until you've tried them on a toy repo.

Local Checker Proposal

The script below uses only the Python standard library and calls no network APIs. Put it in your repo at tools/check_contract.py:

#!/usr/bin/env python3
'''Local contract check. Proposal only, not a vendor SDK.'''
import json
import re
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
SECRET = re.compile(
    r'(?i)(api[_-]?key|secret|token|password)\s*[:=]\s*\S+'
)

def load(name):
    path = ROOT / 'contract' / name
    return json.loads(path.read_text())

def main():
    schema = load('schema.json')
    cases = load('cases.json')
    host = load('host.json')
    errors = []
    required = schema.get('required', [])
    if not required:
        errors.append('schema has no required keys')
    for case in cases.get('cases', []):
        if 'input' not in case or 'expect' not in case:
            errors.append('case missing input or expect')
    role = host.get('role')
    if role not in {'scratch', 'system-of-record'}:
        errors.append('host role is missing or unknown')
    if role == 'scratch' and host.get('stores_user_data'):
        errors.append('scratch host must not store user data')
    for rel in host.get('scan_paths', []):
        path = ROOT / rel
        if not path.is_file():
            errors.append('scan path missing: %s' % rel)
            continue
        text = path.read_text(errors='ignore')
        if SECRET.search(text):
            errors.append('secret-like text in %s' % rel)
    if errors:
        print('\n'.join(errors))
        return 1
    print('contract ok')
    return 0

if __name__ == '__main__':
    sys.exit(main())

Run it from the repo root; a nonzero exit means don't upload yet. A zero exit only means this batch of files is internally consistent.

What this checker does and doesn't do: The script only reads the three JSON files under contract/ and performs purely local consistency validation—whether the schema declares required keys, whether each case has both input and expect, whether the host role is a known value, whether a scratch host is marked as storing user data, and whether scan paths exist and contain no suspected secrets. It does not call any model, and it does not prove that handlers actually match those cases—that requires a real test runner. The secret regex will also miss encoded blobs or split strings, and may produce false positives on toy examples. Its value is moving the "release gate" from the chat window to a command line with a zero exit: a nonzero exit means don't upload yet, and a zero exit only means this batch of files is internally consistent.

Decision Table

SymptomRoot CauseReplacement
Chat only praises the planPrompt is asking for agreementDemand three destructive inputs
Key names rename between runsNo fixed response schemaReject missing or extra keys
Secret text enters logsTemporary path feels privateScan files and redact prompts
Demo host holds real stateRole was never recordedLabel host and block scratch writes
Tests only cheer one happy stringModel wrote its own examYou own the failure cases

Find the row that matches your most recent real incident. If two rows match, fix the secret row first—a leaked token moves faster than a messy schema.

Limitations

The checker doesn't call models on its own, and it can't prove that handlers match cases. That requires a real test runner. The secret regex misses encoded blobs and split strings, and may also false-positive on toy examples—point scan_paths at source files, not at this article. Short sentences sand off real edge cases; the table and script carry the precise parts.

When to Skip It

Skip when data is regulated or customer-confidential. Skip when you need an audit signature this week. Skip when no one is willing to read the diff. If the free server has to be your only database—that's the host-role anti-pattern in a different coat. If the contract won't go into version control—a checker with stale files is just another nodding-along reviewer.

Questions worth asking out loud: what input would make this function lie to you? If the vendor logs, where do the prompts go? Is this host allowed to remember even one user?

Next Steps

Pick a small handler you already understand well. Write three rejection cases before you open the session. Run the checker, then decide whether a temporary host helps. A contract file failing in the repo is far cheaper than a secret failing in public logs.

One-line Summary

The hidden risk in AI code review isn't that the model is too soft—it's treating "agreement" in the chat as a release gate.

Paragraph Summary

The article points out that AI models tend to nod along in code reviews, and the real problem isn't the model but a workflow that treats "agreement" as a review. The author distills five anti-patterns: the nodding-along review, schema roulette, secret leakage, host role drift, and theatre testing. They all occur before code is uploaded to a free host—the stage where discovery costs the least but speed masks it. The core claim: the contract file is the only gate; a green checkmark in the chat window doesn't count. The contract is a set of version-controlled files containing three elements—schema, rejection cases, and host role—paired with a local checker that uses only the standard library, where a nonzero exit means no upload. The author also stresses that failure cases must be written by humans, and that free hosts should be labeled as scratch and forbidden from storing user data.

#AI anti-patterns#code review#contract file#free host#schema validation#secret leakage#host role drift#theatre testing#local checker
Share:

Related articles