Files
bilin/docs/superpowers/plans/2026-07-06-bilin-p2.md
T
bing 91c93954df docs: 添加笔临 P2 实现计划
18 个 Task 覆盖主题修复、schema v2、统一编辑、引用/搜索/版本/地标/用词分析至 v0.2.0。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-06 10:50:52 +08:00

732 lines
21 KiB
Markdown
Raw 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.
# 笔临 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 MapP2 新增/修改核心文件)
| 文件 | 职责 |
|------|------|
| `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<void>
saveCurrent: () => Promise<void>
}
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` extensionstarget.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 分组;底部新建 Dialogtype 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 + scrollbookmark → 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 117 各 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 顺序直接实现,批次间设检查点
你选哪种?