跳到主要内容

SyncEngine 技术设计

# SyncEngine 技术设计

修订记录

版本日期修订说明
v0.12026-05-01建立当前设计基线;延续 kunora-wiki 作为 llm-wiki 方案的既有产品封板和工程设计,不推倒重来。

1. 摘要

SyncEngine 负责把多个来源项目中的文档变更转换为 kunora-wiki publish/** 工作区中的受控同步变更。它读取 ConfigManager 生成的 SourceConfig,通过 SourceReader 获取来源文件,通过 WorkspaceStore 读取当前正式文档和 state,执行三方比较,输出 SourceChanges、更新 SourceLock,并把需要人工审查的变更交给 ReviewBridge。

SyncEngine 不直接合并到 main,不触发展示发布、索引或 agent 改写。任何冲突、删除或高风险变更都必须以报告形式进入 review 流程。

2. 模块目标

  • 根据 SourceConfig 扫描 enabled source。
  • 对来源文件、上次锁定状态和当前 publish/** 内容执行三方比较。
  • 生成 SyncChangeSourceChanges
  • 根据同步结果安全更新 state/source-lock.json
  • 对冲突、删除、来源不可用和部分失败输出标准错误和报告。
  • 为 ReviewBridge 提供可创建 Sync PR 的稳定输入。

3. 非目标

  • 不直接写 main 分支或合并 PR。
  • 不决定内容语义质量是否合格。
  • 不调用 Docusaurus、RAGFlow、Meilisearch 或 Answer API。
  • 不触发 AgentBridge 自动改写文档。
  • 不绕过 WorkspaceStore 直接写 publish/**state/**
  • 不把 source repo 的私有元数据暴露给下游公共契约。

4. 上下文边界

SyncEngine 位于 L1 Governance 层。它可以依赖 ConfigManager、WorkspaceStore 和 SourceReader/GitProvider adapter,但不能依赖 Display Adapter、Index Adapter、Answer API 或 AgentBridge。

5. 输入与输出

5.1 输入

输入来源说明
ConfigBundle.sourcesConfigManagersource 列表、路径映射、同步策略。
source file snapshotSourceReader/GitProvider来源 repo/ref 下的文件内容和 commit。
current DocumentRecord[]WorkspaceStore当前 publish/** 文档状态。
SourceLockWorkspaceStore/state上次成功同步的 source commit 和文件 hash。
run optionsworkflow/manualdry-run、strict mode、指定 source、重试模式。

5.2 输出

输出消费者说明
SourceChangesReviewBridge、维护者本次同步变更、冲突、错误和摘要。
SourceLock updateSyncEngine、ReviewBridge成功同步后的 source 锁定状态。
candidate file writesWorkspaceStore / ReviewBridgeSync PR 分支中的 publish/** 修改。
ErrorObject[]ReviewBridge、CIsource 不可用、冲突、lock 更新失败等错误。

6. 依赖的 common 契约

契约用途
SourceConfig决定 source repo/ref/path 到 publish path 映射。
ConfigBundle读取经过校验的同步配置。
DocumentRecord获取当前 publish 内容状态。
ContentHash / NormalizedPath比较来源和目标文件。
SourceLock记录上次同步基线。
SyncChange单文件同步动作。
SourceChanges本次同步报告。
ErrorObject同步错误和警告。
RunId关联一次同步运行。

7. 三方比较模型

SyncEngine 对每个 source file 使用 A/B/C 三方模型:

版本含义来源
A上次成功同步时的 source hash / publish hashSourceLock
B当前 source 文件 hashSourceReader
C当前 publish/** 文件 hashWorkspaceStore

动作判断:

ABC动作说明
add新来源文件,目标不存在。
conflict新来源映射到已有目标。
有且 B=AC=Akeep来源和目标均未变。
有且 B!=AC=Aupdate来源更新,目标未被本地改动。
有且 B=AC!=Akeep_local来源未变,目标被人工改动。
有且 B!=AC!=Aconflict来源和目标同时变化。
C=Adeletereport_delete来源删除,目标未改,按 deletePolicy 处理。
C!=Adelete_conflict来源删除但目标被改动。

MVP 默认 deletePolicy=report-only,即上游删除不会自动删除正式内容,只生成报告。

keep_localreport_delete 是合法 SyncChange.action,用于让 ReviewBridge 区分“本地人工保留”和“来源删除但仅报告”的治理语义。

8. 核心流程

流程要求:

  • 每个 source 独立处理;单个 source 失败不应阻断所有 source,除非配置错误是全局阻断。
  • 对 failed source 不更新其 SourceLock
  • 对存在 conflict 的文件不写入候选内容。
  • SourceChanges 必须包含 skipped/failed/conflict 统计。
  • dry-run 不写 publish/**state/source-lock.json,但可以输出临时报告。

9. SourceLock 更新规则

场景是否更新 SourceLock
source 完全成功,且无冲突是。
source 部分文件失败否,或只更新明确成功且可安全分片的文件;MVP 建议 source 级不更新。
source 不可用否。
配置错误否。
keep / keep_local可更新时间戳和 commit,但不改变 file hash。
deletePolicy=report-only不移除 lock 文件项,直到删除被人工确认。

SourceLock 更新必须与候选 publish/** 写入保持一致:不能出现 lock 标记成功但目标文件未进入 PR 的情况。

10. 删除策略

策略行为风险控制
report-only只报告来源删除,不改 publish/**MVP 默认。
sync-if-unmodified如果 C=A,可生成删除候选需要 ReviewBridge 阻断性提示。
never忽略来源删除,只保留 lock 信息适合来源不稳定项目。

删除候选必须进入 Sync PR,不能直接删除 main 上的正式内容。

11. 接口设计

接口输入输出说明
runSyncrun optionsSourceChanges执行一次同步。
planSourcesource config、snapshot、current docs、lockSyncChange[]对单个 source 生成计划。
applyPlanToWorkspacesync plan、write modewrite result写候选变更或 dry-run。
loadSourceLockstate pathSourceLock 或 empty读取同步基线。
updateSourceLockprevious lock、successful changesnew lock生成新锁。
classifyChangeA/B/CSyncChange纯函数动作分类。

接口要求:

  • classifyChange 必须无副作用,便于 golden test。
  • runSync 必须支持限定 source 运行。
  • 所有写入通过 WorkspaceStore 完成。
  • SourceReader 输出必须先转换为 common path/hash,不向下游泄漏 adapter 私有结构。

12. 状态与持久化

文件owner写入时机说明
state/source-lock.jsonSyncEngine成功同步后source 基线。
state/source-changes.jsonSyncEngine每次同步运行最近一次同步报告。
publish/**SyncEngine 通过 WorkspaceStore 候选写入Sync PR 分支正式内容候选变更。

如果 ReviewBridge 创建 PR 失败,SourceChanges 仍应保留足够信息供人工恢复。

13. 错误处理

错误码retryable场景处理
sync.source_unavailabletruesource repo/ref 暂不可访问该 source 失败,不更新 lock。
sync.source_ref_not_foundfalsesource ref 不存在阻断该 source。
sync.conflict_detectedfalseA/B/C 同时变化或目标已存在不写冲突文件,进入报告。
sync.delete_conflictfalse来源删除但目标被改动不删除,进入报告。
sync.lock_update_failedtruelock 写入失败不标记同步成功。
sync.partial_source_failedtruesource 部分文件失败report partial,PR 标记 partial。
workspace.conflictfalseWorkspaceStore expected hash 不匹配重新读取或人工处理。
config.invalid_schemafalsesource config 非法阻断 run。

错误报告必须包含 sourceId、sourcePath、publishPath、runId;不包含本地绝对路径或 secret。

14. 幂等与重试

  • 同一 source snapshot、同一 SourceLock、同一 publish 状态必须生成相同 SourceChanges
  • 重试 runSync 不能重复追加相同变更;变更由 sourceId + sourcePath + publishPath + action + hashes 确定。
  • source 不可用时重试不得更新 SourceLock。
  • lock 更新失败时,下一次运行应重新基于旧 lock 计算,不能假设本次成功。
  • 对已经创建的 Sync PR,ReviewBridge 负责 PR 幂等;SyncEngine 只提供稳定 payload。

15. 安全与治理

  • 不允许 source 映射写出 publish/**
  • 不允许一个 source 覆盖另一个 source 的 publish path,配置阶段已阻断,运行时仍需防御。
  • 冲突不自动解决,避免覆盖人工修订。
  • 上游删除默认不删除正式内容。
  • SyncEngine 不调用 AgentBridge,避免“同步失败即自动改写”的隐式行为。

16. 测试要求

测试Fixture预期
add/update/keep/conflictfixtures/common/sync/add-update-keep-conflict.json输出稳定 SourceChanges
source deletefixtures/common/sync/delete-source-page.json默认生成 report delete,不直接删除。
config inputfixtures/common/config/sources.single.valid.yaml正确读取 enabled source。
duplicate publish pathfixtures/common/config/sources.duplicate-publish-path.invalid.yamlConfigManager 阻断,SyncEngine 不运行。
hash normalizationfixtures/common/hash/markdown-lf.mdmarkdown-crlf.md等价内容不产生虚假变更。
concurrent workspace changefixtures/common/agent/concurrent-change.json返回 conflict,不覆盖。

模块验收标准:

  • classifyChange 有完整 A/B/C 表驱动测试。
  • SourceChanges 输出字段顺序和排序稳定。
  • failed source 不更新 SourceLock。
  • conflict/delete conflict 不写候选内容。
  • dry-run 不产生持久化副作用。

17. 设计决策

决策说明取舍
使用 SourceLock 做三方比较能区分来源更新、人工本地修改和冲突。需要维护 state/source-lock.json。
删除默认 report-only避免上游误删传播到正式知识库。需要人工清理长期废弃内容。
source 级失败不阻断全部 source提高多来源同步可用性。报告和 PR 状态需要表达 partial。
SyncEngine 不创建 PR保持同步计算和 GitHub 治理分离。需要 ReviewBridge 承接 PR 幂等。

18. 待确认问题

  • SourceLock 是否支持文件级部分更新,还是 MVP 坚持 source 级原子更新。
  • 上游 rename 是否在 MVP 视为 delete + add,还是尝试通过相似 hash 识别。
  • 当 source 文件 frontmatter 与 publish 规则冲突时,由 SyncEngine 阻断还是交给 WorkspaceStore/ReviewBridge。
对此页面有疑问?

问答功能将在后续接入 Answer API。当前可通过页面底部的反馈链接提交问题。

页面来源草稿
来源项目kunora-wiki
分支docs-publish
路径technology/components/kunora-wiki/development/modules/sync-engine/README.md