docs: add P5 workflow and knowledge MVP design spec for v0.6.0

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-06 22:34:40 +08:00
parent 5d3e264cf3
commit a02a665b0f
@@ -0,0 +1,454 @@
# 笔临 P5 作家工作流 + 知识库 MVP 设计规格
**版本**1.0
**日期**2026-07-06
**范围**:P5 — 驾驶舱 + 更新计划/存稿 + 章间衔接 + 知识库 MVP(手动 CRUD / 审核 / 伏笔追踪)
**前置**:P4.1 自动/向导写作已交付(v0.5.0,`5d3e264`
**参考**`design/readme.md` v1.1 §4.3 / §6.7 / §20.1 / §20.4、`design/ui_pc.html` `#dashboardModal` / `#bridgeModal` / `#knowledge`
**目标版本**v0.6.0
---
## 1. 背景与目标
### 1.1 阶段定位
v0.5.0 已交付四种 AI 写作模式;知识库 Tab 仍为占位(仅命名检查入口),顶栏驾驶舱/章间衔接为 `comingSoon`。本阶段交付 **作家日更工作流****知识库 MVP**,对齐 `design/readme.md` §20 作家专项能力,为后续 AI 知识抽取(P5.2+)与 AI 上下文注入(P6)打基础。
### 1.2 已确认决策(Brainstorming 2026-07-06
| 维度 | 决策 |
|------|------|
| 总范围 | **A 作家工作流 + B 知识库 MVP**,统一 v0.6.0 交付(方案 1) |
| 知识库 | **MVP B**`knowledge_entries` 手动 CRUD + 审核流 + 地标 `foreshadow` 同步;**不做** AI 自动抽取 |
| 驾驶舱 | **MVP B**:现有字数聚合 + `publish_status` 存稿缓冲 + 快速入口;**不含** `writing_logs` / 热力图 / 预计完本 |
| 章间衔接 | **B**:上一章末 + 本章开头文本;LM Studio 可用时追加 AI 建议;离线降级纯文本 |
| 架构 | schema **v6**`CockpitService` / `KnowledgeService` / `ChapterBridgeService` 分层 |
| 首次打开书籍 | 展示驾驶舱一次;日常打开恢复上次编辑位(§4.3) |
| AI 后端 | 衔接建议走现有 `AiClientService`(LM Studio);集成测试禁止 Mock |
| 测试超时 | 衔接 AI 集成 **240s**E2E 含 AI **300s** |
### 1.3 验收标准
用户能完成:
1. 顶栏打开**驾驶舱**,查看全书/本卷字数、存稿缓冲、伏笔摘要(已埋/已回收/疑似遗忘)
2. 在设置中配置**更新频率**与**存稿阈值**;章节列表修改 `publish_status`(草稿/待发布/已发布);存稿不足时状态栏软性提醒
3. 新章字数 < 200 时自动弹出**章间衔接**卡片(可「本章不再提示」);或从驾驶舱手动触发;LM Studio 可用时看到 AI 衔接建议
4. 在**知识库**手动新建/编辑条目,在「待审核」Tab 采纳或拒绝;伏笔类型可标记状态;从地标创建 `foreshadow` 时可同步为待审核条目
5. 驾驶舱「处理遗忘伏笔」跳转知识库并筛选疑似遗忘项;命名一致性检查入口保留
### 1.4 本规格不实现(明确排除)
| 项 | 归属 |
|----|------|
| AI 每章自动知识抽取(§6.7 全自动) | P5.2+ |
| 知识条目注入 AI 写作上下文 | P6 |
| `writing_logs`、365 天热力图、预计完本、番茄钟(§8) | P5.2 / §8 |
| 角色弧线简报、Cytoscape 关系图谱(§7 / §20.3 | P6+ |
| 导入导出、平台投稿预设(§11 / §20.2) | P7 |
| 书籍设置面板「文风控制」(ui 原型占位) | 后续 |
---
## 2. 架构
### 2.1 进程模型
```
┌─────────────────────────────────────────────────────────────┐
│ 主进程(schema v6
│ · KnowledgeRepository / KnowledgeService │
│ · CockpitService(只读聚合) │
│ · ChapterBridgeService(文本提取 + 可选 AiClient
│ · ChapterRepository 扩展 publish_status 读写 │
│ · GlobalSettings 扩展 updateSchedule / stockBufferThreshold │
│ · book_preferencescockpitSeen、bridge 免打扰) │
└───────────────────────────┬─────────────────────────────────┘
│ IPC
┌───────────────────────────▼─────────────────────────────────┐
│ 渲染进程 │
│ · CockpitModal / ChapterBridgeModal │
│ · KnowledgePanel(待审核 | 全部 | 伏笔) │
│ · ChapterList 发布状态 + StatusBar 存稿提醒 │
│ · SettingsPage 更新计划 │
│ · TopBar 驾驶舱按钮(替换 comingSoon
└─────────────────────────────────────────────────────────────┘
```
### 2.2 模块边界
| 模块 | 职责 | 依赖 |
|------|------|------|
| `KnowledgeService` | CRUD、审核、批量操作、伏笔统计、遗忘判定 | `KnowledgeRepository`, `ChapterRepository` |
| `CockpitService` | 聚合字数、存稿数、伏笔摘要、卷占比 | `ChapterRepository`, `KnowledgeService` |
| `ChapterBridgeService` | 提取相邻章片段、生成/缓存 AI 建议 | `ChapterRepository`, `AiClientService` |
| `KnowledgePanel` | 列表 UI、编辑对话框、审核操作 | `useKnowledgeStore` |
| `useKnowledgeStore` | IPC 封装、Tab 筛选状态 | preload `knowledge.*` |
**原则**:驾驶舱只读不写;知识审核后才计入伏笔统计;衔接 AI 失败不阻断文本展示。
---
## 3. 数据模型(schema v6
### 3.1 迁移
- `CURRENT_VERSION = 6`
- 新文件 `schema-v6.sql`
```sql
CREATE TABLE knowledge_entries (
id TEXT PRIMARY KEY,
type TEXT NOT NULL, -- character/foreshadow/location/relationship/fact
title TEXT NOT NULL,
content TEXT NOT NULL DEFAULT '',
importance INTEGER NOT NULL DEFAULT 3, -- 1-5
status TEXT NOT NULL DEFAULT 'pending', -- pending/approved/rejected
foreshadow_status TEXT, -- buried/partial/resolved (type=foreshadow)
source_chapter_id TEXT,
last_mention_chapter_id TEXT,
linked_bookmark_id TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (source_chapter_id) REFERENCES chapters(id) ON DELETE SET NULL,
FOREIGN KEY (last_mention_chapter_id) REFERENCES chapters(id) ON DELETE SET NULL
);
CREATE INDEX idx_knowledge_status ON knowledge_entries(status);
CREATE INDEX idx_knowledge_type ON knowledge_entries(type);
CREATE TABLE book_preferences (
key TEXT PRIMARY KEY,
value TEXT NOT NULL -- JSON
);
CREATE TABLE chapter_bridge_dismiss (
chapter_id TEXT PRIMARY KEY,
dismissed_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (chapter_id) REFERENCES chapters(id) ON DELETE CASCADE
);
```
- v5→v6 迁移测试:`UT-MIG-06`
### 3.2 TypeScript 类型(`src/shared/types.ts`
```typescript
export type KnowledgeType = 'character' | 'foreshadow' | 'location' | 'relationship' | 'fact'
export type KnowledgeStatus = 'pending' | 'approved' | 'rejected'
export type ForeshadowStatus = 'buried' | 'partial' | 'resolved'
export type UpdateSchedule = 'daily' | 'alternate' | 'weekly' | 'none'
export interface KnowledgeEntry { /* 字段与表一致 */ }
export interface CockpitSummary {
totalWords: number
volumeWords: number
stockReadyCount: number
stockThreshold: number
foreshadowBuried: number
foreshadowResolved: number
foreshadowForgotten: number
volumeBreakdown: { volumeId: string; name: string; words: number }[]
}
export interface ChapterBridgeResult {
previousChapterId: string | null
previousTail: string
currentHead: string
aiSuggestion?: string
}
```
### 3.3 GlobalSettings 扩展
```typescript
updateSchedule: UpdateSchedule // default 'none'
stockBufferThreshold: number // default 3
```
`publish_status` 列已在 migrate v2 尝试添加;本阶段确保 `ChapterRepository` 读写并在 UI 暴露。
### 3.4 书籍偏好(`book_preferences`
| key | value | 说明 |
|-----|-------|------|
| `cockpitSeen` | `"true"` | 首次驾驶舱已展示 |
| `openCockpitEveryTime` | `"true"` | 可选:书籍级「每次打开显示驾驶舱」(默认 false,全局可在后续扩展) |
### 3.5 伏笔「疑似遗忘」判定(MVP)
同时满足:
1. `type = 'foreshadow'``status = 'approved'``foreshadow_status = 'buried'`
2.`last_mention_chapter_id ?? source_chapter_id` 对应章节的 `sort_order``mentionOrder`
3. 全书最大 `sort_order``latestOrder`
4. `latestOrder - mentionOrder >= 20` → 计入 `foreshadowForgotten`
用户可在编辑条目时更新 `lastMentionChapterId` 或改为 `resolved` 以清除遗忘标记。
### 3.6 地标同步
创建或编辑 `bookmark.landmarkType = 'foreshadow'` 时,UI 提供 checkbox「同步到知识库」:
- 调用 `knowledge.createFromBookmark(bookmarkId)` → 新建 `pending` 条目,`linked_bookmark_id` 关联,`title` 取自地标 label
---
## 4. IPC 与 Preload
### 4.1 通道(`src/shared/ipc-channels.ts`
```typescript
// knowledge
KNOWLEDGE_LIST: 'knowledge:list'
KNOWLEDGE_CREATE: 'knowledge:create'
KNOWLEDGE_UPDATE: 'knowledge:update'
KNOWLEDGE_DELETE: 'knowledge:delete'
KNOWLEDGE_APPROVE: 'knowledge:approve'
KNOWLEDGE_REJECT: 'knowledge:reject'
KNOWLEDGE_BATCH_APPROVE: 'knowledge:batchApprove'
KNOWLEDGE_CREATE_FROM_BOOKMARK: 'knowledge:createFromBookmark'
KNOWLEDGE_STATS: 'knowledge:foreshadowStats'
// cockpit
COCKPIT_SUMMARY: 'cockpit:summary'
COCKPIT_MARK_SEEN: 'cockpit:markSeen'
COCKPIT_SHOULD_SHOW: 'cockpit:shouldShowOnOpen'
// bridge
BRIDGE_GET: 'bridge:get'
BRIDGE_DISMISS: 'bridge:dismiss'
BRIDGE_SHOULD_PROMPT: 'bridge:shouldPrompt'
// chapter 扩展
CHAPTER_SET_PUBLISH_STATUS: 'chapter:setPublishStatus' // 或合并进现有 update
```
### 4.2 Preload 命名空间
```typescript
knowledge: { list, create, update, delete, approve, reject, batchApprove, createFromBookmark, stats }
cockpit: { getSummary, markSeen, shouldShowOnOpen }
bridge: { get, dismiss, shouldPrompt }
```
---
## 5. 服务层
### 5.1 KnowledgeService
```typescript
list(filter?: { status?: KnowledgeStatus; type?: KnowledgeType; forgottenOnly?: boolean })
create(input: CreateKnowledgeInput): KnowledgeEntry
update(id, patch): KnowledgeEntry
delete(id): void
approve(id) / reject(id) / batchApprove(ids[])
createFromBookmark(bookmarkId): KnowledgeEntry
getForeshadowStats(): { buried, resolved, forgotten }
countPending(): number
```
新建条目默认 `status='pending'`;用户可在对话框勾选「直接采纳」→ `approved`
### 5.2 CockpitService
```typescript
getSummary(bookId, activeVolumeId?): CockpitSummary
shouldShowOnOpen(bookId): boolean // !cockpitSeen
markSeen(bookId): void
```
字数:`stripHtml` 后求和现有 `chapters.content`;不引入 `writing_logs`
### 5.3 ChapterBridgeService
```typescript
shouldPrompt(chapterId): boolean
// 本章字数 < 200 && 存在上一章 && 未 dismiss
getBridge(chapterId, withAi?: boolean): Promise<ChapterBridgeResult>
// previousTail: 上一章 stripHtml 末 300 字
// currentHead: 本章 stripHtml 前 200 字(有则展示)
// withAi && AiClient 可用 → chat 单轮建议(240s timeout
dismiss(chapterId): void
```
**AI Prompt 模板**(简体):
> 你是连载小说编辑。上一章末尾:「{tail}」。本章开头:「{head}」。用 2–3 句话指出衔接是否顺畅,并给出一个开头方向建议。不要续写正文。
失败时返回无 `aiSuggestion`UI 隐藏 AI 区块。
---
## 6. 渲染进程 UI
### 6.1 TopBar
- 驾驶舱按钮(`data-testid="topbar-cockpit"`)打开 `CockpitModal`;移除 `comingSoon`
### 6.2 CockpitModal(对齐 `#dashboardModal`
| data-testid | 元素 |
|-------------|------|
| `cockpit-modal` | 根 overlay |
| `cockpit-total-words` | 全书总字数 |
| `cockpit-volume-words` | 本卷字数 |
| `cockpit-stock-count` | 存稿 ready 数 |
| `cockpit-foreshadow-summary` | 伏笔摘要行 |
| `cockpit-resume-edit` | 回到上次编辑 |
| `cockpit-bridge-check` | 检查章间衔接 |
| `cockpit-forgotten-foreshadow` | 跳转知识库筛选 |
打开书籍时:若 `cockpit.shouldShowOnOpen` → 自动弹出并 `markSeen`
### 6.3 ChapterBridgeModal(对齐 `#bridgeModal`
| data-testid | 元素 |
|-------------|------|
| `bridge-modal` | 根 |
| `bridge-previous-tail` | 上一章末尾 |
| `bridge-current-head` | 本章开头 |
| `bridge-ai-suggestion` | AI 建议(可选) |
| `bridge-dismiss-checkbox` | 本章不再提示 |
| `bridge-start-writing` | 开始写作 |
触发:`EditorLayout``openChapter` 后若 `bridge.shouldPrompt` → 延迟 500ms 弹出(避免与加载冲突)。
### 6.4 KnowledgePanel(替换 placeholder
布局:
1. 工具栏:「新建条目」「命名一致性检查」(保留)
2. 摘要条:伏笔统计(同 cockpit)
3. Tab`待审核` | `全部` | `伏笔`
4. 列表项:类型图标、标题、重要度星、来源章、状态标签
5. 点击 → `KnowledgeEditorDialog`(标题、类型、内容、重要度、伏笔状态、关联章)
| data-testid | 元素 |
|-------------|------|
| `knowledge-panel` | 根 |
| `knowledge-tab-pending` / `-all` / `-foreshadow` | Tab |
| `knowledge-new` | 新建 |
| `knowledge-item-{id}` | 列表项 |
| `knowledge-approve-{id}` | 单条采纳 |
| `knowledge-batch-approve` | 批量采纳待审核 |
### 6.5 章节发布状态
- 章节列表项右键或状态图标循环:`draft``ready``published`
- `data-testid="chapter-publish-{id}"`
### 6.6 StatusBar 存稿提醒
-`stockReadyCount < stockBufferThreshold``updateSchedule !== 'none'` → 显示橙色提示文案(不阻断)
- `data-testid="status-stock-warning"`
### 6.7 SettingsPage
- 更新频率下拉:`updateSchedule`
- 存稿阈值数字输入:`stockBufferThreshold`120,默认 3
### 6.8 i18n
新增键:`cockpit.*``bridge.*``knowledge.*``publish.status.*``settings.updateSchedule.*``stock.warning`
---
## 7. 错误处理
| 场景 | 行为 |
|------|------|
| 无上一章时 bridge | `shouldPrompt=false`;手动打开显示「无上一章」 |
| AI 建议超时/失败 | 仅展示文本片段;toast 可选「AI 建议不可用」 |
| 删除已关联 bookmark 的 knowledge | 保留条目,`linked_bookmark_id` 置 null |
| 空知识库 cockpit 伏笔 | 显示 0,不报错 |
| publish 更新失败 | IPC 错误 toast |
---
## 8. 测试
### 8.1 单元 / 集成(Vitest
| ID | 场景 | AI |
|----|------|-----|
| UT-MIG-06 | v5→v6`knowledge_entries` 存在 | — |
| UT-KNOW-01 | CRUD + approve 后 status 正确 | — |
| UT-KNOW-02 | 遗忘判定:sort_order 差 ≥20 | — |
| UT-KNOW-03 | createFromBookmark 创建 pending | — |
| UT-COCK-01 | getSummary 字数与存稿计数 | — |
| UT-BRIDGE-01 | 提取 tail/head 长度正确 | — |
| IT-BRIDGE-01 | getBridge 含非空 aiSuggestion | 240s LM Studio |
| IT-KNOW-04 | 批量 approve 后 pending 清零 | — |
`vitest.config.ts` 保持 `fileParallelism: false`
### 8.2 E2EPlaywright
| ID | 场景 | 超时 |
|----|------|------|
| E2E-COCK-01 | 打开驾驶舱,统计卡片可见 | 30s |
| E2E-COCK-02 | 首次开书自动弹驾驶舱,二次不再自动 | 30s |
| E2E-PUB-01 | 章节改 publish_status 为 readycockpit 存稿 +1 | 30s |
| E2E-KNOW-01 | 新建 → 待审核 → 采纳 → 列表可见 | 30s |
| E2E-KNOW-02 | 地标 foreshadow 同步知识库 | 30s |
| E2E-BRIDGE-01 | 新章触发衔接 modal,文本非空 | 30s |
| E2E-BRIDGE-02 | 衔接含 AI 建议(LM Studio | 300s |
| E2E-STOCK-01 | 存稿低于阈值,status bar 警告可见 | 30s |
---
## 9. 文件清单(实现参考)
| 文件 | 职责 |
|------|------|
| `src/main/db/schema-v6.sql` | 新表 |
| `src/main/db/repositories/knowledge.repo.ts` | 数据访问 |
| `src/main/services/knowledge.service.ts` | 业务 + 遗忘判定 |
| `src/main/services/cockpit.service.ts` | 聚合 |
| `src/main/services/chapter-bridge.service.ts` | 衔接 + AI |
| `src/main/ipc/handlers/knowledge.handler.ts` | IPC |
| `src/main/ipc/handlers/cockpit.handler.ts` | IPC |
| `src/main/ipc/handlers/bridge.handler.ts` | IPC |
| `src/renderer/components/cockpit/CockpitModal.tsx` | UI |
| `src/renderer/components/bridge/ChapterBridgeModal.tsx` | UI |
| `src/renderer/components/knowledge/KnowledgePanel.tsx` | 重写 |
| `src/renderer/components/knowledge/KnowledgeEditorDialog.tsx` | 编辑 |
| `src/renderer/stores/useKnowledgeStore.ts` | 状态 |
| `tests/main/migrate-v6.test.ts` | 迁移 |
| `tests/main/knowledge.repo.test.ts` | CRUD |
| `tests/main/cockpit.service.test.ts` | 聚合 |
| `e2e/cockpit-knowledge.spec.ts` | E2E |
---
## 10. Definition of Donev0.6.0
- [ ] schema v6 迁移 + 类型 + IPC + preload
- [ ] KnowledgeService + Panel 完整 CRUD / 审核
- [ ] CockpitModal + 首次打开逻辑
- [ ] ChapterBridgeModal + 自动/手动触发 + AI 建议
- [ ] publish_status UI + 存稿提醒 + updateSchedule 设置
- [ ] 全量测试通过(含 LM Studio IT-BRIDGE-01 / E2E-BRIDGE-02
- [ ] README / SettingsPage 版本号 → **0.6.0**
---
## 11. Spec Self-Review
| 检查项 | 结果 |
|--------|------|
| Placeholder 扫描 | 无 TBD;排除项见 §1.4 |
| 内部一致性 | 驾驶舱不依赖 writing_logs;伏笔统计仅 approved |
| 范围 | 单 spec 可支撑一份 implementation plan |
| 歧义 | 遗忘阈值固定 20 章;存稿阈值默认 3;MVP 不做 AI 抽取 |
---
*本规格为笔临 P5 子项目。AI 知识抽取、writing_logs 热力图等在 P5.2+ spec 中增量修订。*