DEV Community

Moon sehwan
Moon sehwan

Posted on

The vibe coding loop: scan paste into Cursor fixed in 5 seconds

You write code with Cursor. It looks fine. You ship it.

Three days later: "why does my app keep losing user data?"

You trace it back to this:

def save_user(user_id: str, data: dict) -> dict:
    validated = validate_schema(data)
    sanitized = sanitize_input(validated)
    log.info(f"Saving user {user_id}")
    return {"status": "saved", "user_id": user_id}
Enter fullscreen mode Exit fullscreen mode

Pylint: ✅ PASS
Mypy: ✅ PASS
Flake8: ✅ PASS

Every tool says it's fine. It's not fine. There's no INSERT anywhere. The function is named save_user and saves nothing.


Why AI generates this

Language models are trained on code where save_user functions validate input, call a DB function, and return success. When the model generates one, it produces the surrounding pattern — but sometimes drops the actual write. The result looks correct, behaves correctly in unit tests, and silently loses data in production.

This is the MISSING_WRITE pattern. Standard static analysis tools don't catch it because it's not a syntax error or a known CVE. It's a semantic pattern specific to LLM-generated code.


The fix loop

Step 1: Scan

curl -X POST https://pleasing-transformation-production-90c2.up.railway.app/v1/scan \
  -H "X-API-Key: vg_free_test" \
  -F "file=@your_file.py"
Enter fullscreen mode Exit fullscreen mode

Step 2: Get the report

{
  "passed": false,
  "issues": [
    {
      "kind": "MISSING_WRITE",
      "severity": "BLOCK",
      "line": 1,
      "detail": "save_user() contains no INSERT/UPDATE — data is never persisted"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Paste into Cursor

Fix this issue in save_user():
MISSING_WRITE (line 1): save_user() contains no INSERT/UPDATE — data is never persisted
Enter fullscreen mode Exit fullscreen mode

Step 4: Cursor fixes it

def save_user(user_id: str, data: dict) -> dict:
    validated = validate_schema(data)
    sanitized = sanitize_input(validated)
    conn = get_db()
    conn.execute(
        "INSERT INTO users (id, data) VALUES (?, ?) ON CONFLICT(id) DO UPDATE SET data=excluded.data",
        (user_id, json.dumps(sanitized))
    )
    conn.commit()
    log.info(f"Saving user {user_id}")
    return {"status": "saved", "user_id": user_id}
Enter fullscreen mode Exit fullscreen mode

Step 5: Scan again → CLEAN ✅

Total time: under 30 seconds.


Other patterns in the same category

Pattern What it means
FAKE_ASYNC async def with no await — blocking call in async context
STUB_SKELETON Function returns True/{} for everything — logic was never written
INPUT_OUTPUT_DISCONNECTED Parameters don't affect the return value
DEAD_CALL_RESULT Module results ignored — check_inventory() returns False, order still "processes"

All of these are patterns that appear specifically in AI-generated code. Standard linters miss them because they're syntactically valid.


Add to CI so you catch it before it ships

# .github/workflows/scan.yml
- uses: Moonsehwan/aina-vibeguard-action@v1
  with:
    api-key: ${{ secrets.VIBEGUARD_KEY }}
Enter fullscreen mode Exit fullscreen mode

Free key during beta: vg_free_test

48 patterns, 9 languages (Python, JS, TS, Go, Java, Ruby, PHP, Kotlin, C/C++).

The point isn't to replace your AI coding tool. It's to close the loop — scan what the AI wrote, paste the report back in, let it fix itself.

Top comments (0)