# https://github.com/BatterWorks/Hatchdoor 项目说明书

生成时间：2026-07-27 20:13:51 UTC

## 目录

- [项目概览](#page-overview)
- [Lib 模块](#page-frontend-src-lib)
- [Api 模块](#page-frontend-src-api)
- [App 模块](#page-frontend-src-app)

<a id='page-overview'></a>

## 项目概览

### 相关页面

相关主题：[Lib 模块](#page-frontend-src-lib)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/BatterWorks/Hatchdoor/blob/main/README.md)
- [Dockerfile](https://github.com/BatterWorks/Hatchdoor/blob/main/Dockerfile)
- [frontend/package.json](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/package.json)
- [frontend/README.md](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/README.md)
- [eval/README.md](https://github.com/BatterWorks/Hatchdoor/blob/main/eval/README.md)
- [docker-compose.yml](https://github.com/BatterWorks/Hatchdoor/blob/main/docker-compose.yml)
- [Cargo.toml](https://github.com/BatterWorks/Hatchdoor/blob/main/Cargo.toml)
- [CHANGELOG.md](https://github.com/BatterWorks/Hatchdoor/blob/main/CHANGELOG.md)
</details>

# 项目概览

Hatchdoor 是一个**自托管、以 Web 为先**的 Obsidian Vault 阅读与编辑平台。它将一个 Markdown 知识库（Vault）以响应式 PWA 前端的方式呈现在浏览器中，同时通过 Rust 后端提供本地 API、缓存、嵌入（embedding）以及 MCP（Model Context Protocol）集成，使外部 LLM 代理能够以语义检索与结构化读写的方式访问 Vault。

## 1. 项目定位与核心能力

Hatchdoor 在 v1.0.0 首次发布时被定位为「Rust 后端 + PWA 前端的自托管 Obsidian Vault 阅读器」，随后逐步演进为兼具**阅读、写入、搜索与代理接口**的完整知识库网关。其核心能力包括：

- **Vault 浏览与渲染**：支持 Obsidian 风格的 Wikilink、双链解析以及 Markdown 笔记的浏览器内渲染。
  资料来源：[README.md:1-60]()
- **写入模式（Write Mode，自 v2.2.0 起）**：通过 Web UI 与 MCP 工具完成笔记的创建、更新、追加、移动、重命名与删除；同时提供附件的导入、移动、重命名与删除。
  资料来源：[CHANGELOG.md:1-40]()
- **混合检索**：结合关键词与基于 Nomic Embed Text v1.5 的语义分块检索，向 MCP 客户端暴露结构化搜索结果。
  资料来源：[CHANGELOG.md:40-80]()
- **附件支持**：通过 `import_attachment` 等 MCP 工具支持图片与文档类附件的入库（v2.4.0 已移除旧的 inbox 暂存路径机制）。
  资料来源：[CHANGELOG.md:80-120]()

## 2. 技术架构

Hatchdoor 的运行时由单一 Rust 可执行进程承担 HTTP 服务、静态前端分发与本地数据管道；前端作为 PWA 由构建产物直接托管在同一进程中。下表概括了主要组件及其职责：

| 组件 | 实现 / 形态 | 主要职责 |
|------|------------|----------|
| 后端服务 | Rust 二进制（`Cargo.toml` 定义） | 监听 HTTP 请求、暴露 `/api/*` 路由、读写 Vault 文件、维护 SQLite 缓存与嵌入索引 |
| 前端应用 | 响应式 PWA（`frontend/package.json` 管理依赖） | 笔记浏览、搜索 UI、Markdown 渲染、移动端适配 |
| 持久化 | SQLite + 文件系统 Vault | v2.0.0 引入持久化缓存层，替代早期内存快照；首次启动或升级后会自动重建缓存 |
| MCP 接入 | 内嵌 MCP 工具集 | 为外部代理提供笔记与附件的读写、检索、Git 同步接口（v2.1.0 起） |
| 嵌入模型 | Nomic Embed Text v1.5（1,024 token 上下文窗口） | 生成分块向量；模型文件通过持久化挂载加载 |

资料来源：[Dockerfile:1-40]() · [Cargo.toml:1-30]() · [frontend/package.json:1-40]() · [CHANGELOG.md:20-100]()

## 3. 版本演进里程碑

Hatchdoor 遵循语义化版本，当前主线已发布至 **v2.4.0**。关键里程碑如下：

- **v1.0.0**：首个稳定版本，Rust + PWA 阅读器，支持 Wikilink 与桌面/移动端浏览。
  资料来源：[CHANGELOG.md:1-20]()
- **v1.1.0 / v1.1.1**：新增 `Download .md` 操作与服务端下载端点 `GET /api/note/{slug}/download`，改善 iOS/PWA 文件落地体验。
  资料来源：[CHANGELOG.md:20-60]()
- **v2.0.0**：引入 MCP 写入工具集（笔记与附件的完整 CRUD）与持久化 SQLite 缓存层。
  资料来源：[CHANGELOG.md:60-80]()
- **v2.1.0 / v2.1.1**：MCP Git 同步、安全审计硬化与 iOS PWA 下载修复。
  资料来源：[CHANGELOG.md:80-100]()
- **v2.2.0**：发布 **写入模式**，将 Web UI 与 MCP 工具升级为可创建/编辑笔记；同时加入只读演示模式。
  资料来源：[CHANGELOG.md:100-120]()
- **v2.3.0**：切换至 Nomic Embed Text v1.5（1,024-token 输入窗口），首次启动触发完整缓存重建。
  资料来源：[CHANGELOG.md:120-140]()
- **v2.4.0**：移除旧的 MCP 附件收件箱暂存系统，引入持久化的 `models` 挂载；要求容器部署同步更新环境变量与绑定卷。
  资料来源：[CHANGELOG.md:140-170]() · [docker-compose.yml:1-40]()

## 4. 部署与运行形态

Hatchdoor 支持两种典型运行方式：

- **容器化部署**（推荐）：通过 `Dockerfile` 构建单一镜像，在 `docker-compose.yml` 中将 Vault 目录、模型目录与缓存目录作为持久化卷挂载。v2.4.0 起，`models` 挂载成为必需项，旧的 `HATCHDOOR_MCP_ATTACHMENT_STAGING_PATH` 环境变量相关机制已被移除。
  资料来源：[Dockerfile:1-60]() · [docker-compose.yml:1-40]()
- **本地开发**：Rust 工作区在仓库根目录提供后端源码；`frontend/README.md` 中给出前端开发服务器与构建指令，`eval/README.md` 提供评估脚本与基准说明。
  资料来源：[frontend/README.md:1-30]() · [eval/README.md:1-30]() · [Cargo.toml:1-30]()

社区中仍有若干公开讨论与改进提案值得关注，包括**Vault 文件/目录排除规则**（#22）、**事件钩子系统**（#23）、**Open Knowledge Format (OKF) v0.1 校验**（#26）、**MCP 搜索暴露 frontmatter/标签元数据**（#19）以及**附件内联导入而非仅暂存文件名**（#32）。这些提案勾勒了 Hatchdoor 在 Vault 治理、代理可观测性与生态互操作方向的下一步演进空间。
资料来源：[README.md:1-60]() · [CHANGELOG.md:1-170]()

---

<a id='page-frontend-src-lib'></a>

## Lib 模块

### 相关页面

相关主题：[项目概览](#page-overview), [Api 模块](#page-frontend-src-api)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [frontend/src/lib/clipboard.test.ts](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/src/lib/clipboard.test.ts)
- [frontend/src/lib/clipboard.ts](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/src/lib/clipboard.ts)
- [frontend/src/lib/folderPaths.test.ts](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/src/lib/folderPaths.test.ts)
- [frontend/src/lib/folderPaths.ts](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/src/lib/folderPaths.ts)
- [frontend/src/lib/imageUpload.test.ts](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/src/lib/imageUpload.test.ts)
- [frontend/src/lib/imageUpload.ts](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/src/lib/imageUpload.ts)
</details>

# Lib 模块

## 模块定位与作用

`frontend/src/lib/` 是 Hatchdoor 前端工程中存放**与 UI 框架无关的纯工具函数**（utility helpers）的目录。该目录下的代码被设计为可独立测试、可在多个组件/页面中复用的最小功能单元，向上服务于组件层（`components/`）和页面层（`pages/`），向下不依赖任何特定的 React/Vue 等视图库，便于在不同视图层之间迁移或单独在 Node 环境中运行测试。

该目录遵循"单一职责 + 配对测试"的组织约定：每个工具模块都有一个同名 `.test.ts` 文件用于 Vitest/Jest 等单元测试，确保核心逻辑（路径处理、剪贴板读写、上传参数构造等）在重构时仍保持行为一致。`v1.1.1` 发布说明中提到的"将仓库路径辅助函数的再导出门控到测试中，以消除运行时警告"也表明 `lib/` 中的纯函数被刻意限制为只在测试或受控上下文中暴露，避免污染生产 bundle。

资料来源：[frontend/src/lib/clipboard.ts]()、[frontend/src/lib/folderPaths.ts]()

## 核心工具模块

### 剪贴板工具（clipboard）

`clipboard.ts` 封装了浏览器剪贴板 API 的异步读写操作，对外暴露简化的 `copy`/`paste` 风格的函数。该模块主要解决两个常见前端痛点：

- 在不同浏览器对 `navigator.clipboard.writeText`/`readText` 的支持差异下提供降级路径；
- 把"复制成功/失败"事件从组件中抽离，便于在通知系统、动作菜单等场景统一处理。

其配对测试文件 `clipboard.test.ts` 通过对 happy path 与异常分支（如权限被拒绝、空字符串、非文本 MIME）进行覆盖，确保上层 UI 不会因剪贴板 API 的细微差异出现闪烁或未捕获异常。资料来源：[frontend/src/lib/clipboard.test.ts]()、[frontend/src/lib/clipboard.ts]()

### 文件夹路径工具（folderPaths）

`folderPaths.ts` 提供与 Obsidian vault 目录结构相关的纯函数，典型职责包括：

- 在"以 `/` 分隔的 vault 相对路径"与"前端展示用的层级数组"之间相互转换；
- 处理 slug、目录前缀规范化，以及空段、相对段（`.`/`..`）等边界情况；
- 为浏览视图、面包屑、搜索过滤等场景提供统一的路径表示。

由于该模块只处理字符串而不接触文件系统，可以被安全地用于 SSR、客户端路由以及单元测试中。`folderPaths.test.ts` 用大量路径样本锁定其行为，避免在 `v2.0.0` 引入的"SQLite 持久化缓存"或后续写模式中对路径规则做隐式修改时引入回归。资料来源：[frontend/src/lib/folderPaths.test.ts]()、[frontend/src/lib/folderPaths.ts]()

### 图片上传工具（imageUpload）

`imageUpload.ts` 是与社区讨论高度相关的模块：Issue #7「Improve attachment UX」要求支持拖拽与 `+` 按钮上传附件（PDF/图片），而该 issue 在最新进展中已明确"后端就绪、前端成为主要工作"。`imageUpload.ts` 因此承担了把 `File`/`Blob` 转换为可上传载荷的工作，包括：

- 校验 MIME 类型是否落在后端允许列表（png/jpg/jpeg/gif/webp/avif 等）中；
- 生成客户端可读的预览对象 URL；
- 构造与 Hatchdoor 后端写入 API 对齐的 multipart/form-data 请求体。

配对的 `imageUpload.test.ts` 在浏览器 API 不可用的 Node 测试环境下，使用注入的 fake `File` 工厂来验证参数构造逻辑，使前端上传策略可以独立于 UI 迭代。资料来源：[frontend/src/lib/imageUpload.test.ts]()、[frontend/src/lib/imageUpload.ts]()

## 模块协作关系

| 调用方 | 典型使用的 `lib/` 模块 | 触发场景 |
| --- | --- | --- |
| 笔记动作菜单（Download `.md` 等） | `clipboard`、`folderPaths` | 复制 wikilink、下载路径归一化 |
| 附件/图片上传面板 | `imageUpload` | 拖拽或点击 `+` 后预处理文件 |
| Vault 浏览器、面包屑 | `folderPaths` | 路径分段、回溯上级目录 |
| 搜索结果渲染 | `clipboard`、`folderPaths` | 命中片段复制、跳转路径构造 |

资料来源：[frontend/src/lib/clipboard.ts]()、[frontend/src/lib/folderPaths.ts]()、[frontend/src/lib/imageUpload.ts]()

## 设计原则与演进

`lib/` 模块整体遵循三项原则：

1. **纯函数优先**：避免在工具层持有可变全局状态，使缓存（`v2.0.0` 引入的 SQLite 层）成为唯一的"可变真相源"，前端只做派生计算。
2. **测试与实现一一对应**：每个 `.ts` 都伴随同名 `.test.ts`，覆盖率达到行为锁定的程度，符合 `v1.1.1` 强调的"测试覆盖、构建可靠性"目标。
3. **紧贴社区需求**：随着 `v2.2.0` 的写模式、`v2.4.0` 的附件摄取重构等演进，`imageUpload.ts` 等模块会被持续调整以匹配新的后端契约，而纯函数边界让这类调整局部化、可回滚。

资料来源：[frontend/src/lib/clipboard.test.ts]()、[frontend/src/lib/folderPaths.test.ts]()、[frontend/src/lib/imageUpload.test.ts]()

---

<a id='page-frontend-src-api'></a>

## Api 模块

### 相关页面

相关主题：[Lib 模块](#page-frontend-src-lib), [App 模块](#page-frontend-src-app)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [frontend/src/api/api.test.ts](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/src/api/api.test.ts)
- [frontend/src/api/api.ts](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/src/api/api.ts)
- [frontend/src/api/apiError.test.ts](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/src/api/apiError.test.ts)
- [frontend/src/api/apiError.ts](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/src/api/apiError.ts)
- [frontend/src/api/writeApi.test.ts](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/src/api/writeApi.test.ts)
- [frontend/src/api/writeApi.ts](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/src/api/writeApi.ts)
</details>

# Api 模块

## 模块概览

`frontend/src/api/` 目录是 Hatchdoor 前端与 Rust 后端之间的 HTTP 通信层。该模块封装了全部面向 Web UI 的 REST 调用，提供强类型的请求/响应模型，并在统一的错误处理模式下进行异常传播，使上层 React 组件可以以同步函数的方式使用异步 API。

模块由三个核心文件组成，按职责拆分如下：

| 文件 | 职责 |
| --- | --- |
| `frontend/src/api/api.ts` | 读取类与浏览类接口（vault 列表、note 详情、搜索、附件下载等） |
| `frontend/src/api/writeApi.ts` | 写入类接口（创建、更新、追加、移动、重命名、删除 note 与附件） |
| `frontend/src/api/apiError.ts` | 统一错误类型与 `fromFetch` 解析逻辑 |

配套的 `*.test.ts` 文件提供针对每个接口的单元测试覆盖。

资料来源：[frontend/src/api/api.ts:1-40]() [frontend/src/api/writeApi.ts:1-40]() [frontend/src/api/apiError.ts:1-30]()

## 读取接口（api.ts）

`api.ts` 暴露了 Hatchdoor 全部只读浏览能力，是最早随 v1.0.0 上线的接口集合。其行为与官方发布说明中的功能一致：

- **Vault 浏览**：返回目录树、标签列表与笔记元数据，用于侧边栏与索引视图。
- **Note 详情**：按 slug 拉取单条 Markdown 笔记，包括正文字符串、frontmatter 与 wikilink 解析结果。
- **搜索**：基于关键词 / 语义向量的 chunk 检索；社区中 issue #19 提出希望在搜索响应里暴露结构化 frontmatter 与标签元数据，相关讨论涉及该接口的扩展。
- **附件下载**：从 v1.1.0 起，新增 `GET /api/note/{slug}/download`，把 Markdown 直接通过服务端响应交付，便于移动端原生下载。

`api.ts` 内部使用 `fetch` 并通过 `apiError.fromFetch` 把任何非 2xx 响应转化为抛出异常的错误对象，确保调用方无需自行处理 `Response.ok`。

资料来源：[frontend/src/api/api.ts:40-120]() [frontend/src/api/apiError.ts:30-90]()

## 写入接口（writeApi.ts）

`writeApi.ts` 自 v2.0.0 起加入，对应发布说明中描述的“Write Mode”。它集中提供全部会修改 vault 文件系统的接口：

- 笔记维度：`createNote`、`updateNote`、`appendNote`、`moveNote`、`renameNote`、`deleteNote`。
- 附件维度：`importAttachment`、`moveAttachment`、`renameAttachment`、`deleteAttachment`。
- 提交选项：可选的 Git 同步字段，由 v2.1.0 引入的 MCP git sync 链路使用。

每个写入函数都包含服务端已实现的硬约束镜像：拒绝空内容、空路径、以及越界目录。客户端在拼装请求体时也会预先校验，避免产生注定失败的请求。

针对 issue #32 中讨论的“远端 MCP 客户端无法访问 Hatchdoor 本地 staging 目录”这一痛点，`writeApi.ts` 与 `importAttachment` 配套的请求模型定义了 `staged_filename` 字段；任何仅可在 Hatchdoor 文件系统上取得的附件都需要先落入 `HATCHDOOR_MCP_ATTACHMENT_STAGING_PATH` 后再被导入。

资料来源：[frontend/src/api/writeApi.ts:1-180]() [frontend/src/api/writeApi.test.ts:1-60]()

## 错误模型（apiError.ts）

`apiError.ts` 抽象出统一的错误类型，便于在 React 组件、React Query 与全局 toast 通知之间复用同一种错误传播路径：

- `ApiError`：承载 HTTP 状态码、后端错误码与可读消息。
- `fromFetch(response)`：把 `fetch` 返回的 `Response` 解析为 `ApiError` 或返回原 `Response`；被 `api.ts` 与 `writeApi.ts` 共用。
- `isApiError(value)`：类型守卫，供 `instanceof` 替代方案使用。

错误模型与后端的错误响应结构对齐（JSON 体里通常包含 `code` 与 `message`），因此前端可以针对不同错误码显示不同提示，例如“vault 路径非法”或“附件类型不允许”。

资料来源：[frontend/src/api/apiError.ts:30-110]() [frontend/src/api/apiError.test.ts:1-50]()

## 测试与维护

每个核心文件都配对了一份 `*.test.ts`：

- `api.test.ts` 覆盖读取类接口的请求拼装、URL 编码与响应解析；
- `writeApi.test.ts` 覆盖写入路径上的边界条件（空内容、路径合法性、附件元数据）；
- `apiError.test.ts` 覆盖错误对象在非 2xx 响应、JSON 解析失败等场景下的行为。

测试文件与运行时实现使用相同的请求工厂函数，保证契约在两端一致；当后端调整错误结构时，仅需修改 `apiError.fromFetch` 与对应测试即可全链路生效。

资料来源：[frontend/src/api/api.test.ts:1-40]() [frontend/src/api/writeApi.test.ts:1-60]() [frontend/src/api/apiError.test.ts:1-50]()

## 社区关注点

- Issue #19：希望在搜索响应中暴露 frontmatter / 标签结构化元数据，会影响 `api.ts` 中搜索接口的返回类型。
- Issue #32：`importAttachment` 目前仅支持文件系统 staging，社区希望支持内联内容（base64 或 URL）以便跨主机场景使用。
- Issue #26：OKF v0.1 校验与现有 `api.ts` 的 vault 列举接口相邻，是潜在的扩展点。

这些讨论表明 `Api 模块` 的稳定性是社区采纳的关键：读取与写入 API 的契约变更都需要在三个实现文件与三份测试中同步更新。

---

<a id='page-frontend-src-app'></a>

## App 模块

### 相关页面

相关主题：[Api 模块](#page-frontend-src-api)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [frontend/src/app/AppTopbar.tsx](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/src/app/AppTopbar.tsx)
- [frontend/src/app/ExplorerPane.tsx](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/src/app/ExplorerPane.tsx)
- [frontend/src/app/constants.ts](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/src/app/constants.ts)
- [frontend/src/app/AppMainShell.tsx](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/src/app/AppMainShell.tsx)
- [frontend/src/app/hooks/useVaultNavigation.ts](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/src/app/hooks/useVaultNavigation.ts)
- [frontend/src/app/state/vaultSelectionStore.ts](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/src/app/state/vaultSelectionStore.ts)
- [frontend/src/app/types.ts](https://github.com/BatterWorks/Hatchdoor/blob/main/frontend/src/app/types.ts)
</details>

# App 模块

## 模块定位与职责

`App` 模块是 Hatchdoor 前端单页应用的根级 UI 容器，位于 `frontend/src/app/` 目录下，承载了从仓库加载、目录浏览、笔记查看、搜索到写模式操作的整条交互链路。该模块采用 React 函数组件 + 局部状态存储（Zustand）的结构，对外通过 REST/MCP 接口与 Rust 后端通信，对内组织 `Topbar`、`ExplorerPane`、`NoteView` 等子组件形成桌面与 PWA 共用的主视图壳。资料来源：[frontend/src/app/AppMainShell.tsx:1-80]()

模块的设计目标是：

- 以一个常驻壳层包裹所有路由级别视图，避免每次切换都重新初始化全局监听器（事件、快捷键、缓存）。资料来源：[frontend/src/app/AppMainShell.tsx:42-78]()
- 将仓库（vault）的导航状态集中到 `vaultSelectionStore`，使侧边栏、面包屑、笔记视图能够共享同一份"当前选中笔记 / 路径"快照。资料来源：[frontend/src/app/state/vaultSelectionStore.ts:1-60]()
- 通过 `useVaultNavigation` 钩子封装键盘导航与历史记录回退，使顶层组件不必关心 DOM 焦点细节。资料来源：[frontend/src/app/hooks/useVaultNavigation.ts:12-58]()

## 主要组件层级

`App` 模块的视图树可以抽象为三栏壳层加顶部条形区域，常量定义集中于 `constants.ts`，包含布局尺寸、断点与存储键名等。资料来源：[frontend/src/app/constants.ts:1-45]()

| 区域 | 主要组件 | 主要职责 |
| --- | --- | --- |
| 顶部 | `AppTopbar` | 搜索框、模式切换、写模式工具栏 |
| 左侧 | `ExplorerPane` | 文件树、附件入口、目录过滤 |
| 中央 | `NoteView`（在壳层内挂载） | Markdown 渲染、双链解析、批注 |
| 共享 | `vaultSelectionStore` | 选中项、面包屑、焦点索引 |

`AppTopbar` 通过读取 `vaultSelectionStore` 中的 `currentSlug` 渲染上下文相关动作，并暴露搜索输入；它同时负责触发 `useVaultNavigation` 提供的快捷键（`j/k`/`Enter`/`Esc`）绑定。资料来源：[frontend/src/app/AppTopbar.tsx:30-120]()

`ExplorerPane` 接收来自 Rust 后端的目录快照，使用 `types.ts` 中定义的 `VaultNode`/`VaultLeaf` 类型渲染可折叠树，并通过 store 的 `selectPath` 方法与中央视图同步。资料来源：[frontend/src/app/ExplorerPane.tsx:18-96]() `ExplorerPane` 还承担附件与图像缩略区的入口占位，对应社区中关于"改进附件 UX"的诉求（Issue #7）。资料来源：[frontend/src/app/ExplorerPane.tsx:100-145]()

## 状态流与数据流

模块内部以 Zustand store 作为单一可信来源，组件通过订阅对应切片避免整树重渲染。下列时序图展示了从用户点击树节点到 Markdown 渲染完成的关键路径：

```mermaid
sequenceDiagram
    participant U as 用户
    participant EP as ExplorerPane
    participant ST as vaultSelectionStore
    participant NV as NoteView
    participant API as 后端 API
    U->>EP: 点击文件节点
    EP->>ST: selectPath(slug)
    ST-->>NV: 触发 currentSlug 变化
    NV->>API: GET /api/note/{slug}
    API-->>NV: 返回 markdown + 元数据
    NV-->>U: 渲染并高亮命中
```

`useVaultNavigation` 在挂载时订阅 `keydown` 事件，识别方向键后调用 `selectPath` 的相邻条目，保持与点击行为一致的状态写入。资料来源：[frontend/src/app/hooks/useVaultNavigation.ts:30-72]() 类型契约由 `types.ts` 中的 `VaultSelection`、`NavDirection` 等统一约束，避免散落的字符串字面量。资料来源：[frontend/src/app/types.ts:1-50]()

## 与写模式及 MCP 的衔接

自 v2.2.0 引入写模式后，`App` 模块成为写操作的视觉中枢：保存、删除、重命名等动作在 `AppTopbar` 中以受控按钮呈现，按钮的可用性由 `vaultSelectionStore` 派生。资料来源：[frontend/src/app/AppTopbar.tsx:122-180]() 写操作最终通过 MCP 工具（`create_note`、`update_note`、`delete_note` 等）落库，对应后端的 `/api/mcp` 端点；前端并不直接耦合 MCP 协议，而是经由统一的请求封装调用。资料来源：[frontend/src/app/constants.ts:46-90]()

针对社区提出的"在 MCP 搜索中暴露结构化 frontmatter/标签元数据"（Issue #19），`App` 模块在 `ExplorerPane` 与搜索结果面板共用同一份 `VaultNode` 派生类型，便于未来在不改壳层的前提下透出元数据字段。资料来源：[frontend/src/app/ExplorerPane.tsx:147-180]() 此外，`constants.ts` 中定义的存储键（如最近访问草稿、上次选中目录）会被写模式下的冲突检测复用，从而在并发编辑场景给出提示。资料来源：[frontend/src/app/constants.ts:20-44]()

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Doramagic 踩坑日志

项目：BatterWorks/Hatchdoor

摘要：发现 16 个潜在踩坑项，其中 3 个为 high/blocking；最高优先级：安装坑 - 来源证据：Improvement: configurable event hooks for vault changes。

## 1. 安装坑 · 来源证据：Improvement: configurable event hooks for vault changes

- 严重度：high
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：Improvement: configurable event hooks for vault changes
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/BatterWorks/Hatchdoor/issues/23 | 来源类型 github_issue 暴露的待验证使用条件。

## 2. 配置坑 · 来源证据：Add Open Knowledge Format (OKF) v0.1 validation for Markdown vaults

- 严重度：high
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个配置相关的待验证问题：Add Open Knowledge Format (OKF) v0.1 validation for Markdown vaults
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/BatterWorks/Hatchdoor/issues/26 | 来源类型 github_issue 暴露的待验证使用条件。

## 3. 能力坑 · 能力证据存在缺口

- 严重度：high
- 证据强度：source_linked
- 发现：Sandbox install result is missing.
- 对用户的影响：缺口未补前，Doramagic 不能把该能力当作可靠推荐卖点。
- 证据：evidence.evidence_gaps | https://github.com/BatterWorks/Hatchdoor | Sandbox install result is missing.

## 4. 安装坑 · 依赖 Docker 环境

- 严重度：medium
- 证据强度：runtime_trace
- 发现：安装/运行入口包含 Docker 命令：docker compose up -d
- 对用户的影响：非工程用户可能没有 Docker，启动成本明显增加。
- 复现命令：`docker compose up -d`
- 证据：identity.distribution | https://github.com/BatterWorks/Hatchdoor | docker compose up -d

## 5. 安装坑 · 安装命令尚未沙箱验证

- 严重度：medium
- 证据强度：runtime_trace
- 发现：当前 install_status=documented，还只是文档/元数据线索。
- 对用户的影响：命令可能缺步骤、过期或依赖本地环境，不能直接作为用户承诺。
- 复现命令：`docker compose up -d`
- 证据：downstream_validation.install_status | https://github.com/BatterWorks/Hatchdoor | install_status=documented; command=docker compose up -d

## 6. 配置坑 · 可能修改宿主 AI 配置

- 严重度：medium
- 证据强度：source_linked
- 发现：项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主，或安装命令涉及用户配置目录。
- 对用户的影响：安装可能改变本机 AI 工具行为，用户需要知道写入位置和回滚方法。
- 证据：capability.host_targets | https://github.com/BatterWorks/Hatchdoor | host_targets=mcp_host, claude_code, claude, cursor

## 7. 配置坑 · 来源证据：[Feature Request] Expose structured frontmatter/tag metadata in MCP search

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个配置相关的待验证问题：[Feature Request] Expose structured frontmatter/tag metadata in MCP search
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/BatterWorks/Hatchdoor/issues/19 | 来源类型 github_issue 暴露的待验证使用条件。

## 8. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 证据：capability.assumptions | https://github.com/BatterWorks/Hatchdoor | README/documentation is current enough for a first validation pass.

## 9. 运行坑 · Quick Start 尚未实际跑通

- 严重度：medium
- 证据强度：source_linked
- 发现：quickstart_status=not_attempted。
- 对用户的影响：用户只能看到安装线索，不能确信 10 分钟内能形成最小可试路径。
- 证据：downstream_validation.quickstart_status | https://github.com/BatterWorks/Hatchdoor | quickstart_status=not_attempted; sandbox_quickstart_status=missing

## 10. 运行坑 · 来源证据：MCP: support attachment import via inline content, not just filesystem staging

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个运行相关的待验证问题：MCP: support attachment import via inline content, not just filesystem staging
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/BatterWorks/Hatchdoor/issues/32 | 来源类型 github_issue 暴露的待验证使用条件。

## 11. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 证据：evidence.maintainer_signals | https://github.com/BatterWorks/Hatchdoor | last_activity_observed missing

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 证据：downstream_validation.risk_items | https://github.com/BatterWorks/Hatchdoor | no_demo; severity=medium

## 13. 安全/权限坑 · 存在安全注意事项

- 严重度：medium
- 证据强度：source_linked
- 发现：No sandbox install has been executed yet; downstream must verify before user use.
- 对用户的影响：用户安装前需要知道权限边界和敏感操作。
- 证据：risks.safety_notes | https://github.com/BatterWorks/Hatchdoor | No sandbox install has been executed yet; downstream must verify before user use.

## 14. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 证据：risks.scoring_risks | https://github.com/BatterWorks/Hatchdoor | no_demo; severity=medium

## 15. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 证据：evidence.maintainer_signals | https://github.com/BatterWorks/Hatchdoor | issue_or_pr_quality=unknown

## 16. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 证据：evidence.maintainer_signals | https://github.com/BatterWorks/Hatchdoor | release_recency=unknown

<!-- canonical_name: BatterWorks/Hatchdoor; human_manual_source: deepwiki_human_wiki -->
