From 91c93954df36a8b298693c2dd1ccb8e81dabeaed Mon Sep 17 00:00:00 2001 From: kun1h Date: Mon, 6 Jul 2026 10:50:52 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=E7=AC=94=E4=B8=B4=20?= =?UTF-8?q?P2=20=E5=AE=9E=E7=8E=B0=E8=AE=A1=E5=88=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 18 个 Task 覆盖主题修复、schema v2、统一编辑、引用/搜索/版本/地标/用词分析至 v0.2.0。 Co-authored-by: Cursor --- docs/superpowers/plans/2026-07-06-bilin-p2.md | 731 ++++++++++++++++++ 1 file changed, 731 insertions(+) create mode 100644 docs/superpowers/plans/2026-07-06-bilin-p2.md diff --git a/docs/superpowers/plans/2026-07-06-bilin-p2.md b/docs/superpowers/plans/2026-07-06-bilin-p2.md new file mode 100644 index 0000000..c89c479 --- /dev/null +++ b/docs/superpowers/plans/2026-07-06-bilin-p2.md @@ -0,0 +1,731 @@ +# 笔临 P2 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.2.0:大纲/设定/灵感持久化、统一中央编辑、引用面板、版本历史、FTS 全局搜索、地标、用词分析,并修复 3 套浅色主题对比度问题。 + +**Architecture:** 延续 electron-vite 单体仓库;主进程 `node:sqlite` schema v2 + FTS5 + Snapshot/Search/WordFreq 服务;渲染进程新增 `useEditStore`(EditTarget)统一 TipTap 编辑;IPC 延续 `IpcResult` 信封;UI 对齐 `design/ui_pc.html` 模态与引用面板。 + +**Tech Stack:** Electron 36、electron-vite、React 18、TypeScript、TipTap、node:sqlite、Zustand、Jotai、Radix UI、i18next、diff-match-patch、Vitest、Playwright + +**Spec:** `docs/superpowers/specs/2026-07-06-bilin-p2-design.md` + +--- + +## File Map(P2 新增/修改核心文件) + +| 文件 | 职责 | +|------|------| +| `src/renderer/styles/themes.css` | 补全浅色 token、`--text-on-accent`、`--input-*` | +| `src/main/db/schema-v2.sql` | v2 表 + FTS5 | +| `src/main/db/migrate.ts` | version 1→2 增量迁移 | +| `src/main/db/repositories/outline.repo.ts` | 大纲 CRUD/树/move | +| `src/main/db/repositories/setting.repo.ts` | 设定 CRUD + chapterRefs | +| `src/main/db/repositories/inspiration.repo.ts` | 灵感 CRUD/convert | +| `src/main/db/repositories/snapshot.repo.ts` | 快照 CRUD/FIFO | +| `src/main/db/repositories/bookmark.repo.ts` | 地标 CRUD | +| `src/main/services/fts-sync.service.ts` | FTS5 增量同步 | +| `src/main/services/search.service.ts` | 查询 + replace dryRun | +| `src/main/services/snapshot.service.ts` | 定时/退出快照 | +| `src/main/services/wordfreq.service.ts` | 词频统计 | +| `src/shared/types.ts` | P2 类型扩展 | +| `src/shared/ipc-channels.ts` | P2 IPC 常量 | +| `src/renderer/stores/useEditStore.ts` | EditTarget 切换 | +| `src/renderer/components/outline/OutlineTree.tsx` | 大纲树 UI | +| `src/renderer/components/reference/ReferencePanel.tsx` | 引用面板 | +| `src/renderer/components/search/SearchModal.tsx` | 全局搜索 | +| `src/renderer/components/version/VersionModal.tsx` | 版本历史 + diff | +| `src/renderer/components/landmark/LandmarkModal.tsx` | 地标清单 | +| `src/renderer/components/wordfreq/WordFreqPanel.tsx` | 用词分析 | +| `e2e/themes-contrast.spec.ts` | 浅色主题对比度 E2E | + +--- + +## Task 1: P2.0 主题 Token 修复 + +**Files:** +- Modify: `src/renderer/styles/themes.css` +- Modify: `src/renderer/styles/layout.css` +- Modify: `src/renderer/styles/globals.css` +- Modify: `src/renderer/components/settings/SettingsPage.tsx` +- Create: `e2e/themes-contrast.spec.ts` + +- [ ] **Step 1: 在 `:root` 新增语义 token** + +```css +/* themes.css :root 追加 */ +--text-on-accent: #ffffff; +--input-text: var(--text-primary); +--input-bg: var(--bg-surface); +--input-border: var(--border); +``` + +为 `[data-theme='ricepaper']`、`mist`、`teagarden` 各补全:`--bg-surface`、`--bg-active`、`--text-dim`、`--accent-glow`、`--border-light`、`--green`、`--orange`、`--red`。 + +- [ ] **Step 2: 替换硬编码 `#fff`** + +在 `layout.css` 中将 `.btn-large.primary`、`.tab.active` 的 `color: #fff` 改为 `color: var(--text-on-accent)`。 + +浅色主题覆盖: + +```css +[data-theme='ricepaper'], +[data-theme='mist'], +[data-theme='teagarden'] { + --text-on-accent: #ffffff; +} +``` + +- [ ] **Step 3: 统一表单控件样式** + +`globals.css` 追加: + +```css +input, select, textarea { + color: var(--input-text); + background: var(--input-bg); + border: 1px solid var(--input-border); +} +``` + +删除 `SettingsPage.tsx` 内联 `color: inherit` / 硬编码 border,改用 class `form-control`(在 globals 定义)。 + +- [ ] **Step 4: 写 contrast E2E** + +`e2e/themes-contrast.spec.ts`:对 `ricepaper`/`mist`/`teagarden`,在主页、设置页、编辑器断言 `#app` 内 `h1,h2,button,.setting-item` 可见(`toBeVisible`)且 computed color 非透明/非背景同色(用 `page.evaluate` 比较 RGB)。 + +- [ ] **Step 5: 运行验证** + +```bash +npm run build +npm run test:e2e -- e2e/themes-contrast.spec.ts +``` + +Expected: PASS + +- [ ] **Step 6: Commit** + +```bash +git add src/renderer/styles e2e/themes-contrast.spec.ts src/renderer/components/settings/SettingsPage.tsx +git commit -m "fix: repair light theme tokens and contrast" +``` + +--- + +## Task 2: 共享类型与 IPC 通道 + +**Files:** +- Modify: `src/shared/types.ts` +- Modify: `src/shared/ipc-channels.ts` +- Modify: `src/main/services/global-settings.ts` + +- [ ] **Step 1: 扩展 types.ts** + +追加(完整定义见 spec §3.2): + +```typescript +export type OutlineStatus = 'pending' | 'writing' | 'done' | 'abandoned' +export type SettingType = 'character' | 'location' | 'item' | 'skill' | 'faction' | 'custom' +export type SnapshotType = 'auto' | 'manual' | 'persist' | 'ai' +export type LandmarkType = 'todo' | 'foreshadow' | 'research' | 'custom' +export type EditTargetKind = 'chapter' | 'outline' | 'setting' | 'inspiration' +export type EditTarget = { kind: EditTargetKind; id: string } +export type SearchScope = 'all' | 'volume' | 'chapter' +export type SearchSourceKind = 'chapter' | 'outline' | 'setting' | 'inspiration' | 'bookmark' + +export interface OutlineItem { /* spec §3.2 字段 */ } +export interface SettingEntry { /* ... */ } +export interface InspirationEntry { /* ... */ } +export interface Snapshot { /* ... */ } +export interface Bookmark { /* ... */ } +export interface SearchResult { + kind: SearchSourceKind + id: string + title: string + snippet: string + chapterId?: string + position?: number +} +``` + +扩展 `GlobalSettings`: + +```typescript +snapshotIntervalMs: number +snapshotMaxAuto: number +snapshotMaxPersist: number +searchHistory: string[] +``` + +扩展 `BookOpenResult`:`outlines`, `settings`, `inspirations`。 + +- [ ] **Step 2: 扩展 ipc-channels.ts** + +```typescript +OUTLINE_LIST: 'outline:list', +OUTLINE_CREATE: 'outline:create', +// ... 全部见 spec §4.1 +SEARCH_QUERY: 'search:query', +WORDFREQ_ANALYZE: 'wordfreq:analyze', +``` + +- [ ] **Step 3: global-settings defaults** + +```typescript +function defaults(): GlobalSettings { + return { + // ...existing + snapshotIntervalMs: 300_000, + snapshotMaxAuto: 20, + snapshotMaxPersist: 3, + searchHistory: [] + } +} +``` + +- [ ] **Step 4: Commit** + +```bash +git commit -am "feat: add P2 shared types and IPC channels" +``` + +--- + +## Task 3: Schema v2 迁移 + +**Files:** +- Create: `src/main/db/schema-v2.sql` +- Modify: `src/main/db/migrate.ts` +- Create: `tests/main/migrate-v2.test.ts` + +- [ ] **Step 1: 写 schema-v2.sql** + +包含 spec §3.1 全部 CREATE TABLE + FTS5: + +```sql +CREATE VIRTUAL TABLE IF NOT EXISTS search_fts USING fts5( + source_kind, source_id, title, body, tokenize='unicode61' +); +``` + +- [ ] **Step 2: 更新 migrate.ts** + +```typescript +import schemaV2 from './schema-v2.sql?raw' + +const CURRENT_VERSION = 2 + +export function migrate(db: SqliteDb): void { + // ... v1 逻辑保留 + if (current >= CURRENT_VERSION) return + if (current < 1) { /* apply schemaV1 */ } + if (current < 2) { + db.exec(schemaV2) + db.prepare('INSERT INTO schema_version (version, description) VALUES (?, ?)').run(2, 'P2 schema') + } +} +``` + +v2 SQL 中对已有库使用 `ALTER TABLE chapters ADD COLUMN ...` 需单独 `schema-v2-alter.sql` 或在 migrate 中 try/catch 忽略 duplicate column。 + +- [ ] **Step 3: 写 migrate 测试** + +```typescript +// tests/main/migrate-v2.test.ts +it('migrates v1 database to v2 with new tables', () => { + const db = new DatabaseSync(':memory:') + // apply v1 only, then migrate full + expect(db.prepare("SELECT name FROM sqlite_master WHERE name='outline_items'").get()).toBeTruthy() +}) +``` + +- [ ] **Step 4: 运行** + +```bash +npm run test -- tests/main/migrate-v2.test.ts +``` + +- [ ] **Step 5: Commit** + +```bash +git commit -am "feat: add schema v2 migration" +``` + +--- + +## Task 4: Outline Repository + +**Files:** +- Create: `src/main/db/repositories/outline.repo.ts` +- Create: `tests/main/outline.repo.test.ts` + +- [ ] **Step 1: 写失败测试** + +```typescript +it('creates nested outline items', () => { + const parent = repo.create(null, '第一幕', 0) + const child = repo.create(parent.id, '开端', 0) + expect(repo.listTree()).toHaveLength(1) + expect(repo.listTree()[0].children).toHaveLength(1) +}) +``` + +- [ ] **Step 2: 实现 outline.repo.ts** + +方法:`create(parentId, title, sortOrder)`、`get`、`listFlat`、`update`、`delete`(级联)、`move`、`listUncovered()`。 + +- [ ] **Step 3: 运行 PASS + Commit** + +```bash +git commit -am "feat: add outline repository" +``` + +--- + +## Task 5: Setting + Inspiration Repository + +**Files:** +- Create: `src/main/db/repositories/setting.repo.ts` +- Create: `src/main/db/repositories/inspiration.repo.ts` +- Create: `tests/main/setting.repo.test.ts` +- Create: `tests/main/inspiration.repo.test.ts` + +- [ ] **Step 1: setting.repo** — CRUD + `syncChapterRefs(settingId, chapterIds[])` + +- [ ] **Step 2: inspiration.repo** — CRUD + `convertToOutline(id)` / `convertToSetting(id, type)` + +- [ ] **Step 3: 测试 PASS + Commit** + +```bash +git commit -am "feat: add setting and inspiration repositories" +``` + +--- + +## Task 6: Snapshot + Bookmark Repository + +**Files:** +- Create: `src/main/db/repositories/snapshot.repo.ts` +- Create: `src/main/db/repositories/bookmark.repo.ts` +- Create: `tests/main/snapshot.repo.test.ts` +- Create: `tests/main/bookmark.repo.test.ts` + +- [ ] **Step 1: snapshot.repo** + +```typescript +create(chapterId, type, content, name?): Snapshot +list(chapterId): Snapshot[] +pruneAuto(chapterId, max: number): void // FIFO 删除最旧 auto +restore(snapshotId): string // 返回 content +``` + +- [ ] **Step 2: bookmark.repo** — CRUD + `listByChapter` + `resolve(id, boolean)` + +- [ ] **Step 3: 测试 + Commit** + +```bash +git commit -am "feat: add snapshot and bookmark repositories" +``` + +--- + +## Task 7: FTS Sync + Search Service + +**Files:** +- Create: `src/main/services/fts-sync.service.ts` +- Create: `src/main/services/search.service.ts` +- Create: `tests/main/search.service.test.ts` + +- [ ] **Step 1: fts-sync.service.ts** + +```typescript +export class FtsSyncService { + upsert(db: SqliteDb, kind: SearchSourceKind, id: string, title: string, body: string): void { + db.prepare('DELETE FROM search_fts WHERE source_kind=? AND source_id=?').run(kind, id) + db.prepare('INSERT INTO search_fts(source_kind, source_id, title, body) VALUES (?,?,?,?)').run(kind, id, title, body) + } + rebuildAll(db: SqliteDb, book: BookRegistryService): void { /* 全量 */ } +} +``` + +HTML → plainText 用现有 `word-count` 同款 strip 或简单 `replace(/<[^>]+>/g,'')`。 + +- [ ] **Step 2: search.service.ts** + +```typescript +query(db, { text, scope, regex, caseSensitive }): SearchResult[] +replace(db, { text, replacement, dryRun }): { count: number; previews: SearchResult[] } +``` + +regex 模式:FTS 不支持时 fallback 遍历 `search_fts` body LIKE。 + +- [ ] **Step 3: 测试 + Commit** + +```bash +git commit -am "feat: add FTS sync and search service" +``` + +--- + +## Task 8: Snapshot Service + WordFreq Service + +**Files:** +- Create: `src/main/services/snapshot.service.ts` +- Create: `src/main/services/wordfreq.service.ts` +- Modify: `src/main/index.ts`(app.on('before-quit') 触发 persist 快照) +- Create: `tests/main/wordfreq.service.test.ts` + +- [ ] **Step 1: 安装 diff 库** + +```bash +npm install diff-match-patch +npm install -D @types/diff-match-patch +``` + +- [ ] **Step 2: snapshot.service.ts** + +```typescript +export class SnapshotService { + startAutoSave(bookId: string, chapterId: string, getContent: () => string): void { + this.timer = setInterval(() => { /* if changed → auto snapshot + prune */ }, settings.snapshotIntervalMs) + } + onPersistSave(bookId, chapterId, content): void { /* type=persist, prune to max 3 */ } +} +``` + +- [ ] **Step 3: wordfreq.service.ts** + +CJK:`text.match(/[\u4e00-\u9fff]/g)` 计数;Latin:`/\b[a-zA-Z]{2,}\b/g`;返回 Top 100。 + +- [ ] **Step 4: 测试 + Commit** + +```bash +git commit -am "feat: add snapshot and word frequency services" +``` + +--- + +## Task 9: IPC Handlers + Preload + +**Files:** +- Create: `src/main/ipc/handlers/outline.handler.ts`(及 setting/inspiration/snapshot/bookmark/search/wordfreq) +- Modify: `src/main/ipc/register.ts` +- Modify: `src/preload/index.ts` +- Modify: `src/shared/electron-api.d.ts` + +- [ ] **Step 1: 每个 handler 遵循现有 chapter.handler 模式** + +```typescript +export function registerOutlineHandlers(books: BookRegistryService): void { + ipcMain.handle(IPC.OUTLINE_LIST, (_e, { bookId }) => + wrap(() => books.getOutlineRepo(bookId).listFlat()) + ) +} +``` + +- [ ] **Step 2: BookRegistryService 扩展** + +```typescript +getOutlineRepo(bookId): OutlineRepository +getSettingRepo(bookId): SettingRepository +// ... +open(bookId): BookOpenResult // 附加 outlines/settings/inspirations +``` + +- [ ] **Step 3: preload 暴露新 API 命名空间** + +```typescript +outline: { list, create, update, delete, move }, +setting: { list, create, update, delete }, +// ... +search: { query, replace, getHistory, saveHistory }, +wordfreq: { analyze }, +``` + +- [ ] **Step 4: `npm run build` + Commit** + +```bash +git commit -am "feat: add P2 IPC handlers and preload API" +``` + +--- + +## Task 10: useEditStore + 统一 TipTap 编辑 + +**Files:** +- Create: `src/renderer/stores/useEditStore.ts` +- Modify: `src/renderer/components/editor/TipTapEditor.tsx` +- Modify: `src/renderer/components/layout/EditorLayout.tsx` +- Modify: `src/renderer/stores/useBookStore.ts` + +- [ ] **Step 1: useEditStore.ts** + +```typescript +interface EditState { + target: EditTarget | null + switchTarget: (next: EditTarget) => Promise + saveCurrent: () => Promise +} + +switchTarget: async (next) => { + await flushEditorSave() + const data = await loadTargetContent(next) // IPC by kind + set({ target: next }) + // TipTapEditor reacts via target prop +} +``` + +- [ ] **Step 2: TipTapEditor 接受 target + contentLoader** + +```typescript +interface TipTapEditorProps { + target: EditTarget | null +} +``` + +`useEditor` extensions:target.kind === 'chapter' ? fullStarterKit : simplifiedKit。 + +save 回调按 kind 分发 IPC:`chapter.update` / `outline.update` / etc. + +- [ ] **Step 3: EditorLayout 四 Tab 选中 → switchTarget** + +删除 `activePanel !== 'chapters'` 占位,替换为 OutlineTree / SettingList / InspirationList。 + +- [ ] **Step 4: Commit** + +```bash +git commit -am "feat: add unified EditSession and TipTap targets" +``` + +--- + +## Task 11: 左栏 CRUD UI(大纲/设定/灵感) + +**Files:** +- Create: `src/renderer/components/outline/OutlineTree.tsx` +- Create: `src/renderer/components/setting/SettingList.tsx` +- Create: `src/renderer/components/inspiration/InspirationList.tsx` +- Modify: `public/locales/zh-CN/translation.json`(及 en) + +- [ ] **Step 1: OutlineTree** — 递归渲染;双击标题 inline 编辑;底部「+ 新建大纲」;未覆盖橙色边框 + +- [ ] **Step 2: SettingList** — 按 type 分组;底部新建 Dialog(type select + name) + +- [ ] **Step 3: InspirationList** — 列表 + 新建;`InspirationModal` 快速捕获(Ctrl+Shift+I) + +- [ ] **Step 4: E2E outline 持久化** + +`e2e/outline.spec.ts`:建书 → 新建大纲 → 输入内容 → 重启 → 内容保留。 + +- [ ] **Step 5: Commit** + +```bash +git commit -am "feat: add outline setting inspiration sidebar UI" +``` + +--- + +## Task 12: 大纲对照视图(P2.3) + +**Files:** +- Create: `src/renderer/components/outline/OutlineCompareView.tsx` +- Modify: `src/renderer/stores/useOutlineStore.ts` + +- [ ] **Step 1: useOutlineStore** — `compareMode: boolean`、`filter: 'all'|'uncovered'|'covered'` + +- [ ] **Step 2: OutlineCompareView** — 35/65 分屏;右侧只读章节 HTML;底部偏差条 + +- [ ] **Step 3: E2E E2E-COV-01/02**(spec §5.5.3) + +- [ ] **Step 4: Commit** + +```bash +git commit -am "feat: add outline compare view and coverage filter" +``` + +--- + +## Task 13: 引用面板(P2.4) + +**Files:** +- Create: `src/renderer/components/reference/ReferencePanel.tsx` +- Create: `src/renderer/stores/useReferenceStore.ts` +- Modify: `src/renderer/styles/layout.css`(`#reference-panel`) +- Create: `src/renderer/extensions/mention.ts` +- Modify: `src/renderer/App.tsx`(openReference 快捷键) + +- [ ] **Step 1: ReferencePanel** — Tab + 搜索 + 钉住 + 拖拽(`onDragStart` setData text/plain) + +- [ ] **Step 2: 与 AI 右栏互斥** — `useAppStore` 或 layout state:`referenceOpen` 时隐藏 RightPanel + +- [ ] **Step 3: Mention 扩展(简化)** — 输入 `@` 弹出设定名列表;点击跳转 `switchTarget({kind:'setting',id})` + +- [ ] **Step 4: E2E E2E-P2-REF-01** + +- [ ] **Step 5: Commit** + +```bash +git commit -am "feat: add reference panel with drag insert and mentions" +``` + +--- + +## Task 14: 版本历史模态(P2.5) + +**Files:** +- Create: `src/renderer/components/version/VersionModal.tsx` +- Modify: `src/renderer/components/layout/EditorLayout.tsx`(工具栏入口) +- Modify: `src/renderer/App.tsx`(Ctrl+S 触发 persist snapshot) + +- [ ] **Step 1: VersionModal UI** — 列表 + 选中版本;双栏 diff 用 `diff-match-patch` + +```typescript +import DiffMatchPatch from 'diff-match-patch' +const dmp = new DiffMatchPatch() +const diffs = dmp.diff_main(oldPlain, newPlain) +dmp.diff_cleanupSemantic(diffs) +``` + +渲染:DIFF_INSERT 绿色背景,DIFF_DELETE 红色删除线。 + +- [ ] **Step 2: 回滚** — 调用 `snapshot:restore`;确认 Dialog + +- [ ] **Step 3: SnapshotService wired** — EditorLayout mount 章节时 `startAutoSave` + +- [ ] **Step 4: E2E E2E-P2-SNAP-01** + +- [ ] **Step 5: Commit** + +```bash +git commit -am "feat: add chapter version history with diff and restore" +``` + +--- + +## Task 15: 全局搜索模态(P2.6) + +**Files:** +- Create: `src/renderer/components/search/SearchModal.tsx` +- Create: `src/renderer/stores/useSearchStore.ts` +- Modify: `src/renderer/App.tsx`(globalSearch 快捷键) + +- [ ] **Step 1: SearchModal** — 对齐 `#searchModal`;范围 select;高级选项折叠(regex/case) + +- [ ] **Step 2: 结果跳转** — chapter → switchTarget + scroll;bookmark → chapter + position + +- [ ] **Step 3: 替换预览** — 调用 `search:replace` dryRun → 确认 → 执行 + +- [ ] **Step 4: searchHistory** — 下拉最近 10 条 + +- [ ] **Step 5: E2E E2E-P2-SEARCH-01 + Commit** + +```bash +git commit -am "feat: add global search modal with FTS and replace" +``` + +--- + +## Task 16: 地标全量(P2.6) + +**Files:** +- Create: `src/renderer/extensions/landmark-mark.ts` +- Create: `src/renderer/components/landmark/LandmarkModal.tsx` +- Modify: `src/renderer/components/editor/TipTapEditor.tsx` + +- [ ] **Step 1: TipTap Mark** — 行内 `[TODO: label]` 样式;insertLandmark 快捷键打开输入 + +- [ ] **Step 2: LandmarkModal** — 按类型/章节分组;跳转 `switchTarget chapter` + `editor.commands.focus(pos)` + +- [ ] **Step 3: FTS 同步 bookmark label** + +- [ ] **Step 4: E2E E2E-P2-LAND-01 + Commit** + +```bash +git commit -am "feat: add writing landmarks and list modal" +``` + +--- + +## Task 17: 用词分析(P2.7) + +**Files:** +- Modify: `src/renderer/components/layout/RightPanel.tsx` +- Create: `src/renderer/components/wordfreq/WordFreqPanel.tsx` + +- [ ] **Step 1: WordFreqPanel** — 调用 `wordfreq:analyze`;Top 100 列表;点击 → 编辑器 `scrollIntoView` + 临时 highlight Mark + +- [ ] **Step 2: 过度用词** — 阈值:每千字 >5 次;TipTap Decoration 淡黄色 + +- [ ] **Step 3: §5.6.2 占位** — 面板底部按钮 → `showToast(t('feature.comingSoon'))` + +- [ ] **Step 4: E2E E2E-P2-WORD-01 + Commit** + +```bash +git commit -am "feat: add word frequency panel and overuse highlight" +``` + +--- + +## Task 18: 全量测试与 v0.2.0 收尾 + +**Files:** +- Modify: `package.json`(version 0.2.0) +- Modify: `README.md` + +- [ ] **Step 1: 运行全量测试** + +```bash +npm run test +npm run build +npm run test:e2e +``` + +Expected: 全部 PASS + +- [ ] **Step 2: 手动验收** — spec §1.3 七项 + §10 DoD + +- [ ] **Step 3: 更新 README** — v0.2.0 功能列表、测试命令 + +- [ ] **Step 4: Commit + tag** + +```bash +git commit -am "chore: prepare v0.2.0 release" +git tag v0.2.0 +``` + +--- + +## Plan Self-Review + +| Spec 章节 | 对应用 Task | +|-----------|-------------| +| §5.9 主题 P2.0 | Task 1 | +| §3 Schema v2 | Task 3 | +| §4 IPC | Task 2, 9 | +| §5.1 四 Tab | Task 10, 11 | +| §5.5 大纲对照/覆盖度 | Task 12 | +| §5.3.8 引用面板 | Task 13 | +| §5.4 版本历史 | Task 8, 14 | +| §5.6.1 搜索 | Task 7, 15 | +| §5.3.9 地标 | Task 16 | +| §5.6.3 用词分析 | Task 17 | +| §5.6.2 AI 命名 | Task 17 Step 3 占位 | +| §7 测试 | Task 1–17 各 E2E + Task 18 | +| §10 DoD | Task 18 | + +**Placeholder 扫描:** 无 TBD;章节拖拽明确未含;语音灵感为占位。 + +**类型一致性:** `EditTarget`、`SearchSourceKind`、`SnapshotType` 在 Task 2 定义,后续任务一致引用。 + +--- + +## 执行方式 + +Plan 已保存至 `docs/superpowers/plans/2026-07-06-bilin-p2.md`。 + +**两种执行选项:** + +1. **Subagent-Driven(推荐)** — 每个 Task 派发独立 subagent,任务间 review,迭代快 +2. **Inline Execution** — 在本会话按 Task 顺序直接实现,批次间设检查点 + +你选哪种?