cordis-plugin-novelist
一套以文件账本为状态载体的长篇写作工具链。同一套工具、同一份能力真源,发行成两个宿主形态:DSH 插件形态,与 WorkBuddy 专家包形态(下表最后一行为第二个宿主形态);此外还可作为独立 MCP server 接到任何客户端。
双宿主一句话:流程只在一份真源里写一次(能力 × 宿主 × 形态 = roles/tool-face.json,生成器 roles/build-tool-face.mjs),宿主只决定"哪一层由机器守、哪一层由纪律守",不决定流程形状。说"本仓是 DSH 插件"没错,但那描述的是机制形态,不是宿主绑定。
本仓五件东西(三件宿主无关 + 两个宿主形态各一件):
| 件 | 是什么 | 给谁用 |
|---|
插件(lib/,详见 README-plugin.md) | 十五个确定性工具(novel_*):每部书一个目录,读写账本文件(项目/设定/人物/伏笔/时间线/章纲/状态)、正文与版本快照、追加式事件日志(JSONL)、以及编辑工作区(事务回执、逐版事实快照、评分、决策记录)。章节提交是事务性的——回执绑正文哈希、expected_rev 乐观并发、同文本重试幂等、编辑期快照、可回滚到任意旧版。代码做记账,模型做写作 | 想在 agent 宿主上做长篇连续性生产的人 |
MCP server(mcp/,详见 mcp/README.md) | 同一套工具的 MCP(Model Context Protocol)形态:执行逻辑零改动复用,路径安全由 fs 适配层自担(书库根在启动时强制校验:词法 + realpath 双防线),工具说明与机制文档走 prompts 注入 | 不用 DSH 的智能体用户(Claude Code / ZCode / Cursor 等任意 MCP 客户端) |
编辑部 starter 预设(preset-starter/) | 两座位制预设(主编 + 主笔,其余按需 one-shot):人格提示词、防自批的工具白名单(子代理禁止写类工具,落盘权只在主编)、盲读输入隔离,附冷读协议与前情事实卡模板 | 想要现成协作编排(而非裸工具集)的 DSH 用户 |
仪器(instruments/) | 零 LLM 的确定性检查与统计层:文体机检(正则规则)、语料证伪、判据聚合、盲池构建、批量日报生成 | 想量化验证写作规范或判官可靠性的人(不依赖 DSH,纯 Node) |
WorkBuddy 专家包(模板 wb-expert-starter/ + 装配器 scripts/build-wb-expert.mjs;第二个宿主形态) | 同一套工具+编辑部编成 WorkBuddy(CodeBuddy 家族)的"专家":team 型,leader 是主编(主智能体)、members 是主笔,另有五个按需工种;工具面隔离由能力表渲进宿主载体(包内定义不带封名单——官方校验器禁止)。装配器认公开单仓与私有 monorepo 两种布局 | 用 WorkBuddy 的用户(装法见下方§五) |
为什么是"运行逻辑"而不是"又一个 AI 写作插件"
我们不认为当前任何模型能自主写出能赚钱的长篇。两个月的对照实验把我们按在这个结论上:
- **文笔层已经够用。**机检无红旗、盲判官四分档、与真人的差距不在句子层。
- **瓶颈在上游:结构与选题。**同一写手换大纲做对照——统计平均值拼装的大纲产出"被量化后的平庸";真人爆款的节拍 1:1 移植能提升文笔/一致性维,但整体仍在真人水位之下。结构 > 文笔,实验证实。
- **编制不买质量。**六角色编辑部管线 vs 通用智能体挂一份技能文件:盲评 3:3 打平。钱应该花在仪器上,不是花在角色编排上。
所以本仓的论点:模型负责生成,代码负责确定性和测量,人只做一件事——当判官(盲读判词、方向投票、终验)。其余全部可以制度化。
仪器层:我们把圈内流行规范拿去验了一遍
instruments/corpus-falsify.mjs 对 59 本起点头部作品(分层抽样、种子可复算)逐条验证流行写作规范,代表性结果:
| 流行规范 | 验证结果 |
|---|
| 感叹号 ≤3/千字 | 不成立:59.3% 的好书超标 |
| "严禁使用"类负向词清单 | 不成立(作为质量判据):84.7% 的好书里这些词常见(中位 4.2/万字)——它们区分的是"AI 稿/人稿",区分不了"好/坏" |
| ≥70% 段落控制在两行以内 | 非普遍事实:仅 33.9% 的书达标——是那位作者的口味,不是行业线 |
| 模板开场套话在好书正章罕见 | 成立(章首命中中位 0%) |
我们还发现自己管线掉进了对称的坑:过度规避——禁词压到 0、感叹号压到 0,同样偏离人类分布。人味 = 落在人类分布带内,不是越干净越好。仪器的正确用法是测双向偏差。
跨层声明(必读):上表语料 100% 为起点系长线作品,结论对"起点长线好书"成立与否——不能直接外推到番茄短平快(节拍密度/章长/爽点频率的分布不同),工具头已显式标注。要让阈值对生产平台成立,需另采番茄头部语料重跑一遍证伪;在此之前,这些数字只作"阈值来源可见、可复算"的参照,不作生产判据。
判据信度同理:宽松判据(within-1 一致率)下,一个只会恒定打 4 分的判官能拿满分信度。instruments/instrument-aggregate.mjs 强制报 exact agreement、ICC(2,1)、量程使用分布,sd=0 / n<5 的维度显式"不可测",绝对分与成对判两把尺子打架时阻断达标结论。
快速开始
# 一、DSH 插件(任选其一)
dsh plugin --profile <你的profile> add github:NovaDev9-bot/cordis-plugin-novelist # 从本仓装
dsh plugin --profile <你的profile> add <本仓本地路径> # 本地装
# 装好后该 profile 的会话即带 novel_* 15 工具与 novelist-guide(无需其他配置)
# 想要现成的编辑部编排(主编/主笔人格与协作框架)→ preset-starter/(v0.8.0 起公开)
# 二、MCP server(不用 DSH 的智能体:Claude Code / ZCode / Cursor 等任意 MCP 客户端)
node mcp/server.mjs --root <书库根目录> # 路径安全硬前置:所有 book_dir 圈在书库根内
# 客户端注册与差异说明见 mcp/README.md(工具与 guide 和 DSH 形态同源)
# 三、仓库自检(Node ≥ 20)
git clone https://github.com/NovaDev9-bot/cordis-plugin-novelist.git
cd cordis-plugin-novelist
npm test # 插件测试
node --test mcp/test/mcp.test.mjs # MCP 测试(根安全+协议+工具全链)
node --test instruments/style-check.test.mjs instruments/instrument-aggregate.test.mjs # 仪器测试
# 四、仪器单用(不依赖任何宿主,纯 Node——机检/证伪/聚合任何人的书稿都能用)
node instruments/style-check.mjs 某章.txt # 文体机检(GBK 自动识别;--lexicon 叠加负向词库)
node instruments/corpus-falsify.mjs --corpus <语料根> --index <索引.csv> --out <输出> # 用你自己的语料证伪规范
node instruments/instrument-aggregate.mjs <书工程目录> --baseline <calibration-baseline.json> # 判据聚合
node instruments/batch-report.mjs <book_dir> --write # 生产批日报(章状态/伏笔收支/待裁事项)
# 五、WorkBuddy 专家包(把同一套工具 + 编辑部编成 WorkBuddy 的"专家")
node scripts/build-wb-expert.mjs --book-root <你的书库目录> --out <专家包目录>
# 纯 Node、零依赖。装配器同时认公开单仓与私有 monorepo 两种布局。
# --handbooks <目录> 可另外带上主编/主笔两份作业规程;不给会**明确报"本次不含"**,不静默少件。
边界说明:本仓=账本工具+编辑部 starter 编排+测量仪器。两宿主形态共享同一份流程真源与能力真源(工具面隔离只渲一次,按宿主映射落地;谁强谁弱逐项分宿主标注,不取平均)。starter 预设(2026-09-17 起人格公开版)与生产预设同源:机制不变,公开侧不含本机私有路径与档案库引用,读者画像卡随包提供。
三分钟:把你自己的一本书变成一张写手参照卡
参照卡带原文,而且每张都有出处行。两条理由:
- 实证:要让模型换一副嗓子,最有效的做法是给它看目标语域的原文——不是"去看第 N 章"这种坐标。主笔的
glob/grep 是被禁的,只能按精确路径读,坐标它解不出来,那种卡在生产链路上等于空转。反过来,把风格写成"句长中位 X、短句占比 Y"这类数字,被提示(prompting)与 LoRA 一致优于;更强的是,追加可逐条核验的约束反而把风格归属准确率拉低(Wang et al. 2025,400+ 位作者、4 万次生成)。机制是 extremal Goodhart——观测出的分布性质一旦变成逐句目标,模型就去凑比例、牺牲真语域。
- 法律:风格不受版权保护,载体受保护。所以卡里贴了别人的正文,就必须指明作者与作品名——这是「适当引用」的前提条件,不是可选项。卡名用风格指纹(形态描述,不点作者),卡头写出处,两者各管各的:名字落在那段字上,不落在这张卡上。
# 1. 把锚书目录交给它(认两种布局:<锚书>/manuscript/chapter_NNN.md,或目录下任意 *.md/*.txt)
# --source 是引用出处:卡里贴的是别人的正文,这一行就是"适当引用"的前提条件
node instruments/build-author-card.mjs --book <你的锚书目录> --source "《书名》· 作者" \
--out 我的卡.md --json 实测.json
# → 我的卡.md(给写手):出处行 + 一段锚段 + 按**场景功能**挑的范例(对话戏配对话戏,不按主题相似度)
# → 实测.json(给审校):句长中位/短句占比/对话段占比——数字只走 stderr 与 --json,永不进卡正文
# 2. 卡里三处空槽只能人填:语域指南一句话、这个作者不会做的事、AI 腔黑名单
# 3. 派工包里**全文**贴给主笔;卡留在库里不贴=这一格空转
设计要点:卡正文 0 个数字型风格断言是硬断言(出现 \d+% 或"中位/占比"即退出码 1、拒发)——这个工具的存在理由就是不让一张自带代理目标的卡出厂。锚书里测不到某类范例时它报"未测到"并说明原因(含引号形态普查,防"语料没带引号"被误读成"这本书没有对白"),不拿别的类顶替;锚书切不出正文时退出码 2 而不是 0——"没测成"和"测到没有"必须分开。
卡目录、六节骨架与建卡纪律见 craft/author-cards/_模板与建卡纪律.md;体量/章长/钩型分布这类参数类参考在 craft/reference/(规格清单形态,只作骨架与审校侧参考,参数不得当写手任务书)。
设计红线
- 判定归模型、代码做壳:机检只报数+软警告,永不作语义质量门禁;符号级护栏(章号/版本链/引文核验)才用确定性代码。
- 一切判断锚正文原句:判据账 evidence 子串核验硬闸,伪引文当场拒收。
- 词库=数据不是散文:
instruments/style-lexicon.json 是 JSON,三层各司其职——L1 forbidden_lexicon(命中即问题,清单随派工包给写手)、L2 negative_lexicon(只报密度、不判违规)、L3 positive_lexicon(正向锚,限特定角色口吻)。发布版与生产版逐字节相同。要叠加自己的清单:--lexicon your.json,格式 {类别:[词...]}。L2 不可当质量判据——它区分"AI 稿/人稿",区分不了"好/坏";压到 0 同样偏离人类分布(实测 78% 的头部作品超其阈值,中位 3.577/万字)。
- novel_count 只返回计数:
file 模式读取任意指定路径文本,但输出仅 汉字数/字节数/行数/来源路径——不回显内容(计数-only,侧信道面=文件长度指纹)。工具面按角色 deny 收口见 preset。
License
MIT。所有实验数字可复算(种子与口径随文件注明),欢迎推翻我们。