feat: ship v0.9.0 with pomodoro, achievements, and injection history
Add pomodoro timer with goal notifications, writing streak milestones, and knowledge injection logging with UI previews across AI writing flows. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# 笔临 P5.3 + P6.1 写作目标 + 知识注入历史 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.
|
||||
> **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 (`- [x]`) syntax for tracking.
|
||||
|
||||
**Goal:** 交付 v0.9.0:§8 番茄钟(15/25/45)、连更里程碑徽章(7/30/100)、日更/番茄/里程碑通知;P6.1 写作流三模式知识注入历史记录与知识库反向链接 UI。
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
- Modify: `src/main/services/global-settings.ts`
|
||||
- Modify: `src/renderer/stores/useSettingsStore.ts`
|
||||
|
||||
- [ ] **Step 1: 扩展 types**
|
||||
- [x] **Step 1: 扩展 types**
|
||||
|
||||
```typescript
|
||||
export type PomodoroDuration = 15 | 25 | 45
|
||||
@@ -115,7 +115,7 @@ enableGoalNotifications?: boolean
|
||||
dailyGoalNotifiedDate?: string // YYYY-MM-DD,防重复达标 Toast
|
||||
```
|
||||
|
||||
- [ ] **Step 2: IPC 通道**
|
||||
- [x] **Step 2: IPC 通道**
|
||||
|
||||
```typescript
|
||||
POMODORO_START: 'pomodoro:start',
|
||||
@@ -129,7 +129,7 @@ POMODORO_TICK: 'pomodoro:tick', // main → renderer push
|
||||
GOAL_NOTIFICATION: 'goal:notification', // main → renderer push
|
||||
```
|
||||
|
||||
- [ ] **Step 3: global-settings 默认值**
|
||||
- [x] **Step 3: global-settings 默认值**
|
||||
|
||||
```typescript
|
||||
pomodoroDurationMinutes: 25,
|
||||
@@ -137,9 +137,9 @@ enableSystemNotifications: false,
|
||||
enableGoalNotifications: true,
|
||||
```
|
||||
|
||||
- [ ] **Step 4: useSettingsStore 同步**
|
||||
- [x] **Step 4: useSettingsStore 同步**
|
||||
|
||||
- [ ] **Step 5: build**
|
||||
- [x] **Step 5: build**
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
@@ -155,7 +155,7 @@ npm run build
|
||||
- Create: `src/main/db/repositories/pomodoro-daily.repo.ts`
|
||||
- Create: `tests/main/achievement.test.ts`(先写 milestone repo 部分)
|
||||
|
||||
- [ ] **Step 1: writing-log.repo migrate 扩展**
|
||||
- [x] **Step 1: writing-log.repo migrate 扩展**
|
||||
|
||||
在 `migrate()` 追加:
|
||||
|
||||
@@ -171,7 +171,7 @@ CREATE TABLE IF NOT EXISTS pomodoro_daily (
|
||||
);
|
||||
```
|
||||
|
||||
- [ ] **Step 2: WritingMilestoneRepository**
|
||||
- [x] **Step 2: WritingMilestoneRepository**
|
||||
|
||||
```typescript
|
||||
export class WritingMilestoneRepository {
|
||||
@@ -182,7 +182,7 @@ export class WritingMilestoneRepository {
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 3: PomodoroDailyRepository**
|
||||
- [x] **Step 3: PomodoroDailyRepository**
|
||||
|
||||
```typescript
|
||||
recordComplete(bookId: string, wordDelta: number, date?: string): void {
|
||||
@@ -191,7 +191,7 @@ recordComplete(bookId: string, wordDelta: number, date?: string): void {
|
||||
getTodayCount(bookId: string): number
|
||||
```
|
||||
|
||||
- [ ] **Step 4: UT-ACH repo smoke**
|
||||
- [x] **Step 4: UT-ACH repo smoke**
|
||||
|
||||
```typescript
|
||||
it('UT-ACH-01: unlock streak_7 once', () => {
|
||||
@@ -201,7 +201,7 @@ it('UT-ACH-01: unlock streak_7 once', () => {
|
||||
})
|
||||
```
|
||||
|
||||
- [ ] **Step 5: 运行**
|
||||
- [x] **Step 5: 运行**
|
||||
|
||||
```bash
|
||||
npm run test -- tests/main/achievement.test.ts -t "UT-ACH-01"
|
||||
@@ -218,9 +218,9 @@ npm run test -- tests/main/achievement.test.ts -t "UT-ACH-01"
|
||||
- Create: `tests/main/migrate-v8.test.ts`
|
||||
- Create: `tests/main/knowledge-injection.test.ts`
|
||||
|
||||
- [ ] **Step 1: schema-v8.sql**(见 spec §3.2)
|
||||
- [x] **Step 1: schema-v8.sql**(见 spec §3.2)
|
||||
|
||||
- [ ] **Step 2: migrate.ts**
|
||||
- [x] **Step 2: migrate.ts**
|
||||
|
||||
```typescript
|
||||
import schemaV8 from './schema-v8.sql?raw'
|
||||
@@ -232,21 +232,21 @@ if (current < 8) {
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 3: KnowledgeInjectionRepository**
|
||||
- [x] **Step 3: KnowledgeInjectionRepository**
|
||||
|
||||
```typescript
|
||||
insertBatch(rows: Array<Omit<KnowledgeInjectionLog, 'id' | 'injectedAt'>>): void
|
||||
listForEntry(entryId: string, limit = 50): KnowledgeInjectionLog[]
|
||||
```
|
||||
|
||||
- [ ] **Step 4: UT-MIG-08 + UT-INJ-01**
|
||||
- [x] **Step 4: UT-MIG-08 + UT-INJ-01**
|
||||
|
||||
```typescript
|
||||
it('UT-MIG-08: v7 database migrates to v8 with injection table', () => { /* ... */ })
|
||||
it('UT-INJ-01: insertBatch creates 3 rows', () => { /* ... */ })
|
||||
```
|
||||
|
||||
- [ ] **Step 5: 运行**
|
||||
- [x] **Step 5: 运行**
|
||||
|
||||
```bash
|
||||
npm run test -- tests/main/migrate-v8.test.ts tests/main/knowledge-injection.test.ts
|
||||
@@ -260,7 +260,7 @@ npm run test -- tests/main/migrate-v8.test.ts tests/main/knowledge-injection.tes
|
||||
- Create: `src/main/services/pomodoro.service.ts`
|
||||
- Create: `tests/main/pomodoro.test.ts`
|
||||
|
||||
- [ ] **Step 1: PomodoroService 实现**
|
||||
- [x] **Step 1: PomodoroService 实现**
|
||||
|
||||
```typescript
|
||||
export class PomodoroService {
|
||||
@@ -304,14 +304,14 @@ export class PomodoroService {
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: UT-POM-01 / UT-POM-02**
|
||||
- [x] **Step 2: UT-POM-01 / UT-POM-02**
|
||||
|
||||
```typescript
|
||||
it('UT-POM-01: complete records word delta', () => { /* mock writingLogs */ })
|
||||
it('UT-POM-02: start different book cancels previous', () => { /* ... */ })
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 运行**
|
||||
- [x] **Step 3: 运行**
|
||||
|
||||
```bash
|
||||
npm run test -- tests/main/pomodoro.test.ts
|
||||
@@ -327,7 +327,7 @@ npm run test -- tests/main/pomodoro.test.ts
|
||||
- Modify: `src/main/services/writing-log.service.ts`
|
||||
- Modify: `tests/main/achievement.test.ts`
|
||||
|
||||
- [ ] **Step 1: GoalNotificationService**
|
||||
- [x] **Step 1: GoalNotificationService**
|
||||
|
||||
```typescript
|
||||
export class GoalNotificationService {
|
||||
@@ -353,7 +353,7 @@ export class GoalNotificationService {
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: AchievementService**
|
||||
- [x] **Step 2: AchievementService**
|
||||
|
||||
```typescript
|
||||
checkMilestones(bookId: string): WritingAchievement[] {
|
||||
@@ -372,7 +372,7 @@ checkMilestones(bookId: string): WritingAchievement[] {
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 3: WritingLogService.addToday 扩展**
|
||||
- [x] **Step 3: WritingLogService.addToday 扩展**
|
||||
|
||||
`addToday` 返回后:
|
||||
|
||||
@@ -384,9 +384,9 @@ if (stats.dailyGoal > 0 && stats.todayWords >= stats.dailyGoal) {
|
||||
this.achievementService.checkMilestones(bookId)
|
||||
```
|
||||
|
||||
- [ ] **Step 4: UT-ACH-02 + IT-GOAL-01**
|
||||
- [x] **Step 4: UT-ACH-02 + IT-GOAL-01**
|
||||
|
||||
- [ ] **Step 5: 运行**
|
||||
- [x] **Step 5: 运行**
|
||||
|
||||
```bash
|
||||
npm run test -- tests/main/achievement.test.ts
|
||||
@@ -403,7 +403,7 @@ npm run test -- tests/main/achievement.test.ts
|
||||
- Modify: `src/main/ipc/handlers/wizard.handler.ts`
|
||||
- Modify: `tests/main/knowledge-injection.test.ts`
|
||||
|
||||
- [ ] **Step 1: KnowledgeInjectionService**
|
||||
- [x] **Step 1: KnowledgeInjectionService**
|
||||
|
||||
```typescript
|
||||
export class KnowledgeInjectionService {
|
||||
@@ -424,7 +424,7 @@ export class KnowledgeInjectionService {
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: interactive.handler 挂钩**
|
||||
- [x] **Step 2: interactive.handler 挂钩**
|
||||
|
||||
在 `INTERACTIVE_CONFIRM_CONTEXT` 的 `buildFlowContextPayload` 成功后:
|
||||
|
||||
@@ -441,13 +441,13 @@ try {
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 3: auto / wizard 同理**
|
||||
- [x] **Step 3: auto / wizard 同理**
|
||||
|
||||
- [ ] **Step 4: IT-INJ-01**
|
||||
- [x] **Step 4: IT-INJ-01**
|
||||
|
||||
直接调用 handler 或 service + 内存 DB,断言 `knowledge_injection_logs` 行数。
|
||||
|
||||
- [ ] **Step 5: 运行**
|
||||
- [x] **Step 5: 运行**
|
||||
|
||||
```bash
|
||||
npm run test -- tests/main/knowledge-injection.test.ts
|
||||
@@ -466,9 +466,9 @@ npm run test -- tests/main/knowledge-injection.test.ts
|
||||
- Modify: `src/preload/index.ts`
|
||||
- Modify: `src/shared/electron-api.d.ts`
|
||||
|
||||
- [ ] **Step 1: pomodoro.handler + achievement.handler**
|
||||
- [x] **Step 1: pomodoro.handler + achievement.handler**
|
||||
|
||||
- [ ] **Step 2: knowledge.handler**
|
||||
- [x] **Step 2: knowledge.handler**
|
||||
|
||||
```typescript
|
||||
ipcMain.handle(IPC.KNOWLEDGE_LIST_INJECTIONS, (_e, { bookId, entryId, limit }) =>
|
||||
@@ -476,7 +476,7 @@ ipcMain.handle(IPC.KNOWLEDGE_LIST_INJECTIONS, (_e, { bookId, entryId, limit }) =
|
||||
)
|
||||
```
|
||||
|
||||
- [ ] **Step 3: register.ts 注入**
|
||||
- [x] **Step 3: register.ts 注入**
|
||||
|
||||
```typescript
|
||||
const goalNotify = new GoalNotificationService(settings, () => getMainWindow())
|
||||
@@ -487,7 +487,7 @@ registerPomodoroHandlers(pomodoro)
|
||||
registerAchievementHandlers(achievementService)
|
||||
```
|
||||
|
||||
- [ ] **Step 4: preload**
|
||||
- [x] **Step 4: preload**
|
||||
|
||||
```typescript
|
||||
pomodoro: {
|
||||
@@ -501,14 +501,14 @@ onPomodoroTick: (cb) => { ipcRenderer.on(IPC.POMODORO_TICK, cb); return () => ..
|
||||
onGoalNotification: (cb) => { ipcRenderer.on(IPC.GOAL_NOTIFICATION, cb); return () => ... },
|
||||
```
|
||||
|
||||
- [ ] **Step 5: CockpitService 扩展**
|
||||
- [x] **Step 5: CockpitService 扩展**
|
||||
|
||||
```typescript
|
||||
achievements: this.achievementService.listAchievements(bookId),
|
||||
pomodoroTodayCount: this.pomodoroDaily.getTodayCount(bookId),
|
||||
```
|
||||
|
||||
- [ ] **Step 6: build**
|
||||
- [x] **Step 6: build**
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
@@ -524,11 +524,11 @@ npm run build
|
||||
- Modify: `src/renderer/App.tsx`(注册 onGoalNotification 全局 Toast)
|
||||
- Modify: `src/renderer/styles/layout.css`
|
||||
|
||||
- [ ] **Step 1: usePomodoroStore**
|
||||
- [x] **Step 1: usePomodoroStore**
|
||||
|
||||
订阅 `onPomodoroTick`;actions:`start/pause/resume/cancel`。
|
||||
|
||||
- [ ] **Step 2: EditorLayout 状态栏控件**
|
||||
- [x] **Step 2: EditorLayout 状态栏控件**
|
||||
|
||||
```tsx
|
||||
<div className="pomodoro-control" data-testid="pomodoro-control">
|
||||
@@ -544,7 +544,7 @@ npm run build
|
||||
</div>
|
||||
```
|
||||
|
||||
- [ ] **Step 3: App.tsx goal notification**
|
||||
- [x] **Step 3: App.tsx goal notification**
|
||||
|
||||
```typescript
|
||||
useEffect(() => {
|
||||
@@ -554,7 +554,7 @@ useEffect(() => {
|
||||
}, [])
|
||||
```
|
||||
|
||||
- [ ] **Step 4: build 验证**
|
||||
- [x] **Step 4: build 验证**
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
@@ -570,7 +570,7 @@ npm run build
|
||||
- Modify: `public/locales/zh-CN/translation.json`
|
||||
- Modify: `public/locales/en/translation.json`
|
||||
|
||||
- [ ] **Step 1: CockpitModal 成就区**
|
||||
- [x] **Step 1: CockpitModal 成就区**
|
||||
|
||||
```tsx
|
||||
{summary.achievements && summary.achievements.length > 0 && (
|
||||
@@ -581,13 +581,13 @@ npm run build
|
||||
</div>
|
||||
```
|
||||
|
||||
- [ ] **Step 2: SettingsPage 三项设置**
|
||||
- [x] **Step 2: SettingsPage 三项设置**
|
||||
|
||||
`settings-pomodoro-duration` / `settings-system-notifications` / `settings-goal-notifications`
|
||||
|
||||
- [ ] **Step 3: i18n**(spec §7 全部键,中英)
|
||||
- [x] **Step 3: i18n**(spec §7 全部键,中英)
|
||||
|
||||
- [ ] **Step 4: build**
|
||||
- [x] **Step 4: build**
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
@@ -602,7 +602,7 @@ npm run build
|
||||
- Modify: `src/renderer/components/knowledge/KnowledgeEditorDialog.tsx`
|
||||
- Modify: `src/renderer/stores/useKnowledgeStore.ts`
|
||||
|
||||
- [ ] **Step 1: KnowledgePanel 加载注入预览**
|
||||
- [x] **Step 1: KnowledgePanel 加载注入预览**
|
||||
|
||||
条目 render 时调用 `knowledge.listInjections(bookId, entry.id, 3)`(或 batch 加载 map)。
|
||||
|
||||
@@ -614,11 +614,11 @@ npm run build
|
||||
</div>
|
||||
```
|
||||
|
||||
- [ ] **Step 2: KnowledgeEditorDialog 完整历史**
|
||||
- [x] **Step 2: KnowledgeEditorDialog 完整历史**
|
||||
|
||||
`data-testid="knowledge-injection-history"`;章节名点击 `switchTarget({ kind:'chapter', id })`。
|
||||
|
||||
- [ ] **Step 3: build**
|
||||
- [x] **Step 3: build**
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
@@ -635,17 +635,17 @@ npm run build
|
||||
- Modify: `README.md`
|
||||
- Modify: `tests/main/migrate-v7.test.ts` 等(若 CURRENT_VERSION→8,期望版本改为 8)
|
||||
|
||||
- [ ] **Step 1: E2E-GOAL-01~03**
|
||||
- [x] **Step 1: E2E-GOAL-01~03**
|
||||
|
||||
- E2E-GOAL-01:设 dailyWordGoal=100,打字保存,断言 toast / status-daily-goal
|
||||
- E2E-GOAL-02:通过测试 hook 或 seed API 写入 streak_7 milestone,打开驾驶舱断言 `cockpit-achievements`
|
||||
- E2E-GOAL-03:`POMODORO_TEST_SEC=3`,启动番茄,等待完成 Toast
|
||||
|
||||
- [ ] **Step 2: E2E-INJ-01**
|
||||
- [x] **Step 2: E2E-INJ-01**
|
||||
|
||||
向导 confirm 知识上下文(可 stub 空 AI),断言 `knowledge-injection-preview-*` 可见。
|
||||
|
||||
- [ ] **Step 3: 全量测试**
|
||||
- [x] **Step 3: 全量测试**
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
@@ -653,11 +653,11 @@ npm run test
|
||||
npm run test:e2e -- e2e/writing-goals.spec.ts e2e/knowledge-injection-history.spec.ts
|
||||
```
|
||||
|
||||
- [ ] **Step 4: 版本 0.9.0**
|
||||
- [x] **Step 4: 版本 0.9.0**
|
||||
|
||||
`package.json`、`README.md`、`SettingsPage` about 版本号。
|
||||
|
||||
- [ ] **Step 5: 更新 migrate-v2~v7 测试期望版本 → 8**(与 P5.2 v7 时同样处理)
|
||||
- [x] **Step 5: 更新 migrate-v2~v7 测试期望版本 → 8**(与 P5.2 v7 时同样处理)
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user