跳到主要内容

路径、Hash 与 ID 规则

# 路径、Hash 与 ID 规则

修订记录

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

1. 文档目标

本文定义 kunora-wiki 自研模块共享的路径规范化、内容 hash、对象 ID、运行 ID、请求 ID、幂等键和去重键规则。

这些规则会被 DocumentRecordSyncChange、manifest、索引、引用回跳、反馈去重和审计日志共同使用。任何模块不得私自定义第二套路径、hash 或 ID 规则。

2. 总体原则

原则约束
稳定同一逻辑对象在不同运行中应得到相同 ID。
可重建ID 和 hash 应尽量能从已有事实源重新计算。
可比较path、hash、documentId 必须能跨模块比较。
不泄密dedupeKey、idempotencyKey 不包含明文敏感信息。
不依赖时间内容 hash、documentId 不依赖文件修改时间。
不依赖外部产品私有 IDRAGFlow、Meilisearch、GitHub 的内部 ID 不能作为 LLM-WIKI 主 ID。

3. 路径类型

路径类型示例Owner说明
repoPathdocs/index.mdSourceReader来源仓库内路径。
sourcePathdocs/**SourceConfig来源配置声明的读取范围。
publishPathpublish/system/components/kunora-kgent/index.mdSourceConfig / WorkspaceStoreLLM-WIKI 工作目录路径。
statePathstate/source-lock.jsonWorkspaceStore状态和 manifest 路径。
siteUrl/system/components/kunora-kgent/DisplayBackend Adapter展示站 URL。
anchor#配置说明DisplayBackend Adapter / Answer API页面内锚点。

4. 路径规范化规则

所有自研模块内部统一使用 NormalizedPath

规则:

  • 使用 UTF-8 字符串。
  • 使用 / 作为路径分隔符。
  • 不允许 Windows 反斜杠 \\ 进入契约对象。
  • 不允许绝对文件系统路径进入契约对象。
  • 不允许 ...、空 segment。
  • 不允许路径末尾 /,除非该字段明确表示 URL 目录。
  • publishPath 必须以 publish/ 开头。
  • statePath 必须以 state/ 开头。
  • 路径比较默认大小写敏感。
  • URL path 和 repository path 是不同类型,不能混用。

非法路径示例:

输入原因
C:\\repo\\publish\\a.md绝对文件系统路径。
publish/../docs/a.md包含 ..
/publish/a.mdrepository contract 中不允许前导 /
publish//a.md空 segment。
publish/a.md/文件路径不允许尾随 /

5. Markdown 内容规范化

内容 hash 计算前必须先规范化 Markdown。

规范化规则:

规则
encodingUTF-8。
line ending统一为 LF。
BOM移除 UTF-8 BOM。
trailing whitespace默认保留,除非后续格式化策略明确修改。
final newline统一确保文件以单个 LF 结尾。
frontmatter order不在 hash 阶段重排;重排属于内容变更。
path separators in links不在 hash 阶段改写;链接规范化属于内容处理。

重要约束:

  • hash 规范化只能消除平台差异,不能改变文档语义。
  • 不允许在 hash 计算中忽略 frontmatter,除非字段明确标记为 runtime-only 并在数据结构文档中定义。
  • 文件修改时间、Git author、提交时间不参与 content hash。

6. Hash 类型

Hash 类型输入格式用途
contentHash规范化后的 Markdown 内容sha256:<hex>判断文档内容是否变化。
sourceHash来源文件规范化内容sha256:<hex>SyncEngine 判断上游变化。
publishHashpublish 文件规范化内容sha256:<hex>SyncEngine 判断工作目录变化。
renderedHash展示构建产物规范化内容sha256:<hex>展示层漂移检测。
configHash规范化配置文件内容或配置 bundle canonical JSONsha256:<hex>配置影响检测。
payloadHashcanonical JSON payloadsha256:<hex>幂等、去重和审计。

Hash 格式规则:

  • 必须使用小写 hex。
  • 必须带算法前缀:sha256:
  • MVP 只允许 sha256
  • 如未来更换算法,必须通过版本化字段或 ADR。

7. Canonical JSON 规则

用于 payloadHashdedupeKeyidempotencyKey 的 JSON 必须先 canonicalize。

规则:

  • object key 按 Unicode code point 升序排序。
  • 不输出多余空格和换行。
  • 字符串使用 JSON 标准 escaping。
  • array 顺序保持原始语义顺序。
  • 忽略值为 null 的可选字段,仅当该字段在契约中声明为 nullable 且 null 有语义时保留。
  • 时间字段必须使用 UTC ISO-8601 格式。

示例:

{"path":"publish/a.md","sourceId":"demo"}

8. documentId

documentId 是索引、引用、manifest 对账的稳定文档 ID。

MVP 规则:

doc:<sha256(normalized publishPath)>

其中 hash 输入为不带前导 /publishPath,例如:

publish/system/components/kunora-kgent/index.md

输出示例:

doc:4f2c...

规则:

  • documentId 不包含 content hash,因此同一路径内容更新时 ID 不变。
  • documentId 不依赖 Docusaurus URL,因此展示层 URL 变化不改变文档身份。
  • documentId 不依赖 RAGFlow 或 Meilisearch 内部 ID。
  • rename/move 在 MVP 中视为旧 documentId 删除、新 documentId 新增。
  • 如未来需要跨路径保留身份,必须引入显式 stableDocumentId,并通过 ADR 修改规则。

9. chunkId

chunkId 用于引用 RAGFlow 或其他索引中的片段。

MVP 规则:

  • LLM-WIKI 不把 chunkId 作为内容事实源。
  • 如果 RAGFlow 返回 chunk ID,Answer API 可以保存为 externalChunkId
  • 标准引用必须至少包含 documentIdpathurlanchor 中的可回跳信息。
  • 如果需要自研 chunk,chunkId 规则另行设计,不能复用 RAGFlow 私有 ID 作为主键。

建议格式:

chunk:<documentId>:<ordinal-or-hash>

但 MVP 不要求自研 chunkId 稳定。

10. runId

runId 表示一次 workflow 或批处理运行。

格式:

run:<kind>:<yyyyMMddTHHmmssZ>:<short-random>

示例:

run:sync:20260429T081530Z:a1b2c3
run:publish:20260429T082000Z:f9e8d7
run:index:20260429T083000Z:012abc

规则:

  • kind 必须来自受控枚举:syncpublishindexansweragentreviewconfig
  • 时间使用 UTC。
  • short-random 至少 6 个 base16 或 base36 字符。
  • runId 用于关联报告、manifest、workflow summary 和日志。
  • 失败重试是否复用 runId 由对应 workflow 决定;同一逻辑发布重试应复用 publishRunId

11. requestId

requestId 表示一次 API 或工具调用。

格式:

req:<yyyyMMddTHHmmssZ>:<random>

示例:

req:20260429T083015Z:8f3a21c4

规则:

  • API 入口收到请求时生成,或接受可信上游传入的 requestId。
  • requestId 必须进入 response audit 字段和服务日志。
  • requestId 不参与业务幂等判断。

12. publishRunId

publishRunId 是一次发布、展示和索引对账的全局 ID。

格式:

pub:<yyyyMMddTHHmmssZ>:<gitShortSha>:<short-random>

示例:

pub:20260429T090000Z:5cad315:a1b2c3

规则:

  • 一个 publishRunId 必须贯穿 publish-impact-reportpublish-manifestsite-manifestindex-manifest 和 workflow summary。
  • 同一 publishRunId 的失败步骤可以重试。
  • 新 publishRunId 不能复用旧 publishRunId 的半完成状态。
  • publishRunId 不等于 Git commit,但必须记录对应 Git commit。

13. taskId

taskId 表示一个文档迭代任务。

格式:

task:<source>:<external-or-hash>

示例:

task:issue:123
task:manual:sha256abcd
task:quality-event:qa-no-answer-001

规则:

  • GitHub Issue 触发的任务优先使用 Issue number。
  • 人工任务使用 canonical payload hash。
  • taskId 必须进入 IterationTaskAgentBridgeReport 和 Release PR body。

14. dedupeKey

dedupeKey 用于合并重复反馈或重复改进任务。

MVP 规则:

dedupe:<eventType>:<sha256(canonical payload)>

推荐 payload 字段:

事件类型payload 字段
qa_no_answereventTypenormalizedQuestionnormalizedScopecitationPaths
qa_low_confidenceeventTypenormalizedQuestionnormalizedScopecitationPaths
search_no_resulteventTypenormalizedQuerynormalizedScope
page_feedbackeventTypepathfeedbackTypenormalizedMessage
source_conflicteventTypesourceIdsourcePathpublishPathbaseHashsourceHashpublishHash

规则:

  • dedupeKey 不应包含 caller id,避免同一问题被不同 caller 重复建 Issue。
  • caller 信息应作为 Issue comment 或 audit event 保留。
  • dedupeKey 不应包含完整原始问题文本,应使用规范化文本或 hash。
  • dedupeKey 命中已有开放 Issue 时,应追加 comment 或计数,不创建新 Issue。

15. idempotencyKey

idempotencyKey 用于防止同一次客户端请求重复执行。

格式:

idem:<callerId>:<sha256(canonical request payload)>

规则:

  • idempotencyKey 可以由客户端提供,也可以由服务端基于请求生成。
  • idempotencyKey 包含 caller 维度,避免不同 caller 的同构请求互相覆盖。
  • idempotencyKey 的生命周期短于 dedupeKey,适合请求级重试。
  • create feedback / create improvement task 必须同时支持 dedupeKey 和 idempotencyKey。

区别:

Key目的作用范围
dedupeKey合并同一知识问题跨 caller、跨请求、较长生命周期
idempotencyKey防止同一请求重试重复执行单 caller、单请求、较短生命周期

16. auditId

auditId 表示一条审计事件。

格式:

audit:<requestId-or-runId>:<ordinal>

示例:

audit:req:20260429T083015Z:8f3a21c4:001

规则:

  • auditId 不作为业务对象 ID。
  • 同一 request/run 下可以有多条 audit event。
  • audit event 必须至少包含 caller、scope、action、result、timestamp。

17. URL 和 anchor 规则

siteUrl 由 DisplayBackend Adapter 生成。

规则:

  • URL 使用站点相对路径,必须以 / 开头。
  • 目录型页面 URL 应以 / 结尾。
  • URL 不能反推 publishPath,必须通过 PageManifest 映射。
  • 引用回跳必须优先使用 manifest 中的 URL。
  • anchor 生成规则必须由展示 adapter 和 Answer API 共享,避免引用失效。

MVP anchor 规则:

  • 若 Docusaurus 能生成 heading anchor,则以 Docusaurus heading anchor 为准。
  • Answer API 不自行猜测复杂 anchor;无法确定时可以返回页面 URL 而不返回 anchor。
  • anchor 失效应成为质量事件,而不是静默忽略。

18. 路径和 ID 的 owner

对象OwnerProducerConsumer
NormalizedPathWorkspaceStoreWorkspaceStore所有模块
contentHashWorkspaceStoreWorkspaceStoreSyncEngine、Display、Index、AgentBridge
sourceHashSyncEngineSyncEngineSyncEngine、ReviewBridge
publishHashWorkspaceStore / SyncEngineWorkspaceStore / SyncEngineSyncEngine、AgentBridge
documentIdWorkspaceStoreWorkspaceStore / Index AdapterDisplay、Index、Answer、Agent Access
siteUrlDisplayBackend AdapterDisplayBackend AdapterAnswer、Agent Access、Docusaurus
runIdworkflow entrypointworkflow entrypoint所有报告和日志
requestIdAPI entrypointAnswer API / Agent Access APIresponse、audit log
publishRunIdpublish workflowpublish workflowDisplay、Index、drift check
dedupeKeyAgent Access APIAnswer API / Agent Access APIIssueTracker
idempotencyKeyAPI entrypointcaller 或服务端write tools

19. 验收用例

用例预期
Windows 路径输入 publish\\a.md规范化为 publish/a.md 或拒绝,契约中不得保留反斜杠。
输入 publish/../a.md拒绝。
同一 Markdown 在 CRLF 和 LF 下计算 hash得到相同 contentHash
文件修改时间变化但内容不变contentHash 不变。
同一路径内容更新documentId 不变,contentHash 变化。
路径 move/renamedocumentId 删除,新 documentId 新增。
同一 publishRunId 重试索引不产生重复索引文档。
同一 no-answer 问题由两个 caller 提交命中同一 dedupeKey,追加反馈,不创建重复 Issue。
同一 caller 重试 create_feedbackidempotencyKey 命中,返回同一结果。
RAGFlow 返回私有 chunk id记录为 externalChunkId,不作为主文档 ID。

20. 后续文档衔接

03-data-structures.md 必须复用本文定义的基础类型:

  • NormalizedPath
  • ContentHash
  • DocumentId
  • RunId
  • RequestId
  • PublishRunId
  • TaskId
  • DedupeKey
  • IdempotencyKey
  • AuditId
  • SiteUrl
  • Anchor

任何数据结构需要新增 ID 或 hash 类型时,必须先更新本文。

对此页面有疑问?

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

页面来源草稿
来源项目kunora-wiki
分支docs-publish
路径technology/components/kunora-wiki/development/common/05-path-hash-and-id.md