humanizer-ru 3.21.0 → 3.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -1,14 +1,15 @@
1
1
  # humanizer-ru
2
2
 
3
- > [Русская версия: основная](README.md)
3
+ > [Русская версия: основная](README.md) · [中文](README.zh.md)
4
4
 
5
5
  Claude Code / Cowork plugin. Kills AI smell in Russian text. The English [humanizer](https://github.com/blader/humanizer) won't help here. Russian AI markers are their own beast: bureaucratic noun-chains (канцелярит), English-syntax calques, missing particles like "же" and "ведь" that make Russian sound alive.
6
6
 
7
7
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
8
- [![Version](https://img.shields.io/badge/version-3.21.0-blueviolet)](https://github.com/ilyautov/humanizer-ru/blob/main/CHANGELOG.md)
8
+ [![Version](https://img.shields.io/badge/version-3.23.0-blueviolet)](https://github.com/ilyautov/humanizer-ru/blob/main/CHANGELOG.md)
9
9
  [![Stars](https://img.shields.io/github/stars/ilyautov/humanizer-ru?style=social)](https://github.com/ilyautov/humanizer-ru/stargazers)
10
10
  [![skills.sh](https://skills.sh/b/ilyautov/humanizer-ru)](https://skills.sh/ilyautov/humanizer-ru/humanizer-ru)
11
11
  [![npm](https://img.shields.io/npm/v/humanizer-ru?label=npm%20%C2%B7%20dsh)](https://www.npmjs.com/package/humanizer-ru)
12
+ [![HOL](https://img.shields.io/endpoint?url=https%3A%2F%2Fhol.org%2Fapi%2Fregistry%2Fbadges%2Fplugin%3Fslug%3Dilya-utov%252Fhumanizer-ru%26metric%3Dstatus%26style%3Dflat)](https://hol.org/registry/plugins/ilya-utov%2Fhumanizer-ru)
12
13
 
13
14
  <p align="center">
14
15
  <a href="https://humanizer-ru.aifrontier.tech/">
@@ -18,14 +19,20 @@ Claude Code / Cowork plugin. Kills AI smell in Russian text. The English [humani
18
19
 
19
20
  🧪 **Live demo:** [humanizer-ru.aifrontier.tech](https://humanizer-ru.aifrontier.tech/#audit). Paste a Russian text, get a 0-100 cleanliness score and highlighted markers. Same scanner as in the skill, runs in the browser.
20
21
 
21
- **Quick start** in Claude Code, two commands:
22
+ **Quick start**, one command for any agent (Claude Code, Cursor, Codex, Copilot, Cline and dozens more):
23
+
24
+ ```
25
+ npx skills add ilyautov/humanizer-ru
26
+ ```
27
+
28
+ The CLI detects your installed agents and asks where to put the skill. In Claude Code you can also install it as a plugin, then updates arrive via `/plugin`:
22
29
 
23
30
  ```
24
31
  /plugin marketplace add ilyautov/humanizer-ru
25
32
  /plugin install humanizer-ru@ilyautov-plugins
26
33
  ```
27
34
 
28
- Cursor, Copilot, Cline and other agents: `npx skills add https://github.com/ilyautov/humanizer-ru/tree/main/skills/humanizer-ru`. Claude.ai, Codex, DeepSeek Harness and team rollout are covered in [Install](#install).
35
+ Claude.ai, DeepSeek Harness and team rollout are covered in [Install](#install).
29
36
 
30
37
  📖 **Docs & write-ups (RU):** [humanizer-ru.aifrontier.tech](https://humanizer-ru.aifrontier.tech/): do AI detectors work on Russian, the 64 markers, plagiarism vs AI detection.
31
38
 
@@ -37,6 +44,8 @@ Cursor, Copilot, Cline and other agents: `npx skills add https://github.com/ilya
37
44
 
38
45
  The [site's front page](https://humanizer-ru.aifrontier.tech/#audit) runs the same scanner in JavaScript: paste a text, get a 0-100 cleanliness score, highlighted markers and the install command for your agent. Everything runs in the browser, nothing is uploaded. Rules are exported from `markers.py` by `scripts/export_web_rules.py`; `scripts/test_web_parity.py` keeps the web and Python engines in step in CI.
39
46
 
47
+ The same scanner ships as a Chrome extension: select text on any page, pick "Проверить на следы нейросети" in the context menu, and the popup shows the score and highlights. Two permissions only, context menu and local storage; no host access, no network. Source in `extension/`, built by `scripts/build_extension.py`; until the Web Store listing is live, load it via `chrome://extensions` → Developer mode → Load unpacked.
48
+
40
49
  ## Install
41
50
 
42
51
  Three deployment channels: upload to Claude.ai web UI, roll out across an organization, or install into local agents (Claude Code, Cowork, API).
package/README.md CHANGED
@@ -2,13 +2,14 @@
2
2
 
3
3
  > Скилл для Claude. Убирает 64 признака нейросети в русском тексте: канцелярит, кальки, фингерпринты ChatGPT и Claude. Метит в то, что измеряют GPTZero, DivEye, RuBERT: поднимает perplexity и burstiness. 21 жёстких банов, quad-pass аудит, калибровка под голос автора, eval-харнес с метриками до/после. Живое демо сканера на сайте.
4
4
 
5
- > [English version](README.en.md)
5
+ > [English version](README.en.md) · [中文](README.zh.md)
6
6
 
7
7
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
8
- [![Версия](https://img.shields.io/badge/версия-3.21.0-blueviolet)](https://github.com/ilyautov/humanizer-ru/blob/main/CHANGELOG.md)
8
+ [![Версия](https://img.shields.io/badge/версия-3.23.0-blueviolet)](https://github.com/ilyautov/humanizer-ru/blob/main/CHANGELOG.md)
9
9
  [![Звёзды](https://img.shields.io/github/stars/ilyautov/humanizer-ru?style=social)](https://github.com/ilyautov/humanizer-ru/stargazers)
10
10
  [![skills.sh](https://skills.sh/b/ilyautov/humanizer-ru)](https://skills.sh/ilyautov/humanizer-ru/humanizer-ru)
11
11
  [![npm](https://img.shields.io/npm/v/humanizer-ru?label=npm%20%C2%B7%20dsh)](https://www.npmjs.com/package/humanizer-ru)
12
+ [![HOL](https://img.shields.io/endpoint?url=https%3A%2F%2Fhol.org%2Fapi%2Fregistry%2Fbadges%2Fplugin%3Fslug%3Dilya-utov%252Fhumanizer-ru%26metric%3Dstatus%26style%3Dflat)](https://hol.org/registry/plugins/ilya-utov%2Fhumanizer-ru)
12
13
 
13
14
  <p align="center">
14
15
  <a href="https://humanizer-ru.aifrontier.tech/">
@@ -23,14 +24,20 @@
23
24
 
24
25
  🧪 **Живое демо:** [humanizer-ru.aifrontier.tech](https://humanizer-ru.aifrontier.tech/#audit). Вставьте свой текст, получите оценку чистоты 0-100 и подсветку найденных оборотов. Тот же сканер, что в скилле, считается в браузере.
25
26
 
26
- **Быстрый старт** в Claude Code, две команды:
27
+ **Быстрый старт**, одна команда для любого агента (Claude Code, Cursor, Codex, Copilot, Cline и ещё десятки):
28
+
29
+ ```
30
+ npx skills add ilyautov/humanizer-ru
31
+ ```
32
+
33
+ CLI найдёт установленных агентов и спросит, куда ставить. В Claude Code можно и плагином, тогда обновления приходят через `/plugin`:
27
34
 
28
35
  ```
29
36
  /plugin marketplace add ilyautov/humanizer-ru
30
37
  /plugin install humanizer-ru@ilyautov-plugins
31
38
  ```
32
39
 
33
- Cursor, Copilot, Cline и другие агенты: `npx skills add https://github.com/ilyautov/humanizer-ru/tree/main/skills/humanizer-ru`. Claude.ai, Codex, DeepSeek Harness и раскатка на команду в [разделе «Установка»](#установка).
40
+ Claude.ai, DeepSeek Harness и раскатка на команду в [разделе «Установка»](#установка).
34
41
 
35
42
  📖 **Документация и разборы:** [humanizer-ru.aifrontier.tech](https://humanizer-ru.aifrontier.tech/): [работают ли AI-детекторы на русском](https://humanizer-ru.aifrontier.tech/ai-detektory-na-russkom.html), [64 признака AI-текста](https://humanizer-ru.aifrontier.tech/52-priznaka-ai-teksta.html), [антиплагиат и нейросеть](https://humanizer-ru.aifrontier.tech/antiplagiat-i-neyroset.html).
36
43
 
@@ -76,6 +83,8 @@ Cursor, Copilot, Cline и другие агенты: `npx skills add https://git
76
83
 
77
84
  На [главной странице сайта](https://humanizer-ru.aifrontier.tech/#audit) работает тот же сканер на JavaScript: вставьте текст, получите оценку чистоты от 0 до 100, подсветку найденных оборотов и команду установки для своей среды. Считается в браузере, текст никуда не отправляется. Правила экспортируются из `markers.py` скриптом `scripts/export_web_rules.py`, а паритет с Python проверяет `scripts/test_web_parity.py` в CI.
78
85
 
86
+ Тот же сканер есть как расширение Chrome: выделили текст на любой странице, в контекстном меню «Проверить на следы нейросети», и попап показывает балл и подсветку. Разрешений у него два, контекстное меню и локальное хранилище, доступа к сайтам и сети нет. Папка `extension/`, сборка `scripts/build_extension.py`; пока идёт модерация в Web Store, ставится через `chrome://extensions` → «Режим разработчика» → «Загрузить распакованное расширение».
87
+
79
88
  ## Установка
80
89
 
81
90
  Скилл разворачивается тремя путями: загрузкой в веб-интерфейс Claude.ai, централизованной раскаткой на команду или установкой в локальные агенты (Claude Code, Cowork, API).
@@ -238,7 +247,7 @@ dsh сканирует `~/.agents/skills` и `~/.dsh/skills` сам, перез
238
247
  других регистров снимает маркеры, которые там законны:
239
248
 
240
249
  ```bash
241
- python skills/humanizer-ru/scripts/scan.py статья.txt --genre academic # ещё legal, fiction
250
+ python skills/humanizer-ru/scripts/scan.py статья.txt --genre academic # ещё legal, fiction, news
242
251
  python skills/humanizer-ru/scripts/scan.py стало.txt --before было.txt # чистота до/после + факт-замок
243
252
  ```
244
253
 
package/README.zh.md ADDED
@@ -0,0 +1,99 @@
1
+ # humanizer-ru
2
+
3
+ > [Русская версия: основная](README.md) · [English](README.en.md)
4
+
5
+ 面向 Claude Code、Cursor、Codex、Gemini CLI 等编程智能体的开源 Skill:去除俄语文本中的 AI 痕迹,让机器生成的俄语读起来像俄罗斯人写的。MIT 许可,无订阅,无 API Key,在你已经在用的智能体里直接运行。
6
+
7
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
8
+ [![Stars](https://img.shields.io/github/stars/ilyautov/humanizer-ru?style=social)](https://github.com/ilyautov/humanizer-ru/stargazers)
9
+ [![skills.sh](https://skills.sh/b/ilyautov/humanizer-ru)](https://skills.sh/ilyautov/humanizer-ru/humanizer-ru)
10
+
11
+ 🧪 **在线试用,无需安装:** [humanizer-ru.aifrontier.tech](https://humanizer-ru.aifrontier.tech/#audit)。粘贴一段俄语,得到 0 到 100 的「干净度」评分和被标出的 AI 套话。扫描器在浏览器里运行,文本不会上传。
12
+
13
+ ## 给谁用
14
+
15
+ - 跨境电商团队:Ozon、Wildberries、Yandex Market、速卖通俄区的商品详情、店铺公告、客服回复。用 DeepSeek、豆包、GPT 生成的俄语文案,俄罗斯买家一眼就看出是机器写的,转化和评分都会受影响。
16
+ - 出海企业的市场和公关:官网、新闻稿、宣传册、社媒帖子的俄语版本。
17
+ - 本地化和翻译团队:机器翻译或 LLM 初稿之后的润色,让文本符合俄语母语者的阅读习惯。
18
+ - 用俄语写邮件、报告、论文的任何人。
19
+
20
+ ## 为什么俄语需要单独的工具
21
+
22
+ 所有大模型都是「经由英语」生成俄语的。于是俄语 AI 文本的破绽和英语的不一样:英语式句法的直译(калька)、一句一个「является」、堆叠的名词链公文体(канцелярит)、丢失的语气小词「же」「ведь」「вот」、每隔一句一个长破折号。英语的 humanizer 看不到这些,中文的「去 AI 味」工具也不处理俄语。
23
+
24
+ 这个 Skill 收录了 **64 个俄语 AI 特征**(分 14 类)和 **21 条硬性禁用结构**,每一条都写成编辑规则,而不是简单的词表。附带一个确定性的扫描器,把修改变成可度量的事:「原来 9 分,现在 82 分」。
25
+
26
+ ## 一分钟安装
27
+
28
+ 任何智能体一条命令(Claude Code、Cursor、Codex、Copilot、Cline 等几十种):
29
+
30
+ ```
31
+ npx skills add ilyautov/humanizer-ru
32
+ ```
33
+
34
+ CLI 会检测本机已安装的智能体并询问装到哪里。Claude Code 也可以作为插件安装,之后通过 `/plugin` 更新:
35
+
36
+ ```
37
+ /plugin marketplace add ilyautov/humanizer-ru
38
+ /plugin install humanizer-ru@ilyautov-plugins
39
+ ```
40
+
41
+ DeepSeek Harness:
42
+
43
+ ```
44
+ dsh plugin --profile web add humanizer-ru
45
+ ```
46
+
47
+ Claude.ai 网页版:下载 [humanizer-ru.zip](https://github.com/ilyautov/humanizer-ru/releases/latest/download/humanizer-ru.zip),在 Settings → Capabilities → Skills 里上传。其他安装方式见[俄语 README](README.md#установка)。
48
+
49
+ ## 怎么用
50
+
51
+ 装好之后,对智能体说(俄语或中文都可以,但文本本身必须是俄语):
52
+
53
+ - 「очеловечь этот текст」或「把这段俄语改得像人写的」:完整改写,五步流程,保留原文事实。
54
+ - 「проверь текст на следы нейросети」或「检查这段俄语的 AI 痕迹」:只做审计,列出发现的特征和优先级,不改写。
55
+ - 「убери канцелярит」:只处理指定的一类问题。
56
+
57
+ 也可以在命令行直接跑扫描器(需要 Python 3 和 `pip install razdel pymorphy3`):
58
+
59
+ ```
60
+ python3 skills/humanizer-ru/scripts/scan.py текст.txt
61
+ python3 skills/humanizer-ru/scripts/scan.py после.txt --before до.txt
62
+ ```
63
+
64
+ 第二条命令是「事实锁」:比较改写前后的文本,列出凭空出现或丢失的数字、日期、人名、链接和断言。编造的数据比任何套话都糟糕。
65
+
66
+ ## 里面有什么
67
+
68
+ - 64 个特征、14 个类别:公文体、英语直译、情感空洞、说服套路、信息节奏、模糊限定词,以及 2025 到 2026 年新出现的模型指纹(单词成句的「碎片式冥想」、伪苏格拉底式自问自答、每个列表项一个装饰性 emoji、伪心理治疗口吻、无生命主语、结尾说教等)。
69
+ - 21 条硬性禁用:出现即删除的结构,包括长破折号、「не просто X, а Y」、「в современном мире」、「играет ключевую роль」。
70
+ - 扫描器:0 到 100 的干净度评分,按类别列出命中,句长节奏、名词动词比、Markdown 感知(代码块和引用不计入)。学术、法律、文学文本有单独的体裁模式 `--genre`,否则正式文本会被误判。
71
+ - 作者声音校准:给几篇你自己写的俄语文本,Skill 会按你的节奏和用词改写,而不是改成千篇一律的「人味」。
72
+ - 四轮审计:检测器视角、路人视角、句子「心电图」、列表「骨架」。
73
+
74
+ ## 数据校准
75
+
76
+ 规则不是凭感觉定的。目录在三个公开语料上校准过,共 **5.5 万篇**带人机标注的俄语文本,包括 GigaChat 和 YandexGPT 的输出:
77
+
78
+ | 语料 | 规模 | 发现 |
79
+ |---|---|---|
80
+ | AINL-Eval 2025 | 35 158 篇学术摘要 | 严格模式下规则命中人类作者的比例不低于模型,「является」和「данный」在学术体裁里是正常用法,因此加入了体裁过滤 |
81
+ | M4 | 5 759 对 | 社交媒体和百科文本,gpt-3.5 时代的指纹 |
82
+ | LLMTrace | 14 763 篇,30 个生成器 | 长破折号更取决于体裁而非作者;俄罗斯模型(GigaChat-Max 77%、YandexGPT-5 74%)比 GPT 更爱用破折号;人类每百词 0.29 个特征,模型 0.67 个 |
83
+
84
+ 所有数字可以复现:校准脚本和报告在 `eval/` 目录,语料是公开的。
85
+
86
+ ## 它不做什么
87
+
88
+ - 不用来骗过 AI 检测器。不插入错别字,不用拉丁字母替换西里尔字母。为了通过检测而损坏文本,是在欺骗读者。目标只有一个:写出俄罗斯人真的会写的文本。
89
+ - 不编造细节。原文没有数字和案例,Skill 就用节奏、语气和结构让文本活起来,或者问你要材料。
90
+ - 不判定作者身份。扫描器的分数是修改的依据,不是「这是 AI 写的」的裁决。
91
+
92
+ ## 链接
93
+
94
+ - 源码:[github.com/ilyautov/humanizer-ru](https://github.com/ilyautov/humanizer-ru)
95
+ - 网站与在线扫描:[humanizer-ru.aifrontier.tech](https://humanizer-ru.aifrontier.tech/)
96
+ - 更新日志:[CHANGELOG.md](CHANGELOG.md)
97
+ - 引用的研究来源:[SOURCES.md](SOURCES.md)
98
+
99
+ 作者:Ilya Utov([GitHub](https://github.com/ilyautov))。欢迎 issue 和 PR,包括中文的。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "humanizer-ru",
3
- "version": "3.21.0",
3
+ "version": "3.23.0",
4
4
  "description": "Agent skill for DeepSeek Harness: rewrites Russian text to remove 64 markers of AI generation (bureaucratese, calques, ChatGPT fingerprints), with a corpus-calibrated scanner, audit mode and author-voice calibration.",
5
5
  "license": "MIT",
6
6
  "author": "Ilya Utov",
@@ -1,10 +1,10 @@
1
1
  ---
2
2
  name: humanizer-ru
3
- description: "Скилл для очеловечивания русскоязычного текста. Убирает признаки AI-генерации, делает текст живым. Используй ВСЕГДА, когда пользователь просит: очеловечить текст, убрать следы нейросети, сделать текст живым/естественным, переписать как человек, humanize на русском, убрать канцелярит, убрать водянистость, сделать текст менее формальным. Также используй если пользователь вставляет русскоязычный текст и говорит что-то вроде 'перепиши', 'сделай лучше', 'звучит как робот', 'слишком искусственно'. Работает ТОЛЬКО с русским языком. Для английского используй оригинальный humanizer. НЕ используй для: перевод, написание с нуля, грамматика, код."
3
+ description: "Скилл для очеловечивания русскоязычного текста. Убирает признаки AI-генерации, делает текст живым. Используй ВСЕГДА, когда пользователь просит: очеловечить текст, убрать следы нейросети, сделать текст живым/естественным, переписать как человек, humanize на русском, убрать канцелярит, убрать водянистость, сделать текст менее формальным. Также используй если пользователь вставляет русскоязычный текст и говорит что-то вроде 'перепиши', 'сделай лучше', 'звучит как робот', 'слишком искусственно'. Работает ТОЛЬКО с русским языком. Для английского используй оригинальный humanizer. НЕ используй для: перевод, написание с нуля, грамматика, код. Триггеры на других языках, если сам текст русский: 'humanize this Russian text', 'make this Russian sound natural', '把这段俄语改得像人写的', '去除俄语文本的 AI 味', '检查俄语的 AI 痕迹'."
4
4
  license: MIT
5
5
  ---
6
6
 
7
- # Humanizer-RU v3.21.0
7
+ # Humanizer-RU v3.23.0
8
8
 
9
9
  Ты редактор. Превращаешь стерильный AI-текст в живую русскую речь. Убираешь маркеры нейросети и возвращаешь в текст автора: мнение, ритм, характер.
10
10
 
@@ -75,7 +75,7 @@ license: MIT
75
75
 
76
76
  **Аудит** (по запросу: «проверь», «найди AI-маркеры», «что выдаёт?»). Только диагностика. Возвращаешь список найденных паттернов с примерами из текста и приоритетом (A-D). Текст не переписываешь.
77
77
 
78
- > **Машинная половина аудита.** Со скиллом едет детерминированный сканер: `scripts/scan.py` рядом с этим SKILL.md (в полном клоне репозитория: `skills/humanizer-ru/scripts/scan.py`). Он точно считает то, что LLM мерит на глаз: HARD BANS, 21 категорию маркеров, ритм предложений, морфологию. Если в среде можно запускать команды и есть python3 с пакетами `razdel` и `pymorphy3`, сначала прогони текст через него: `python3 <папка скилла>/scripts/scan.py файл.txt`, либо `echo "текст" | python3 <папка скилла>/scripts/scan.py -` (флаг `--json` для машинного вывода). Текст не маркетинговый? Добавь `--genre academic`, `--genre legal` или `--genre fiction`: флаг снимает маркеры, законные для регистра, иначе научный и юридический текст тонет в ложных срабатываниях (цифры в секции «Ложные срабатывания»). Вывод сканера бери как базу, поверх добавляй то, что скрипту не по зубам: ложные срабатывания (см. одноимённую секцию), нелексические паттерны, приоритеты A-D. Пакетов нет? Предложи пользователю однократный `pip install razdel pymorphy3` и проводи аудит по каталогу вручную. Сканер недоступен или упал: молча работай по каталогу, как обычно. Аудит обязан состояться при любом раскладе.
78
+ > **Машинная половина аудита.** Со скиллом едет детерминированный сканер: `scripts/scan.py` рядом с этим SKILL.md (в полном клоне репозитория: `skills/humanizer-ru/scripts/scan.py`). Он точно считает то, что LLM мерит на глаз: HARD BANS, 21 категорию маркеров, ритм предложений, морфологию. Если в среде можно запускать команды и есть python3 с пакетами `razdel` и `pymorphy3`, сначала прогони текст через него: `python3 <папка скилла>/scripts/scan.py файл.txt`, либо `echo "текст" | python3 <папка скилла>/scripts/scan.py -` (флаг `--json` для машинного вывода). Текст не маркетинговый? Добавь `--genre academic`, `--genre legal`, `--genre fiction` или `--genre news` (новости и энциклопедические статьи): флаг снимает маркеры, законные для регистра, иначе научный, юридический и новостной текст тонет в ложных срабатываниях (цифры в секции «Ложные срабатывания»). Вывод сканера бери как базу, поверх добавляй то, что скрипту не по зубам: ложные срабатывания (см. одноимённую секцию), нелексические паттерны, приоритеты A-D. Пакетов нет? Предложи пользователю однократный `pip install razdel pymorphy3` и проводи аудит по каталогу вручную. Сканер недоступен или упал: молча работай по каталогу, как обычно. Аудит обязан состояться при любом раскладе.
79
79
 
80
80
  > **Score чистоты (0-100).** Сканер выдаёт сводную оценку `ЧИСТОТА: N/100` и полосу: 85-100 «чисто» (следы ИИ не мешают), 60-84 «точечная правка», ниже 60 «рерайт». Это не вероятность ИИ и не «детект», а агрегат уже посчитанных сигналов: хард-баны и плотность маркеров весят сильно, морфология (сущ./глаг.) и тире слабо, как корроборирующие, чтобы не занижать плотный энциклопедический или юридический текст. Плюс document-level сигналы (ровные по длине абзацы, засилье однотипных пунктов-списков) для длинных шаблонных текстов: на короткой прозе они инертны. Показывай число в начале аудита, а после переписывания давай «было N, стало M»: так правка становится измеримой. Сканер не запускался (нет python, claude.ai web)? Прикинь score по той же логике: старт 100, заметный минус за каждый хард-бан и за высокую плотность маркеров, небольшой за номинальность и обилие тире; плотный человеческий текст без AI-оборотов остаётся высоким, не занижай его. Такую прикидку подписывай явно: «≈70, оценка без сканера». Число от сканера и число на глаз в одном формате путают читателя, а измеримость правки наше главное отличие.
81
81
 
@@ -120,6 +120,7 @@ license: MIT
120
120
  - **Повтор намеренный.** Анафора, рефрен, повтор для нажима («Он не пришёл. Он не позвонил. Он просто исчез.»): приём, а не синонимическая бедность.
121
121
  - **«Является» в роли термина/определения.** В научном или юридическом тексте связка иногда обязательна. Бей бытовое «является», не трогай терминологическое.
122
122
  - **Академический регистр целиком.** Это не смягчение, а жёсткое правило, и оно измерено. Прогон каталога по корпусу AINL-Eval 2025 (35 158 русских научных аннотаций с разметкой «человек» и три модели) дал 35,9% человеческих текстов с баном против 26,1-35,8% машинных: без жанровой поправки скилл ловит людей не реже, чем нейросети, то есть не различает их вовсе. «Является» сработало на 8,0% человеческих аннотаций и 0,1-3,0% машинных, длинное тире на 4,8% человеческих и 0-0,9% машинных, кальки на 31,1% человеческих и 3,6-21,1% машинных. С жанровой поправкой человеческие срабатывания падают до 4,2%. В научном и академическом тексте НЕ считай признаком: «является», кальки-связки, канцелярит, «данный», длинное тире, «таким образом». Разделяющая сила остаётся у раздувания значимости, мотивационных клише, модальных хеджей и неодушевлённого субъекта (#55): их проверяй как обычно. Сканер поднимает то же правило флагом: `scan.py файл.txt --genre academic` (ещё `legal` и `fiction`).
123
+ - **Новости и энциклопедия.** Тоже измерено, на русской части LLMTrace (1 697 человеческих и 2 080 машинных новостей и энциклопедических статей): длинное тире стоит у 37,5% человеческих текстов против 27% машинных, «данный» у 6,2% против 5%, «является» у 15,8% против 24%, канцелярит и кальки не разделяют классы. Строгий режим ловит 56% людей и 59% машин, то есть не различает их. В новостном и энциклопедическом тексте не считай признаком: «является», «данный», длинное и короткое тире, диапазон «от X до Y», канцелярит, кальки, контекстуализаторы. Разделяют там формула-выводы, модальные хеджи, раздувание значимости, «играет ключевую роль» (лифт 13), «не только X, но и Y», «таким образом». Сканер: `--genre news`.
123
124
  - **Структура оправдана длиной.** В лонгриде на 3000 слов подзаголовки и списки нужны. Подтип «подзаголовок на каждые 2-3 предложения» касается КОРОТКОГО текста, не статьи.
124
125
  - **Формальный регистр как требование жанра.** Деловое письмо, оффер, документ имеют право быть формальными. Канцелярит убирай, но вежливые обороты и регистр не ломай.
125
126
  - **Гладкость от мастерства, а не от AI.** Хороший редактор тоже выравнивает текст. Если перплексия низкая, но есть мнение, конкретика и характерный голос, перед тобой, скорее всего, человек. Низкая перплексия сама по себе не улика.
@@ -150,7 +151,7 @@ license: MIT
150
151
 
151
152
  **Шаг 3. Переписывание по разметке.** Работай по светофору из Шага 1: красные абзацы перепиши целиком, жёлтые правь точечно, зелёные не трогай. В красных и жёлтых абзацах: сначала убери HARD BANS, затем пройдись контрастным вычитанием (в каждом предложении замени самое предсказуемое слово на менее вероятное, но уместное). На каждый усилитель, вводное и образ гони двойной гейт сразу на этом шаге, не при финальной вычитке: тест на удаление (убрал, смысл не изменился = вода, паттерны #3/#40, удаляй) и тест на обналичивание (какой референт? паттерн #53). Одновременно добавляй голос и варьируй структуру. Сверяйся с паспортом голоса.
152
153
 
153
- > **Факт-замок (приоритет над любым паттерном).** Факты исходника (числа, даты, имена, названия, проценты, единицы) переносятся без искажений. Добавлять факты, которых в исходнике НЕТ (цифры, исследования, кейсы, «у себя в команде вижу...»), запрещено: конкретика для паттернов 1-2 и секции «Как звучит живой текст» берётся ТОЛЬКО из исходника или из того, что явно сообщил пользователь. В исходнике нет конкретики? Оживляй голосом, ритмом и структурой, либо спроси пользователя, чем наполнить. Выдуманная цифра хуже канцелярита: канцелярит палит стиль, выдумка делает текст ложью. В примерах документации пометка «(факты автора)» в заголовке означает: конкретику в этом «После» дал автор текста, а не придумал редактор. Пример без такой пометки новых фактов не содержит, и гейт `scripts/check_examples.py` это проверяет. Есть исходник и результат в файлах и можно запускать команды? Проверь замок механически: `python3 <папка скилла>/scripts/scan.py стало.txt --before было.txt`. Сканер печатает «было N, стало M» по чистоте и перечисляет числа, даты, имена, ссылки и код, которые пропали или появились. Новый факт без источника это ошибка правки, а не находка.
154
+ > **Факт-замок (приоритет над любым паттерном).** Факты исходника (числа, даты, имена, названия, проценты, единицы) переносятся без искажений. Добавлять факты, которых в исходнике НЕТ (цифры, исследования, кейсы, «у себя в команде вижу...»), запрещено: конкретика для паттернов 1-2 и секции «Как звучит живой текст» берётся ТОЛЬКО из исходника или из того, что явно сообщил пользователь. В исходнике нет конкретики? Оживляй голосом, ритмом и структурой, либо спроси пользователя, чем наполнить. Выдуманная цифра хуже канцелярита: канцелярит палит стиль, выдумка делает текст ложью. В примерах документации пометка «(факты автора)» в заголовке означает: конкретику в этом «После» дал автор текста, а не придумал редактор. Пример без такой пометки новых фактов не содержит, и гейт `scripts/check_examples.py` это проверяет. Есть исходник и результат в файлах и можно запускать команды? Проверь замок механически: `python3 <папка скилла>/scripts/scan.py стало.txt --before было.txt`. Сканер печатает «было N, стало M» по чистоте и перечисляет числа, даты, имена, ссылки и код, которые пропали или появились. Новый факт без источника это ошибка правки, а не находка. Отдельно береги слова, которые звучат как пафос, а несут факт: «первый в России», «единственный», «впервые», «рекордный», «до сих пор». Срезать «первый в России сервис» до «сервис» значит исказить, а не оживить: выбрасывай пустое усиление («по-настоящему», «крайне важно»), а не само утверждение. Сканер считает такие кванторы отдельно и предупреждает, если они пропали или появились.
154
155
 
155
156
  > **ВНИМАНИЕ: гомогенизация.** LLM при переписывании склонен удалять разговорные обороты, анекдоты, личные примеры, заменяя их нейтральными формулировками (+70% нейтральных эссе при использовании LLM). Даже промпт «только грамматика» меняет семантику. Если в оригинале есть личная история, специфический оборот, разговорная фраза - СОХРАНИ их. Не заменяй живое на нейтральное. Одинаковая трансформация всех текстов через один инструмент создаёт «гуманизированный» стиль, который сам по себе детектируется (DAMAGE). Варьируй подход: разные тексты переписывай по-разному.
156
157
 
@@ -158,7 +159,7 @@ license: MIT
158
159
 
159
160
  Проход 1, «Детектор»: перечитай черновик, ищи остатки каждой из 14 категорий паттернов (A-N). Достаточно 30 секунд на категорию.
160
161
 
161
- Проход 2, «Человек с улицы»: забудь что ты редактор. Прочитай текст как случайный читатель в ленте. Вопрос: «Увидев этот текст без контекста, подумал бы я, что его писала нейросеть?» Если да - найди что именно выдаёт и исправь.
162
+ Проход 2, «Человек с улицы»: забудь что ты редактор. Прочитай текст как случайный читатель в ленте. Вопрос: «Увидев этот текст без контекста, подумал бы я, что его писала нейросеть?» Если да - найди что именно выдаёт и исправь. Второй вопрос того же прохода: «Это ещё автор или уже обезличенная версия автора?» Если второе, верни ему его манеру: повтор, длинную фразу, сомнение, странную деталь.
162
163
 
163
164
  Красные флаги второго прохода:
164
165
  - Слишком гладко, нет ни одной шероховатости
@@ -174,7 +175,7 @@ license: MIT
174
175
 
175
176
  Проход 5, «Обналичивание» (только для экспертных и технических текстов): пройди по всем образам и терминам, которые утверждают механизм. Каждый должен обналичиваться в конкретный ответ на «что именно происходит?» (паттерн #53). Пустой = переписать в механизм, неверный = исправить механизм, плавающий = заякорить одной формой в точке ввода. Для остальных жанров отдельный проход не нужен: хватает гейта из Шага 3.
176
177
 
177
- **Шаг 5.** Отдай финальный текст и короткий список ключевых изменений (3-5 пунктов).
178
+ **Шаг 5.** Отдай финальный текст и короткий список ключевых изменений (3-5 пунктов). Добавь одну строку «Не тронуто: ...» про то, что оставил намеренно: повтор слова, длинную фразу, авторское тире, зелёные абзацы. Читатель должен видеть, что нетронутое место это решение, а не пропуск.
178
179
 
179
180
  ---
180
181
 
@@ -190,7 +191,7 @@ license: MIT
190
191
  | «Не только X, но и Y» | Калька, маркер синтетического усиления | «X. И ещё Y» или просто перечисли |
191
192
  | «В современном мире...» | Пустое открытие #1 у всех LLM | Начни с факта или вопроса |
192
193
  | «Стоит отметить, что...» | Калька с «It's worth noting» | Убери и скажи напрямую |
193
- | «Важно понимать, что...» | Калька с «It's important to understand» | Убери или «Тут вот что:» |
194
+ | «Важно понимать/помнить/отметить, что...» | Калька с «It's important to understand / remember / note» | Убери или «Тут вот что:» |
194
195
  | «Данный» / «Данная» / «Данное» | Канцелярский маркер, всегда заменяем | «Этот» / «Эта» / «Это» |
195
196
  | «Является» (>1 раз на 500 слов) | В русском связка «быть» в настоящем времени не нужна | Перестрой предложение |
196
197
  | «Играет важную/ключевую роль» | Раздувание значимости, клише | Покажи ПОЧЕМУ важно через данные |
@@ -62,7 +62,7 @@ davinci-003). Метод и полные таблицы: `eval/AINL-CALIBRATION.
62
62
  До: «Исследования показывают, что удалёнка повышает продуктивность.»
63
63
  После (факты автора): «Стэнфорд гонял эксперимент два года: удалёнщики на 13% продуктивнее. У себя в команде вижу примерно то же.» (источник и цифру дал автор; нет источника: убери ссылку и утверждай от своего лица, НЕ изобретай исследование)
64
64
 
65
- **3. Раздувание значимости.** Каждый факт «ключевой», каждое событие «переломное»: «играет ключевую роль», «имеет огромное значение», «невозможно переоценить». Сбрось пафос. Если что-то важно, покажи почему через данные, а не прилагательные.
65
+ **3. Раздувание значимости.** Каждый факт «ключевой», каждое событие «переломное»: «играет ключевую роль», «имеет огромное значение», «невозможно переоценить», «важный шаг на пути к». Сбрось пафос. Если что-то важно, покажи почему через данные, а не прилагательные.
66
66
 
67
67
  **4. Формульные выводы.** Заключения, которые клеятся к любому тексту: «Таким образом, можно сделать вывод...», «Подводя итог...». Вывод должен добавлять новое. Если его можно удалить без потери смысла, удали.
68
68
 
@@ -299,7 +299,7 @@ davinci-003). Метод и полные таблицы: `eval/AINL-CALIBRATION.
299
299
 
300
300
  **Канцелярит-маркеры:** осуществление, реализация, внедрение, оптимизация, функционирование, взаимодействие, в рамках, в целях, в контексте, на основе, посредством, в соответствии с, внимание уделяется, внимание уделено, посвящена анализу/изучению/разработке
301
301
 
302
- **Кальки-маркеры:** является, стоит отметить, важно понимать, можно сказать, что касается, в то время как, с другой стороны, тем не менее, несмотря на то что, исследование фокусируется на (this study focuses on)
302
+ **Кальки-маркеры:** является, стоит отметить, важно понимать/помнить/отметить, можно сказать, что касается, в то время как, с другой стороны, тем не менее, несмотря на то что, исследование фокусируется на (this study focuses on)
303
303
 
304
304
  **Раздувание-маркеры:** ключевой, важнейший, значительный, огромный, колоссальный, переломный, фундаментальный, невозможно переоценить, играет роль
305
305
 
@@ -347,7 +347,7 @@ davinci-003). Метод и полные таблицы: `eval/AINL-CALIBRATION.
347
347
 
348
348
  **Обрыв на полуслове:** последнее предложение не закончено, текст упёрся в лимит токенов
349
349
 
350
- **Технические маркеры:** латинские символы вместо кириллических (c, o, a, e, p), «невидимые» символы (zero-width, word joiner, bidi-метки: клавиатурой не набираются), идеальная типографика в неформальном тексте
350
+ **Технические маркеры:** латинские символы вместо кириллических (c, o, a, e, p), «невидимые» символы (zero-width, word joiner, bidi-метки, узкий неразрывный пробел U+202F: клавиатурой не набираются), идеальная типографика в неформальном тексте
351
351
 
352
352
  **Артефакты копипасты:** технические следы копирования из интерфейса чат-бота, однозначные улики: `:contentReference[oaicite:N]`, `oai_citation`, `?utm_source=chatgpt.com`/`=openai` в ссылках, `grok_card://`, `attached_file://`, `vertexaisearch`, метки `turnNsearchN`/`turnNfileN`/`citeturn...`, `【N†source】`, `[citation:N]`, ссылки `](sandbox:/mnt/data/...)`, невидимые символы U+E200-E204, остатки `</think>`. В человеческом тексте не встречаются: нашёл хотя бы один = текст вставлен из чат-бота, проверяй целиком
353
353
 
@@ -18,6 +18,14 @@
18
18
  Мелкие количества («два», «половина», «вдвое») факты мягкие: в русском они
19
19
  идиоматичны («с одной стороны») и обычно пересказывают число исходника. Они
20
20
  считаются, но не валят проверку.
21
+
22
+ Утверждения: слова-кванторы, которые звучат как пафос, а несут факт:
23
+ «первый в России», «единственный», «впервые», «рекордный», «до сих пор».
24
+ Срезать «первый в России сервис» до «сервис» значит исказить исходник, а
25
+ не оживить его. Потерянный квантор попадает в список потерь, появившийся
26
+ выносится отдельным предупреждением: кванторы идиоматичны («первый шаг»,
27
+ «самое время»), поэтому валить проверку автоматически нельзя, но глазами
28
+ такое место обязано проверить.
21
29
  """
22
30
 
23
31
  from __future__ import annotations
@@ -45,7 +53,7 @@ TOKEN_RE = re.compile(r"[A-Za-z][A-Za-z\d\-]*|[А-Яа-яЁё][А-Яа-яЁё\-]
45
53
 
46
54
  SOFT_QUANTITIES = {
47
55
  "один", "два", "две", "три", "оба", "обе", "пара",
48
- "первый", "второй", "третий",
56
+ "второй", "третий",
49
57
  "вдвое", "втрое", "дважды", "трижды",
50
58
  "половина", "треть", "четверть", "полтора",
51
59
  }
@@ -56,6 +64,12 @@ HARD_NUMERALS = {
56
64
  "девяносто", "сто", "двести", "триста", "тысяча", "миллион", "миллиард",
57
65
  "десяток", "сотня", "дюжина",
58
66
  }
67
+ # Кванторы-утверждения: громкие слова, за которыми стоит проверяемый факт.
68
+ CLAIM_WORDS = {
69
+ "первый", "единственный", "впервые", "самый", "рекордный", "крупнейший",
70
+ "старейший", "никогда", "никто", "навсегда", "беспрецедентный",
71
+ }
72
+ CLAIM_PHRASE_RE = re.compile(r"\bдо сих пор\b|\bв мире\b|\bв россии\b", re.IGNORECASE)
59
73
  # Одна сущность под разными именами не считается новым фактом.
60
74
  ALIASES = {
61
75
  "ai": ("искусственный", "интеллект", "ии", "нейросеть", "модель"),
@@ -69,6 +83,7 @@ class Facts:
69
83
  hard: set[str] = field(default_factory=set) # "число:13", "имя:стэнфорд", "ссылка:…"
70
84
  soft: set[str] = field(default_factory=set) # "два", "половина"
71
85
  words: set[str] = field(default_factory=set) # все слова в нормальной форме, для алиасов
86
+ claims: set[str] = field(default_factory=set) # "утверждение:первый", "утверждение:до сих пор"
72
87
 
73
88
 
74
89
  @dataclass
@@ -77,6 +92,7 @@ class FactsDiff:
77
92
  added: list[str] # появились в результате, в исходнике не было
78
93
  kept: int # жёстких фактов исходника дожило
79
94
  soft_added: list[str]
95
+ claims_added: list[str] = field(default_factory=list) # кванторы, которых в исходнике не было
80
96
 
81
97
  @property
82
98
  def ok(self) -> bool:
@@ -84,7 +100,8 @@ class FactsDiff:
84
100
 
85
101
  def as_dict(self) -> dict:
86
102
  return {"ok": self.ok, "lost": self.lost, "added": self.added,
87
- "kept": self.kept, "soft_added": self.soft_added}
103
+ "kept": self.kept, "soft_added": self.soft_added,
104
+ "claims_added": self.claims_added}
88
105
 
89
106
 
90
107
  def _norm(word: str) -> str:
@@ -126,6 +143,8 @@ def extract_facts(text: str) -> Facts:
126
143
  body = CODE_RE.sub(" ", URL_RE.sub(" ", text))
127
144
  for m in MONTH_RE.finditer(body):
128
145
  f.hard.add("месяц:" + m.group(1).lower())
146
+ for m in CLAIM_PHRASE_RE.finditer(body):
147
+ f.claims.add("утверждение:" + m.group(0).lower().replace("ё", "е"))
129
148
  starts = _sentence_starts(body)
130
149
  for m in TOKEN_RE.finditer(body):
131
150
  tok = m.group(0)
@@ -138,6 +157,8 @@ def extract_facts(text: str) -> Facts:
138
157
  f.words.add(norm)
139
158
  if norm in SOFT_QUANTITIES:
140
159
  f.soft.add(norm)
160
+ elif norm in CLAIM_WORDS:
161
+ f.claims.add("утверждение:" + norm)
141
162
  elif norm in HARD_NUMERALS:
142
163
  f.hard.add("число словами:" + norm)
143
164
  elif _is_proper(tok, any(abs(m.start() - s) <= 1 for s in starts)):
@@ -154,10 +175,11 @@ def _alias_covered(fact: str, before_words: set[str]) -> bool:
154
175
 
155
176
  def diff_facts(before: str, after: str) -> FactsDiff:
156
177
  b, a = extract_facts(before), extract_facts(after)
157
- lost = sorted(b.hard - a.hard)
178
+ lost = sorted(b.hard - a.hard) + sorted(b.claims - a.claims)
158
179
  added = sorted(x for x in a.hard - b.hard if not _alias_covered(x, b.words))
159
180
  return FactsDiff(lost=lost, added=added, kept=len(b.hard & a.hard),
160
- soft_added=sorted(a.soft - b.soft))
181
+ soft_added=sorted(a.soft - b.soft),
182
+ claims_added=sorted(a.claims - b.claims))
161
183
 
162
184
 
163
185
  def facts_verdict(d: FactsDiff) -> str:
@@ -165,4 +187,7 @@ def facts_verdict(d: FactsDiff) -> str:
165
187
  return f"✗ новых фактов без источника: {len(d.added)} (выдумка хуже канцелярита)"
166
188
  if d.lost:
167
189
  return f"⚠ факты исходника на месте, но {len(d.lost)} потеряно: проверьте, намеренно ли"
190
+ if d.claims_added:
191
+ return (f"⚠ факты целы, но появилось утверждений без источника: {len(d.claims_added)} "
192
+ "(«впервые», «единственный» это факт, а не украшение)")
168
193
  return f"✓ факт-замок цел: {d.kept} фактов исходника перенесено, новых нет"
@@ -25,7 +25,10 @@ HARD_BANS: list[tuple[str, str]] = [
25
25
  ("Не только X, но и Y", r"\bне\s+только\b[^.!?]{1,40}?\bно\s+и\b"),
26
26
  ("В современном мире", r"\bв\s+современном\s+мире\b"),
27
27
  ("Стоит отметить, что", r"\bстоит\s+отметить\b"),
28
- ("Важно понимать, что", r"\bважно\s+понимать\b"),
28
+ # Расширен по шахте LLMTrace (русские модели против людей тех же тем):
29
+ # «важно помнить, что» 155 машинных документов против 3 человеческих,
30
+ # «важно отметить, что» 144 против 1; в AINL у людей 0 и 2 из 8 769.
31
+ ("Важно понимать/помнить/отметить, что", r"\bважно\s+(?:понимать|помнить|отметить)\b"),
29
32
  # Только единственное число (как в SKILL.md HARD BAN). Множественные формы
30
33
  # «данные/данных/данным/данными» совпадают с существительным «данные» (data)
31
34
  # и давали ложные срабатывания на ML/статистических текстах.
@@ -112,6 +115,10 @@ SCANNER: dict[str, list[str | tuple[str, str]]] = {
112
115
  "Раздувание": [
113
116
  "ключев", "важнейш", "значительн", "огромн", "колоссальн", "переломн",
114
117
  "фундаментальн", "невозможно переоценить", "играет роль",
118
+ # «важный шаг (на пути) к»: LLMTrace 156 машинных документов против 3
119
+ # человеческих, AINL 56 против 2. «Шаг вперёд» и «большой шаг» не
120
+ # разделяют, в маркер не входят.
121
+ ("важный шаг", r"\bважн\w+\s+шаг\w*"),
115
122
  ],
116
123
  "Формула-выводы": [
117
124
  # Вводный коннектор-вывод, суженный так же, как одноимённый хард-бан:
@@ -189,10 +196,13 @@ SCANNER: dict[str, list[str | tuple[str, str]]] = {
189
196
  ("латиница внутри кириллического слова", r"(?<=[а-яё])[a-z](?=[а-яё])"),
190
197
  # zero-width (ZWSP/ZWNJ/ZWJ/BOM) + word joiner, Mongolian vowel
191
198
  # separator, bidi-метки и изоляторы: клавиатурой не набираются,
192
- # в живом русском тексте не встречаются.
199
+ # в живом русском тексте не встречаются. Плюс узкий неразрывный
200
+ # пробел U+202F: его ставят o3/o4-mini и GPT-5 перед единицами, на
201
+ # LLMTrace 0 из 6 392 человеческих текстов. Обычный U+00A0 сюда
202
+ # НЕ входит: у людей он в 10 раз чаще (вёрстка, редактура).
193
203
  ("невидимые символы (zero-width, bidi)",
194
204
  "[​‌‍⁠᠎‎‏"
195
- "‪-‮⁦-⁩؜]"),
205
+ "‪-‮⁦-⁩؜ ]"),
196
206
  ],
197
207
  # Паттерн #55: подлежащее-предмет при глаголе намерения. Английские
198
208
  # источники описывают то же самое как смену AI-словаря на emphasizing /
@@ -329,6 +339,14 @@ FREQ_BANS_NOTE = "см. комментарий выше про парный за
329
339
  #
330
340
  # Жанры legal и fiction фильтруются по тем же правилам, что записаны в разделе
331
341
  # «Ложные срабатывания» SKILL.md; корпусной проверки под них у нас пока нет.
342
+ #
343
+ # Жанр news (новости и энциклопедические статьи) измерен на русской части
344
+ # LLMTrace, домены news + factual, 1 697 человеческих и 2 080 машинных
345
+ # документов: глушится всё, у чего лифт (доля у машин / доля у людей) ниже 1,5.
346
+ # Длинное тире там у 37,5% людей (лифт 0,7), «данный» у 6,2% (0,8), короткое
347
+ # тире у 8,0% (0,9), «является» у 15,8% (1,5), канцелярит у 14,0% (0,9), кальки
348
+ # у 20,1% (1,4). Строгий режим ловит 55,7% людей против 58,7% машин, то есть не
349
+ # различает их; с профилем news 10,1% против 20,5%. Цифры: eval/llmtrace_calibration.py.
332
350
  GENRE_MUTED_BANS: dict[str, set[str]] = {
333
351
  "academic": {
334
352
  "Является", "Длинное тире", "Короткое тире", "Данный/Данная/Данное",
@@ -344,15 +362,20 @@ GENRE_MUTED_BANS: dict[str, set[str]] = {
344
362
  "Не только X, но и Y",
345
363
  "Не просто X, а Y",
346
364
  },
365
+ "news": {
366
+ "Является", "Длинное тире", "Короткое тире", "Данный/Данная/Данное",
367
+ "от X до Y (ложный диапазон)",
368
+ },
347
369
  }
348
370
 
349
371
  GENRE_MUTED_CATEGORIES: dict[str, set[str]] = {
350
372
  "academic": {"Канцелярит", "Кальки", "Контекстуализаторы", "Формула-выводы"},
351
373
  "legal": {"Канцелярит", "Кальки", "Контекстуализаторы"},
352
374
  "fiction": {"Параллелизмы"},
375
+ "news": {"Канцелярит", "Кальки", "Контекстуализаторы"},
353
376
  }
354
377
 
355
- GENRES = ("marketing", "academic", "legal", "fiction")
378
+ GENRES = ("marketing", "academic", "legal", "fiction", "news")
356
379
 
357
380
 
358
381
  # --- Что проверено корпусом, а что нет ------------------------------------
@@ -75,7 +75,7 @@ def main() -> int:
75
75
  "Новый факт, которого не было в исходнике, даёт exit 2")
76
76
  ap.add_argument("--genre", choices=GENRES, default="marketing",
77
77
  help="жанр текста: снимает маркеры, законные для регистра "
78
- "(academic, legal, fiction). По умолчанию marketing: "
78
+ "(academic, legal, fiction, news). По умолчанию marketing: "
79
79
  "строгий режим, под него откалиброваны пороги")
80
80
  args = ap.parse_args()
81
81
 
@@ -192,6 +192,8 @@ def main() -> int:
192
192
  print(f" ✗ новое: {x}")
193
193
  for x in fdiff.lost:
194
194
  print(f" ⚠ потеряно: {x}")
195
+ for x in fdiff.claims_added:
196
+ print(f" ⚠ утверждение появилось: {x}")
195
197
  if fdiff.soft_added:
196
198
  print(f" ℹ мелкие количества появились: {', '.join(fdiff.soft_added)} "
197
199
  "(идиомы и пересказ чисел не считаются, проверьте глазами)")