Skill: chn012cjus/web-novel-publishing-readiness-and-quality-check-skill (version 1.0.9)

--- name: novel-quality-check description: 小说质量检查技能。触发关键词：检查正文、质量报告、违禁词、套路句、章节衔接、逻辑漏洞、自检、人写感、大纲、人设。执行最大算力深度推理五步链，每章必须跑freq_check.py词频扫描+逐行违禁词扫描双轨制，复核自检通过方可出报告。 --- # 小说质量检查技能 ## 工具依赖 - **词频脚本**：`./freq_check.py`（必用，每章必跑） ## 核心原则 **禁用词优先级（五级铁律）：** 1. **禁用词优先** > 大纲原文 > 世界观设定 2. **词频扫描必须穷尽**整章，不得遗漏 3. **上下文穷尽原则**：同一词汇不同语境逐一判断 4. **主观→客观**：总结性描述替换为身体本能反应 5. **修正答案本身必须干净**：替换词不得含违禁词，不得改变原文语义/情感色彩 **动态高频词库**：每章检查完毕，将重复词（同一短语≥2次）追加入库，下次检查同步扫描。 **人写感优先**：文本读起来要像真实作者写的，而非AI批量生成。 ## 执行要求：最大算力深度推理模式 检查必须完整执行五步推理链，不得省略跳步： 1. **任务全量解析**：核心需求/硬性约束/交付标准/问题边界 2. **多分支穷尽**：≥3条不同路径，逐一分析利弊，选最优+备选 3. **主路径全链路推理**：前提→执行→推导→校验，缺一不可 4. **多维交叉校验**：逻辑/需求匹配/严谨性/反向攻击 5. **最终交付物**：逻辑自洽+细节完整+推理依据+风险提示 **禁止偷懒**：禁止跳步/省略推理/占位符/TODO/套话凑数。 ## 检查流程（十二步） ### 第一步：预检档位 | 档位 | 状态 | 操作 | |:---|:---|:---| | A档 | 段落错落，有对话有风格 | ✅保持 | | B档 | 整体尚可，句式单一缺少停顿 | ⚠️改风险段 | | C档 | 大段描述高度一致，像说明书 | 🔧必须改 | ### 第二步：违禁词扫描（必须穷尽，逐条列行号） | 问题类型 | 修正方向 | |---------|---------| | 比喻词：如、像、如同、仿佛、好像 | 禁用 | | 状态副词：猛然、陡然、骤然、缓缓 | 替换或具体动作 | | 模板句式：冷笑一声、一阵剧痛、涌来、抖了抖、偏了偏 | 具体神态/体感/动词 | | 感官：腥气、腥味、腥甜、颤抖、盯着、盯着看 | 其他感官词或具体动作 | | 肢体动作类：没有回答、没有离开、站在原地、愣了、愣住了、愣了一下、抬起手、低头、看着手掌/手心/手背、没说话、没回、没应、看着她/他、盯着他/她、没动、没敢动、没有动、没回头、一沉、心里一沉 | 替换或删除 | | 身体部位：指尖、指节、嘴角、嘴唇 | 手指、手骨等 | | 生理反应：眼眶通红、绷得发白、哆嗦了半天 | 其他生理反应描写 | | 水文痕迹：没人说话、整整 | 删除或具体细节 | | 废话伏笔：他知道、她知道、可他不去找她她就不会来找他 | 删除 | | X了X格式：攥了攥、偏了偏、收了收 | 动词替代 | | 英文残留 | 中文替代 | ### 第三步：模板化句子 - **原则**：不是换词，是换画面/动作/场景 - 抽象心理→身体反应；固定句式→全新场景；模板比喻→原创画面 - **来源**：仅用字典基础词重组，不用AI库词汇 - 例："目光冷得像冰"（禁）→"他把脸别开"✓ ### 第四步：词频检查（必跑freq_check.py） - 任意词汇一章仅出现1次（人名除外） - 四字成语全文禁止 - 词频脚本≠违禁词扫描，两步必须同执行 ### 第五步：章节衔接 - 上章结尾→本章开头是否衔接 - ⚠️跨章节重复检查：调出上章结尾500字与本章开头500字逐段对比 ### 第六步：大纲对照 - 正文是否偏离主线/关键情节点 - 角色行为是否与大纲设定一致 ### 第七步：人设一致性 - 语言风格/关键特征/反应是否前后统一 - ⚠️ NPC必须正经名字，禁止"刀疤脸""火系异能者"等地摊称呼 - 发现一处地摊称呼→全文扫描所有同类，一次性列完 ### 第八步：节奏代入感 - 对话比率/情绪起伏/代入感是否到位 ### 第九步：重复内容 - 不同角色说出相同的话/相同动作场景重复出现 ### 第十步：数量词术语一致性 - 等级/人数/距离/时间线是否矛盾 ### 第十一步：世界观一致性 - 瞳色/技能/等级体系/势力名称是否统一 ### 第十二步：复核自检（满足2/3项合格） - 有无"依据/来源/伏笔" - 有无"条件/边界/例外" - 有无"取舍/代价/备选" **修正后必须重跑第二步+第四步，确认无新增问题方可出报告。** ## 输出格式 ``` 🔍 【章节名】质量检查报告 📌 档位评估：[A档/B档/C档] ❌ 违禁词/套路句：[行号] "原文" → "修正" ⚠️ 模板化句子：[行号] "原文" → "替换方案" 🔗 章节衔接：[衔接/问题] 📋 大纲对照：[未偏离/偏离描述] 👤 人设一致性：[一致/问题] 🎭 节奏代入感：[达标/问题] 🔄 重复内容：[有/无+描述] 🔢 数量词术语：[一致/问题] 🌍 世界观一致性：[一致/问题] ✅ 复核自检：[满足X/3项] 📝 总体评价：[通过/需修改/重大问题] ```

