Your Students Are Using AI and You're Not Seeing It

You’ve run the assignment through MOSS. You’ve glanced at the submissions. Nothing screams blatant copy-paste. The functions are oddly neat, the comments are present, and the logic mostly works. You sigh, assign a B+, and move on. You’ve just been fooled.

The new wave of academic dishonesty isn't about students sharing files. It's about students prompting a large language model to generate a solution that deliberately evades traditional similarity checkers. Tools like MOSS, designed for pairwise code comparison, are fundamentally blind to this. They look for shared fingerprints between two human-written submissions. They can't detect the singular fingerprint of an AI model trained on billions of lines of public code.

After analyzing thousands of submissions flagged by next-generation detectors like Codequiry, a distinct pattern of AI-authored artifacts emerges. It’s not about perfect code; it’s about code that feels off. Here are the seven subtle signs you need to start looking for.

1. The Impossibly Consistent Code Style

Human programmers, especially students under deadline, are messy. Their style evolves within a single file. They might start with descriptive variable names, get tired, and resort to `x`, `temp`, or `data`. Their comment style changes. Indentation might slip. An AI, however, generates code in a single, coherent pass. It exhibits a stylistic uniformity that is statistically improbable for a novice.

Look for submissions where the style is monotonously perfect from line 1 to line 200. Every variable is perfectly camelCased or snake_cased without a single deviation. Every comment follows an identical grammatical structure. The formatting is so consistent it feels sterile.

"When a first-year student's code has the stylistic consistency of a senior Google engineer's linter output, that's not talent. That's a signal." — Dr. Anya Petrova, CS Department Chair, University of Edinburgh

Example: A student submits a Python script. The first function uses `calculate_average_score()`. The last function, written presumably hours later, uses `compute_final_grade()`. A human might mix `calc`, `calculate`, and `compute`. An AI will often pick one semantic pattern and stick to it rigidly across the entire codebase, as if following an internal style guide.

2. The Hallucinated Library or API

LLMs are notorious for "hallucinating" – generating plausible-sounding but non-existent information. In code, this manifests as calls to libraries, functions, or language features that don't exist in the version or context specified.

A student writing their own code will use the libraries they were taught. An AI, trained on a vast corpus, might pull in a more elegant, obscure, or simply fabricated solution. This is a dead giveaway, but it requires you to know your ecosystem.

// AI might generate this for a Java JSON parsing task
import com.example.json.QuickParser; // A completely fictional library

public class Main {
    public static void main(String[] args) {
        QuickParser parser = new QuickParser();
        Data result = parser.parse("data.json"); // 'Data' type and method are also made up
    }
}

The human equivalent would be struggling with `org.json` or `Jackson`, resulting in messy but real code. The AI gives them clean, broken code. Ask the student to run the program in your environment. If it fails on import statements or unknown methods they can't explain, you have your answer.

3. The Over-Engineered Simple Solution

Given a simple problem, a student will write a simple solution. An AI, trained on millions of examples including complex enterprise code, often defaults to patterns that are correct but wildly inappropriate for the task's context.

You ask for a function to read a file and count lines. You expect a `with open()` block and a loop. What you get is a full-blown class with error handling for edge cases you never mentioned, configuration loading, and a factory method pattern. It solves the problem, but it's like using a satellite to hammer a nail.

# Student-like solution (direct, maybe fragile)
def count_lines(filename):
    f = open(filename)
    lines = f.readlines()
    return len(lines)

# AI-leaning solution (overly robust, design-pattern heavy)
from abc import ABC, abstractmethod
import logging

class FileLineCounter(ABC):
    @abstractmethod
    def count(self, filepath: str) -> int:
        pass

class SimpleFileLineCounter(FileLineCounter):
    def __init__(self, logger: logging.Logger = None):
        self.logger = logger

    def count(self, filepath: str) -> int:
        try:
            with open(filepath, 'r', encoding='utf-8') as file:
                return sum(1 for _ in file)
        except FileNotFoundError as e:
            if self.logger:
                self.logger.error(f"File not found: {filepath}")
            raise e

This is a critical sign. It indicates the code wasn't written to fulfill a learning objective but to satisfy a functional requirement without understanding the underlying simplicity.

4. The Comment-Explanation Mismatch

Comments in AI-generated code are often eerily accurate descriptions of what the code does, because the AI generates them simultaneously. Comments in human-written code, particularly from students, often describe intent or struggle, or are added as an afterthought.

