Files
bilin/docs/superpowers/specs/2026-07-07-bilin-p53-p61-goals-injection-design.md
T
bing 1099cb2b0e docs: add P5.3 and P6.1 goals and injection history design spec for v0.9.0
Define pomodoro, milestone badges, goal notifications, and knowledge injection logging for the next release.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 18:51:45 +08:00

18 KiB
Raw Blame History

笔临 P5.3 + P6.1 写作目标补全 + 知识注入历史 设计规格

版本1.0
日期2026-07-07
范围:P5.3(§8 补全)番茄钟、连更里程碑徽章、达标通知;P6.1 知识库条目注入历史与反向链接
前置:P5.2 写作日志 + AI 知识抽取已交付(v0.8.0,a39e06f);P6 AI 知识上下文(v0.7.0
参考design/readme.md v1.1 §8 / §5.5.7、docs/superpowers/specs/2026-07-07-bilin-p52-writing-logs-extraction-design.mddocs/superpowers/specs/2026-07-07-bilin-p6-ai-context-design.md

目标版本v0.9.0


1. 背景与目标

1.1 阶段定位

v0.8.0 已交付 writing_logs 日更追踪、驾驶舱热力图/连更、状态栏日更进度,以及 AI 章节知识抽取与 P6 注入链路。但 design/readme.md §8 仍缺 番茄钟7/30/100 天连更里程碑徽章达标/完成通知P6 spec 延后的 注入历史 / 反向链接 尚未落地,作者无法在知识库条目上查看「这条知识曾在哪些写作流中被 AI 使用」。

本阶段(v0.9.0)双线交付:

  • P5.3:补齐 §8 剩余能力,强化日更作者的正反馈与专注工具
  • P6.1:在知识库条目上记录并展示写作流(交互/自动/向导)上下文确认时的注入历史

1.2 已确认决策(Brainstorming 2026-07-07

维度 决策
交付版本 v0.9.0 单版交付 P5.3 + P6.1
架构方案 主进程服务分层PomodoroService + AchievementService + GoalNotificationService + KnowledgeInjectionService
统计范围 当前书籍(与 P5.2 一致:连更、里程碑、番茄字数增量、成就均按 bookId
通知 Toast + 可选 Electron 系统通知;设置页可关闭系统通知与目标通知
番茄钟 UI 状态栏紧凑控件(▶/⏸ + 剩余时间);驾驶舱展示今日番茄完成次数
番茄时长 设置页 15 / 25 / 45 分钟 三档,默认 25
里程碑 UI 庆祝 + 持久展示:达成时 Toast/系统通知;驾驶舱「成就区」展示已解锁 7/30/100 天徽章
P6.1 范围 仅知识库条目(不含设定条目 AI 注入历史)
P6.1 记录场景 交互 / 自动 / 向导 三模式 confirmContextknowledgeIds 非空;不含 AI 对话助手
注入历史 UI 列表最近 3 条预览 + 编辑对话框完整时间线
切换书籍(番茄进行中) 自动取消番茄并 Toast 提示

1.3 验收标准

用户能完成:

  1. 在状态栏启动 15/25/45 分钟番茄钟,暂停/取消/完成后看到剩余时间变化;完成时 Toast 显示本次新增字数
  2. enableSystemNotifications 开启时,番茄完成与里程碑解锁可收到 系统通知(权限被拒则降级 Toast
  3. dailyWordGoal > 0 且当日首次达标时收到 Toast(及可选系统通知);同一自然日不重复提醒
  4. 连更达到 7 / 30 / 100 天(基于 P5.2 streakDays)时:庆祝通知 + 驾驶舱成就区永久展示对应徽章;每档仅庆祝一次
  5. 交互/自动/向导 确认知识上下文后,被注入的 approved 知识条目在 KnowledgePanel 卡片显示最近 3 条注入记录
  6. 打开 KnowledgeEditorDialog 可查看该条目完整注入历史(时间、模式、关联章节)
  7. 注入记录失败 不阻断 写作流确认步骤

1.4 本规格不实现(明确排除)

归属
预计完本、写作速度仪表盘、时段热力图 §9 延后
设定条目「被 AI 注入的轮次」 P6.2
AI 对话助手注入历史 本阶段排除(用户确认 C
番茄钟自定义任意分钟数、休息间隔、番茄统计全屏页 后续
里程碑 365 天等扩展档位 后续
语义 embedding、注入内容 diff 后续
导入导出、章节模板 P7 / §10

2. 架构

2.1 进程模型

┌────────────────────────────────────────────────────────────────────┐
│ 主进程                                                              │
│  · PomodoroService(倒计时、开始/暂停/取消、完成字数差分)            │
│  · AchievementService7/30/100 里程碑解锁检测与持久化)              │
│  · GoalNotificationServiceToast IPC + Notification,受设置控制)  │
│  · WritingLogService(已有,番茄快照/差分、streakDays)               │
│  · KnowledgeInjectionService(写入/查询 injection logs              │
│  · CockpitService 扩展(成就区、pomodoroTodayCount                  │
│  · interactive/auto/wizard confirmContext 挂钩 injection 记录       │
└──────────────────────────────┬─────────────────────────────────────┘
                               │ IPC
┌──────────────────────────────▼─────────────────────────────────────┐
│ 渲染进程                                                            │
│  · EditorLayout 状态栏:番茄控件 + 日更进度(已有)                   │
│  · CockpitModal:成就区徽章 + 今日番茄次数                            │
│  · SettingsPage:番茄时长、通知开关                                   │
│  · KnowledgePanel:注入历史最近 3 条预览                              │
│  · KnowledgeEditorDialog:完整注入历史列表                            │
└────────────────────────────────────────────────────────────────────┘

2.2 模块边界

模块 职责 依赖
PomodoroService 单实例番茄状态机;完成时计算 wordDelta WritingLogService, GlobalSettings
AchievementService streakDays,写 writing_milestones,触发庆祝 WritingLogService, GoalNotificationService
GoalNotificationService 统一发送 goal-met / milestone / pomodoro 通知 GlobalSettings, NotificationElectron
KnowledgeInjectionService batch 写入、按 entry 查询、recent N 每书 KnowledgeInjectionRepository
CockpitService 聚合 achievements[]pomodoroTodayCount 上述服务

原则

  • 番茄钟状态在主进程,保证最小化/失焦时计时准确、完成时可发系统通知
  • 注入记录与 confirmContext 同事务意图build 成功即写 log;写 log 失败仅 console.error,不抛给 IPC
  • 成就不回溯:仅在未来 streakDays 首次跨档时解锁

3. 数据模型

3.1 全局 userData:扩展 writing_logs.sqlite

在现有 writing_logs 表基础上 同库追加WritingLogRepository.migrate() 扩展):

CREATE TABLE IF NOT EXISTS writing_milestones (
  book_id      TEXT NOT NULL,
  milestone    TEXT NOT NULL,   -- 'streak_7' | 'streak_30' | 'streak_100'
  unlocked_at  TEXT NOT NULL DEFAULT (datetime('now')),
  PRIMARY KEY (book_id, milestone)
);

CREATE TABLE IF NOT EXISTS pomodoro_daily (
  date            TEXT NOT NULL,
  book_id         TEXT NOT NULL,
  completed_count INTEGER NOT NULL DEFAULT 0,
  total_words     INTEGER NOT NULL DEFAULT 0,
  PRIMARY KEY (date, book_id)
);

pomodoro_daily 在每次番茄 完成completed_count += 1total_words += wordDelta

3.2 每书 schema v8

新文件 schema-v8.sql

CREATE TABLE IF NOT EXISTS knowledge_injection_logs (
  id                  TEXT PRIMARY KEY,
  knowledge_entry_id  TEXT NOT NULL,
  flow_mode           TEXT NOT NULL,   -- 'interactive' | 'auto' | 'wizard'
  flow_id             TEXT NOT NULL,
  chapter_id          TEXT,
  injected_at         TEXT NOT NULL DEFAULT (datetime('now')),
  FOREIGN KEY (knowledge_entry_id) REFERENCES knowledge_entries(id) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_injection_entry_time
  ON knowledge_injection_logs (knowledge_entry_id, injected_at DESC);

migrate.tsCURRENT_VERSION = 8v7→v8 仅 exec(schemaV8)

3.3 TypeScript 类型(src/shared/types.ts

export type PomodoroDuration = 15 | 25 | 45
export type WritingMilestone = 'streak_7' | 'streak_30' | 'streak_100'
export type InjectionFlowMode = 'interactive' | 'auto' | 'wizard'

export interface PomodoroState {
  running: boolean
  paused: boolean
  remainingSec: number
  bookId: string | null
  startedAt: string | null
}

export interface WritingAchievement {
  milestone: WritingMilestone
  unlockedAt: string
}

export interface KnowledgeInjectionLog {
  id: string
  knowledgeEntryId: string
  flowMode: InjectionFlowMode
  flowId: string
  chapterId?: string
  injectedAt: string
}

export interface CockpitSummary {
  // 已有字段…
  achievements?: WritingAchievement[]
  pomodoroTodayCount?: number
}

扩展 GlobalSettings

pomodoroDurationMinutes?: PomodoroDuration   // default 25
enableSystemNotifications?: boolean         // default false
enableGoalNotifications?: boolean           // default true

4. 服务行为

4.1 PomodoroService

  • start(bookId):若已有运行中番茄且 bookId 不同,先 cancel 再 start;记录 wordSnapshot = WritingLogService.getStats(bookId).todayWords
  • pause / resume / cancel:标准状态机;cancel 清空快照
  • tick:主进程 setInterval(1s) 递减;remainingSec === 0 触发 complete()
  • complete()
    • wordDelta = max(0, todayWords_now - wordSnapshot)
    • 更新 pomodoro_daily
    • GoalNotificationService.notifyPomodoroComplete(bookId, wordDelta)
    • 重置状态

渲染进程每 1s 通过 IPC pomodoro:getState 同步 UI(或由主进程 push POMODORO_TICK 事件,实现时二选一,计划阶段选定 push 以减少轮询)。

4.2 AchievementService

  • WritingLogService 写入后Cockpit getSummary 时调用 checkMilestones(bookId)
    • streakDays(需 dailyWordGoal > 0
    • streakDays >= 7 且 DB 无 streak_7 → insert + notify
    • 同理 30、100
  • listAchievements(bookId)WritingAchievement[] 按 milestone 排序

4.3 GoalNotificationService

事件 Toast 系统通知(enableSystemNotifications
日更首次达标 ✓(enableGoalNotifications 可选
里程碑解锁 可选
番茄完成 可选

Toast 经现有 useAppStore.showToast 模式:主进程 webContents.send(GOAL_NOTIFICATION, payload) 或复用通用 notification IPC。

系统通知权限被拒:catch 并忽略,不抛错。

4.4 KnowledgeInjectionService

挂钩点(均在 buildFlowContextPayload 成功返回之后):

  • interactive.handlerINTERACTIVE_CONFIRM_CONTEXT
  • auto.handlerAUTO_CONFIRM_CONTEXT
  • wizard.handlerWIZARD_CONFIRM_CONTEXT
recordInjection(bookId, {
  knowledgeIds: binding.knowledgeIds,
  flowMode: 'interactive' | 'auto' | 'wizard',
  flowId,
  chapterId?: string  // flow 关联章或 registry meta lastChapterId
})

对每个 knowledgeId:校验 entry 存在且 status === 'approved'(防御性;UI 本不应注入 pending)。

查询:

  • listRecentForEntry(entryId, limit=3)
  • listForEntry(entryId, limit=50) 供编辑对话框

5. UI 规格

5.1 状态栏番茄控件

  • 位置:EditorLayout #editor-statusbar,日更进度右侧
  • 控件:data-testid="pomodoro-control"
  • idle:▶ 按钮,点击 start
  • running:⏸ + MM:SS + ✕取消
  • paused:▶ 继续 + ✕取消
  • currentBookId 时禁用

5.2 驾驶舱成就区

  • 位置:CockpitModal 写作统计区下方
  • data-testid="cockpit-achievements"
  • 展示已解锁徽章(7🔥 / 30🔥 / 100🔥 或 i18n 文案);未解锁灰显或隐藏
  • data-testid="cockpit-pomodoro-today":今日完成番茄次数

5.3 设置页

控件 testid 说明
番茄时长 settings-pomodoro-duration select: 15/25/45
系统通知 settings-system-notifications checkbox,默认 false
目标通知 settings-goal-notifications checkbox,默认 true

5.4 知识库注入历史

KnowledgePanel 列表项

  • data-testid="knowledge-injection-preview-{entryId}"
  • 最多 3 行:{date} · {flowMode} · {chapterTitle}

KnowledgeEditorDialog

  • 折叠区「注入历史」data-testid="knowledge-injection-history"
  • 完整列表,按时间倒序;章节名可点击跳转(调用现有 switchTarget

6. IPC 通道

POMODORO_START: 'pomodoro:start',
POMODORO_PAUSE: 'pomodoro:pause',
POMODORO_RESUME: 'pomodoro:resume',
POMODORO_CANCEL: 'pomodoro:cancel',
POMODORO_GET_STATE: 'pomodoro:getState',
ACHIEVEMENT_LIST: 'achievement:list',
KNOWLEDGE_LIST_INJECTIONS: 'knowledge:listInjections',
GOAL_NOTIFICATION: 'goal:notification',  // main → renderer push

preload / electron-api.d.ts 同步扩展。


7. i18n 键(节选)

"pomodoro.start": "开始番茄钟",
"pomodoro.pause": "暂停",
"pomodoro.cancel": "取消",
"pomodoro.complete": "番茄钟完成!本次写作 {{words}} 字",
"pomodoro.switchedBook": "已切换书籍,番茄钟已取消",
"goal.dailyMet": "今日目标已达成 {{current}} / {{goal}} 字",
"achievement.streak7": "连更 7 天",
"achievement.streak30": "连更 30 天",
"achievement.streak100": "连更 100 天",
"achievement.unlocked": "解锁成就:{{name}}",
"cockpit.achievements": "写作成就",
"cockpit.pomodoroToday": "今日番茄 {{count}} 次",
"knowledge.injectionHistory": "注入历史",
"knowledge.injectionPreview": "最近注入",
"knowledge.injectionEntry": "{{date}} · {{mode}} · {{chapter}}",
"settings.pomodoroDuration": "番茄钟时长(分钟)",
"settings.systemNotifications": "启用系统通知",
"settings.goalNotifications": "启用目标达成提醒"

8. 测试要求

8.1 单元 / 集成

用例ID 场景 预期
UT-POM-01 start → completetodayWords +50 wordDelta=50pomodoro_daily 更新
UT-POM-02 切换 bookId start 旧番茄 cancel,新番茄 running
UT-ACH-01 streakDays=7 首次检测 writing_milestones 写入 streak_7
UT-ACH-02 streak_7 已存在 不重复 notify
UT-INJ-01 recordInjection 3 ids 3 rows inserted
IT-INJ-01 interactive confirmContext with knowledgeIds DB 有对应 logs
IT-GOAL-01 addToday 达标首次 notification payload 发送一次

8.2 E2E(对齐 design/readme §8.2

用例ID 场景 预期
E2E-GOAL-01 日更 3000 目标写 3500 进度变绿,达标 Toast
E2E-GOAL-02 连更 7 天(测试数据 seed 成就区显示 7 天徽章
E2E-GOAL-03 启动番茄并完成(测试环境可缩短 duration mock 或 settings=15 + 加速 hook 仅限 E2E 完成 Toast 含字数
E2E-INJ-01 向导 confirm 知识上下文 Panel 预览可见注入记录

E2E 番茄加速:主进程识别 BILIN_E2E=1 时允许 POMODORO_TEST_SEC=3 环境变量覆盖时长(仅 E2E,不暴露给生产 UI)。

8.3 原则

  • 注入历史 IT/E2E 不需要 AI 调用,可纯 DB 断言
  • 含通知的 E2E 断言 Toast DOM,不断言 OS 通知栏

9. 文件映射

文件 职责
src/main/db/schema-v8.sql knowledge_injection_logs
src/main/db/migrate.ts v8
src/main/db/repositories/writing-milestone.repo.ts 全局 milestones
src/main/db/repositories/pomodoro-daily.repo.ts 全局 pomodoro 日统计
src/main/db/repositories/knowledge-injection.repo.ts 每书 injection logs
src/main/services/pomodoro.service.ts 番茄状态机
src/main/services/achievement.service.ts 里程碑
src/main/services/goal-notification.service.ts 通知
src/main/services/knowledge-injection.service.ts 注入记录
src/main/services/cockpit.service.ts 扩展 summary
src/main/ipc/handlers/pomodoro.handler.ts 番茄 IPC
src/main/ipc/handlers/achievement.handler.ts 成就 IPC
src/main/ipc/handlers/knowledge.handler.ts 扩展 listInjections
`src/main/ipc/handlers/interactive auto
src/renderer/components/layout/EditorLayout.tsx 番茄控件
src/renderer/components/cockpit/CockpitModal.tsx 成就区
src/renderer/components/knowledge/KnowledgePanel.tsx 注入预览
src/renderer/components/knowledge/KnowledgeEditorDialog.tsx 完整历史
src/renderer/components/settings/SettingsPage.tsx 新设置
tests/main/pomodoro.test.ts UT-POM-*
tests/main/achievement.test.ts UT-ACH-*
tests/main/knowledge-injection.test.ts UT/IT-INJ-*
e2e/writing-goals.spec.ts E2E-GOAL-*
e2e/knowledge-injection-history.spec.ts E2E-INJ-*

10. Definition of Donev0.9.0

  • §8 番茄钟 + 里程碑 + 通知按 §1.3 验收
  • P6.1 注入历史按 §1.3 第 5–6 条验收
  • schema v8 + 全局 sqlite 扩展迁移
  • npm run build 通过
  • npm run test 全绿(新增 UT/IT
  • E2E-GOAL-01~03、E2E-INJ-01 通过
  • package.json / README → v0.9.0
  • i18n zh-CN / en 键齐全

本规格为笔临 P5.3 + P6.1 子项目。§9 个人写作分析、设定条目注入历史等在后续 spec 增量修订。