# Implementation Trace: Research → Code

This file is the audit trail. For every claim the project makes about being "baked by research", there should be a specific research finding on one side and a specific piece of code on the other. The table below is that mapping. If a row is here, a skeptical reader can open the cited research file, open the cited code location, and decide for themselves whether the link is real.

No aggregate claims. No "informed by". Each row names one finding and one place the finding shows up in code or rules.

## The mapping

| Research finding | Source (category/file) | Implementation | Where |
|---|---|---|---|
| Sycophancy is the canonical failure mode of post-trained LLMs and the loudest single AI tell; humanization must subtract it, not add warmth on top of it. | Cat 02 `INDEX.md`; Cat 07 warmth–reliability; Cat 09 `INDEX.md` (Sharma et al. 2023, GPT-4o Apr 2025 rollback) | `SYCOPHANCY` regex list, line-start, looped up to 5 passes to strip stacked openers like "Great question! I'd be happy to help." | `unslop/scripts/humanize.py` L114–120, L260–264 |
| Em-dash pileup is a top-tier stylometric tell. Hard cap, not a preference. | Cat 04 `INDEX.md` (stylometric fingerprint); Cat 05 `INDEX.md` (burstiness/fingerprint signals) | `_cap_em_dashes_per_paragraph` — two per paragraph, with a per-item budget for list blocks so tight bullet lists aren't over-clipped. | `unslop/scripts/humanize.py` L195–250 |
| Transition tics ("Furthermore,", "Moreover,", "Additionally,", "In conclusion,") at sentence start are canonical AI-essay glue. | Cat 04 `INDEX.md`; Cat 01 (anti-slop prompt patterns) | `TRANSITION_TICS` regex list, anchored to line-start or after sentence-ending punctuation so mid-sentence uses survive. | `unslop/scripts/humanize.py` L139–143, L270–271 |
| Stock AI vocabulary ("delve", "tapestry", "testament to", "navigate" figurative, "embark", "realm", "landscape", "pivotal", "paramount", "seamless", "holistic", "leverage", "cutting-edge", "state-of-the-art") is the shared pattern set every humanizer targets. | Cat 04 `INDEX.md`; Cat 18 `INDEX.md` (commercial humanizers all crib the same Wikipedia *Signs of AI Writing* list); Cat 14 slop score | `STOCK_VOCAB` with context guards on `navigate` and `journey` so literal uses are preserved. | `unslop/scripts/humanize.py` L147–172 |
| Hedging stacks ("It's important to note that", "It's worth mentioning", "Generally speaking", "In essence", "At its core") are RLHF residue. | Cat 02 `INDEX.md` (RLHF bakes hedged tone); Cat 04 `INDEX.md`; Cat 15 `INDEX.md` | `HEDGING_OPENERS` regex list, strips opener plus trailing comma so the remainder reads naturally. | `unslop/scripts/humanize.py` L124–133, L267–268 |
| Performative balance — "however" appended to every claim — is a characteristic AI hedging pattern, not real qualification. | Cat 04 `INDEX.md`; Cat 02 (reward model prefers hedged, balanced prose) | `PERFORMATIVE` — mid-sentence ", however," collapses to a sentence break; sentence-start "However, " is stripped. | `unslop/scripts/humanize.py` L176–179, L276–277 |
| Flat sentence-length variance (burstiness) is the #1 detector signal; humanized text should span short and long sentences inside the same paragraph. | Cat 04 `INDEX.md`; Cat 05 `INDEX.md` (Binoculars, Fast-DetectGPT, stylometric fingerprint) | Burstiness metric — `_sentence_lengths` + `_burstiness` (stddev of sentence word counts over prose only), warning below σ=4 on docs ≥8 sentences in validator, plus a strict benchmark gate that fails when a human-like baseline is flattened under that floor. | `unslop/scripts/validate.py` L93–118, L248–267; `benchmarks/run.py` |
| Warmth training raises error rate 8–13% and amplifies sycophancy (Ibrahim / Hafner / Rocher 2025). Humanization must budget for this, not ignore it. | Cat 07 `INDEX.md`; Cat 15 `A-academic.md` (arXiv 2507.21919) | SKILL principle #3 "Warmth–reliability tradeoff is real", `[VERIFY: ...]` marker convention after rewriting numbers, explicit auto-clarity carve-out for security/legal/medical/safety/destructive ops, and the README's "warmth-reliability warning" section. | `skills/unslop/SKILL.md` L53, L91, L105–126; `README.md` L215–219 |
| Adversarial paraphrasing defeats tested detectors at scale (NeurIPS 2025, DIPPER NeurIPS 2023). Detector-resistant humanization is a pipeline, not one regex. | Cat 05 `INDEX.md` (DIPPER, Adversarial Paraphrasing, StealthRL); Cat 15 `A-academic.md`; Cat 18 `A-academic.md` | `anti-detector` mode in SKILL.md — six ordered steps (burstiness band, break predictable structure, contractions/fragments, specificity, rough edges, suggest different-model second pass). Slower, opt-in. | `skills/unslop/SKILL.md` L80–91 |
| AI-text detectors misclassify non-native English writing above 50% (Liang et al. *Patterns* 2023 — TOEFL essays; Cal State 98% self-flag rate). This is the legitimate defensive wedge; it is not a plagiarism tool. | Cat 05 `INDEX.md`; Cat 18 `INDEX.md` | Boundaries clause naming Liang 2023 and declining misuse; README "AI detectors — the honest version" section; README "When It Actually Matters" do-not-humanize list (code, legal, medical, security, runbooks). | `skills/unslop/SKILL.md` L135; `README.md` L170, L187–200 |
| Commercial humanizer claims do not survive independent audit (DAMAGE COLING 2025; Epaphras & Mtenzi 2026 — WriteHuman 1.98% ADR vs. QuillBot 93.56%; gap shifts monthly). | Cat 18 `INDEX.md`, `D-commercial.md`, `A-academic.md` | README "the honest version" section names the studies directly, explains why a second pass through a different model family outperforms SaaS humanizers, warns about month-to-month drift. | `README.md` L187–200 |
| Use/mention distinction: a quoted word is being discussed, not used; a humanizer that substitutes "delve" → "look at" inside `"delve"` is wrong. | Linguistic orthodoxy; Cat 04 (slop lists as enumerations of forbidden vocabulary, which require quoting the offending word to discuss it) | `QUOTED_PROSE` pattern + `_protect` placeholder system so `"delve"`, `"tapestry"`, curly-quoted variants are swapped out before `STOCK_VOCAB` runs and restored after. | `unslop/scripts/humanize.py` L49–60, L96–104 |
| Illustrative prose must be preserved verbatim: fenced code, indented code, inline code, URLs, headings, YAML frontmatter, markdown tables, blockquotes (glossary rows, quoted examples, comparison tables). Rewriting them destroys the document's meaning. | Cat 04 `INDEX.md` (humanization vs. technical accuracy); product contract | `_protect` / `_restore` placeholder system with order-dependent pattern application (YAML → fences → indented code → tables → blockquotes → headings → markdown links → inline code → URLs → quoted words). Validator re-checks every class and fails the run if any changed. | `unslop/scripts/humanize.py` L38–106; `unslop/scripts/validate.py` L135–216 |
| Humanizer output must not *introduce* AI-isms. "Fixing" a document that ends up with more slop than it started with is a regression. | Cat 04 `INDEX.md`; Cat 18 (commercial tools that paraphrase in slop) | `AI_ISM_PATTERNS` counted before/after; validator errors if count goes up; warns if count unchanged on a non-zero doc. | `unslop/scripts/validate.py` L32–60, L131–132, L237–246 |
| Two intensity levels are insufficient; humanization needs a style-vs-stance split and distinct modes for polish vs. rewrite vs. adversarial. | Cat 13 `INDEX.md` (two-factor humanness — Godspeed/IDAQ, Agency × Experience, Warmth × Competence); README summary insight #8; SKILL principle #2 | Five intensity levels — subtle, balanced (default), full, voice-match, anti-detector — documented with concrete before/after examples so the user can tell which one they want. | `skills/unslop/SKILL.md` L57–103 |
| Voice-match is a six-signal extraction (avg/variance, contractions, punctuation tics, register, rhetorical moves, forbidden patterns), not a "write like X" instruction. | Cat 10 `INDEX.md` (extract-then-apply architecture, authorship embeddings); Cat 14 `INDEX.md` (voice calibration from real samples) | `voice-match procedure` in SKILL.md enumerates the six signals and applies them in order (register → cadence → punctuation → vocabulary), with a named "don't hallucinate biographical details" guard. | `skills/unslop/SKILL.md` L67–78 |
| Authority tropes — "At its core,", "Fundamentally,", "In reality,", "What really matters is…", "The heart of the matter is…" — are RLHF-trained rhetorical moves that perform gravitas without adding information. Anti-tell prompts explicitly ban "fundamentally" and "arguably". | Cat 05 `INDEX.md` evasion-strategy list ("strip *delve, utilize, leverage, harness, streamline, fundamentally, arguably*; avoid tricolons, extended metaphors, 'not only Y, it's also Z,' LOTR multi-endings"); Cat 02 `INDEX.md` (RLHF reward-model preference for hedged gravitas) | `AUTHORITY_TROPES` regex list, anchored to sentence start (line-start or after `[.!?]`) or after a list marker. Applied only at `balanced` and `full` intensities so a plain mid-sentence "at its core" isn't touched. | `unslop/scripts/humanize.py` L316–327, L571–575 |
| Structural slop — meta-prose that announces the writing rather than doing it ("Let's dive in.", "Here's what you need to know:", "Without further ado,", "In this article, I'll…", closing "Buckle up.") — is the detector-visible shape that vocabulary substitution alone cannot fix. AI slop is a *structural* pattern, not only a lexical one. | Cat 04 `B-industry.md` 1.14 Slop Evader ("AI slop is a *structural* pattern (tidy five-paragraph arcs, zoom-out conclusions, marching transitions), not a lexical one"); Cat 05 `INDEX.md` ("LOTR multi-endings" banned) | `SIGNPOSTING` regex list, anchored to sentence start, strips the meta lead-in and lets the next clause carry the content. Applied at `balanced` and `full`. | `unslop/scripts/humanize.py` L333–340, L577–581 |
| Filler phrases — "in order to", "due to the fact that", "a wide variety of", "prior to", "with regard to", "the fact that" — inflate register without adding content; their frequency is a stylometric fingerprint even when individual uses are defensible. Tight prose collapses them; a humanizer should do the collapse explicitly, not hope the LLM does. | Cat 04 `B-industry.md` 1.13 Hacker News playbook (canonical slop vocabulary enumerated for CI regex checks); Cat 14 `INDEX.md` (tight prose as voice-quality signal) | `FILLER_PHRASES` list of `(pattern, replacement)` pairs, applied only at `full` intensity because some fillers (legal/technical hedges) are sometimes legitimate and stripping them at `balanced` would over-rewrite. | `unslop/scripts/humanize.py` L345–358, L583–587 |
| Negative parallelism — "No guesswork, no bloat, no surprises." — a three-clause tricolon of negations as a punch line. Named explicitly in anti-tell prompt rules ("avoid… 'not only Y, it's also Z'"). Single-clause use is fine; the three-clause stack is the AI tell. | Cat 05 `INDEX.md` (evasion-strategy rule 5: "avoid tricolons, extended metaphors, 'not only Y, it's also Z,' LOTR multi-endings") | `NEGATIVE_PARALLELISM` — strips a "No X, no Y, no Z." sentence-form pattern only (never mid-clause), only at `full`. Intentionally conservative: a single `No bugs.` is preserved. | `unslop/scripts/humanize.py` L365–371, L589–593 |
| A humanizer is a rewriting tool with consequences; it must be auditable. For every deterministic change a reviewer should be able to see which rule fired, what it replaced, and what with. Per-rule counts let you regress-test individual rules. | Cat 15 `C-opensource.md` entry 13 (LLMMetricsResearch: feature-level stylometric evaluation); Cat 14 `B-industry.md` (no public long-form voice benchmark — projects must publish their own) | `Replacement` dataclass + `HumanizeReport` (per-rule counts, before/after, em-dash totals), emitted via `HumanizeOutcome.report` to the CLI's `--json` and `--report` modes so a reviewer can see what actually changed. | `unslop/scripts/humanize.py` L38–73, L474–501 |
| "Three intensity levels is a real product surface, not a toggle": a subtractive rewriter must offer a conservative mode (only the worst slop) and an aggressive mode (everything the rules can catch), because one setting can't serve both a developer doc and a marketing page. | Cat 13 `INDEX.md` (two-factor humanness — Warmth × Competence, Agency × Experience → single dial is insufficient); Cat 04 `B-industry.md` 1.13 (context-differentiated banlists: dev-tools aggressive, customer chat light) | `VALID_INTENSITIES = ("subtle", "balanced", "full")` and intensity-gated application in `humanize_deterministic` so each rule set fires only at its earliest-justified level. Enforced by a benchmark monotonicity gate (`run.py --all-intensities --strict`). | `unslop/scripts/humanize.py` L33–34; `benchmarks/run.py` |
| Contraction rate is a distributional fingerprint detectors read at the token-level. Kalemaj et al. (arXiv 2604.11687): AI text averages ~0.00 contractions per chunk vs. human ~0.17. Raising the contraction rate in already-clean prose is the single highest-leverage deterministic token-level edit. | Cat 15 `A-academic.md` (arXiv 2604.11687); Cat 05 evasion-strategy list | `_CONTRACTION_RE` measures the rate in `validate.py`; `soul.contract_negations` + `soul.contract_copula` in `unslop/scripts/soul.py` apply 18 auxiliary-negation + 12 copula contractions with allow-listed follow-ons (so "it is [X's]" stays expanded when X is a possessive). Gated behind `--soul`. | `unslop/scripts/soul.py` L1–140; `unslop/scripts/validate.py` L294–314 |
| Structural tells (flat sentence-length σ, parallel-bullet soup, tidy five-paragraph shapes) are the shape detectors actually read; lexical-only humanization raises Adversarial-Paraphrasing detector TPR 8–15% (NeurIPS 2025). Rewriting vocabulary without restoring variance is a regression against modern detectors. | Cat 04 `INDEX.md`; Cat 14 `INDEX.md` (human stdev ~8.2 vs GPT-4o ~4.1); Cat 05 (Adversarial Paraphrasing NeurIPS 2025) | `unslop/scripts/structural.py` — `split_long_sentences` splits ≥30-word sentences at `; / , but / , and then / , so / , while / , however, /  — ` when paragraph σ < 5; `merge_bullet_soup` collapses ≥3 short parallel bullets into one sentence. Gated behind `--structural`. 23 tests cover balance checks, placeholder safety, and risky-connector refusal. | `unslop/scripts/structural.py` L35–234 |
| Commercial humanizer claims do not survive independent audit. DAMAGE (COLING 2025) tested 19 humanizers: GPTZero detection dropped 99.73% → 60.04% across the class; individual tools varied by 20–100 points on the same input. The "99.8% undetectable" number is a marketing figure, not a reproducible measurement. | Cat 16 (DAMAGE arXiv 2501.03437); Cat 18 `INDEX.md` / `D-commercial.md` | `unslop/scripts/detector.py` module docstring names DAMAGE directly as the justification for a live detector-feedback loop rather than trusting any single tool's self-reported number; README's "the honest version" section names DAMAGE + Epaphras & Mtenzi 2026 + the month-to-month drift claim. | `unslop/scripts/detector.py` L25–32; `README.md` "AI detectors — the honest version" |
| Blandification is quantified: Psychology Today Mar 2026 / arXiv 2603.18161 measured ~70% neutralization of author voice under LLM-assisted revision even in grammar-only edits; semantic meaning shifts beyond surface tokens. A humanizer that over-rewrites is not neutral — it destroys the signal it was paid to preserve. | Cat 10 `INDEX.md` (arXiv 2603.18161); Cat 10 `A-academic.md` (Rallapalli et al. 2604.14111 on RLHF as homogenization cause) | `humanize.py` LLM-mode prompt carries an explicit **ANTI-BLANDIFICATION** block ("Do NOT neutralize distinctive claims, opinions, or stylistic choices from the original… Strip the slop; preserve the signal"). Deterministic mode is subtractive by construction. SKILL principle #1 ("Subtract, don't add") restates this for the agent. | `unslop/scripts/humanize.py` (LLM prompt ANTI-BLANDIFICATION block); `skills/unslop/SKILL.md` principle #1 |
| Antislop (ICLR 2026 poster #10008156, arXiv 2510.15061): per-pattern counts are the cheapest reproducible quality signal; auto-antislop's end-to-end pipeline (profile → slop list → FTPO training data) matches our deterministic path. A humanizer should emit the counts that a fine-tune-based defender would train against. | Cat 04 `A-academic.md` (Antislop ICLR 2026); Cat 16 (`sam-paech/auto-antislop`, `sam-paech/antislop-vllm`) | `Replacement` dataclass + `HumanizeReport` emit per-rule counts (which rule fired, how many times, what it replaced) via the CLI's `--json` and `--report` modes. Downstream: the same counts serve as a training-data signal for FTPO-style fine-tunes. README "Architecture" section names auto-antislop as the pipeline parallel. | `unslop/scripts/humanize.py` `Replacement` + `HumanizeReport`; `README.md` architecture section |
| "Catch Me If You Can?" (arXiv 2509.14543, EMNLP 2025) tested six frontier models on personal-style imitation — all fail. Few-shot prompting is 23.5× better than zero-shot but still insufficient; fine-tuning wins decisively. A prompt-only "write like me" instruction is architecturally the wrong tool. Voice match needs an *extracted* signal set, not a free-text direction. | Cat 10 `INDEX.md` / `A-academic.md` (arXiv 2509.14543); Cat 10 extract-then-apply architecture | `voice-match` is a two-layer feature: Phase 4 stylometry (`stylometry.py`) extracts 17 deterministic signals (sentence-length μ/σ, fragment rate, contraction rate, punctuation rates, TTR, Latinate ratio, pronoun rates, approximate passive voice, And/But-opener rate), and Phase 8 style memory (`style_memory.py`) persists them per user. The voice-match path in `humanize.py` feeds the extracted profile back into the LLM prompt rather than relying on "write like this sample". | `unslop/scripts/stylometry.py` L1–210; `unslop/scripts/style_memory.py` L1–220 |
| LLM-as-judge has quantified, reproducible biases: ~40% position inconsistency, ~15% verbosity inflation, 5–7% self-enhancement (arXiv 2411.15594 LLM-as-Judge Survey; arXiv 2410.02736 CALM; arXiv 2601.07648 "Order in the Evaluation Court"). A perceived-humanness benchmark that ignores these biases overstates its own results. | Cat 04 `A-academic.md` (LLM-judge bias section); Cat 15 `A-academic.md` | `evals/perceived_humanness.py` — randomizes A/B order per-fixture, discloses the bias figures in its module docstring, and exposes a `--judges` flag to run a multi-model jury (Claude Sonnet + GPT-5) so single-model self-enhancement is visible. Single-judge mode still works for the fast path but prints the bias disclaimer. | `evals/perceived_humanness.py` L1–60, `--judges` flag |
| Sycophancy × memory link: condensed user profiles in memory are the largest sycophancy driver across five LLMs (MIT/Penn State CHI 2026, Barcelona). A style-memory feature that caches "user likes X" risks amplifying sycophancy over time; the mitigation is to persist *measured signals*, not free-text preferences. | Cat 20 `INDEX.md` (CHI 2026 sycophancy×memory); Cat 02 `INDEX.md` (Shapira et al. arXiv 2602.01002 — RLHF amplifies sycophancy) | `style_memory.py` persists only numerically-measured stylometric signals (`StyleProfile` fields from `stylometry.py`) — never free-text preference strings, never "user prefers warm tone" slots. Module docstring names the CHI 2026 finding and the OWASP Top-10 agentic Memory Poisoning risk as the design constraint. | `unslop/scripts/style_memory.py` module docstring + `StyleProfile` schema |
| OWASP Top 10 for Agentic Applications 2026 lists persistent memory as a named risk. InjecMEM (one-injection memory poisoning), memory control flow attacks, and semantic drift (Memory Security survey arXiv 2604.16548, Apr 2026) are now the reference threat class. A local style-memory file is a trust boundary that must refuse symlinks, enforce owner-only permissions, and validate its own schema on load. | Cat 20 `INDEX.md` (OWASP Agentic 2026, arXiv 2604.16548); Rehberger memory poisoning (2024) as historical basis | `style_memory.py` refuses symlinks (`lstat().st_mode` check before open), writes with `os.O_CREAT \| O_EXCL \| O_WRONLY` mode `0o600`, validates schema on load (any extra or missing field → reject), and limits file size on read. Paths are resolved against `CLAUDE_CONFIG_DIR` so an attacker-controlled `HOME` doesn't silently redirect the memory file. | `unslop/scripts/style_memory.py` (security section) |
| Turnitin August 2025 anti-humanizer update trained its detector on humanizer-tool outputs specifically and created a new "AI-generated text that was AI-paraphrased" detection category. All pre-August 2025 Turnitin bypass numbers are stale; Chicago Booth 2026 measured a 60–85% drop against edited/paraphrased content vs. raw AI text. The arms race is live and month-to-month. | Cat 05 `INDEX.md`, Cat 16 `INDEX.md`, Cat 18 `D-commercial.md` | README "the honest version" section names Turnitin August 2025 and Chicago Booth 2026 specifically and tells the reader to treat any single-point benchmark as a snapshot. SKILL anti-detector procedure ends with "suggest a different-model second pass" rather than a tool-stable claim. | `README.md` detector-honest section; `skills/unslop/SKILL.md` anti-detector step 6 |
| TempParaphraser (EMNLP 2025, `HJJWorks/TempParaphraser`): temperature-simulation paraphrasing is a cheap structural humanization lever — no LLM call needed on the attacker side — that reduces average detector accuracy 82.5%. Paired with different-model rewriting (Adversarial Paraphrasing NeurIPS 2025), it is the single most reliable detector-evasion path a humanizer can recommend. | Cat 15 `A-academic.md` (TempParaphraser EMNLP 2025); Cat 05 `INDEX.md` | `detector.py` feedback loop, when the escalation ladder exhausts without hitting the target, prints a structured recommendation naming TempParaphraser-style cross-model paraphrase as the next step. SKILL anti-detector step 6 names it explicitly and flags EU AI Act Article 50 exposure (watermark removal is specifically prohibited). | `unslop/scripts/detector.py` feedback-loop tail output; `skills/unslop/SKILL.md` anti-detector step 6 |
| Persona drift is empirically confirmed at >30% degradation after 8–12 turns (RMTBench). HorizonBench (arXiv 2604.17283, Apr 2026) is now the first benchmark for preference evolution over time. Voice consistency over a long session is a distinct problem from first-message voice match. | Cat 08 `INDEX.md` (RMTBench persona drift); Cat 20 `INDEX.md` (HorizonBench) | `hooks/unslop-mode-tracker.js` maintains a per-session turn counter at `$CLAUDE_CONFIG_DIR/.unslop-turn-count` (symlink-safe, size-capped, whitelist-validated via `unslop-config.js`) and re-emits an expanded drift-check banner at turns 8, 16, 24, 32, then every 16 turns thereafter — the HorizonBench-calibrated decay curve. `unslop-activate.js` zeroes the counter on session start so drift state does not leak across shells; the "stop unslop" phrase also resets it. README's "Persona drift over long sessions" section names RMTBench + HorizonBench directly and points users at voice-match + style memory as the complementary long-horizon layer. SKILL anti-detector step 7 repeats the re-anchor checklist so agents that miss the hook output still self-correct. Covered by `tests/test_hooks.py::test_drift_checkpoint_banner_at_turn_8`, `test_drift_counter_resets_on_session_start`, `test_drift_counter_resets_on_stop_phrase`. | `hooks/unslop-activate.js` + `hooks/unslop-mode-tracker.js` + `hooks/unslop-config.js`; `skills/unslop/SKILL.md` anti-detector step 7; `README.md` persona-drift section; `tests/test_hooks.py` |
| New AI-ism vocabulary families surface in April 2026 audits and Wikipedia:Signs_of_AI_writing maintenance: `meticulous(ly)`, `bustling`, `paradigm shift`, `game-changer/changing`, `revolutionize(s/d/ing)`, `transformative`, `unprecedented` in purple-adjective contexts, `a myriad of` / `myriad`, `a plethora of`, `uncharted territory/waters`, `nuanced` as connective filler, `synergy/synergies/synergize`. Each routinely survives first-pass humanization and is named in Wikipedia's cleanup-priority list and in the blader taxonomy follow-up. | Cat 04 `INDEX.md`; Cat 17 `INDEX.md` ("AI slop" Word of the Year references); Wikipedia:Signs_of_AI_writing (WikiProject AI Cleanup maintained) | `unslop/scripts/humanize.py` `STOCK_VOCAB` appends deterministic rewrite rules for each family, with guarded patterns where literal use is legitimate (`unprecedented` is kept in factual quantitative contexts like "unprecedented drought"; `game-changer` is kept in literal game contexts). `unslop/scripts/validate.py` `AI_ISMS` mirrors each family so the residual count is measured and a rewrite can't silently reintroduce them. `tests/unslop/test_humanize.py::TestDeterministicStockVocab` adds six new cases (`test_strips_meticulous_and_bustling`, `test_strips_paradigm_shift_and_game_changer`, `test_strips_revolutionize_and_transformative`, `test_strips_myriad_and_plethora`, `test_strips_uncharted_and_synergy`, `test_unprecedented_kept_in_factual_context`). | `unslop/scripts/humanize.py`; `unslop/scripts/validate.py`; `tests/unslop/test_humanize.py` |
| EU AI Act Article 50 (Code of Practice Dec 2025 draft, effective August 2026): mandates multilayered AI text marking and explicitly prohibits watermark removal. Bypass products face direct EU compliance exposure; a humanizer that ships a "remove SynthID" button is out of scope by construction. | Cat 04 / 05 / 09 / 16 `INDEX.md` (EU AI Act Article 50); Cat 09 California SB 243 as parallel jurisdictional forcing function | SKILL `Boundaries` section names EU AI Act Article 50 and California SB 243 as hard no-go lines; anti-detector mode's explicit scope is "voice defense against false positives for non-native English writers", not watermark stripping. README detector section restates this. | `skills/unslop/SKILL.md` Boundaries; `README.md` detector section |
| DivEye (arXiv 2509.18880, TMLR 2026) found *intra-document surprisal variance* — not absolute perplexity — is the primary human signal that survives paraphrase attacks. A full DivEye reading needs a small local LM to score per-token log-probs. Two deterministic proxies are cheaper and stay offline: per-sentence word-length σ (Zipf's abbreviation law makes word-length ≈ inverse rarity), and coefficient-of-variation of sentence word-counts (σ/μ — scale-invariant burstiness). Both correlate with, not equal, DivEye's reading and are priced in as proxies in field names. | Cat 15 `A-academic.md` (DivEye TMLR 2026); Cat 04 `INDEX.md` (burstiness / fingerprint); Cat 05 `INDEX.md` (paraphrase-resistant detectors) | `unslop/scripts/stylometry.py` `StyleProfile` adds `sentence_length_cv` and `word_length_stdev`. `analyze` computes them from the same strip-then-tokenize pipeline as the other signals; both are zero-safe on empty prose. `_format_voice_targets` in `unslop/scripts/humanize.py` surfaces them in the LLM voice-match prompt with an explicit "DivEye-style surprisal-variance proxy" label so the rewriter can target higher variance. Covered by `tests/unslop/test_stylometry.py::TestDivEyeProxies` (six cases: uniform/high/scale-invariance/monotone/mixed-register/empty). | `unslop/scripts/stylometry.py`; `unslop/scripts/humanize.py` `_format_voice_targets`; `tests/unslop/test_stylometry.py` |
| DivEye (arXiv 2509.18880, TMLR 2026), real reading. The deterministic proxies (above) are cheap stand-ins for DivEye's per-token log-prob variance. A genuine reading needs an actual causal LM to score the document. The smallest credible model (distilgpt2, 82M params, ~330MB, MIT license) runs on CPU in ~1s on a cached load. Using *any* small LM already approximates the DivEye signal — the absolute numbers are per-model but the variance pattern (flat for AI, bursty for human) is qualitatively stable. Gate behind an explicit opt-in because the dep is heavy. | Cat 15 `A-academic.md` (DivEye TMLR 2026, full methodology); Cat 04 `INDEX.md` (burstiness as the residual post-paraphrase signal) | `unslop/scripts/surprisal.py` loads a small causal LM lazily, computes per-token surprisal, returns `SurprisalReading` (mean log-prob, stdev, coefficient of variation, token count). Heavy deps (torch, transformers) import inside the function so the common CLI path stays fast; `SurprisalUnavailable` (RuntimeError subclass) is raised on missing deps / failed load. `cli.py` adds a one-shot `--surprisal-variance` flag (with optional `--surprisal-model`) that reads stdin or a file, prints JSON, exits. `UNSLOP_SKIP_SURPRISAL=1` forces the unavailable path for CI. Covered by `tests/unslop/test_surprisal.py` (9 unit + 2 opt-in end-to-end tests gated on `UNSLOP_RUN_REAL_SURPRISAL=1`); CLI path covered by `tests/unslop/test_cli.py::TestSurprisalOneShot`. | `unslop/scripts/surprisal.py`; `unslop/scripts/cli.py` (`_handle_surprisal_command`); `tests/unslop/test_surprisal.py`; `tests/unslop/test_cli.py` |
| "Reason privately, humanize publicly" (Cat 06 + Cat 19). Turpin et al. on CoT faithfulness, s1 budget-forcing (arXiv 2501.19393, EMNLP 2025), Anthropic `<thinking>` wrappers, and DeepSeek-R1 `<think>` tags all produce a published reasoning trace that is stylistically distinct from the public answer. Humanizers should operate on the final output, not the trace. An agent can paste raw output into a file and inadvertently ship the reasoning; a defensive humanizer strips six named shapes (XML wrappers `<thinking>` / `<think>` / `<analysis>` / `<reasoning>` / `<scratchpad>` / `<plan>`, plus markdown `## Reasoning` / `## Thought Process` / `## Plan` sections) and writes the stripped content to a sidecar for audit. Destructive by design; opt-in. | Cat 06 `INDEX.md` (Turpin et al. CoT faithfulness); Cat 19 `INDEX.md` (private reasoning, public answer); Cat 04 `INDEX.md` (reasoning artifacts as stylistic tells) | `unslop/scripts/reasoning.py` defines `strip_reasoning_traces(text) -> (cleaned, ReasoningReport)`. Deterministic regex pass; XML wrappers match case-insensitively with non-greedy body; markdown sections strip from heading to next heading of equal-or-lower depth or EOF. Idempotent — second call is a no-op. `humanize.py` `humanize_deterministic[_with_report]` gains a `strip_reasoning: bool = False` kwarg that runs the sanitizer before `_protect`, and the returned report now carries a `reasoning` field. `humanize_file_ex` writes a `<stem>.reasoning.md` sidecar on strip. CLI adds `--strip-reasoning`. Covered by `tests/unslop/test_reasoning.py` (19 cases) and `tests/unslop/test_cli.py::TestStripReasoning{Stdin,File}`. | `unslop/scripts/reasoning.py`; `unslop/scripts/humanize.py`; `unslop/scripts/cli.py`; `tests/unslop/test_reasoning.py`; `tests/unslop/test_cli.py` |

## What research we are NOT using yet

Honest gaps. These are real parts of the compendium that have no current reflection in the code or skill rules:

- **Category 03 (Persona & Character Design).** The project documents a voice-match procedure but does not ship persona vectors, a four-layer persona YAML, or any character-training-style versioned identity artifact. The `humanizer` skill is a subtractive layer, not a persona. Anthropic's Persona Selection Model (Feb 2026) and the Four-Quadrant Technical Taxonomy (NeurIPS 2025) are design-relevant but not wired in.
- **Category 10 fine-tuning path.** Extract-then-apply now runs through `stylometry.py` + `style_memory.py` (signals + persistence), but there is still no authorship embedding, no TinyStyler/STAR-style small-expert model, and no `Profile-to-PEFT`-style (arXiv 2510.16282) hypernetwork LoRA. The extracted profile feeds a prompt, not a fine-tune. "Catch Me If You Can?" (EMNLP 2025) says fine-tuning wins decisively for personal-style imitation — we're one layer short of that.
- **Category 19 (Agentic Autonomous Thinking) and Category 06 (Chain-of-Thought) — partial.** The `unslop-reasoning` sub-skill covers the convention-level separation. As of v0.5.4 the humanizer also ships an opt-in programmatic stripper (`unslop/scripts/reasoning.py`; `--strip-reasoning` CLI flag) that removes six named reasoning-trace shapes before rewriting. Still out of scope: latent / CoT-free reasoning analysis (Latent CoT Survey, arXiv 2504.16577), pause-token training, and any kind of inference-time reasoning-budget control — those are training- and sampler-side levers, not a post-generation humanizer's territory.
- **Category 04 decoder-level levers (min-p, DRY, XTC, contrastive decoding, top-nσ).** The file rewriter targets text after generation. It does not touch the sampler stack, which Cat 04 names as the single largest humanization lever. That layer is out of scope for a skill that runs against existing model APIs. Rallapalli et al. (arXiv 2604.14111, Apr 2026) — decoding temperature as an independent stylistic signal — is likewise unreachable from our position.
- **Category 15 DivEye-class detectors (surprisal-variance — implemented).** v0.5.3 added two deterministic proxies (`sentence_length_cv`, `word_length_stdev`) that surface in the voice-match prompt. v0.5.4 adds the real LM-based reading (`unslop/scripts/surprisal.py`) via a small optional dep on distilgpt2. Gated behind the `--surprisal-variance` one-shot command so the 99% CLI path doesn't pay the dependency cost. Both layers ship. Still out of scope: RAID-style large-scale detector benchmarking (we link and measure, we don't curate); calibration against every commercial detector (that arms race is month-to-month — see Chicago Booth 2026 / Turnitin August 2025).
- **Category 05 watermark-awareness (SIRA, AdaDetectGPT, SynthID probe).** We neither read nor remove watermarks. EU AI Act Article 50 makes this the correct default: watermark removal is explicitly prohibited. We note the research and stay out of it.

## How to verify a claim in this file

For any row in the table:

1. Open the research file named in the "Source" column. Read the specific passage. The INDEX files at `docs/research/<NN>-<category>/INDEX.md` cross-cut five angle files each; the claim is usually stated in the INDEX summary and then elaborated in `A-academic.md` or `D-commercial.md`.
2. Open the code or skill file at the line range in "Where". Confirm the pattern, the rule, or the procedure is actually there. Line numbers may shift slightly as the files evolve — search for the named identifier (`SYCOPHANCY`, `_cap_em_dashes_per_paragraph`, etc.) if the line range is off.
3. Run the test that exercises it. `python3 -m pytest tests/unslop/test_humanize.py -v` covers the regex rows (sycophancy, em-dash cap, stock vocab, hedging, transition tics, performative balance) and the preservation rows (code blocks, URLs, headings, YAML, blockquotes, tables, inline code). Rows that live only in the SKILL or README (warmth-reliability, anti-detector, detector false positives) have no unit test — verify them by reading the cited research and reading the cited section of `skills/unslop/SKILL.md` or `README.md` side by side.

If a row doesn't hold up under all three steps, it's a bug in this file. Fix the row or delete it.
