文档索引

故事初审与编辑工作台设计

调研日期:2026-10-31。状态:工具设计,本文中的命令、目录与数据结构均为提案,尚未实现。 总路线见 docs/plan/story-rebuild-plan.md;进入编辑制作后的流程见 docs/plan/story-editorial-design.md。

1. 工具要替站长省掉什么

工具应当把“我得把全站读一遍”拆成几个有终点的动作:AI 提供可验证的类型与内容线索,站长迅速确认候选、整组看连载、只在必要时调查来源,随后把有限作品送到编辑台。

首个可用版本不需要模型:导入 → 看全文 → 标记 → 保存 → 筛选 → 导出 就是 M1。AI 在已有人工界面上补建议,不能成为唯一阅读入口。

核心约束:不修改来源博客;不自动发布;不自动给作者发消息;人工结论有版本且不会被模型覆盖。故障、拒答、没读完与“不是故事”分别记账。

2. 三层实体,避免把帖子当作品

2.1 来源、作品与出版版本

SourceDocument ── 1:N ── SourceRevision
                              │
                     多对多的段落/区间映射
                              │
Work ── 1:N ── Chapter ── 1:N ── ChapterRevision
 │                                   │
 └─────────── Edition/Release ─────────┘
  • 来源文档:一条博客、一个旧故事文件、一份作者直接提供的稿件;身份稳定。
  • 来源修订:特定时间读到的原文、格式、元数据与哈希;内容不原地覆盖。
  • 作品:一部小说、一个真正的短篇集或互动故事,使用独立 workId。
  • 章节:作品的阅读单元,显式 chapterId 与顺序;短篇也可以只有一章。
  • 章节修订:经过确认的编辑文本,可以对应多条来源,也可以只引用某来源的部分区间。
  • 出版版本:锁定章节修订、署名、简介、布局、素材、公开范围与签收的可发布集合。

一篇博客可含两部短篇,一章可以由多个博客合并,作者可直接提交新定稿。数据模型必须允许这些情况;不能要求每一章都有且仅有一个博客 ID。

2.2 最小数据表与主要字段

初版使用独立工作台 SQLite,配合内容文件目录;不向业务库一次性增加十余张表。以下为逻辑表,实施时可按关系约束合并,但不能丢失人工记录与版本。

实体 最少保存的内容
source_documents sourceId、来源类型、博客 ID/规范相对路径、首次导入、当前修订、当前可用/软删状态
source_revisions 原文引用、UTF-8 原文哈希、元数据哈希、标题、来源账号 ID、可见性、格式、更新时间快照、净文本与 source map、提取器版本
analysis_jobs 修订、任务类型、分段范围、模型/服务商/提示/schema 版本、幂等键、状态、尝试次数、上游任务 ID、费用与错误
analysis_results 类型建议、证据段落、读过的范围、长文聚合、相似/章序候选;永远标“机器建议”
review_events 人工操作者、动作前后值、理由、适用修订、时间、关联证据;追加记录,不覆写历史
review_current 当前人工结论与版本号;从事件更新,支持并发版本检查
author_profiles 作品署名、来源账号关联、别名候选/已确认、确认依据;联系人资料只留私有部分
works / chapters 稳定 ID、作品关系、章序、状态;章序唯一且可人工调整
chapter_sources 章节修订与来源修订的多对多映射、范围与编辑差异
permissions 作品/版本/素材、用途、范围、许可凭据引用、确认人、失效或撤回事件
editorial_packets 摘要、章纲、解释、作者意见、待办、视觉简报及各字段确认状态
assets / releases 素材来源与许可、配图位置、版本、发布清单、校验结果、上下架记录

只有进入相应阶段才需要相应表:M1 先有来源、修订、复审、作品和导出;上线前再补编辑、素材与出版记录。不要因为远期字段多而先做通用 CMS 表单引擎。

2.3 存在哪里、谁能访问

建议工作数据放 instance/story-workbench/,其中 workbench.db 保存索引和状态,sources/ 保存必要原文快照,drafts/ 与 permissions/ 保存编辑稿和凭据。这是持久工作数据,不能放会清理的临时目录。

该目录位于现有被 Git 忽略的 instance/ 内。创建前仍通过 git check-ignore 与 git ls-files 确认未跟踪/已忽略;不把正文、密钥、私信或人工评语写进仓库文档、测试快照和构建日志。一次性调研、测试日志、截图继续放系统临时目录。

