Files
bilin/docs/superpowers/plans/2026-07-06-bilin-p5-workflow-knowledge.md
T

25 KiB
Raw Blame History

笔临 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_dismissKnowledgeService 负责 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:1234model=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 增加 publishStatusupdate 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-01240s 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.tslist / create / update / delete / approve / reject / batchApprove / createFromBookmark / stats

cockpit.handler.tsgetSummary(bookId, volumeId?) / markSeen / shouldShowOnOpen

bridge.handler.tsget(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、foreshadowStatustype=foreshadow 时)、sourceChapter select、「直接采纳」checkbox。

  • Step 3: 重写 KnowledgePanel

布局见 spec §6.4;保留 naming-check-openTab 切换过滤列表;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.tsopenBook 后检查 cockpit

  • Modify: src/renderer/App.tsxEditorLayout.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

替换 comingSoondata-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.tsbridgeOpen 状态,可选)

  • Step 1: ChapterBridgeModal

打开时 bridge.get(bookId, chapterId, true);展示 tail/head/aiSuggestioncheckbox 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 summarypublish 变更后 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/publishedsettings.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 23, 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 15, 12
v0.6.0 DoD Task 13