diff --git a/docs/superpowers/specs/2026-07-06-bilin-p5-workflow-knowledge-design.md b/docs/superpowers/specs/2026-07-06-bilin-p5-workflow-knowledge-design.md new file mode 100644 index 0000000..76feaf0 --- /dev/null +++ b/docs/superpowers/specs/2026-07-06-bilin-p5-workflow-knowledge-design.md @@ -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_preferences(cockpitSeen、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 + // 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`(1–20,默认 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 E2E(Playwright) + +| ID | 场景 | 超时 | +|----|------|------| +| E2E-COCK-01 | 打开驾驶舱,统计卡片可见 | 30s | +| E2E-COCK-02 | 首次开书自动弹驾驶舱,二次不再自动 | 30s | +| E2E-PUB-01 | 章节改 publish_status 为 ready,cockpit 存稿 +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 Done(v0.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 中增量修订。*