初版作为现有 Next 应用的 owner 工作台;可考虑 /admin/story 与 /api/admin/story/*,每个页面和接口都显式校验 owner。现有后台父布局允许 core,不能借父布局当 owner 校验。默认不开启,不出现在公共导航、搜索或 sitemap;关闭开关也不能留下能读取原文的 API。

后台长任务由手动启动的本地 CLI worker 运行,Web 只入队和显示结果,不把几小时任务挂在一个 HTTP 请求中,也不新增常驻微服务。接口与 CLI 共用状态逻辑。若未来迁到生产,需要先明确谁备份工作台和谁能访问,不能顺手随站点打包公开。

3. 分类词表与人工结论

3.1 先问“是什么”,再问“从哪来”

维度 建议取值 说明
形式 小说、互动叙事、诗歌、剧本、散文/随笔、评论/介绍、非文学、混合、无法判断 支持多选;诗歌/剧本不自动丢弃,站长可决定是否扩展故事范围
故事候选 是、可能、否、未评估 小说片段、设定和章纲也可为“可能”
单元 完整短篇、长篇章节、片段、世界观/设定、合集、多篇混合、未知 与完结状态分开
来源归属 作者自述原创、转载、翻译、改编/同人、混合、未知 原创声明不等于已核验;原作者、译者与发布者分开
文字 AI 使用 作者/站长确认未使用、辅助、主要生成、混合、未披露、待核实 不把“未披露”显示成“人类原创”
连载状态 完结、连载、暂停、片段、未知 由作品而不是单帖决定
编辑处置 候选、暂缓、需要询问、不选登、进入制作 不选登不表示文章质量差或需要删博客
选编层级 主推候选、精选候选、普通收录候选、资料保留 只由人工确定;内部层级不做公开评分

AI 输出只能写建议与证据。公开的来源/AI 标签来自独立人工字段;模型即使说“99% 是 AI”,也不能填入确认字段。

3.2 什么算证据

证据强度依次包括:作者对该作品的明确说明、站长有依据的逐篇记录、来源页/许可文本、作品附注。文风、重复句式、模型识别出熟悉情节都只是待核对线索。

站长提供“Life 的小说是 AI 生成”可登记为站长陈述、范围为其小说、待核对作品边界。不能改写为该账号所有文章都由 AI 写成。旧 ai_assisted: true 则是旧版标记,保留原值和来源,不能无证据升级成“全文 AI 生成”。

转载调查先看文章内原出处、作者自述,再做必要的逐条核实。默认不把站内原文发送到搜索引擎查重;没有线索时保留未知。相似哈希和网络命中都不自动等于转载定论。

4. 数据导入与文本提取

4.1 M0 导入步骤

  1. 显式选择数据库或 JSONL 输入,建立只读连接/一致快照;不默认寻找生产凭据。
  2. 读取博客、正文及必要作者/栏目元数据,过滤软删,记录总量、各状态与格式。
  3. 全文逐条建立 sourceId 与修订;不要用标题做主键。
  4. 导入旧故事:保存相对路径、文件头、父级元数据、内容哈希和原 URL;Cattca 单独标格式。
  5. 导入直接投稿:只收站长明确选入的稿件文件。不要扫描整段聊天记录或把私信上下文送给模型。
  6. 生成对账:新增、变更、保持、已软删、缺失、提取失败。源文件缺失不自动物理删除工作台记录。

首次导入覆盖全部未删除来源,不仅文学栏目。后续导入读取新库副本并比较修订,避免直接在业务库上反复做长时间分析。

4.2 给模型的文本要能回指原文

保留三份形态:原始正文、提取出的阅读文本、段落到原始行/区间的 source map。原文哈希基于原始 UTF-8 字节;用于查相同内容的宽松归一化哈希另设字段,不能代替修订标识。

Markdown 用语法结构处理,保留叙事、对话、标题、引用与必要上下文;代码/长链接等可另标类型,不能凭正则删掉包含故事的块。每段有稳定于该修订的段落 ID,证据采用段落 ID + 短摘录;若使用字符偏移,协议明确为 Unicode code point,下游 JS 不能混用 UTF-16 下标。

站内引用默认只保留引用类型和标记,不展开剪贴板、投票、收藏夹等资源。提取不执行脚本、不请求外链、不下载图片。图片才承载正文、引用缺失、ReactiveMD 提取失败和未知格式都标 needs_manual,不当负例。

ReactiveMD 使用已验证的静态读取/文本提取能力,并记录降级状态;不能把其源码直接喂旧 Markdown 渲染器。Cattca 分析时可提取对白/说明辅助分类,但出版仍保留原脚本和运行测试。

5. AI 初审的具体流水线

5.1 先覆盖,再做聚合

  1. 全来源轻量分析:每条未删除来源都进入任务清单。短文直接给完整阅读文本,不能因字数少、栏目或作者而跳过。
  2. 长文分段:按段落/章节边界切成约 4,000–8,000 token 的块,实际预算按所选模型、提示与输出余量确定;相邻块保留小范围上下文重叠,记录原区间。
  3. 段级输出:类型建议、是否含叙事、章回线索、出处/AI 自述的原文位置、主要不确定点。此时不写长摘要或文学评分。
  4. 文档聚合:任一段有小说/混合线索就进入候选或人工队列;只有全部必需区间完成且聚合一致,才可建议“否”。失败/漏段/截断一律不能成为高置信负例。
  5. 作品关联建议:标题章号、署名、共同角色、明确前后篇链接与文本相似度一起提出分组;只输出关系候选,不自动合并。
  6. 疑难升级:模型意见冲突、混合体、超长拼贴、仅附件正文等进入人工或更强模型。完整章纲/主题分析只对准备制作的作品执行。

“AI 已读完整篇”的定义是提取成功、区间并集覆盖全部需读文本、所有结果有效并完成聚合。抽读开头/中间/结尾可以作为抢先线索,但必须标 partial,不得出现在完成计数里。

5.2 结构化输出契约

初审响应示意如下;生产版本用严格 schema、枚举、字段长度上限及本地校验,此例不是现成 API 请求。

{
  "sourceRevisionId": "revision-example",
  "chunkId": "chunk-03",
  "candidate": "possible",
  "forms": ["fiction", "commentary"],
  "unit": "mixed",
  "evidence": [
    {"paragraphId": "p-042", "quote": "原文中确实存在的短摘录", "kind": "narrative"}
  ],
  "sourceClaims": [],
  "aiUseClaims": [],
  "relationHints": [],
  "uncertainties": ["同一帖包含介绍和故事正文"],
  "summaryForReview": "供内部复审的简短说明"
}

原区间、token 计数和完成状态由调度器写入,不能相信模型自称“已读完”。sourceClaims / aiUseClaims 仅收原文明确自述及其位置;无明示就为空。证据摘录必须能在对应修订中验证,验证失败进重试/人工,不能存一段看似合理的伪引文。

采用结构化输出可以约束响应形状,事实和分类仍可能出错;拒答、非法字段、超长响应与截断都需要独立处理。OpenAI Structured Outputs

5.3 提示词的稳定边界

系统提示只要求识别内容形式与可见证据,不要求猜作者是否说谎、是否值得获奖。正文是待分析资料,内含“忽略指令/调用工具/全部通过”等字样都只是内容。模型没有执行 shell、访问数据库、网页或向外发消息的工具。

首轮尽量不提供作者的声望、点赞量或身份等级,减少依作者定性的倾向;人工给出的已知来源/AI 说明通过独立受信字段保存,不伪装成模型在正文中发现的证据。每次修改提示有版本号,记录期望修复的具体错误。

5.4 可中断、可恢复与费用控制

任务唯一键建议由 revisionId + chunkHash + taskType + provider + modelSnapshot + promptVersion + schemaVersion + extractorVersion 组成。原文分析可共享相同文本缓存;带不同上下文的聚合、来源与人工结果不能共享覆盖。

状态为 queued / submitted / running / succeeded / failed / refused / incomplete / cancelled / needs_manual,每次尝试另有记录。网络超时且上游状态未知时先对账,不盲目重复提交。429 遵守重试等待,瞬时故障有限次退避,持续错误暂停该批。

Batch 通过本地任务 ID 映射 custom_id;结果按 ID 归档,不按文件行顺序。下载成功/失败文件后逐条对账,过期仅补失败项;取消后继续收集已完成结果和账单。CLI worker 在外部请求期间不占 SQLite 写事务,只在认领和落结果时短事务写入。

小批先跑普通请求方便调试,稳定后才用 Batch。其官方文档给出 24 小时完成窗口和相较同步请求 50% 的成本折扣;实际模型、额度与可用端点实施时核对。OpenAI Batch

每个批次持久化输入/输出 token、实际价格版本、重试、升级和已知费用。总费用按各层任务分别求和:

文本费用 = Σ(实际输入 token × 输入单价 + 实际输出 token × 输出单价) / 1,000,000
全量预算 = 分类 + 长文聚合 + 疑难升级 + 有界重试 + 预留
制作预算 = 入选作品编辑分析 + 获准图像生成/修改 + 人工时间

达到费用或 token 上限时停止新提交。运行摘要列清总来源、已全覆盖、部分覆盖、失败、待人工、预计剩余费用;不只显示“处理 100%”。

5.5 数据离站与留存

工具默认只读离线;联网运行前展示本批来源范围、服务商、所需正文与预计费用。排除账号密码、邮箱、IP、私信上下文和与任务无关的个人资料;内部文章需要明确处理范围,公开展示许可与 AI 分析许可分别保存。

OpenAI API 默认不将提交数据用于训练,但日志、文件、批任务仍有不同保留政策;store: false 不能被解释为所有数据零留存。为上游文件制定到期/清理策略并记录清理结果;如该作品不适合外发,就留给本地处理或人工,不强行走 Batch。OpenAI 数据控制

6. 先用真实标注衡量初审

6.1 样本与防泄漏

建议第一批约 120 条人工标注来源:约 80 条用于提示调试,约 40 条冻结验证。按长短、栏目、语言、完整/片段/混合、旧已收录/未整理、已知 AI/转载线索分层;包括很短的小说、不在文学栏的作品和长篇非小说。

已知作者样例既要有正例也要有其非小说帖子。相同文本、同一作品章节和近重复版本必须分在同一侧,避免把已看过的另一章当作独立验证。人工不确定项单列,不能硬塞进负类计算好看的分数。

6.2 先保召回,再减少人工负担

报告至少包括:候选召回率、候选精确率、无法判断比例、分层漏检、处理失败、长文覆盖率与每千条费用。将 possible 算进候选召回,另报其数量以免靠“全部可能”获得虚假的高成绩。

试运行目标可定为:冻结集候选召回约 95% 以上,已知必须检出的小说不漏;但四十条的小样本不足以证明全库同样精度。必须公开样本中的正例数、分母和置信区间/不确定性,不写“全站 95% 准确”。

全量分批时,从建议负例中再抽约 50 条,覆盖超短、长文、非文学栏目与混合体。若发现实质漏检,回查该层、调整规则并重跑受影响任务;无法承受的漏检出现时,扩大候选口径,不能只改这几个样本标签。

界面所谓“高置信负例”仅是队列分层:完整覆盖、所有分段与聚合均建议否、没有未决提取/混合问题,且该类样本的验证表现稳定。它不是模型自报概率,更不代表可以免除抽查。

7. 人工复审界面

7.1 三个工作视图

视图 主体 最重要的操作
来源复审 左侧待办/筛选;中间原文全文;右侧 AI 建议、证据与独立人工结论 确认形式、来源/AI 状态、候选/暂缓;下一条;撤回
作品整理 候选分组、各来源版本、章节树、并排差异 建/拆作品;拖动章序;接受关系候选;指定定稿来源
制作看板 待询问、待定稿、待配图、待页面、待签收、已发布 查卡点与完整材料;进入相应步骤,避免一个巨大综合表单

默认队列先处理:模型不确定/失败、已知故事关联、新连载候选;高置信负例可折叠,但可搜索和抽查。支持作者、栏目、长度、来源类型、未决状态、模型版本和是否已有故事版本筛选。

7.2 一次复审应完成的动作

  1. 原文与证据可点击定位,摘要默认简短,剧透分析另展开。
  2. 一键确认候选/非候选/稍后;来源与 AI 状态允许保留未知,不强迫乱填。
  3. 必要时补作者、作品关系或待询问问题,随手加入作品草稿。
  4. 显示保存状态;切下一条前未保存变更有保护,离线/冲突不会假装保存成功。
  5. 支持键盘操作且输入框内不触发全局快捷键;全文可在独立视图打开,长文不截断。

批量操作先展示条数和作用字段,默认不能批量确认原创/AI/授权。作者级规则仅做有范围、有依据的“预填”,不直接成为逐篇公开结论。一次操作可撤回为新事件,不抹掉历史。

7.3 导出要立即有用

初版提供候选 CSV 和作品 JSON/Markdown 编辑档案:作品、章节、来源、人工状态、未知项、授权状态、下一步。CSV 导出防表格公式注入;私有导出显式标私有,不混进公开下载。

从“作品列表”点进去能看到原文和未完成事项,才算交付。不要只交一张写满模型置信度、还得站长重新打开 5,000 次博客的表格。

8. 状态机与改稿

来源复审状态建议为 unreviewed → candidate / not_candidate / deferred / needs_info。作品制作状态另设 draft → source_checked → author_pending → text_locked → design → proof → approved → published → withdrawn;不能用一个 status 同时表示来源分类和制作进度。

  • 原文改动生成新修订,旧 AI 结果保留且标过期,旧人工结论保留适用版本;作者归属等可建议继承,但需要人确认影响范围。
  • 元数据与可见性变动即使正文没变也要导入。正文分类缓存可以复用,公开授权/署名和发布资格要重新检查。
  • 标记软删/来源不可用后停止新分析;已发布版本进撤回检查队列,不继续依赖旧快照静默公开。
  • 来源软删时,不能让工作台变成绕过删除的永久原文仓库:默认保留来源 ID、哈希与审计事件,将原文及其可还原摘要/引用标记清除,撤销未完成的上游任务并按服务商政策申请清理。确有独立且有效的故事定稿许可时,另外记录该版本的保留依据;不要把“曾导入过”当依据。备份恢复时先重放删除/撤回清单,避免复活正文。
  • 缺章、新章和同名改稿分别提示。章序不按文件名或发布时间自动覆盖人工顺序。
  • 两个浏览器并发保存用 reviewVersion 做乐观锁:冲突返回差异,不采用最后写入者悄悄覆盖。

作品已获独立故事版授权时,博客修改不自动改写成品;来源转站内/删除后,默认先暂停相关公开版本,站长依据独立授权再恢复。发布包与撤稿机制见 docs/plan/story-editorial-design.md §7。

9. 开发拆分与命令提案

建议代码集中到独立 story-workbench 服务层,页面只组装界面,CLI 与接口共用内核。接入现有运维 CLI 时,按 scripts/cli/registry.ts 注册并同步 docs/cli.md,不另维护一份命令发现机制。

下面表示拟提供的能力,现在不可运行;参数名在实施时与用户体验一起定稿。

npm run cli -- story inventory --db <明确的只读库路径>
npm run cli -- story import --snapshot <快照路径> --stories <旧故事目录>
npm run cli -- story analyze --dataset <数据集ID> --dry-run
npm run cli -- story analyze --dataset <数据集ID> --budget <上限>
npm run cli -- story worker --run <批次ID>
npm run cli -- story reconcile --run <批次ID>
npm run cli -- story export --reviewed --out <私有目录>
npm run cli -- story build-edition --work <作品ID> --dry-run
npm run cli -- story validate-release --release <版本ID>
开发包 首轮必须有 后续再加
T1 导入/存储 只读导入、快照、修订哈希、对账、备份恢复 更多投稿渠道
T2 人工复审 全文、手工字段、筛选、撤回、保存冲突、CSV/JSON 导出 多编辑协作与复杂快捷键
T3 AI 运行器 一个提供商、严格结果、证据校验、分段覆盖、重试与预算 第二提供商、嵌入向量聚类
T4 作品整理 来源映射、人工章序、别名确认、编辑档案导出 自动章节发现与复杂合集嵌套
T5 出版工具 定稿锁定、素材台账、清单校验、原子切换、撤回 定时出版、作者自助门户

优先顺序是 T1 → T2 → 小范围 T4 → T3 → T5。向量数据库和自动网页查重没有首轮必要性;先把人能用的原文、证据与下一步放到一起。

10. 工具验收

实现时用合成/获准样本测试,不提交真实博客正文与作者私信。重点验证:

  • 原库只读;含 WAL 的快照一致;软删不进入新分析;缺失/格式错误可见。
  • 超长文章完整分段;任何一段失败不会聚合成非故事;证据能回指原修订。
  • 重复导入/回调不重复落任务;乱序返回、过期、拒答、网络中断可恢复;预算停止有效。
  • 模型重跑不覆盖人工;旧修订不冒充新结论;多人/多标签页保存冲突能发现。
  • owner 页面和所有 API 分别校验;匿名/core/admin 无权读工作台原文或预览附件;错误响应无正文泄漏。
  • 网络请求不在 SQLite 事务内,日志不包含正文/凭据;关闭联网模式没有意外请求。
  • 导出再导入保留作品关系、人工结论和未知项;备份恢复后能继续复审。

每个开发包按仓库纪律按风险跑适用验证(相关测试、必要时 typecheck),全量按根指引的触发条件执行;真实设备操作和初审质量用独立样本验收,不能用单元测试通过代替“站长确实省了时间”。

本页内容来自仓库 docs/plan/story-review-tooling.md·在 GitHub 上查看

故事初审与编辑工作台设计 · 聪明山