The mismatch occurs when you ask the student to explain the why behind a complex line. The comment says "iterate through the list to find the maximum." You ask, "Why did you use a `reduce` function with a lambda here instead of a simple loop?" A blank stare follows. The comment explains the operation, not the design choice, because the AI made the choice automatically.

Practical Test: During a viva or quick oral check, point to a non-trivial block of their own code. Ask: "This is clever. What was the alternative approach you considered before settling on this?" A student who genuinely wrote it will have a memory of the struggle. An AI prompter will only be able to paraphrase the code's function.

5. The Absence of Pedagogical Fingerprints

Your course has a rhythm. You teach loops before functions. You introduce arrays before lists. You solve Problem Set 3 with a specific technique that becomes a building block for Problem Set 4. Human students carry these fingerprints forward. Their code reflects the sequential, constrained learning path of your syllabus.

AI has no such constraints. It draws from the entirety of coding knowledge. So you might see a second-year C++ assignment solved with perfect use of the Standard Template Library algorithms (`std::transform`, `std::accumulate`) that you haven't covered yet, while the student still struggles with basic pointer syntax in person. The code uses advanced features correctly but in isolation, disconnected from the scaffold of knowledge you're building.

// Problem: Sum all positive numbers in a vector.
// Pedagogical fingerprint (expected, using recently taught for-loop)
int sum = 0;
for (int i = 0; i < vec.size(); ++i) {
    if (vec[i] > 0) {
        sum += vec[i];
    }
}

// AI fingerprint (correct, but uses advanced idioms not yet taught)
int sum = std::accumulate(vec.begin(), vec.end(), 0,
    [](int acc, int val) { return val > 0 ? acc + val : acc; });

When the code is more idiomatic than the coder, suspicion is warranted.

6. The Statistical Anomaly in Token Probability

This is the technical core that platforms like Codequiry leverage, and while you can't eyeball it, understanding it explains the detection. LLMs generate code by predicting the next most likely token (word, symbol). Human writing has more surprising, lower-probability choices—a quirky variable name, a slight inefficiency, a personal flourish.

AI-generated text has a different, smoother statistical profile. It clusters around high-probability tokens. Detectors analyze this "perplexity" and "burstiness." Does the code flow with the unnatural smoothness of average probability? This is why changing variable names or adding comments doesn't fool a good detector; the underlying statistical fingerprint of the logic and structure remains.

Think of it like writing style. A human will sometimes use a semicolon; sometimes an em-dash—sometimes a comma. An AI will pick the most statistically common choice every time, creating a uniform rhythm a human can't sustain.

7. The Perfect Solution to the Wrong Problem

This is the most damning sign, and it requires you to craft assignments with nuance. Students often misread or slightly misunderstand a problem spec. Their code reflects this misunderstanding—it's a correct solution to a slightly different problem.

An AI, however, will generate a perfect solution to the problem as literally stated in the prompt. If your assignment PDF has a minor ambiguity, every human student might interpret it one way, but an AI might latch onto a different, literal interpretation. Its submission will be an outlier, perfectly solving a problem no one else even attempted.

Real Scenario: You assign: "Write a function that takes a list of integers and returns the median." You meant the statistical median. One submission comes back that correctly finds the "median" (the middle value) of the unsorted list, which is nonsense. The AI took the word "median" in its most literal, non-statistical sense. The student, not understanding the code they submitted, cannot explain why their function sorts the list first (which would be necessary for the real median). The code is perfectly logical for a different world.

What To Do Next

Spotting these signs is the first step. Action is the second. Banning AI is a futile arms race. Instead, adapt your assessment strategy.

  • Implement in-class, proctored coding components for core competency verification.
  • Design assignments that require personalization—unique datasets, specific user stories, or integration with a codebase only you provide.
  • Use oral examinations focused on design rationale, not just function.
  • Employ detection tools built for this new reality. This is where modern systems differ from MOSS. They don't just compare; they analyze the code's statistical genesis. Running submissions through a dedicated AI code detector provides the objective data to support your subjective suspicions, creating a fair and defensible process for addressing academic integrity cases.

The goal isn't to become a detective. It's to create an environment where learning is validated, and tools like AI are understood rather than weaponized. Start looking for these seven signs. You'll be surprised at what you've been missing.