Whitespace-Driven Machine-Generated Code Detection
This skill enables Claude to analyze source code and assess whether it was likely written by a human or generated by an LLM (ChatGPT, Copilot, Claude, etc.) by extracting and evaluating whitespace patterns, indentation consistency, stylometric features, and structural properties. The approach is based on the empirical finding that AI-generated code exhibits mechanically uniform formatting -- especially in indentation and whitespace -- while human-written code carries idiosyncratic, inconsistent formatting signatures. A feature-based detector using these signals achieves ROC-AUC 0.995 and F1 0.971 on a 600k-sample benchmark.
When to Use
- When a user pastes code and asks "Was this written by AI?" or "Is this code machine-generated?"
- When reviewing student submissions for academic integrity and needing to flag potential AI-generated code
- When performing authorship attribution on code of unknown origin
- When auditing a codebase to estimate what proportion may have been AI-assisted
- When a user wants to understand what stylistic signals distinguish human code from AI code
- When building or evaluating a code-origin detection pipeline and needing feature engineering guidance
Key Technique
The core insight is that whitespace and indentation patterns are the most discriminative features for separating human-written from AI-generated code. Human developers accumulate idiosyncratic habits: mixing tabs and spaces, varying indentation depth across blocks, leaving trailing whitespace inconsistently, inserting irregular blank-line groupings, and aligning code to personal aesthetic preferences. AI models, trained on normalized corpora and generating token-by-token, produce mechanically consistent formatting -- uniform indentation depth, predictable blank-line placement, and almost no trailing whitespace or tab/space mixing.
The paper compares two approaches. The feature-based approach extracts lightweight, interpretable features across four categories: (1) whitespace features (blank-line ratios, trailing whitespace frequency, space-to-tab ratios), (2) indentation features (indentation depth variance, consistency score, tab-vs-space preference), (3) structural features (cyclomatic complexity, nesting depth, function/block density), and (4) stylometric features (variable naming patterns, comment density, line length distribution). These feed into gradient-boosted tree classifiers (XGBoost, Random Forest) that achieve near-perfect discrimination. The embedding-based approach uses CodeBERT to encode semantic code representations, achieving slightly higher precision but less interpretability.
The practical takeaway: you do not need a neural network to detect AI code. A small set of formatting-focused features -- extractable with simple regex and counting logic -- provides excellent detection. Indentation variance and whitespace consistency alone carry most of the signal. This makes the technique fast, explainable, and deployable without GPU infrastructure.
Step-by-Step Workflow
Collect the code sample. Obtain the source code to analyze. Ensure it is raw (not reformatted by a linter or auto-formatter like black, prettier, or clang-format), since auto-formatting destroys the whitespace signals this technique relies on.
Extract whitespace features. For every line, compute:
- Leading whitespace character sequence (tabs vs. spaces vs. mixed)
- Indentation depth (number of leading whitespace characters or tab-equivalent spaces)
- Whether the line has trailing whitespace
- Whether the line is blank
Then aggregate: mean/median/stddev of indentation depth, ratio of blank lines to total lines, percentage of lines with trailing whitespace, ratio of tabs to spaces in leading whitespace.
Compute indentation consistency score. Measure the variance in indentation increments (the change in indentation depth between consecutive non-blank lines). Human code typically shows high variance (irregular jumps); AI code shows low variance (consistent 4-space or 2-space increments). Calculate the coefficient of variation of indentation deltas.
Extract structural features. Count: number of functions/methods, average function length (lines), maximum nesting depth, number of code blocks, cyclomatic complexity (branch count). AI code tends toward moderate, uniform complexity; human code varies more widely.
Extract stylometric features. Measure: average line length and its standard deviation, comment-to-code ratio, variable name length distribution, use of single-letter variable names, keyword diversity (unique keywords / total keywords). Human code tends to have more variable line lengths and more comments.
Score each feature against known distributions. Compare extracted values to typical ranges:
- AI indicators: indentation depth stddev < 1.0, zero trailing whitespace, consistent indent increment (always 4 or always 2), blank-line ratio between 0.10-0.15, line length stddev < 15
- Human indicators: indentation depth stddev > 2.0, some trailing whitespace present, mixed indent increments, tab/space mixing, irregular blank-line clustering, line length stddev > 20
Compute a weighted confidence score. Weight indentation/whitespace features highest (they carry ~60% of the discriminative power), structural features at ~25%, and stylometric features at ~15%. Produce a 0-1 score where values near 1.0 indicate likely AI-generated and values near 0.0 indicate likely human-written.
Present the analysis with evidence. Report the overall assessment (likely human / likely AI / uncertain), the confidence score, and the top 3-5 most informative features with their observed values and what they suggest. Always caveat that auto-formatted code will appear AI-like regardless of true origin.
Recommend follow-up if inconclusive. If the score falls in the uncertain range (0.3-0.7), suggest examining commit history for incremental development patterns (human signal), checking if an auto-formatter was applied, or requesting additional samples from the same author for cross-comparison.
Optionally generate a detection script. If the user needs to analyze many files, produce a Python script that extracts these features and outputs a CSV of per-file scores for batch analysis.
Concrete Examples
Example 1: Analyzing a single code snippet
User: "Can you tell if this Python code was written by a human or AI?"
def fibonacci(n):
if n <= 0:
return []
elif n == 1:
return [0]
elif n == 2:
return [0, 1]
fib_sequence = [0, 1]
for i in range(2, n):
fib_sequence.append(fib_sequence[i-1] + fib_sequence[i-2])
return fib_sequence
Approach:
- Extract whitespace features: all indentation is exactly 4 spaces, zero trailing whitespace, one blank line before
fib_sequence, consistent spacing around operators
- Compute indentation consistency: indent increments are exactly {+4, 0, 0, 0, -4, +0, +4, -4, +0, -4} -- perfectly mechanical
- Structural features: single function, low complexity, textbook structure
- Stylometric features: descriptive variable names, no comments, uniform line lengths (stddev ~12)
Output:
Assessment: LIKELY AI-GENERATED (confidence: 0.82)
Key signals:
- Indentation: perfectly consistent 4-space indent, zero variance in increment magnitude (strong AI signal)
- Whitespace: no trailing whitespace on any line (AI signal)
- Structure: textbook fibonacci implementation with no personal style markers
- Line lengths: low standard deviation (13.2) suggesting uniform generation
- Comments: zero comments (mild AI signal -- humans often add at least one)
Caveat: If this code was auto-formatted (e.g., by black), these whitespace
signals would appear AI-like regardless of true authorship. Check whether a
formatter is configured in this project.
Example 2: Comparing two implementations
User: "I have two solutions to the same problem. Which one looks human-written?"
Solution A:
def merge_sort(arr):
if len(arr) <= 1:
return arr
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge(left, right)
def merge(left, right):
result = []
i = j = 0
while i < len(left) and j < len(right):
if left[i] <= right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
result.extend(left[i:])
result.extend(right[j:])
return result
Solution B:
def merge_sort(arr):
if len(arr) <= 1:
return arr
mid = len(arr)// 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return _merge(left, right)
def _merge(l, r):
res = []
i=j=0
while i < len(l) and j<len(r):
if l[i] <= r[j]:
res.append(l[i])
i+=1
else:
res.append(r[j])
j += 1
res.extend(l[i:])
res.extend(r[j:])
return res
Output:
Solution A: LIKELY AI-GENERATED (confidence: 0.79)
- Perfect 4-space indentation throughout
- Consistent spacing around all operators
- Descriptive variable names (left, right, result)
- Uniform blank-line placement (exactly one between functions)
Solution B: LIKELY HUMAN-WRITTEN (confidence: 0.75)
- Uses tabs for indentation (personal preference signal)
- Inconsistent operator spacing: "len(arr)// 2" vs "i < len(l)" vs "i+=1" vs "j += 1"
- Abbreviated variable names (l, r, res) -- personal shorthand
- Leading underscore on _merge (style choice)
- Irregular spacing patterns across the file
The inconsistent operator spacing in Solution B is a strong human signal.
AI models almost never produce "i+=1" on one line and "j += 1" two lines later.
Example 3: Batch analysis request
User: "I need to scan a directory of student submissions for AI-generated code."
Approach:
- Generate a Python script that walks a directory, extracts the feature set per file, and outputs scores
- Focus on the highest-signal features to keep it lightweight
Output script (key excerpt):
import os, re, statistics
def extract_features(code: str) -> dict:
lines = code.split('\n')
non_blank = [l for l in lines if l.strip()]
indents = [len(l) - len(l.lstrip()) for l in non_blank]
deltas = [abs(indents[i] - indents[i-1]) for i in range(1, len(indents))]
features = {}
features['indent_stddev'] = statistics.pstdev(indents) if indents else 0
features['delta_stddev'] = statistics.pstdev(deltas) if deltas else 0
features['trailing_ws_ratio'] = sum(1 for l in lines if l != l.rstrip()) / max(len(lines), 1)
features['blank_line_ratio'] = sum(1 for l in lines if not l.strip()) / max(len(lines), 1)
features['tab_space_mix'] = any('\t' in l[:len(l)-len(l.lstrip())] for l in non_blank) and \
any(' ' in l[:len(l)-len(l.lstrip())] for l in non_blank)
lengths = [len(l) for l in non_blank]
features['line_len_stddev'] = statistics.pstdev(lengths) if lengths else 0
# Heuristic score: lower = more likely AI
score = 0.0
if features['indent_stddev'] < 1.5: score += 0.25
if features['delta_stddev'] < 2.0: score += 0.20
if features['trailing_ws_ratio'] == 0: score += 0.15
if not features['tab_space_mix']: score += 0.10
if features['line_len_stddev'] < 15: score += 0.15
if 0.08 < features['blank_line_ratio'] < 0.18: score += 0.15
features['ai_score'] = score
return features
# Walk directory and score each file
for root, _, files in os.walk('submissions/'):
for f in files:
if f.endswith('.py'):
path = os.path.join(root, f)
code = open(path).read()
feat = extract_features(code)
flag = 'LIKELY AI' if feat['ai_score'] > 0.65 else \
'UNCERTAIN' if feat['ai_score'] > 0.35 else 'LIKELY HUMAN'
print(f"{path}: {flag} (score={feat['ai_score']:.2f})")
Best Practices
- Do: Always check whether an auto-formatter (black, prettier, gofmt, rustfmt) has been applied before drawing conclusions. Auto-formatted code will appear AI-like regardless of true origin.
- Do: Weight indentation and whitespace features most heavily -- the paper shows these carry the majority of discriminative power over structural or naming features.
- Do: Report confidence levels honestly and present the specific features that drove the assessment, not just a binary label.
- Do: Analyze multiple files from the same author when available. Consistent patterns across files strengthen the signal.
- Avoid: Claiming certainty. Even at 0.995 ROC-AUC, false positives occur. Frame results as "likely" not "definitely."
- Avoid: Applying this technique to code in languages with enforced formatting (Go with gofmt, Rust with rustfmt) -- the forced consistency eliminates whitespace signals.
- Avoid: Using only a single feature. The technique's strength comes from combining multiple independent signals across categories.
Error Handling
- Auto-formatted code: If you detect signs of auto-formatting (perfectly consistent style matching a known formatter's output), warn the user that whitespace-based detection is unreliable for this sample and suggest examining commit history or semantic features instead.
- Very short snippets (<10 lines): Too few lines produce unreliable statistics. Report that the sample is too small for confident analysis and ask for more code.
- Minified or obfuscated code: Whitespace has been intentionally removed. Report that the technique is inapplicable and suggest alternative analysis (variable naming patterns, control flow structure).
- Mixed-origin code: Some files contain both human and AI code (e.g., human skeleton with AI-filled functions). If feature distributions are bimodal, flag this possibility and suggest per-function analysis.
- Language-specific norms: Python's significant whitespace and PEP 8 conventions make some formatting uniform by community norm. Adjust thresholds accordingly -- focus on operator spacing, blank-line patterns, and trailing whitespace rather than indent depth alone.
Limitations
- Auto-formatters neutralize the technique. Any code run through black, prettier, clang-format, gofmt, or similar tools will have its whitespace signals destroyed. This is the single biggest limitation.
- AI models are improving. As LLMs are fine-tuned on more diverse code, their formatting may become less uniform. Features that discriminate today may lose power over time.
- Not effective on Go or Rust. These languages have canonical formatters (gofmt, rustfmt) that virtually all code is run through, eliminating whitespace variation.
- The approach is statistical, not forensic. It estimates likelihood based on population-level patterns. An unusually disciplined human coder may be flagged; a prompted AI told to "write messy code" may evade detection.
- Language coverage. The underlying benchmark (600k samples) covers common languages (Python, Java, C++, JavaScript). Performance on niche languages (Haskell, Kotlin, Elixir) is unvalidated.
- Single-sample reliability. The technique is most reliable when analyzing multiple files from the same source. A single short file provides weak evidence.
Reference
1---2name: whitespaces-dont-lie-feature-driven3description: Detect whether source code was written by a human or generated by an AI (ChatGPT, Copilot, etc.) using whitespace, indentation, and stylometric feature analysis. Trigger phrases: 'is this code AI generated', 'detect machine generated code', 'check if code is human written', 'analyze code origin', 'code authorship detection', 'AI code detector'4---56# Whitespace-Driven Machine-Generated Code Detection78This skill enables Claude to analyze source code and assess whether it was likely written by a human or generated by an LLM (ChatGPT, Copilot, Claude, etc.) by extracting and evaluating whitespace patterns, indentation consistency, stylometric features, and structural properties. The approach is based on the empirical finding that AI-generated code exhibits mechanically uniform formatting -- especially in indentation and whitespace -- while human-written code carries idiosyncratic, inconsistent formatting signatures. A feature-based detector using these signals achieves ROC-AUC 0.995 and F1 0.971 on a 600k-sample benchmark.910## When to Use1112- When a user pastes code and asks "Was this written by AI?" or "Is this code machine-generated?"13- When reviewing student submissions for academic integrity and needing to flag potential AI-generated code14- When performing authorship attribution on code of unknown origin15- When auditing a codebase to estimate what proportion may have been AI-assisted16- When a user wants to understand what stylistic signals distinguish human code from AI code17- When building or evaluating a code-origin detection pipeline and needing feature engineering guidance1819## Key Technique2021The core insight is that **whitespace and indentation patterns are the most discriminative features** for separating human-written from AI-generated code. Human developers accumulate idiosyncratic habits: mixing tabs and spaces, varying indentation depth across blocks, leaving trailing whitespace inconsistently, inserting irregular blank-line groupings, and aligning code to personal aesthetic preferences. AI models, trained on normalized corpora and generating token-by-token, produce mechanically consistent formatting -- uniform indentation depth, predictable blank-line placement, and almost no trailing whitespace or tab/space mixing.2223The paper compares two approaches. The **feature-based approach** extracts lightweight, interpretable features across four categories: (1) whitespace features (blank-line ratios, trailing whitespace frequency, space-to-tab ratios), (2) indentation features (indentation depth variance, consistency score, tab-vs-space preference), (3) structural features (cyclomatic complexity, nesting depth, function/block density), and (4) stylometric features (variable naming patterns, comment density, line length distribution). These feed into gradient-boosted tree classifiers (XGBoost, Random Forest) that achieve near-perfect discrimination. The **embedding-based approach** uses CodeBERT to encode semantic code representations, achieving slightly higher precision but less interpretability.2425The practical takeaway: you do not need a neural network to detect AI code. A small set of formatting-focused features -- extractable with simple regex and counting logic -- provides excellent detection. Indentation variance and whitespace consistency alone carry most of the signal. This makes the technique fast, explainable, and deployable without GPU infrastructure.2627## Step-by-Step Workflow28291. **Collect the code sample.** Obtain the source code to analyze. Ensure it is raw (not reformatted by a linter or auto-formatter like `black`, `prettier`, or `clang-format`), since auto-formatting destroys the whitespace signals this technique relies on.30312. **Extract whitespace features.** For every line, compute:32 - Leading whitespace character sequence (tabs vs. spaces vs. mixed)33 - Indentation depth (number of leading whitespace characters or tab-equivalent spaces)34 - Whether the line has trailing whitespace35 - Whether the line is blank36 Then aggregate: mean/median/stddev of indentation depth, ratio of blank lines to total lines, percentage of lines with trailing whitespace, ratio of tabs to spaces in leading whitespace.37383. **Compute indentation consistency score.** Measure the variance in indentation increments (the change in indentation depth between consecutive non-blank lines). Human code typically shows high variance (irregular jumps); AI code shows low variance (consistent 4-space or 2-space increments). Calculate the coefficient of variation of indentation deltas.39404. **Extract structural features.** Count: number of functions/methods, average function length (lines), maximum nesting depth, number of code blocks, cyclomatic complexity (branch count). AI code tends toward moderate, uniform complexity; human code varies more widely.41425. **Extract stylometric features.** Measure: average line length and its standard deviation, comment-to-code ratio, variable name length distribution, use of single-letter variable names, keyword diversity (unique keywords / total keywords). Human code tends to have more variable line lengths and more comments.43446. **Score each feature against known distributions.** Compare extracted values to typical ranges:45 - **AI indicators**: indentation depth stddev < 1.0, zero trailing whitespace, consistent indent increment (always 4 or always 2), blank-line ratio between 0.10-0.15, line length stddev < 1546 - **Human indicators**: indentation depth stddev > 2.0, some trailing whitespace present, mixed indent increments, tab/space mixing, irregular blank-line clustering, line length stddev > 2047487. **Compute a weighted confidence score.** Weight indentation/whitespace features highest (they carry ~60% of the discriminative power), structural features at ~25%, and stylometric features at ~15%. Produce a 0-1 score where values near 1.0 indicate likely AI-generated and values near 0.0 indicate likely human-written.49508. **Present the analysis with evidence.** Report the overall assessment (likely human / likely AI / uncertain), the confidence score, and the top 3-5 most informative features with their observed values and what they suggest. Always caveat that auto-formatted code will appear AI-like regardless of true origin.51529. **Recommend follow-up if inconclusive.** If the score falls in the uncertain range (0.3-0.7), suggest examining commit history for incremental development patterns (human signal), checking if an auto-formatter was applied, or requesting additional samples from the same author for cross-comparison.535410. **Optionally generate a detection script.** If the user needs to analyze many files, produce a Python script that extracts these features and outputs a CSV of per-file scores for batch analysis.5556## Concrete Examples5758**Example 1: Analyzing a single code snippet**5960User: "Can you tell if this Python code was written by a human or AI?"61```python62def fibonacci(n):63 if n <= 0:64 return []65 elif n == 1:66 return [0]67 elif n == 2:68 return [0, 1]6970 fib_sequence = [0, 1]71 for i in range(2, n):72 fib_sequence.append(fib_sequence[i-1] + fib_sequence[i-2])7374 return fib_sequence75```7677Approach:781. Extract whitespace features: all indentation is exactly 4 spaces, zero trailing whitespace, one blank line before `fib_sequence`, consistent spacing around operators792. Compute indentation consistency: indent increments are exactly {+4, 0, 0, 0, -4, +0, +4, -4, +0, -4} -- perfectly mechanical803. Structural features: single function, low complexity, textbook structure814. Stylometric features: descriptive variable names, no comments, uniform line lengths (stddev ~12)8283Output:84```85Assessment: LIKELY AI-GENERATED (confidence: 0.82)8687Key signals:88- Indentation: perfectly consistent 4-space indent, zero variance in increment magnitude (strong AI signal)89- Whitespace: no trailing whitespace on any line (AI signal)90- Structure: textbook fibonacci implementation with no personal style markers91- Line lengths: low standard deviation (13.2) suggesting uniform generation92- Comments: zero comments (mild AI signal -- humans often add at least one)9394Caveat: If this code was auto-formatted (e.g., by black), these whitespace95signals would appear AI-like regardless of true authorship. Check whether a96formatter is configured in this project.97```9899**Example 2: Comparing two implementations**100101User: "I have two solutions to the same problem. Which one looks human-written?"102103Solution A:104```python105def merge_sort(arr):106 if len(arr) <= 1:107 return arr108 mid = len(arr) // 2109 left = merge_sort(arr[:mid])110 right = merge_sort(arr[mid:])111 return merge(left, right)112113def merge(left, right):114 result = []115 i = j = 0116 while i < len(left) and j < len(right):117 if left[i] <= right[j]:118 result.append(left[i])119 i += 1120 else:121 result.append(right[j])122 j += 1123 result.extend(left[i:])124 result.extend(right[j:])125 return result126```127128Solution B:129```python130def merge_sort(arr):131 if len(arr) <= 1:132 return arr133134 mid = len(arr)// 2135 left = merge_sort(arr[:mid])136 right = merge_sort(arr[mid:])137138 return _merge(left, right)139140def _merge(l, r):141 res = []142 i=j=0143 while i < len(l) and j<len(r):144 if l[i] <= r[j]:145 res.append(l[i])146 i+=1147 else:148 res.append(r[j])149 j += 1150 res.extend(l[i:])151 res.extend(r[j:])152 return res153```154155Output:156```157Solution A: LIKELY AI-GENERATED (confidence: 0.79)158- Perfect 4-space indentation throughout159- Consistent spacing around all operators160- Descriptive variable names (left, right, result)161- Uniform blank-line placement (exactly one between functions)162163Solution B: LIKELY HUMAN-WRITTEN (confidence: 0.75)164- Uses tabs for indentation (personal preference signal)165- Inconsistent operator spacing: "len(arr)// 2" vs "i < len(l)" vs "i+=1" vs "j += 1"166- Abbreviated variable names (l, r, res) -- personal shorthand167- Leading underscore on _merge (style choice)168- Irregular spacing patterns across the file169170The inconsistent operator spacing in Solution B is a strong human signal.171AI models almost never produce "i+=1" on one line and "j += 1" two lines later.172```173174**Example 3: Batch analysis request**175176User: "I need to scan a directory of student submissions for AI-generated code."177178Approach:1791. Generate a Python script that walks a directory, extracts the feature set per file, and outputs scores1802. Focus on the highest-signal features to keep it lightweight181182Output script (key excerpt):183```python184import os, re, statistics185186def extract_features(code: str) -> dict:187 lines = code.split('\n')188 non_blank = [l for l in lines if l.strip()]189 indents = [len(l) - len(l.lstrip()) for l in non_blank]190 deltas = [abs(indents[i] - indents[i-1]) for i in range(1, len(indents))]191192 features = {}193 features['indent_stddev'] = statistics.pstdev(indents) if indents else 0194 features['delta_stddev'] = statistics.pstdev(deltas) if deltas else 0195 features['trailing_ws_ratio'] = sum(1 for l in lines if l != l.rstrip()) / max(len(lines), 1)196 features['blank_line_ratio'] = sum(1 for l in lines if not l.strip()) / max(len(lines), 1)197 features['tab_space_mix'] = any('\t' in l[:len(l)-len(l.lstrip())] for l in non_blank) and \198 any(' ' in l[:len(l)-len(l.lstrip())] for l in non_blank)199 lengths = [len(l) for l in non_blank]200 features['line_len_stddev'] = statistics.pstdev(lengths) if lengths else 0201202 # Heuristic score: lower = more likely AI203 score = 0.0204 if features['indent_stddev'] < 1.5: score += 0.25205 if features['delta_stddev'] < 2.0: score += 0.20206 if features['trailing_ws_ratio'] == 0: score += 0.15207 if not features['tab_space_mix']: score += 0.10208 if features['line_len_stddev'] < 15: score += 0.15209 if 0.08 < features['blank_line_ratio'] < 0.18: score += 0.15210 features['ai_score'] = score211 return features212213# Walk directory and score each file214for root, _, files in os.walk('submissions/'):215 for f in files:216 if f.endswith('.py'):217 path = os.path.join(root, f)218 code = open(path).read()219 feat = extract_features(code)220 flag = 'LIKELY AI' if feat['ai_score'] > 0.65 else \221 'UNCERTAIN' if feat['ai_score'] > 0.35 else 'LIKELY HUMAN'222 print(f"{path}: {flag} (score={feat['ai_score']:.2f})")223```224225## Best Practices226227- **Do:** Always check whether an auto-formatter (black, prettier, gofmt, rustfmt) has been applied before drawing conclusions. Auto-formatted code will appear AI-like regardless of true origin.228- **Do:** Weight indentation and whitespace features most heavily -- the paper shows these carry the majority of discriminative power over structural or naming features.229- **Do:** Report confidence levels honestly and present the specific features that drove the assessment, not just a binary label.230- **Do:** Analyze multiple files from the same author when available. Consistent patterns across files strengthen the signal.231- **Avoid:** Claiming certainty. Even at 0.995 ROC-AUC, false positives occur. Frame results as "likely" not "definitely."232- **Avoid:** Applying this technique to code in languages with enforced formatting (Go with gofmt, Rust with rustfmt) -- the forced consistency eliminates whitespace signals.233- **Avoid:** Using only a single feature. The technique's strength comes from combining multiple independent signals across categories.234235## Error Handling236237- **Auto-formatted code:** If you detect signs of auto-formatting (perfectly consistent style matching a known formatter's output), warn the user that whitespace-based detection is unreliable for this sample and suggest examining commit history or semantic features instead.238- **Very short snippets (<10 lines):** Too few lines produce unreliable statistics. Report that the sample is too small for confident analysis and ask for more code.239- **Minified or obfuscated code:** Whitespace has been intentionally removed. Report that the technique is inapplicable and suggest alternative analysis (variable naming patterns, control flow structure).240- **Mixed-origin code:** Some files contain both human and AI code (e.g., human skeleton with AI-filled functions). If feature distributions are bimodal, flag this possibility and suggest per-function analysis.241- **Language-specific norms:** Python's significant whitespace and PEP 8 conventions make some formatting uniform by community norm. Adjust thresholds accordingly -- focus on operator spacing, blank-line patterns, and trailing whitespace rather than indent depth alone.242243## Limitations244245- **Auto-formatters neutralize the technique.** Any code run through black, prettier, clang-format, gofmt, or similar tools will have its whitespace signals destroyed. This is the single biggest limitation.246- **AI models are improving.** As LLMs are fine-tuned on more diverse code, their formatting may become less uniform. Features that discriminate today may lose power over time.247- **Not effective on Go or Rust.** These languages have canonical formatters (gofmt, rustfmt) that virtually all code is run through, eliminating whitespace variation.248- **The approach is statistical, not forensic.** It estimates likelihood based on population-level patterns. An unusually disciplined human coder may be flagged; a prompted AI told to "write messy code" may evade detection.249- **Language coverage.** The underlying benchmark (600k samples) covers common languages (Python, Java, C++, JavaScript). Performance on niche languages (Haskell, Kotlin, Elixir) is unvalidated.250- **Single-sample reliability.** The technique is most reliable when analyzing multiple files from the same source. A single short file provides weak evidence.251252## Reference253254- **Paper:** [Whitespaces Don't Lie: Feature-Driven and Embedding-Based Approaches for Detecting Machine-Generated Code](https://arxiv.org/abs/2601.19264v1) (Nirob et al., 2026)255- **Key insight to look for:** Table/figure showing feature importance rankings -- indentation variance and whitespace consistency features dominate the top positions, providing the empirical basis for the whitespace-first detection strategy used in this skill.