Co-authored-by: Cursor <cursoragent@cursor.com>
25 KiB
笔临 P5 作家工作流 + 知识库 MVP Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: 交付 v0.6.0:驾驶舱 + 存稿/更新计划 + 章间衔接(可选 AI)+ 知识库 MVP(手动 CRUD / 审核 / 伏笔追踪)。
Architecture: schema v6 新增 knowledge_entries / book_preferences / chapter_bridge_dismiss;KnowledgeService 负责 CRUD 与遗忘判定;CockpitService 只读聚合字数与存稿;ChapterBridgeService 提取相邻章片段 + 可选 AiClientService;渲染层 CockpitModal / ChapterBridgeModal / 重写 KnowledgePanel。测试 禁止 Mock AI 集成/E2E 打真实 LM Studio。
Tech Stack: Electron 36、electron-vite、React 18、TypeScript、node:sqlite、Zustand、Jotai、i18next、Vitest、Playwright
Spec: docs/superpowers/specs/2026-07-06-bilin-p5-workflow-knowledge-design.md
LM Studio 默认: baseUrl=http://127.0.0.1:1234,model=gemma-4-e4b-it
File Map
| 文件 | 职责 |
|---|---|
src/main/db/schema-v6.sql |
v6 DDL |
src/main/db/migrate.ts |
v5→v6 |
src/main/db/repositories/knowledge.repo.ts |
knowledge_entries CRUD |
src/main/db/repositories/book-prefs.repo.ts |
book_preferences KV |
src/main/db/repositories/bridge-dismiss.repo.ts |
chapter_bridge_dismiss |
src/main/services/knowledge.service.ts |
审核、遗忘判定、bookmark 同步 |
src/main/services/cockpit.service.ts |
驾驶舱聚合 |
src/main/services/chapter-bridge.service.ts |
衔接文本 + AI |
src/main/db/repositories/chapter.repo.ts |
publish_status 读写 |
src/main/ipc/handlers/knowledge.handler.ts |
knowledge IPC |
src/main/ipc/handlers/cockpit.handler.ts |
cockpit IPC |
src/main/ipc/handlers/bridge.handler.ts |
bridge IPC |
src/main/ipc/register.ts |
注册 handler |
src/shared/types.ts |
KnowledgeEntry / CockpitSummary 等 |
src/shared/ipc-channels.ts |
新通道 |
src/preload/index.ts |
knowledge / cockpit / bridge API |
src/shared/electron-api.d.ts |
类型 |
src/renderer/stores/useKnowledgeStore.ts |
知识库状态 |
src/renderer/stores/useCockpitStore.ts |
驾驶舱状态 |
src/renderer/components/knowledge/KnowledgePanel.tsx |
重写 |
src/renderer/components/knowledge/KnowledgeEditorDialog.tsx |
编辑对话框 |
src/renderer/components/cockpit/CockpitModal.tsx |
驾驶舱 UI |
src/renderer/components/bridge/ChapterBridgeModal.tsx |
衔接 UI |
src/renderer/components/layout/TopBar.tsx |
驾驶舱按钮 |
src/renderer/components/layout/EditorLayout.tsx |
发布状态、bridge 触发、statusbar |
src/renderer/components/settings/SettingsPage.tsx |
updateSchedule |
src/main/services/global-settings.ts |
默认值扩展 |
public/locales/zh-CN/translation.json |
文案 |
public/locales/en/translation.json |
文案 |
tests/main/migrate-v6.test.ts |
UT-MIG-06 |
tests/main/knowledge.service.test.ts |
UT-KNOW-* |
tests/main/cockpit.service.test.ts |
UT-COCK-01 |
tests/main/chapter-bridge.test.ts |
UT-BRIDGE-01 / IT-BRIDGE-01 |
e2e/cockpit-knowledge.spec.ts |
E2E-COCK-* / KNOW-* / BRIDGE-* / STOCK-* |
Task 1: Schema v6 + 类型 + IPC 通道
Files:
-
Create:
src/main/db/schema-v6.sql -
Modify:
src/main/db/migrate.ts -
Modify:
src/shared/types.ts -
Modify:
src/shared/ipc-channels.ts -
Create:
tests/main/migrate-v6.test.ts -
Modify:
tests/main/migrate-v5.test.ts(期望 version 6) -
Step 1: 写迁移失败测试
tests/main/migrate-v6.test.ts:
import { describe, it, expect, afterEach } from 'vitest'
import { DatabaseSync } from 'node:sqlite'
import { migrate } from '../../src/main/db/migrate'
import type { SqliteDb } from '../../src/main/db/types'
describe('migrate v6', () => {
let db: SqliteDb
afterEach(() => db?.close())
it('UT-MIG-06: applies v6 on fresh database', () => {
db = new DatabaseSync(':memory:')
migrate(db)
const version = db.prepare('SELECT MAX(version) AS v FROM schema_version').get() as { v: number }
expect(version.v).toBe(6)
const tables = db
.prepare("SELECT name FROM sqlite_master WHERE type='table'")
.all() as { name: string }[]
expect(tables.some((t) => t.name === 'knowledge_entries')).toBe(true)
expect(tables.some((t) => t.name === 'book_preferences')).toBe(true)
expect(tables.some((t) => t.name === 'chapter_bridge_dismiss')).toBe(true)
})
})
- Step 2: 运行确认 FAIL
npm run test -- tests/main/migrate-v6.test.ts
- Step 3: 实现 schema v6
src/main/db/schema-v6.sql(与 spec §3.1 一致)。
src/main/db/migrate.ts:
import schemaV6 from './schema-v6.sql?raw'
const CURRENT_VERSION = 6
// ...
if (current < 6) {
db.exec(schemaV6)
db.prepare('INSERT INTO schema_version (version, description) VALUES (?, ?)').run(6, 'P5 knowledge/cockpit schema')
}
src/shared/types.ts 新增:
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 {
id: string
type: KnowledgeType
title: string
content: string
importance: number
status: KnowledgeStatus
foreshadowStatus?: ForeshadowStatus
sourceChapterId?: string
lastMentionChapterId?: string
linkedBookmarkId?: string
createdAt: string
updatedAt: string
}
export interface CreateKnowledgeInput {
type: KnowledgeType
title: string
content?: string
importance?: number
status?: KnowledgeStatus
foreshadowStatus?: ForeshadowStatus
sourceChapterId?: string
lastMentionChapterId?: string
linkedBookmarkId?: string
}
export interface CockpitSummary {
totalWords: number
volumeWords: number
stockReadyCount: number
stockThreshold: number
foreshadowBuried: number
foreshadowResolved: number
foreshadowForgotten: number
}
export interface ChapterBridgeResult {
previousChapterId: string | null
previousTail: string
currentHead: string
aiSuggestion?: string
}
扩展 GlobalSettings:
updateSchedule: UpdateSchedule // default 'none'
stockBufferThreshold: number // default 3
扩展 Chapter:
publishStatus?: PublishStatus
src/shared/ipc-channels.ts 追加 spec §4.1 全部通道。
- Step 4: 更新 migrate-v5 期望 version 6;运行 PASS
npm run test -- tests/main/migrate-v5.test.ts tests/main/migrate-v6.test.ts
- Step 5: Commit
git add src/main/db/schema-v6.sql src/main/db/migrate.ts src/shared/types.ts src/shared/ipc-channels.ts tests/main/migrate-v6.test.ts tests/main/migrate-v5.test.ts
git commit -m "feat: add schema v6 for knowledge and cockpit workflow"
Task 2: Repository 层
Files:
-
Create:
src/main/db/repositories/knowledge.repo.ts -
Create:
src/main/db/repositories/book-prefs.repo.ts -
Create:
src/main/db/repositories/bridge-dismiss.repo.ts -
Modify:
src/main/db/repositories/chapter.repo.ts -
Create:
tests/main/knowledge.repo.test.ts -
Step 1: UT-KNOW-01 失败测试
it('UT-KNOW-01: CRUD and approve updates status', () => {
const db = new DatabaseSync(':memory:')
migrate(db)
const repo = new KnowledgeRepository(db)
const entry = repo.create({ type: 'foreshadow', title: '测灵石异常', foreshadowStatus: 'buried' })
expect(entry.status).toBe('pending')
const approved = repo.update(entry.id, { status: 'approved' })
expect(approved.status).toBe('approved')
db.close()
})
- Step 2: 实现 KnowledgeRepository
export class KnowledgeRepository {
create(input: CreateKnowledgeInput): KnowledgeEntry { /* INSERT */ }
get(id: string): KnowledgeEntry | null
list(filter?: { status?: KnowledgeStatus; type?: KnowledgeType }): KnowledgeEntry[]
update(id: string, patch: Partial<...>): KnowledgeEntry
delete(id: string): void
countByStatus(status: KnowledgeStatus): number
}
mapRow 蛇形 ↔ 驼峰映射。
- Step 3: BookPrefsRepository + BridgeDismissRepository
// book-prefs.repo.ts
get(key: string): string | null
set(key: string, value: string): void
// bridge-dismiss.repo.ts
isDismissed(chapterId: string): boolean
dismiss(chapterId: string): void
- Step 4: ChapterRepository 扩展 publish_status
mapRow 增加 publishStatus;update patch 支持 publishStatus;新增:
setPublishStatus(id: string, publishStatus: PublishStatus): Chapter
countByPublishStatus(status: PublishStatus): number
getPreviousChapter(chapterId: string): Chapter | null // 按 sort_order 找上一章
- Step 5: 运行 PASS + Commit
npm run test -- tests/main/knowledge.repo.test.ts
git commit -m "feat: add knowledge and bridge repositories with publish status"
Task 3: KnowledgeService
Files:
-
Create:
src/main/services/knowledge.service.ts -
Create:
tests/main/knowledge.service.test.ts -
Step 1: UT-KNOW-02 遗忘判定测试
it('UT-KNOW-02: forgotten when sort_order gap >= 20', () => {
// 创建 25 章,在第 1 章埋 foreshadow approved buried
// latestOrder - mentionOrder >= 20 → forgotten count 1
})
- Step 2: UT-KNOW-03 bookmark 同步测试
it('UT-KNOW-03: createFromBookmark creates pending entry', () => {
const bm = bookmarkRepo.create(chapterId, 0, '测灵石发热', 'foreshadow')
const entry = service.createFromBookmark(bm.id)
expect(entry.status).toBe('pending')
expect(entry.linkedBookmarkId).toBe(bm.id)
})
- Step 3: 实现 KnowledgeService
const FORGOTTEN_GAP = 20
export class KnowledgeService {
list(filter?: { status?: KnowledgeStatus; type?: KnowledgeType; forgottenOnly?: boolean })
create(input: CreateKnowledgeInput): KnowledgeEntry
update(id: string, patch: Partial<CreateKnowledgeInput>): KnowledgeEntry
delete(id: string): void
approve(id: string): KnowledgeEntry
reject(id: string): KnowledgeEntry
batchApprove(ids: string[]): number
createFromBookmark(bookmarkId: string): KnowledgeEntry
getForeshadowStats(): { buried: number; resolved: number; forgotten: number }
countPending(): number
private isForgotten(entry: KnowledgeEntry): boolean {
if (entry.type !== 'foreshadow' || entry.status !== 'approved' || entry.foreshadowStatus !== 'buried') return false
const mentionId = entry.lastMentionChapterId ?? entry.sourceChapterId
if (!mentionId) return false
const mentionOrder = chapterRepo.get(mentionId)?.sortOrder ?? 0
const latestOrder = Math.max(...chapterRepo.list().map((c) => c.sortOrder), 0)
return latestOrder - mentionOrder >= FORGOTTEN_GAP
}
}
- Step 4: IT-KNOW-04 批量采纳
it('IT-KNOW-04: batchApprove clears pending', () => {
// create 3 pending → batchApprove → countPending === 0
})
- Step 5: 运行 PASS + Commit
npm run test -- tests/main/knowledge.service.test.ts
git commit -m "feat: add KnowledgeService with foreshadow forgotten logic"
Task 4: CockpitService + GlobalSettings 扩展
Files:
-
Create:
src/main/services/cockpit.service.ts -
Modify:
src/main/services/global-settings.ts -
Create:
tests/main/cockpit.service.test.ts -
Step 1: UT-COCK-01 测试
it('UT-COCK-01: getSummary counts words and ready stock', () => {
volRepo.create('卷一', 0)
chapterRepo.create(volId, 'A', 0, '<p>hello world</p>')
chapterRepo.setPublishStatus(chId, 'ready')
const summary = service.getSummary(activeVolumeId)
expect(summary.totalWords).toBeGreaterThan(0)
expect(summary.stockReadyCount).toBe(1)
})
- Step 2: 实现 CockpitService
export class CockpitService {
constructor(
private db: SqliteDb,
private settings: GlobalSettingsService
) {}
getSummary(activeVolumeId?: string): CockpitSummary {
const chapters = new ChapterRepository(this.db).list()
const totalWords = chapters.reduce((s, c) => s + stripHtml(c.content).length, 0)
const volumeWords = activeVolumeId
? chapters.filter((c) => c.volumeId === activeVolumeId).reduce(...)
: totalWords
const stockReadyCount = new ChapterRepository(this.db).countByPublishStatus('ready')
const stats = new KnowledgeService(this.db).getForeshadowStats()
const { stockBufferThreshold } = this.settings.get()
return { totalWords, volumeWords, stockReadyCount, stockThreshold: stockBufferThreshold, ...stats }
}
shouldShowOnOpen(): boolean {
return new BookPrefsRepository(this.db).get('cockpitSeen') !== 'true'
}
markSeen(): void {
new BookPrefsRepository(this.db).set('cockpitSeen', 'true')
}
}
- Step 3: global-settings defaults
updateSchedule: 'none',
stockBufferThreshold: 3,
get() merge 时补默认值。
- Step 4: 运行 PASS + Commit
npm run test -- tests/main/cockpit.service.test.ts
git commit -m "feat: add CockpitService and extend global settings"
Task 5: ChapterBridgeService
Files:
-
Create:
src/main/services/chapter-bridge.service.ts -
Create:
tests/main/chapter-bridge.test.ts -
Step 1: UT-BRIDGE-01 文本提取测试
it('UT-BRIDGE-01: extracts tail and head', () => {
const prev = chapterRepo.create(volId, '上一章', 0, '<p>' + '甲'.repeat(400) + '</p>')
const cur = chapterRepo.create(volId, '本章', 1, '<p>开头内容</p>')
const result = service.getBridgeSync(cur.id) // 无 AI 同步方法
expect(result.previousTail.length).toBeLessThanOrEqual(300)
expect(result.previousTail.length).toBeGreaterThan(50)
expect(result.currentHead).toContain('开头')
})
- Step 2: 实现 ChapterBridgeService
export class ChapterBridgeService {
shouldPrompt(chapterId: string): boolean {
if (dismissRepo.isDismissed(chapterId)) return false
const ch = chapterRepo.get(chapterId)
if (!ch || stripHtml(ch.content).length >= 200) return false
return chapterRepo.getPreviousChapter(chapterId) !== null
}
extract(chapterId: string): ChapterBridgeResult {
const prev = chapterRepo.getPreviousChapter(chapterId)
const cur = chapterRepo.get(chapterId)!
const prevText = prev ? stripHtml(prev.content) : ''
const curText = stripHtml(cur.content)
return {
previousChapterId: prev?.id ?? null,
previousTail: prevText.slice(-300),
currentHead: curText.slice(0, 200)
}
}
async getBridge(chapterId: string, withAi: boolean): Promise<ChapterBridgeResult> {
const base = this.extract(chapterId)
if (!withAi || !base.previousTail) return base
try {
const suggestion = await this.aiClient.chat([
{ role: 'user', content: `你是连载小说编辑。上一章末尾:「${base.previousTail}」。本章开头:「${base.currentHead || '(尚未撰写)'}」。用 2-3 句话指出衔接是否顺畅,并给出一个开头方向建议。不要续写正文。` }
])
return { ...base, aiSuggestion: suggestion.trim() }
} catch {
return base
}
}
dismiss(chapterId: string): void {
dismissRepo.dismiss(chapterId)
}
}
- Step 3: IT-BRIDGE-01(240s LM Studio)
it('IT-BRIDGE-01: getBridge returns aiSuggestion from LM Studio', async () => {
// 两章有内容 → getBridge(id, true) → aiSuggestion.length > 10
}, 240_000)
- Step 4: 运行 PASS + Commit
npm run test -- tests/main/chapter-bridge.test.ts
git commit -m "feat: add ChapterBridgeService with optional AI suggestion"
Task 6: IPC + Preload
Files:
-
Create:
src/main/ipc/handlers/knowledge.handler.ts -
Create:
src/main/ipc/handlers/cockpit.handler.ts -
Create:
src/main/ipc/handlers/bridge.handler.ts -
Modify:
src/main/ipc/handlers/chapter.handler.ts -
Modify:
src/main/ipc/register.ts -
Modify:
src/preload/index.ts -
Modify:
src/shared/electron-api.d.ts -
Step 1: 实现 handlers
参照 auto.handler.ts 模式,wrap(() => ...),BookRegistryService.getDb(bookId)。
knowledge.handler.ts:list / create / update / delete / approve / reject / batchApprove / createFromBookmark / stats
cockpit.handler.ts:getSummary(bookId, volumeId?) / markSeen / shouldShowOnOpen
bridge.handler.ts:get(bookId, chapterId, withAi?) / dismiss / shouldPrompt
chapter.handler.ts 新增:
IPC.CHAPTER_SET_PUBLISH_STATUS → chapterRepo.setPublishStatus(chapterId, status)
- Step 2: register.ts
registerKnowledgeHandlers(books, settings)
registerCockpitHandlers(books, settings)
registerBridgeHandlers(books, settings, aiClient)
- Step 3: preload 命名空间
knowledge: { list, create, update, delete, approve, reject, batchApprove, createFromBookmark, stats },
cockpit: { getSummary, markSeen, shouldShowOnOpen },
bridge: { get, dismiss, shouldPrompt },
chapter: { /* 现有 */ setPublishStatus },
- Step 4: build 验证
npm run build
- Step 5: Commit
git commit -m "feat: add knowledge cockpit bridge IPC and preload"
Task 7: KnowledgePanel UI
Files:
-
Create:
src/renderer/stores/useKnowledgeStore.ts -
Create:
src/renderer/components/knowledge/KnowledgeEditorDialog.tsx -
Modify:
src/renderer/components/knowledge/KnowledgePanel.tsx -
Modify:
src/renderer/styles/layout.css -
Step 1: useKnowledgeStore
interface KnowledgeState {
entries: KnowledgeEntry[]
stats: { buried: number; resolved: number; forgotten: number }
tab: 'pending' | 'all' | 'foreshadow'
load: (bookId: string) => Promise<void>
setTab: (tab: ...) => void
create / update / delete / approve / batchApprove
openForgottenFilter: () => void // tab=foreshadow + forgottenOnly
}
- Step 2: KnowledgeEditorDialog
Radix Dialog 或现有 .modal-overlay 模式;字段:type select、title、content textarea、importance 1-5、foreshadowStatus(type=foreshadow 时)、sourceChapter select、「直接采纳」checkbox。
- Step 3: 重写 KnowledgePanel
布局见 spec §6.4;保留 naming-check-open;Tab 切换过滤列表;data-testid 与 spec 一致。
-
Step 4: CSS
.knowledge-panel/.kb-item对齐 ui_pc.html -
Step 5: Commit
git commit -m "feat: implement KnowledgePanel with review workflow UI"
Task 8: CockpitModal + TopBar + 首次打开
Files:
-
Create:
src/renderer/stores/useCockpitStore.ts -
Create:
src/renderer/components/cockpit/CockpitModal.tsx -
Modify:
src/renderer/components/layout/TopBar.tsx -
Modify:
src/renderer/stores/useBookStore.ts(openBook 后检查 cockpit) -
Modify:
src/renderer/App.tsx或EditorLayout.tsx(挂载 CockpitModal) -
Step 1: useCockpitStore
loadSummary(bookId, volumeId?)
open / close
markSeen(bookId)
shouldShowOnOpen(bookId): Promise<boolean>
- Step 2: CockpitModal
加载 summary 展示卡片;按钮:
-
cockpit-resume-edit→ close + 恢复 lastChapterId -
cockpit-bridge-check→ close + 打开 ChapterBridgeModal -
cockpit-forgotten-foreshadow→ close +useKnowledgeStore.openForgottenFilter()+ 切 rightPanel knowledge -
Step 3: TopBar
替换 comingSoon 为 data-testid="topbar-cockpit" → useCockpitStore.open()
- Step 4: 首次打开书籍
useBookStore.openBook 成功后:
if (await ipcCall(() => window.electronAPI.cockpit.shouldShowOnOpen(bookId))) {
await ipcCall(() => window.electronAPI.cockpit.markSeen(bookId))
useCockpitStore.getState().open()
}
- Step 5: Commit
git commit -m "feat: add CockpitModal and first-open behavior"
Task 9: ChapterBridgeModal + EditorLayout 集成
Files:
-
Create:
src/renderer/components/bridge/ChapterBridgeModal.tsx -
Modify:
src/renderer/components/layout/EditorLayout.tsx -
Modify:
src/renderer/stores/useAppStore.ts(bridgeOpen 状态,可选) -
Step 1: ChapterBridgeModal
打开时 bridge.get(bookId, chapterId, true);展示 tail/head/aiSuggestion;checkbox dismiss + bridge-start-writing 关闭。
- Step 2: EditorLayout 自动触发
switchTarget 到 chapter 后:
const should = await ipcCall(() => window.electronAPI.bridge.shouldPrompt(chapterId))
if (should) setTimeout(() => setBridgeOpen(true), 500)
- Step 3: 驾驶舱手动触发
CockpitModal cockpit-bridge-check 设置 bridgeChapterId 为当前章并打开 modal。
- Step 4: Commit
git commit -m "feat: add ChapterBridgeModal with auto prompt on new chapter"
Task 10: 发布状态 + 存稿提醒 + 设置
Files:
-
Modify:
src/renderer/components/layout/EditorLayout.tsx -
Modify:
src/renderer/stores/useBookStore.ts -
Modify:
src/renderer/components/settings/SettingsPage.tsx -
Step 1: 章节 publish 循环按钮
在 chapter-item 内增加小图标按钮 data-testid={chapter-publish-${ch.id}},点击循环 draft → ready → published,调用 chapter.setPublishStatus,刷新 chapters。
- Step 2: StatusBar 存稿警告
EditorLayout #editor-statusbar 内:
const summary = await cockpit.getSummary(bookId, activeVolumeId)
if (settings.updateSchedule !== 'none' && summary.stockReadyCount < summary.stockThreshold) {
// 渲染 data-testid="status-stock-warning"
}
书籍打开时 load summary;publish 变更后 refresh。
- Step 3: SettingsPage
新增「更新计划」区块:updateSchedule select、stockBufferThreshold number input (1-20)。
- Step 4: Commit
git commit -m "feat: add publish status UI stock warning and update schedule settings"
Task 11: 地标同步 + i18n
Files:
-
Modify:
src/renderer/components/editor/TipTapEditor.tsx或 landmark 插入流程 -
Modify:
public/locales/zh-CN/translation.json -
Modify:
public/locales/en/translation.json -
Step 1: 插入 foreshadow 地标时 checkbox
在 insert landmark 对话框(或插入后 toast 行动)增加「同步到知识库」;勾选则 knowledge.createFromBookmark(bookmarkId)。
若当前无独立 insert UI,在 LandmarkModal 或 TipTap landmark 命令回调中加 post-create hook。
- Step 2: i18n 键
cockpit.*、bridge.*、knowledge.*、publish.status.draft/ready/published、settings.updateSchedule.*、stock.warning
- Step 3: Commit
git commit -m "feat: add foreshadow landmark sync and P5 i18n strings"
Task 12: E2E 测试
Files:
-
Create:
e2e/cockpit-knowledge.spec.ts -
Step 1: 无 AI 门槛测试
test('E2E-COCK-01: cockpit modal shows stats', async () => { /* openBookWithContent → topbar-cockpit → cockpit-total-words visible */ })
test('E2E-COCK-02: first open shows cockpit once', async () => { /* 开书两次 */ })
test('E2E-PUB-01: publish ready increases stock count', async () => { /* chapter-publish click → cockpit-stock-count */ })
test('E2E-KNOW-01: create approve knowledge entry', async () => { /* knowledge-new → pending tab → approve */ })
test('E2E-BRIDGE-01: new chapter triggers bridge modal', async () => { /* 新章 → bridge-previous-tail visible */ })
test('E2E-STOCK-01: low stock warning in statusbar', async () => { /* set threshold + schedule in settings, 0 ready chapters */ })
- Step 2: LM Studio 测试(300s)
test('E2E-BRIDGE-02: bridge shows AI suggestion', async () => {
test.setTimeout(300_000)
// 两章有内容 → 手动打开 bridge → bridge-ai-suggestion 非空
})
test('E2E-KNOW-02: foreshadow landmark sync', async () => { /* 插入 foreshadow + sync */ })
- Step 3: 运行 E2E
npm run test:e2e -- e2e/cockpit-knowledge.spec.ts
- Step 4: Commit
git commit -m "test: add P5 cockpit knowledge and bridge E2E specs"
Task 13: v0.6.0 交付
Files:
-
Modify:
package.json -
Modify:
README.md -
Modify:
src/renderer/components/settings/SettingsPage.tsx(版本号展示) -
Modify:
docs/superpowers/plans/2026-07-06-bilin-p5-workflow-knowledge.md(勾选完成项) -
Step 1: 版本号 →
0.6.0 -
Step 2: README 功能概览追加 P5
- 驾驶舱:全书/本卷字数、存稿缓冲、伏笔摘要、快速入口(P5)
- 知识库 MVP:手动条目、审核流、伏笔追踪、地标同步(P5)
- 章间衔接:上下章片段 + 可选 AI 建议(P5)
- 更新计划:发布状态、存稿阈值提醒(P5)
- Step 3: 全量测试
npm run build
npm run test
npm run test:e2e
- Step 4: Commit
git commit -m "feat: ship v0.6.0 with cockpit knowledge and chapter bridge"
Spec Coverage Checklist
| Spec 要求 | Task |
|---|---|
| schema v6 三表 | Task 1 |
| Knowledge CRUD / 审核 / 遗忘 | Task 2–3, 7 |
| Cockpit 聚合 + 首次打开 | Task 4, 8 |
| ChapterBridge + AI | Task 5, 9 |
| publish_status UI | Task 10 |
| updateSchedule / 存稿提醒 | Task 4, 10 |
| 地标 foreshadow 同步 | Task 11 |
| IPC / preload | Task 6 |
| i18n | Task 11 |
| 全部测试 ID | Task 1–5, 12 |
| v0.6.0 DoD | Task 13 |