Files
bilin/docs/superpowers/specs/2026-07-06-bilin-p5-workflow-knowledge-design.md

455 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 笔临 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 中增量修订。*