path: freq_check.py
content: # -*- coding: utf-8 -*-
"""
小说质量检查工具 - 违禁词+高频词+替代表达扫描
用法: python freq_check.py <文件路径>
"""
import re
import sys
import os

# ============================================================
# 第一类：违禁词（出现即违规，必须修改）
# ============================================================
METAPHOR = ['像', '如同', '仿佛', '好像', '如']
XLE_X = ['顿了顿', '掂了掂', '紧了紧', '攥了攥', '偏了偏', '收了收', '摇了摇', '抖了抖',
         '动了动', '摸了摸', '闻了闻', '沉了沉', '白了白', '红了红',
         '没出声', '翻了翻', '瞥了瞥', '盯了盯', '白了白', '咬了咬']
DISABLE_ADV = ['猛然', '陡然', '骤然', '缓缓', '却', '但', '于是', '然后']
DISABLE_PAT = ['冷笑一声', '一阵剧痛', '涌来', '腥气', '腥甜', '绷得发白', '哆嗦了半天',
               '没人说话', '没人吭声', '盯着帐顶发呆', '可他不去找她她就不会来找他',
               'preY', 'prey', 'Prey', '指节', '指尖', '眼眶通红', '绷得发白',
               '整整', '脸上没有任何表情']
废话 = ['他知道', '她知道', '它知道', '我知道', '我觉得', '她觉得', '它觉得']
哑词 = ['哑得', '哑得厉害', '嗓子哑', '声音哑']
HIGH_WORDS = ['眼神', '眼睛', '目光', '心脏', '心里']

ALL_FORBIDDEN = (METAPHOR + DISABLE_ADV + DISABLE_PAT + 废话 + 哑词)

# ============================================================
# 第二类：替代表达库（模板词 -> 画面/动作替代，不近义词替换）
# ============================================================
REPLACE_MAP = {
    # 抽象心理 -> 具体动作/身体反应
    '心里一沉': '胃拧了一下',
    '心脏猛地一缩': '胸口发紧',
    '心脏狠狠一跳': '呼吸一滞',
    '眼神冷了下来': '他把脸别开了',
    '眼神里有一瞬间的茫然': '她歪了歪头，在辨认他',
    '目光没有温度': '他的目光没有焦点',

    # 重复动作描写 -> 场景替换
    '扫了一眼': '目光落在',
    '扫了': None,
    '扫了他一眼': '他瞥了对方一眼',

    # 身体部位 -> 动作替代
    '指节泛白': '手指发僵',
    '攥紧了任务单': '他捏着任务单',
    '攥紧了手里的': '他捏着',

    # 高频心理 -> 画面替代
    '脸色复杂': '他没说话',
    '眼神里闪过': '他的眼睛动了动',
}

def check_file(target):
    script_dir = os.path.dirname(os.path.abspath(__file__))
    output_path = os.path.join(script_dir, 'freq_result.txt')

    with open(target, 'r', encoding='utf-8') as f:
        text = f.read()
    lines = text.split('\n')

    # ---- 高频词 ----
    words = re.findall(r'[\u4e00-\u9fa5]{2,4}', text)
    freq = {}
    for w in words:
        freq[w] = freq.get(w, 0) + 1

    # ---- 违禁词扫描 ----
    forbidden_results = []
    for i, line in enumerate(lines, 1):
        issues = []
        # 违禁词检查
        for kw in ALL_FORBIDDEN:
            if kw in line:
                idx = line.index(kw)
                start = max(0, idx - 10)
                end = min(len(line), idx + len(kw) + 10)
                snippet = line[start:end]
                issues.append(f'[{kw}] ...{snippet}...')
        # X了X格式
        for kw in XLE_X:
            if kw in line:
                idx = line.index(kw)
                start = max(0, idx - 10)
                end = min(len(line), idx + len(kw) + 10)
                snippet = line[start:end]
                issues.append(f'[X了X:{kw}] ...{snippet}...')
        # 替代表达
        for kw, rep in REPLACE_MAP.items():
            if kw in line:
                idx = line.index(kw)
                start = max(0, idx - 10)
                end = min(len(line), idx + len(kw) + 10)
                snippet = line[start:end]
                note = f'建议替: {rep}' if rep else '建议删除'
                issues.append(f'[替:{kw}] ...{snippet}... | {note}')
        # 高频词警告（眼神/眼睛/目光/心脏+心理词组合）
        for hw in HIGH_WORDS:
            if hw in line and any(k in line for k in ['里了', '里透', '里闪', '里浮']):
                idx = line.index(hw)
                start = max(0, idx - 5)
                end = min(len(line), idx + 20)
                snippet = line[start:end]
                issues.append(f'[高频组合:{hw}...] ...{snippet}...')

        if issues:
            for issue in issues:
                forbidden_results.append(f'  L{i}: {issue}')

    # ---- 高频词汇总（次数>=2）----
    high_freq = [(w, c) for w, c in freq.items() if c >= 2]
    high_freq.sort(key=lambda x: -x[1])

    with open(output_path, 'w', encoding='utf-8') as f:
        f.write('=== 高频词（出现次数>=2）===\n')
        if high_freq:
            for w, c in high_freq:
                f.write(f'  {w}: {c}\n')
        else:
            f.write('  无\n')

        f.write('\n=== 违禁词+替代表达扫描 ===\n')
        if forbidden_results:
            f.write('发现问题：\n')
            for r in forbidden_results:
                f.write(r + '\n')
        else:
            f.write('  无违禁词 ✅\n')

    print(f'Done. 结果已写入: {output_path}')

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print("用法: python freq_check.py <文件路径>")
        sys.exit(1)
    check_file(sys.argv[1])


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)