# 正文结构与中文选区 ## 正式结构 正文使用受限文档树,支持稳定段落身份、显式换行和小说需要的有限行内样式。顶层合同包含 document_id、chapter_id、branch_id、revision、format_version、document_hash、visible_text_hash 和 paragraphs。每段包含 paragraph_id 及允许的内容节点。 文档结构与可见文本有确定性序列化规则。document_hash 保护结构和段落身份;visible_text_hash 保护模型实际看到的文本。编辑器 HTML 是显示适配格式,不是正式值的替代权威。元数据可描述结构面扩展,但不能改变正文协议的身份、哈希及位置语义。 格式 v1 的草稿载荷为 `format_version=1` 与有序 `paragraphs`,空稿保留一个空段落。段落通过 `paragraph_id` 定位,`content` 接受 `text` 和 `line_break` 节点;文字节点的样式限定为 `strong`、`emphasis`,不接受任意HTML属性。可见文本按段内节点连接、段间一个 LF 连接,空段落原样保留;段内显式换行保存其原换行序列。结构哈希使用草稿的UTF-8规范JSON(键排序、紧凑分隔、不转义中文),可见哈希只对实际文本UTF-8字节计算。数据revision和章节归属位于业务版本外壳,不因保存动作改变同一草稿的内容哈希。 ## 位置和修改合同 格式 v1 的行内结构规范化与编辑器一致:省去空文字节点、相邻同样式文字节点合并,样式去重并固定为 strong、emphasis 的顺序;空段落及段落身份仍保留。该步骤不做 NFC、不改变任何可见字符或换行字节。后端构造、编辑器适配和哈希均使用这一结构,避免未修改内容仅因编辑器内部文本节点合并产生假差异。 传输统一 UTF-8。位置按 Unicode 码点、左闭右开区间计数;前端集中转换 JS UTF-16 位置。段落 ID 与段内区间共同定位,不能只提交整章字符偏移或正文中的第一次字符串匹配。 每个自动修改项携带 paragraph_id、paragraph_hash、start、end、原文和替换内容;修订包带文档基线、修改目的和允许范围。应用前重验原文与位置、范围、不重叠及必要诊断对应。重复片段不能按任意首次命中替换。 跨段修改显式表达受影响段落与操作顺序。保留未修改段落身份;拆分与合并生成确定的新身份并记录映射,不能每次保存重建全部段落 ID。 ## 中文与编辑行为 不擅自规范化作者正文中的全角标点、异体字、组合字符和有意空白。文件名可以做 NFC 检查,正文规范化需成为明确的编辑操作。空行、换行和段落必须在导入、编辑、生成、保存及导出中保持约定。 输入法组合期间不提交半成文字。自动保存以章、分支、基线和请求代次绑定;后发请求或切章不能让迟到响应更新其他文档。保存失败保留本地缓冲,服务器成功后依据回执确认已保存。 人工编辑可以修改故事内容,但不会自动确认由此推导的事实。AI 保护区只限制相应自动任务,不能禁止作者主动编辑自己的正文。 ## 分支与回退 分支记录共同基线及本分支当前版本。部分采纳、分支合并和回滚形成新版本;合并重新验证主分支当前版本、结构与来源。跨章快照是固定的版本清单,不是指向各章 latest 的查询。 ## 验收例 中文输入法组合、emoji、组合字符、全角引号、连续空行、跨段选区、重复原句、快速切章、并发保存、断网刷新、结构格式升级及 TXT/DOCX/EPUB 往返均要验证。比较实际可见文本、段落映射、授权范围和服务器版本;不能只检查编辑器没有抛异常。