跳到主要内容

WorkspaceStore 技术设计

# WorkspaceStore 技术设计

修订记录

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

1. 摘要

WorkspaceStore 是 kunora-wiki 自研系统的受控工作区访问层。它负责 publish/**state/** 的路径规范化、Markdown 内容读取、内容 hash、DocumentRecord 派生、manifest 读写和受控文件写入。

WorkspaceStore 不做同步策略、不创建 PR、不调用外部产品、不判断内容语义正确性。所有上层模块必须通过它获得一致的路径、hash、文档记录和 manifest 视图,避免各模块直接读写文件导致契约漂移。

2. 模块目标

  • publish/**state/** 提供统一读写边界。
  • 生成和校验 NormalizedPathContentHashDocumentId
  • 从 Markdown 文件派生 DocumentRecord
  • 读写 PageManifest 等受控 manifest 文件。
  • 为 SyncEngine、Display Adapter、Index Adapter、Answer API、AgentBridge 提供一致文档视图。
  • 对非法路径、并发冲突、hash 不一致、manifest 损坏输出标准 ErrorObject

3. 非目标

  • 不读取外部 source repo;来源读取由 SourceReader 或 SyncEngine adapter 负责。
  • 不决定上游变更是否应覆盖 publish/**;同步策略属于 SyncEngine。
  • 不创建 GitHub PR、check 或 review comment;治理属于 ReviewBridge。
  • 不调用 Docusaurus、RAGFlow、Meilisearch 或模型服务。
  • 不生成问答结果、不执行 agent policy、不批准 agent 写入。
  • 不把本地绝对路径暴露给公共契约对象。

4. 上下文边界

WorkspaceStore 位于 L0 Common Foundation 层,可被上层模块依赖,但不能依赖上层模块。

5. 输入与输出

5.1 输入

输入来源说明
ConfigBundleConfigManager确定 managed paths、source 映射和运行模式。
publish/** 文件Git 工作区正式文档内容。
state/** 文件Git 工作区或 workflow 产物manifest、lock、changes 等状态文件。
write requestSyncEngine、AgentBridge、Display Adapter受控写入请求,必须带 expected base/hash。
manifest request上层模块读取或写入标准 manifest。

5.2 输出

输出消费者说明
DocumentRecordSyncEngine、Display、Index、Answer、AgentBridge标准文档记录。
PageManifestDisplay、Index、Answer、Agent Access、AgentBridge页面级 manifest。
ContentHashSyncEngine、Index、Display、AgentBridge内容变化判断。
NormalizedPath全部路径消费者统一路径表示。
ErrorObject调用方、ReviewBridge、CI路径、读写、hash、manifest 错误。

6. 依赖的 common 契约

契约用途
NormalizedPath所有 repo path、publish path、state path 输入输出。
ContentHashMarkdown 内容 hash、manifest 对账。
DocumentId基于 publishPath 派生稳定文档身份。
DocumentRecord文档视图输出。
PageManifest页面 manifest 读写。
PublishManifest / SiteManifest / IndexManifest只读或校验下游 manifest。
SourceLock / SourceChanges受控 state 文件读写支持。
ErrorObject标准错误输出。

7. 受控目录

目录权限说明
publish/**读;受控写正式文档工作区。
state/**读;受控写manifest、lock、changes、派生状态。
config/**默认只读禁止ConfigManager owner,WorkspaceStore 不应写。
外部仓库目录禁止来源读取由 SourceReader/SyncEngine 负责。
构建产物目录默认只读或禁止不作为正式内容事实源。

受控写入必须由上层模块明确传入目标路径、内容、expected hash 或 expected revision。WorkspaceStore 不能主动决定写入内容。

8. 核心流程

8.1 文档扫描流程

扫描规则:

  • 只扫描 publish/** 管理范围。
  • 默认只处理 Markdown 文件。
  • 路径排序必须稳定。
  • 读取失败不得静默跳过,必须返回 partial result 或阻断错误,由调用方决定。
  • DocumentRecord 不包含本地绝对路径。

8.2 受控写入流程

写入规则:

  • 不接受绝对路径或包含 .. 的路径。
  • 不允许写入 config/**
  • publish/** 必须带 expected hash,除非是明确 create 操作。
  • 删除必须带 expected hash 或 expected document id。
  • 写入后必须重新计算 hash,不信任调用方传入的 hash。

8.3 Manifest 写入流程

Manifest 写入采用 canonical JSON:

  1. 校验 manifest schema。
  2. 校验路径、hash、documentId 引用存在或符合允许缺失规则。
  3. 按稳定字段顺序序列化。
  4. 写入 state/** 目标路径。
  5. 重新读取并校验可解析。

9. 接口设计

本文只定义语义,不绑定具体语言。

接口输入输出说明
normalizePathraw path、path kindNormalizedPath 或错误统一路径规则。
readMarkdownpublishPathnormalized content、contentHash读取并规范化 Markdown。
writeMarkdownpublishPath、content、expectedHashDocumentRecord 或错误受控写入。
deleteMarkdownpublishPath、expectedHashdelete result 或错误受控删除。
listDocumentsscope/filterDocumentRecord[]扫描 publish 文档。
getDocumentpublishPath/documentIdDocumentRecord 或 none单文档读取。
buildPageManifestrecords、site mappingPageManifest派生页面 manifest。
readManifestmanifest kind/pathtyped manifest 或错误读取 state manifest。
writeManifestmanifest kind、payloadwrite result 或错误写 canonical manifest。
computeContentHashmarkdown contentContentHash复用 common hash 规则。

接口要求:

  • 所有接口返回公共类型,不返回本地文件系统对象。
  • 所有写接口必须支持 dry-run。
  • 所有写接口必须可审计:调用方应能记录 request/run id、path、old hash、new hash。
  • 读接口不得隐式修复文件内容。

10. DocumentRecord 派生规则

字段派生来源
documentIddoc:<sha256(normalized publishPath)>
publishPath规范化后的 publish/** 路径。
contentHash规范化 Markdown 内容 hash。
titlefrontmatter title 优先,其次第一个 H1。
frontmatterMarkdown frontmatter 解析结果。
sourceIdsource 映射或 frontmatter/source metadata。
sourcePathsource metadata;没有则为空。
sourceRefsource metadata;没有则为空。
siteUrl可由 Display Adapter 或 site mapping 补齐。
qualityStatusfrontmatter 或 page manifest;默认 unknown
qaVisiblequalityStatus 和配置策略共同决定,默认 false 或由上层声明。

WorkspaceStore 可以提取元数据,但不能判断内容质量是否合格。

11. 冲突与幂等

11.1 冲突类型

冲突场景错误码
hash conflictexpected hash 与当前内容 hash 不一致workspace.conflict
path conflict目标路径非法或与目录/文件类型冲突workspace.path_conflict
manifest conflictmanifest 引用不存在或 hash 不一致workspace.manifest_conflict
delete conflict删除目标已变化或不存在workspace.conflictworkspace.not_found

11.2 幂等规则

  • 重复写入相同 path、相同 content、相同 expectedHash,应返回相同结果或 safe no-op。
  • 重复删除同一已删除 path,在调用方声明 idempotent delete 时可返回 safe no-op。
  • Manifest 写入相同 canonical payload 不应产生语义变化。
  • WorkspaceStore 不生成业务级 idempotencyKey,但必须让调用方能以 path/hash 判断幂等。

12. 错误处理

错误码retryable场景处理
path.invalidfalse路径不满足 common 规则拒绝读写。
path.traversalfalse路径越界拒绝并审计。
workspace.not_foundfalse文档或 manifest 不存在返回 none 或错误,由接口语义决定。
workspace.read_failedtrue文件读取失败返回错误,不静默跳过。
workspace.write_failedtrue文件写入失败调用方可重试。
workspace.conflictfalseexpected hash/revision 不匹配调用方重新读取或人工解决。
workspace.invalid_markdownfalsefrontmatter 或编码不可解析可返回 partial record 或阻断。
workspace.invalid_manifestfalsemanifest schema 错误拒绝下游消费。

所有错误必须包含 module=WorkspaceStoreoperation、相关 normalized path 和不含本地绝对路径的上下文。

13. 安全约束

  • 禁止路径穿越、绝对路径、Windows 反斜杠进入契约对象。
  • 错误信息不得泄漏本地 workspace 绝对路径。
  • 不允许通过 symlink 跳出受控目录;实现阶段必须校验 real path 在 workspace 内。
  • 不写 config/**,避免绕过配置审查。
  • 不直接处理 secret 或 token。
  • 不把 draft/working 文档暴露为 qaVisible,除非上层 policy 明确允许。

14. 测试要求

WorkspaceStore 必须通过 common fixture 中的路径、hash、工作区和 manifest 测试。

测试Fixture预期
valid publish pathsfixtures/common/path/valid-publish-paths.json全部生成合法 NormalizedPath
invalid pathsfixtures/common/path/invalid-paths.json拒绝绝对路径、..、空 segment。
markdown LF/CRLFfixtures/common/hash/markdown-lf.mdmarkdown-crlf.md等价内容 hash 一致。
document id stablefixtures/common/id/document-id-stable.json同一路径内容变化时 documentId 不变。
document record validfixtures/common/workspace/document-record.valid.json字段完整且可被 schema 接受。
missing hash invalidfixtures/common/workspace/document-record-missing-hash.invalid.jsonschema contract 拒绝。
manifest validfixtures/common/manifest/publish-manifest.valid.jsoncanonical JSON 稳定。
concurrent changefixtures/common/agent/concurrent-change.jsonexpected hash 不匹配时返回冲突。

模块验收标准:

  • 所有路径入口都经过 normalizePath
  • 所有 Markdown hash 使用 common 规范化规则。
  • 写入冲突有 deterministic error,不覆盖当前内容。
  • Manifest 写入可 round-trip 读取并通过 schema。
  • 测试中不依赖文件修改时间判断内容变化。

15. 设计决策

决策说明取舍
WorkspaceStore 作为唯一受控文件访问层避免各模块直接读写导致路径/hash 不一致。上层模块需要通过接口表达写入意图。
documentId 基于 publish path保持可重建且不依赖外部产品。rename/move 在 MVP 中视为删除加新增。
写入必须校验 expected hash防止 agent 或同步任务覆盖人工变更。create 场景需要显式区分。
Manifest 使用 canonical JSON降低无意义 diff 和 golden test 波动。人工编辑可读性略低于格式自由 JSON。

16. 待确认问题

  • PageManifest 的 owner 是否由 WorkspaceStore 独立承担,还是与 Display Adapter 共同维护。
  • qaVisible 的默认值应为 false,还是由 qualityStatus 自动推导。
  • 是否需要在 MVP 引入 stableDocumentId 支持跨路径 rename identity。
  • Markdown frontmatter 解析失败时,是阻断整次扫描还是返回 partial result。
对此页面有疑问?

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

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