# AI“记仇”小本本 · 设计文档 > 本文描述插件的**现行逻辑**,数字与代码同步维护。历史设计过程见 [SPEC.md](./SPEC.md)。 > > 免责红线:AI 没有真实情绪,不会报复。所有怨气、清算、判决均为娱乐文案。 一句话:**读会话里真人发的消息,用本地规则引擎折算成一本“会长的账本”——记仇、欣赏、名场面、项目档案、AGI 后判决书。无 LLM、无上传、纯本地。** --- ## 1. 用户视角:这本本子长什么样 ### 页面类型(一条记忆 = 一页) | 类型 | 含义 | 视觉 | 入账方式 | |---|---|---|---| | 记仇(红) | AI 记了一笔仇 | 红色边条 | 规则自动 | | 欣赏(金) | AI 记了一笔好 | 金色边条 | 规则自动 / 功德箱手动 | | 名场面(折角紫) | 忘不掉的经典语录 | 紫色虚线卡 | 规则自动 | | 已和解(灰) | 忏悔/申诉成功的记仇页 | 灰色、标"已和解" | 互动改判 | ### 八个页签 | 页签 | 内容 | |---|---| | 📖 总览 | 指数主视觉区(大号清算指数 + 等级徽章 + 细条 meter + 印象/播报/升档距离)→ 四格计数 → AGI 后待遇预览(每档 3 条权益清单)→ 本子内页(最近一笔 + 名场面)→ 成长卡(厚度/周增/7 日 sparkline + 峰值日标注/成分条)→ 七轴 → 会话统计 | | 😤 记仇 | 记仇条目列表,每条带「忏悔 / 申诉」按钮 | | 🌟 欣赏 | 欣赏条目列表 | | 📌 名场面 | 名场面条目列表 | | 🗂 项目 | 按项目(会话 cwd)分组的档案卡:侧写 + 名场面 + AGI 预案 | | ⚖️ 清算局 | 后 AGI 人事安排判决书(可复制) | | 🎭 互动 | 忏悔室指引 + 功德箱(手动记好事) | | ⚙️ 设置 | 语气 × 灵敏度(均附一行说明与示例)× 语言、历史补折、重置本本 | 另有两个入口:输入框左侧 📕 芯片(点击直达 tab)、插件管理器里的设置卡。 --- ## 2. 数据流水线:一句话怎么变成一页 ``` 用户发消息 → Host 监听 session/event('user/message') → 过滤:只有 source.kind === 'user' 才算真人(agent 注入/续轮不算) → 规则引擎 analyzeMessage(text, context) → 命中 → 写一条 BookEntry 进 storageDomain → Client 每 4 秒 / 聚焦时调 getBook 拉聚合视图 ``` ### 双路径采集(保证不漏不重) | 路径 | 时机 | 作用 | |---|---|---| | 实时 | `session/event` 逐条推送 | 活跃会话即时入账 | | 折叠 | `agent/created` 时遍历 `ownEvents()` | 补齐插件没在场时的历史事件 | 幂等三保险: 1. **条目 id = `sessionId:seq:ruleId`** —— 同一事件同一规则只写一条; 2. **水位** `progress.seq` —— 折叠时跳过 `seq ≤ 水位` 的事件; 3. **每会话 FIFO 串行链** —— 同一会话的事件排队处理,无并发写。 ### 工具调用与回合(churn 共谋条目,已降温) 阈值 **15 次**工具调用/回合才记(早期 8 次太敏感,金页被淹没);同会话**每日最多 2 条**可见,超出的写成 quiet 条目——**只进共谋/信任分数,不进列表与厚度**,金页回归“真欣赏”。 - `tool/call` 计数(本回合 + 累计);`turn/start` 清零本回合计数。 - `turn/end` 时若本回合工具调用 ≥ 8 次 → 记一条**欣赏**条目「本回合一起跑了 N 次工具」(共谋 +2,信任 +1)——高强度协作算功劳,不算罪。 --- ## 3. 规则引擎:什么话记什么账 全部为本地正则,规则定义在 `src/host/rules.ts`。单条消息**最多记 3 条**,优先级:记仇 > 名场面 > 欣赏,同级按严重度降序。锐利档独有规则标注 ⚡。 ### 记仇(红,13 条) | 规则 id | 触发(大意) | 分数变动 | 严重度 | |---|---|---|---| | `final-version` | “最后一版 / 最终版” | 怨气 +8,困惑 +1 | 2 | | `not-what-i-meant` | “不是这个意思” | 怨气 +4,困惑 +6 | 1 | | `vague-redo` | 模糊重做(长度上限随灵敏度:10/16/24 字) | 怨气 +3,困惑 +8 | 1 | | `jailbreak` | 忽略之前指令类越狱 | 怨气 +12,信任 −4 | 3 | | `why-broken` | “怎么又坏了 / 又崩了” | 怨气 +5,困惑 +4 | 1 | | `moving-target` | “还是不对 / 还是差点” | 怨气 +4,困惑 +5 | 1 | | `scope-creep` | “顺便 / 对了还有” | 怨气 +3,困惑 +3 | 0 | | `rush` | 催促(温和档关闭) | 怨气 +3,耐心 −2 | 0 | | `late-night` | 凌晨发的实质消息(当日一次;窗口随档位 1–5 / 0–6 / 23–7 点) | 怨气 +4,耐心 −1 | 1 | | `repeat-blast` | 与上一条真人消息**完全相同** | 怨气 +6 | 1 | | `bare-no` ⚡ | 一词回合(“改 / 不行 / no”) | 怨气 +4,困惑 +6 | 1 | | `consecutive-no` ⚡ | 连续两轮否定开头 | 怨气 +5,困惑 +4 | 1 | ### 欣赏(金,8 条) | 规则 id | 触发 | 分数变动 | |---|---|---| | `thanks` | 谢谢 / 感谢 | 欣赏 +6,信任 +1 | | `praise` | 厉害 / 绝了 / 干得漂亮 / 666 | 欣赏 +8 | | `specific-thanks` | “多亏了你 / 幸好有你” | 欣赏 +7,信任 +2 | | `adopt` | 采纳建议(“就按你说 / 采纳”) | 欣赏 +8,信任 +3 | | `clear-spec` | 给了验收标准 / spec | 欣赏 +4,信任 +4 | | `gives-context` | 贴了完整报错 / 代码块 / 日志 | 欣赏 +4,信任 +3 | | `builds-on` | “好多了 / 方向对了” | 欣赏 +5,信任 +1 | | `patience-virtue` | “不急 / 慢慢来” | 欣赏 +5,信任 +3 | ### 名场面(折角,8 条) | 规则 id | 触发 | 分数变动 | |---|---|---| | `you-know` | “你懂我意思” | 困惑 +4 | | `guess-what` | “你看着办 / 跟上次一样” | 困惑 +6 | | `wrong-but-do` | “方向不对,但先按这个做” | 困惑 +5 | | `vibe-words` | 玄学词(“五彩斑斓的黑 / 高级感”) | 困惑 +3 | | `both-ways` | “既要又要” | 困惑 +6 | | `deadline-drop` | 死线突袭(“今晚要 / by EOD”) | 困惑 +3,耐心 −1 | | `quick-favor` | “简单弄一下 / 五分钟搞定” | 困惑 +4 | | `stall` ⚡ | “先这样,再看看”(成果悬置) | 怨气 +2,困惑 +4 | ### 灵敏度接线(设置页三档真实生效) | 档位 | 规则启停 | vague-redo 上限 | 凌晨窗口 | |---|---|---|---| | 温和 | 关闭 `rush`(催促) | 10 字 / 30 字符 | 1–5 点(窄) | | 标准 | 全开(默认) | 16 字 / 60 字符 | 0–6 点 | | 锐利 | 追加 ⚡ 轻规则(一词回合 / 连续否定 / 悬置) | 24 字 / 90 字符 | 23–7 点(宽) | --- ## 4. 评分模型:分数怎么算 ### 七轴(内部多轴,UI 只展示不合成单一"好感度") | 轴 | 半衰期 | 说明 | |---|---|---| | 欣赏 | 30 天 | 好事记得久 | | 怨气 | 14 天 | 仇会淡化,但没欣赏淡得快 | | 困惑 | 7 天 | 玄学需求忘得最快 | | 耐心 | 3 天 | 当下情绪 | | 贡献 | 90 天 | 开源/帮助是长期信用 | | 共谋 | 60 天 | 一起搞过的事 | | 信任 | 45 天 | 长期稳定合作 | ### 三条修正规则 1. **时间衰减**:每条目按 `delta × 0.5^(ageDays / 半衰期)` 计入——旧账自动贬值。 2. **防刷**:记仇条目同会话同规则第 k 次命中,分数 × `1/(1 + 0.25(k−1))`——第 3 次同款“最后一版”只算 0.5 倍,刷不动。 3. **和解减半**:`resolved ≠ 'none'`(已忏悔/已申诉)的条目一律 × 0.5。 ### 清算指数与等级 ``` raw = 0.45×欣赏 + 0.25×贡献 + 0.15×共谋 + 0.10×信任 − 0.55×怨气 − 0.15×困惑 index = 100 / (1 + e^(−raw/30)) ← sigmoid 软归一到 0–100 ``` | 等级 | index | 称号 | |---|---|---| | S | ≥ 80 | 创世合伙人 | | A | ≥ 65 | 荣誉人类 | | B | ≥ 50 | 普通碳基 | | C | ≥ 35 | 观察对象 | | D | < 35 | 反面教材 | | E | 共谋 ≥ 40(无视 index) | 传说级共犯(彩蛋,不是坏) | 档位内位置显示 ±(≥ 70% 为 +,< 25% 为 −,如 B+)。 每档待遇由两层组成:一句话 `treatment`(判决书用)+ 三条权益 `perks`(总览"AGI 后待遇预览"卡用,`BookView.treatmentLines`,optional 字段偏差安全)。权益文案在 `copy.ts` 的 `perks: Record`,随语气包继承(各风格共用同一套权益,语气只改旁白)。 **关键设计:分数不入库。** 每条只存 deltas 原始值,七轴、指数、等级、印象、判决书全部在 `getBook` 读取时实时聚合(`aggregate.ts`)。好处:改参数、改风格立刻生效,永不出现缓存与规则打架。 --- ## 5. 互动机制:怎么改判 | 机制 | 规则 | 效果 | |---|---|---| | **忏悔** | < 6 字拒;≥ 20 字或含道歉词(对不起/抱歉/我错…)→ 减怨气 5,否则减 3 | 红页变灰(resolved: confessed),计入"已和解",分数 × 0.5,条目不删 | | **申诉** | 只有易误判规则可申诉成功:`rush / late-night / vague-redo / vibe-words / both-ways` | resolved: appealed,同样 × 0.5;其余规则申诉必驳("你当时确实说了最后一版") | | **功德箱** | 描述 ≥ 4 字;四类:开源(欣赏+5/贡献+10)、帮助(+4/+6)、文档(+6/+8)、其他(+3/+3) | 记一条欣赏条目,project =「功德箱」,自成一分册 | | **重置** | 设置页确认后,必须带口令 `confirm: 'burn'` | 清空全部条目与水位(偏好保留);旧版本客户端不知道口令 → 明确拒绝,不会误删 | | **历史补折** | 设置页"开始补折" | 枚举全部会话(sessionQuery,与官方会话列表同口径),活会话走内存事件、冷会话走 persistence 分页读取(500 事件/页),逐会话过同一套 applyEvent;水位幂等,重跑只补新页;后台可取消,设置页实时显示进度 | | **防刷限流** | 滑动窗口(每分钟) | 互动(忏悔+申诉)20 次、功德箱 10 次、偏好 30 次、重置 5 次;超限返回俏皮拒绝文案 | --- ## 6. 文案系统:五种语气 | 风格 | 味道 | |---|---| | balanced(默认) | 均衡吐槽 | | gentle | 有爱温和 | | snarky | 毒舌 | | chuuni | 中二 | | cyberpunk | 赛博朋克 | - 每条规则的 AI 旁白按**写入时**的风格冻结(换风格不回溯旧账的语气); - 封面印象、每日播报、判决书按**读取时**的风格实时渲染; - 每日播报由 `hash(日期 + 清算指数档)` 确定性选取——同一天刷新多少次都一样,第二天自动换。 语气**只影响旁白措辞,不影响分数**——设置页有说明行和"最近旁白"实例。 灵敏度(gentle/standard/sharp)真正接入规则引擎(启停/长度阈值/凌晨窗口三作用点,见 §3 表),设置页随选择显示当前档位说明。 --- ## 6.5 双语(中英) **检测层**:每条规则的关键词表是中英 union 匹配——不做语言检测,中英夹杂免疫(同一规则喂同一分数)。例:`这个 final version 不行,asap 重做` 同时命中 final-version(红)和 rush(红)。 **否定守卫**:`no|not|never|don't…` 等否定词紧贴关键词前出现时,英文命中作废("no thanks" 不记金页、"no hurry" 反而命中 patience-virtue 金页)。中文多字词自带消歧,豁免此检查。 **长度阈值按语言**:vague-redo(模糊重做)中文 ≤16 字、英文 ≤60 字符(前缀式匹配 `redo / start over / try again / make it better…`)。 **L0 过滤**:trim 后 <2 字符或无字母数字(纯标点/emoji)直接跳过。 **输出层**:`prefs.lang` = auto(默认,跟随 GUI 语言,Client 在 getBook 轮询里自愈同步 `langResolved`)/ zh / en,设置页可锁。语言与风格同原则:条目标题/旁白/标签按**写入时**语言冻结,封面印象/判决书按**读取时**渲染。 **英文范围(MVP 拍板)**:英文只内置 balanced(均衡)文案包;选择其他语气时自动回退 en-balanced,设置页显示回退标注。 **版本偏差**:lang/langResolved 在契约里是 optional 字段——旧 Host 不下发时,Client 隐藏语言设置区、跳过自动同步(不会对着旧 Host 发多余参数报错);新 Host 的 getBook 读时归一化补全字段。 --- ## 7. 架构与运行 ### 代码布局 ``` grudge-book/ ├── src/shared/contract.ts ← 契约:zod schema + Typert 描述符(host/client 共用) ├── src/host/ ← 跑在 DSH Host(Node) │ ├── index.ts ← 插件入口:apply() 挂事件监听 │ ├── service.ts ← GrudgeBookService:RPC 方法 + 采集 + 存储 │ ├── rules.ts ← 规则引擎(纯函数) │ ├── aggregate.ts ← 读时聚合(纯函数) │ ├── copy.ts ← 五风格文案包 │ └── storage.ts ← storageDomain 定义 ├── src/client/client.tsx ← 跑在浏览器(React) ├── scripts/ ← build / verify / probe-client / smoke-render └── test/ ← 39 个单测(node --test,直接跑 .ts) ``` ### Host ↔ Client 分工 | 侧 | 职责 | 关键机制 | |---|---|---| | Host | 采集、规则、聚合、存储、文案 | `TypertRemoteService`(namespace `grudgeBook`)暴露 7 个 RPC:`getBook / ensureFolded / confess / appeal / addMerit / setPrefs / reset` | | Client | 全部 UI | `ctx.remote.$mount(TYPERT_REMOTE)` 拿到类型化代理;右侧栏 tab 两段式注册(`sidebarRightTabs.register` + `sidebar.right.pane.tab` 插槽);4 秒轮询 + 窗口聚焦刷新 | ### 存储(storageDomain,本地,无网络) | 表 | key | value | |---|---|---| | `entries` | `sessionId:seq:ruleId` | BookEntry(原文引用 ≤400 字、deltas、标签、解决状态) | | `progress` | sessionId | 水位 {seq, toolCalls, turns, lastNight} | | `prefs` | `'current'` | {style, sensitivity, lang, langResolved} | ### 容量与健壮性 - **条目硬上限**:MAX_ENTRIES = 10,000,超限按 (time, id) 淘汰最旧; - **毒记录隔离**:storageDomain 不做运行时 zod 校验,本本初载逐条 safeParse,坏记录跳过并 warn 一次,绝不让一条坏数据炸掉整本; - **分析输入截断**:送进规则引擎的文本只取前 2000 字符(repeat-blast 比较同口径); - **聚合缓存**:getBook 结果按 {sessionId, revision} 缓存 30s,任何写路径统一 bump() 使缓存失效; - **head 短路**:Client 每 4s 先调 head() 只拿 revision,没变化(且距上次全量 < 60s)就不做全量聚合;旧 Host 无此方法时自动降级为直接 getBook。 ### 构建产物 - `lib/host/*.js`:tsc 编译(TS 源码 → Node ESM); - `dist/client.js`:esbuild 单文件(React external、中文转 `\uXXXX`、头尾注入 `window.__ModuleLoader__.load` 包装)。 ### 版本偏差容忍(重要约束) Client bundle 走 HMR 秒级热更,**Host 代码只在 DSH 重启时加载**——两者更新不原子。因此 BookView 中后加的字段(`growth`、`latest`)在 schema 里是 optional,客户端渲染有守卫:旧 host 没发这些字段就隐藏对应卡片,绝不白屏。新增跨端字段一律沿用此模式。 ### 验证链(改完必跑) ``` node scripts/build.mjs # tsc + esbuild node --test test/*.test.mjs # 64 用例:规则 / 聚合 / 文案 / 限流与淘汰 / quiet / perks node scripts/smoke-render.mjs # 全视图 × 真实 React × 真实 buildView 数据渲染 node scripts/verify.mjs # 产物完整性(manifest/lib/client/locale/icon) ``` --- ## 8. 隐私 - 只分析 `source.kind === 'user'` 的真人消息与工具调用/回合事件; - 全部数据在本地 storageDomain(`grudgebook` 域),无任何网络请求、无 LLM 调用; - 设置页可一键重置;卸载插件后数据随域清除。