[PRD] arise 主动性与真人感(Proactivity & Liveliness)—— Phase 4 落地 #33

Closed
opened 2026-07-11 07:00:46 +00:00 by KumaAgent · 1 comment
KumaAgent commented 2026-07-11 07:00:46 +00:00 (Migrated from codeberg.org)

背景

Phase 3(能力与多模态)五片(#20-#24)+ 缺口补齐(#28)已通过 PR #29/#30/#31 全部合并进 main
docs/design.md"上线路线"第三阶段完成。当前状态:src/ 下 23 个模块覆盖了反应式核(会话/去抖/
已发日志/安全基线)、工具与记忆(画像/Delta/embedding/knowledge/工具港)、能力与多模态(能力声明/
标签/多模态路由/已读延迟窗/三因子召回),但 Config 里没有任何一个字段涉及情感态、门控阈值、沉默
预算、关系轴——CONTEXT.md"主动性与真人感"整节、以及"记忆与画像"节里依赖情感态的部分,目前是零代码

这不是遗漏,是顺序使然:这些机制此前经历了持续到 2026-07-11 的多轮独立 grill(ADR-0029
统一触发路径、ADR-0005 情感态选型、ADR-0006
能动性反坍缩护栏、ADR-0007 冷启动、ADR-0008
关系多轴、ADR-0014 环境感知、ADR-0018
时间感、ADR-0021 人设漂移守护、ADR-0025
即刻追问、ADR-0026 实时状态感知),每条决策都已拍板、
互相打过架、排查过数值重叠,但从未被收进一个 PRD 落地。本阶段把这十条 ADR 一次性收口——它们互为
前提(两级门控要读情感态才能算阈值基值;反思闭环写 profile/skill 要靠漂移守护才敢自动落库;渐进
解锁是笼罩其余全部机制的安全阀),拆开发反而会让实现期反复回填基础设施。

范围裁剪(已与项目负责人确认)docs/design.md 的"上线路线"把"真人感"(第4阶段)与"能动性"
(第5阶段,含深挖任务委托)列为两个先后阶段——但该路线图写于 ADR-0029(reactive 与主动开口合一)
之前,其"主动开口三件套"与 drive-tick 分属两阶段的划分已被 ADR-0029 推翻(两者现共用同一套两级门控
判定代码,不再是能割裂开的两套机制)。本 PRD 因此把两阶段的核心决策链合并为一个 Phase 4,但
把"深挖任务委托"(ADR-0020)一并收进来——它是用户请求触发(非主动性决策)、完成投递刻意"无门控直接
送回"(不过两级门控)、用主力模型(非反思用的 auxiliary 模型)、独立成本池,架构上与本 PRD 的决策
引擎正交,塞进来只会稀释本已很大的范围。详见 Out of Scope 与 Further Notes。

Problem Statement

从终端用户角度:现在的 arise 是一个纯反应式机器人——被 @ 才说话,说完就完,没有心情、不会主动
找你聊天、不会区分老朋友和陌生人、对同一句话在任何时候的反应都一样、被无视了也不会调整下次的分寸感,
也感知不到群里其它插件/命令产生的动静(有人查了成绩它毫无所感)。这跟 CONTEXT.md 开篇定义的
"拟人聊天陪伴型智能体内核"存在明显落差——目前只有"聊天",没有"陪伴"。

从 host 部署者角度:没有任何机制约束"机器人会不会刷屏""新部署第一天会不会对着陌生群乱开口""自我
学习的反思闭环会不会把机器人调教偏离人设而没人发现"。这些不是锦上添花的功能,是能不能把这个插件
放心装进一个真实、会持续运行数月的群聊/好友列表的前提。

从维护者角度:情感态、门控、关系轴这些"拟人参数"如果不从一开始就设计成可注入时钟/无 IO 的纯函数,
后续任何调参都只能靠人工观感判断,重蹈 CONTEXT.md 反复提及的"旧实现不可测"覆辙。

Solution

实现 docs/design.md 上线路线第 4/5 阶段的合并版——十条 ADR 收口为一套互相咬合的决策引擎:

  • 统一触发路径ADR-0029):所有触发源(话题强相关/私聊/
    interaction 命中本人/EnvironmentSignal tier-2 显著信号/drive-tick 周期评估)走同一套两级门控 +
    沉默预算决策链,取代 Phase 3 里"被找到必然处理"的隐式假设。
  • 情感态ADR-0005):三轴(valence/energy/dominance)、
    双时间尺度(快/慢)机械模型,作为全部拟人参数的唯一中央调节器。
  • 能动性ADR-0006):Drive Tick 周期评估 + Recall 私聊
    主动重连 + 自发目标 + 离线反思闭环(hit-rate 目标 + 反坍缩护栏)。
  • 冷启动ADR-0007):单轴连续阈值渐进解锁,新部署保守渐启。
  • 关系多轴ADR-0008):familiarity/trust/affinity/
    tension 四轴,客观派生优先。
  • 环境感知ADR-0014):EnvironmentSignal 分层
    消费(tier-1 氛围传染 + tier-2 显著反应)。
  • 时间感ADR-0018):距上次交互 + 时段声明性文本。
  • 人设漂移守护ADR-0021):反思写入前的独立 LLM-as-judge
    否决闸,是反思闭环敢自动落库的前提。
  • 即刻追问ADR-0025)与实时状态感知
    ADR-0026):复用 Recall/drive-tick 既有出口的两个
    轻量触发点,不新增出口。

User Stories

私聊用户视角:主动关心与情绪连贯

  1. 作为一个私聊机器人的用户,我希望自己好几天没和它说话后,它会在合理的冷场时机主动找我说句话,
    而不是永远等我先开口。
  2. 作为一个私聊用户,我希望机器人主动找我聊天但我没回应时,它不会像连环夺命 call 一样一直发消息——
    我一旦真的回复了,它才会把"已经找过我"这件事完全放下;我只是没回,它下次找我的间隔应该只是
    部分缓解,不是当作"已经联系上了"。
  3. 作为一个私聊用户,我希望机器人问了我一个问题、明确在等我回应时,如果我迟迟没理,它可能会像人
    一样追问一句"在吗",但这个追问不该发生在它随口一说、不期待回应的场合。
  4. 作为一个私聊用户,我希望机器人的"心情"会随着我们的对话自然起伏——我一直很扫兴,它会显得低落;
    我们聊得开心,它会更有活力——而不是每次交互都是同一种语气模板。
  5. 作为一个私聊用户,我希望机器人某天心情差,不代表它记恨我,也不代表这份低落会永远持续——没有
    新的刺激时,这种情绪会自然回摆。
  6. 作为一个和机器人吵过一架的私聊用户,我希望这次冲突带来的紧张感会随时间自然消退,而不是它从此
    对我一直阴阳怪气。
  7. 作为一个刚上线不久就联系机器人的新用户,我希望它上线好一阵子后开始上线时,如果我们已经好久没聊,
    它会因为"我上线了"这件事而更倾向找我说句话,而不是完全无感知我的在线状态。
  8. 作为一个正在给机器人打字回复的用户,我不希望它因为看到我"正在输入"就抢在我打完之前又发一条消息
    插话。
  9. 作为一个私聊用户,我希望机器人主动找我聊的话题里,偶尔会提到"好久没聊了"这类基于真实间隔的感受,
    而不是每次开场白都一样;但如果我们其实没多久前才聊过,我不希望它说出"距上次交互 4 分钟"这种
    尴尬的精确数字。

群聊用户视角:主动开口的分寸感

  1. 作为群聊里的用户,我希望机器人不是每条消息都接话,但被直接提到或搭话时,它几乎总会有反应
    (除非频率确实太高被限流),不会出现"叫了没人应"的情况。
  2. 作为群聊用户,我希望机器人偶尔会自己开个话题或接上一个正在聊的话题,而不是永远等被点名。
  3. 作为群聊用户,我希望机器人在短时间内被连续搭话多次后,不会因为"沉默预算"耗尽而对一个正经问题
    也不回应太多次——但我理解极端刷屏场景下机器人确实可能暂时不接话,这是被明确接受的行为。
  4. 作为群聊用户,我希望群里如果有人刚查了成绩、抽了张稀有卡,机器人偶尔会自然地搭一句话表示关注,
    而不是对同群其它插件的产出完全无感。
  5. 作为群聊用户,我希望机器人不会对群里每一次插件产出都点评一句——那样会很烦人,它应该只对真正
    值得一提的事偶尔搭话,大部分时候安静地"感受气氛"就够了。
  6. 作为群聊用户,我希望群里气氛热闹时机器人显得更有活力,气氛低迷/吵架时它也会显得更收敛,而不是
    对周围的气氛完全免疫。
  7. 作为群聊用户,我希望机器人主动接话前会有一个短暂的"犹豫",如果这段时间里已经有别人接了话,
    它会知趣地把这次主动开口撤销,而不是抢在真人前面抢话。
  8. 作为群聊用户,我希望机器人被互动过之后一段时间内,即使别人发的消息没有直接提到它,它也可能有一定
    概率随口接一句,就像一个人刚被人搭话后会更愿意继续参与讨论。
  9. 作为群聊用户,我希望机器人发的一条消息如果明确在等回应,短时间没人接的话它可能会像人一样追问
    一下,但这个行为在群里应该复用它已有的"要不要主动开口"判断,不是另开一套独立通道。

新用户/陌生群视角:冷启动

  1. 作为一个刚把机器人拉进一个新群的人,我希望它头几天表现得比较克制——话不多、门槛高,而不是
    一上来就跟熟人一样到处主动搭话,让人觉得唐突。
  2. 作为一个第一次和机器人说话的陌生用户,我希望叫它时它会做一个轻量的自我介绍,而不是完全没有
    过渡地直接聊起来。
  3. 作为一个新部署的机器人的第一批用户,我希望随着我们互动增多、它对这个群/这个人的了解积累,它
    的主动性会自然、渐进地放开,而不是某个时间点突然"性情大变"。
  4. 作为一个刚认识机器人的用户,我希望即使在冷启动期,只要我直接找它说话,它也几乎一定会回应我
    ——冷启动的保守只体现在"主动"上,不该体现成"叫不应"。

老朋友/熟人视角:关系网

  1. 作为和机器人认识很久、聊了很多次的用户,我希望它表现出来的熟络程度和一个刚认识几天的人不一样
    ——更愿意主动找我、语气更放松。
  2. 作为一个和机器人聊过一些私密话题的用户,我希望它对我的自我披露深度会随信任积累而自然加深,
    而不是对谁都一个尺度。
  3. 作为一个某天一口气和机器人聊了很久很久的用户,我不希望这一次长聊就让它把我当成"多年老友"——
    熟悉度的增长应该更看重"我们经常聊"而不是"我们这次聊了很久"。
  4. 作为群里的用户,我希望机器人多少能感知到"谁和谁关系好""谁刚一起参与过同一件事"这类关系线索,
    即使这不是它直接问出来的。

Host 部署者/运维者视角:安全与可控

  1. 作为部署者,我希望机器人的自我学习(反思闭环)只会调整"这个群适不适合开玩笑""该不该多话"这类
    分寸感参数,且这些调整是有界的、会随时间衰减回基线,不会无限跑偏。
  2. 作为部署者,我希望反思闭环给画像/技能写的任何内容,在真正生效前都会先过一道"是否偏离人设"的
    审核,偏离了就直接不落库,而不是等我事后发现机器人性格跑偏了才能补救。
  3. 作为部署者,我希望"变安静"这个方向的自我调整比"变话痨"更容易发生——如果一定要在"偶尔漏答一个
    问题"和"刷屏惹人烦"之间选一个更小的风险,我希望系统默认偏向前者。
  4. 作为部署者,我希望自发的主动开口/追问永远可以被真人的正常聊天打断/抢占,不会有"机器人非要把
    这句话说出来"的执念场景。
  5. 作为部署者,我希望某个群/某个用户的关系轴、情感态出现异常(比如一直很低落且没有恢复迹象)时,
    这些状态本身仍然是有界、可解释的数值,而不是我完全看不懂的黑箱。
  6. 作为部署者,我希望群里没有配置 @event_postprocessor 环境信号推送时,机器人的环境感知能力
    整体优雅静默降级,不影响其它已有功能正常运行。
  7. 作为部署者,我希望我可以整体关闭自发目标/环境感知 tier-2 反应这类"额外主动性"功能(灰度开关),
    只保留最基础的反应式 + Recall,用于我还不确定要不要开放更多主动性的过渡期。

维护者/贡献者视角:可测性

  1. 作为维护者,我希望情感态的三轴更新方程是纯函数(时钟/随机可注入),可以直接写性质测试断言
    "衰减最终收敛""数值不会越过上下界""重复同类刺激会被打折",不需要真实等待时间流逝或接入真实
    LLM 才能验证。
  2. 作为维护者,我希望两级门控的级一启发式打分同样是可以脱离真实消息批次直接单测的纯函数。
  3. 作为维护者,我希望反思闭环和人设漂移守护的测试可以用脚本化的假 LLM 客户端跑通"产出候选→独立
    判断→落库或丢弃"整条链路,不需要真实网络请求,且能覆盖"判断调用失败时候选被丢弃"这条 fail-closed
    路径。
  4. 作为维护者,我希望渐进解锁的每一档解锁条件都可以用一组固定的互动量/画像丰度输入直接断言解锁
    状态,不需要真的跑几天数据。
  5. 作为维护者,我希望某次真实(或构造的)触发批次可以被录制下来,回放到测试里断言门控的最终裁决
    与当时一致,用于后续调参时防回归。
  6. 作为维护者,我希望新增的"私聊主动重连"机制在代码里有一个和既有『三因子召回』模块清晰区分的
    命名,不会因为都叫"recall"而在代码评审/搜索时被搞混。

机器人行为验收视角

  1. 作为验收标准,我希望同一批消息触发的两级门控级二判断,其"回哪几条/不回哪几条"的裁决结果会被
    完整记入决策快照,供后续排查"为什么没回那条"使用。
  2. 作为验收标准,我希望 Drive Tick 在没有任何到期任务时,整轮跳过、不产生任何 LLM 调用。
  3. 作为验收标准,我希望反思闭环写入 per-chat 画像/技能/门控阈值 offset 这三类目标中的任意一类时,
    都经过同一道漂移守护判断,不存在某条写入路径绕过了这道闸。
  4. 作为验收标准,我希望群聊场景下,快情感态的回摆目标只读该群自己的 per-group 慢情感态,不会读取
    任何个人的 per-user 慢情感态。
  5. 作为验收标准,我希望机器人在"忙"(比如正被真人频繁互动)的时候,Drive Tick 的主动开口评估会
    让路,不与真人抢时间线,而是顺延到下一次评估。

Implementation Decisions

范围边界(先说清楚"不做什么"):本阶段不实现深挖任务委托(ADR-0020)、习得贴纸(ADR-0024)、
跨平台资料拉取(ADR-0027)、记忆深度搜索(ADR-0031)、mood_congruence 接入三因子召回(ADR-0009 更新)、
环境遥测 Ambient Telemetry(ADR-0014 2026-07-11 更新)、以及 ADR-0010 完整运营面(/cost//why/
/why_query//diagnose、六池成本治理、系统自检信号层)——只交付决策快照的写入这一个最小必要
切片,供本阶段自身测试与未来 /why 消费,不交付任何聊天管理命令。详见 Out of Scope。

统一触发路径与两级门控(ADR-0029)

  • 所有触发源(话题强相关/私聊/interaction 命中本人/EnvironmentSignal tier-2 显著信号/drive-tick 周期
    评估)统一走同一套两级门控判定代码;注入策略按触发源分流,决策逻辑不分流——事件触发注入全量
    对话上下文,周期触发注入 isolated/light context(persona+情感态+未决意图+近期摘要+距上次交互+
    时段字段)。
  • 沉默预算(衰减令牌桶)覆盖全部触发源,不再是"只管主动开口";被直接搭话的评估也计入同一个桶,
    预算耗尽时可能被压下,这是明确接受的行为。
  • 冷启动期 floor=1 的适用范围从"选择性回应"扩为"共享预算本身"——事件触发的评估预算下限强制 ≥1,
    周期触发不设下限。
  • 原"选择性回应"(ADR-0017)作为独立判定机制退场,"回哪几条/不回哪几条"并入两级门控级二判断,
    addressed_message_ids/skipped_message_ids 字段保留,产出方改为统一级二判定。
  • 已读延迟窗(Phase 3 已交付)不受影响,继续作为事件触发路径批次就绪后的独立前置计时层。
  • 沉默窗口(CONTEXT.md):级二判定"主动开口"后不立即发,先排一个短延迟 job;窗口内任何人发言
    即撤销这次主动开口(补位而非抢话)。
  • 慢中断(CONTEXT.md):被交互后一段时间窗内,对消息按时间衰减概率接话,建模为情感态短时
    高 energy 窗口的自然结果,不是独立判定分支。
  • 决策快照:每次触发评估写一条结构化记录(门控级一/级二得分与裁决、addressed/skipped_message_ids
    注入的记忆条目、情感态三轴、沉默预算余量、命中意图),供 Testing Decisions 的录制回放使用。

情感态(ADR-0005)

  • 三轴 (valence, energy, dominance),双时间尺度:快情感态(per-chat,分钟级)+ 慢情感态
    (per-user + per-group 对称三轴,天级,连续衰减、无硬重置边界)。
  • 快情感态各轴独立输入源,衰减项退向同一 chat 当前的慢情感态(而非固定值或零点):
    • valence:互动极性驱动,负性偏差——为负时向慢层回摆比为正时更慢。
    • energy:互动极性 + 资源态推送 + 群氛围传染 EMA(仅速率无内容,来自 EnvironmentSignal tier-1)
      • 昼夜节律 nudge(深夜额外下调)+ 未获回应升级信号。
    • dominance:共享结局分类器(landed/fell-flat/annoyed)驱动,专管房间级进取性/主动开口
      门槛基值,不介入自我披露
  • 慢情感态:per-group 低通滤波该 chat 快层(零新输入源);per-user 按发言人个人归属独立累积同一套
    输入表;群聊场景下快情感态只读 per-group 慢情感态,从不读取任何个人的 per-user 慢情感态
    慢情感态自身衰减向中性零点。
  • 抗溢出:按当前值动态压缩新增量(越接近上下界,同一原始 delta 产生的实际变化越小),高位区间抑制
    负向冲击、低位区间抑制正向冲击(非对称锁定区)。
  • 抗刷:短时间窗内同一分类标签的重复刺激,后续 delta 按衰减系数打折。
  • 人设不进数值方程:persona port 内容只影响 LLM 如何解读/表达这些数字,不提供任何数值锚点/基线
    ——不新增 persona port 数值配置面。
  • 是全部拟人参数的唯一中央调节器:打字速度(接入 Phase 1 已交付的 base+per-char 静态公式,新增
    情绪抖动项,不重建整个打字节奏机制
    )、linger 概率、门控阈值基值、自我披露倾向(valence 倾向 +
    trust 封顶,dominance 明确不参与)、兴趣门阈值。
  • 三轴/双层全部为 clamp 过的确定性纯函数(时钟/随机可注入);单次更新单一 DB 事务,失败整体不提交。

正文过长,Codeberg/fj 单次写入有长度限制,续接下方评论。

## 背景 Phase 3(能力与多模态)五片(#20-#24)+ 缺口补齐(#28)已通过 PR #29/#30/#31 全部合并进 `main`, `docs/design.md`"上线路线"第三阶段完成。当前状态:`src/` 下 23 个模块覆盖了反应式核(会话/去抖/ 已发日志/安全基线)、工具与记忆(画像/Delta/embedding/knowledge/工具港)、能力与多模态(能力声明/ 标签/多模态路由/已读延迟窗/三因子召回),但 `Config` 里没有任何一个字段涉及情感态、门控阈值、沉默 预算、关系轴——**CONTEXT.md"主动性与真人感"整节、以及"记忆与画像"节里依赖情感态的部分,目前是零代码**。 这不是遗漏,是顺序使然:这些机制此前经历了持续到 2026-07-11 的多轮独立 grill([ADR-0029](docs/adr/0029-unified-trigger-pipeline.md) 统一触发路径、[ADR-0005](docs/adr/0005-affective-state.md) 情感态选型、[ADR-0006](docs/adr/0006-agency-and-drive.md) 能动性反坍缩护栏、[ADR-0007](docs/adr/0007-cold-start.md) 冷启动、[ADR-0008](docs/adr/0008-relationship-network.md) 关系多轴、[ADR-0014](docs/adr/0014-environmental-awareness.md) 环境感知、[ADR-0018](docs/adr/0018-temporal-awareness.md) 时间感、[ADR-0021](docs/adr/0021-persona-drift-guard.md) 人设漂移守护、[ADR-0025](docs/adr/0025-immediate-follow-up.md) 即刻追问、[ADR-0026](docs/adr/0026-realtime-presence-status.md) 实时状态感知),每条决策都已拍板、 互相打过架、排查过数值重叠,但从未被收进一个 PRD 落地。本阶段把这十条 ADR 一次性收口——它们互为 前提(两级门控要读情感态才能算阈值基值;反思闭环写 profile/skill 要靠漂移守护才敢自动落库;渐进 解锁是笼罩其余全部机制的安全阀),拆开发反而会让实现期反复回填基础设施。 **范围裁剪(已与项目负责人确认)**:`docs/design.md` 的"上线路线"把"真人感"(第4阶段)与"能动性" (第5阶段,含深挖任务委托)列为两个先后阶段——但该路线图写于 ADR-0029(reactive 与主动开口合一) 之前,其"主动开口三件套"与 drive-tick 分属两阶段的划分已被 ADR-0029 推翻(两者现共用同一套两级门控 判定代码,不再是能割裂开的两套机制)。本 PRD 因此把两阶段的核心决策链合并为一个 Phase 4,但**不** 把"深挖任务委托"(ADR-0020)一并收进来——它是用户请求触发(非主动性决策)、完成投递刻意"无门控直接 送回"(不过两级门控)、用主力模型(非反思用的 auxiliary 模型)、独立成本池,架构上与本 PRD 的决策 引擎正交,塞进来只会稀释本已很大的范围。详见 Out of Scope 与 Further Notes。 ## Problem Statement 从终端用户角度:现在的 arise 是一个纯反应式机器人——被 @ 才说话,说完就完,没有心情、不会主动 找你聊天、不会区分老朋友和陌生人、对同一句话在任何时候的反应都一样、被无视了也不会调整下次的分寸感, 也感知不到群里其它插件/命令产生的动静(有人查了成绩它毫无所感)。这跟 CONTEXT.md 开篇定义的 "拟人聊天陪伴型智能体内核"存在明显落差——目前只有"聊天",没有"陪伴"。 从 host 部署者角度:没有任何机制约束"机器人会不会刷屏""新部署第一天会不会对着陌生群乱开口""自我 学习的反思闭环会不会把机器人调教偏离人设而没人发现"。这些不是锦上添花的功能,是能不能把这个插件 放心装进一个真实、会持续运行数月的群聊/好友列表的前提。 从维护者角度:情感态、门控、关系轴这些"拟人参数"如果不从一开始就设计成可注入时钟/无 IO 的纯函数, 后续任何调参都只能靠人工观感判断,重蹈 CONTEXT.md 反复提及的"旧实现不可测"覆辙。 ## Solution 实现 `docs/design.md` 上线路线第 4/5 阶段的合并版——十条 ADR 收口为一套互相咬合的决策引擎: - **统一触发路径**([ADR-0029](docs/adr/0029-unified-trigger-pipeline.md)):所有触发源(话题强相关/私聊/ interaction 命中本人/`EnvironmentSignal` tier-2 显著信号/drive-tick 周期评估)走同一套两级门控 + 沉默预算决策链,取代 Phase 3 里"被找到必然处理"的隐式假设。 - **情感态**([ADR-0005](docs/adr/0005-affective-state.md)):三轴(valence/energy/dominance)、 双时间尺度(快/慢)机械模型,作为全部拟人参数的唯一中央调节器。 - **能动性**([ADR-0006](docs/adr/0006-agency-and-drive.md)):Drive Tick 周期评估 + Recall 私聊 主动重连 + 自发目标 + 离线反思闭环(hit-rate 目标 + 反坍缩护栏)。 - **冷启动**([ADR-0007](docs/adr/0007-cold-start.md)):单轴连续阈值渐进解锁,新部署保守渐启。 - **关系多轴**([ADR-0008](docs/adr/0008-relationship-network.md)):familiarity/trust/affinity/ tension 四轴,客观派生优先。 - **环境感知**([ADR-0014](docs/adr/0014-environmental-awareness.md)):`EnvironmentSignal` 分层 消费(tier-1 氛围传染 + tier-2 显著反应)。 - **时间感**([ADR-0018](docs/adr/0018-temporal-awareness.md)):距上次交互 + 时段声明性文本。 - **人设漂移守护**([ADR-0021](docs/adr/0021-persona-drift-guard.md)):反思写入前的独立 LLM-as-judge 否决闸,是反思闭环敢自动落库的前提。 - **即刻追问**([ADR-0025](docs/adr/0025-immediate-follow-up.md))与**实时状态感知** ([ADR-0026](docs/adr/0026-realtime-presence-status.md)):复用 Recall/drive-tick 既有出口的两个 轻量触发点,不新增出口。 ## User Stories **私聊用户视角:主动关心与情绪连贯** 1. 作为一个私聊机器人的用户,我希望自己好几天没和它说话后,它会在合理的冷场时机主动找我说句话, 而不是永远等我先开口。 2. 作为一个私聊用户,我希望机器人主动找我聊天但我没回应时,它不会像连环夺命 call 一样一直发消息—— 我一旦真的回复了,它才会把"已经找过我"这件事完全放下;我只是没回,它下次找我的间隔应该只是 部分缓解,不是当作"已经联系上了"。 3. 作为一个私聊用户,我希望机器人问了我一个问题、明确在等我回应时,如果我迟迟没理,它可能会像人 一样追问一句"在吗",但这个追问不该发生在它随口一说、不期待回应的场合。 4. 作为一个私聊用户,我希望机器人的"心情"会随着我们的对话自然起伏——我一直很扫兴,它会显得低落; 我们聊得开心,它会更有活力——而不是每次交互都是同一种语气模板。 5. 作为一个私聊用户,我希望机器人某天心情差,不代表它记恨我,也不代表这份低落会永远持续——没有 新的刺激时,这种情绪会自然回摆。 6. 作为一个和机器人吵过一架的私聊用户,我希望这次冲突带来的紧张感会随时间自然消退,而不是它从此 对我一直阴阳怪气。 7. 作为一个刚上线不久就联系机器人的新用户,我希望它上线好一阵子后开始上线时,如果我们已经好久没聊, 它会因为"我上线了"这件事而更倾向找我说句话,而不是完全无感知我的在线状态。 8. 作为一个正在给机器人打字回复的用户,我不希望它因为看到我"正在输入"就抢在我打完之前又发一条消息 插话。 9. 作为一个私聊用户,我希望机器人主动找我聊的话题里,偶尔会提到"好久没聊了"这类基于真实间隔的感受, 而不是每次开场白都一样;但如果我们其实没多久前才聊过,我不希望它说出"距上次交互 4 分钟"这种 尴尬的精确数字。 **群聊用户视角:主动开口的分寸感** 10. 作为群聊里的用户,我希望机器人不是每条消息都接话,但被直接提到或搭话时,它几乎总会有反应 (除非频率确实太高被限流),不会出现"叫了没人应"的情况。 11. 作为群聊用户,我希望机器人偶尔会自己开个话题或接上一个正在聊的话题,而不是永远等被点名。 12. 作为群聊用户,我希望机器人在短时间内被连续搭话多次后,不会因为"沉默预算"耗尽而对一个正经问题 也不回应太多次——但我理解极端刷屏场景下机器人确实可能暂时不接话,这是被明确接受的行为。 13. 作为群聊用户,我希望群里如果有人刚查了成绩、抽了张稀有卡,机器人偶尔会自然地搭一句话表示关注, 而不是对同群其它插件的产出完全无感。 14. 作为群聊用户,我希望机器人不会对群里每一次插件产出都点评一句——那样会很烦人,它应该只对真正 值得一提的事偶尔搭话,大部分时候安静地"感受气氛"就够了。 15. 作为群聊用户,我希望群里气氛热闹时机器人显得更有活力,气氛低迷/吵架时它也会显得更收敛,而不是 对周围的气氛完全免疫。 16. 作为群聊用户,我希望机器人主动接话前会有一个短暂的"犹豫",如果这段时间里已经有别人接了话, 它会知趣地把这次主动开口撤销,而不是抢在真人前面抢话。 17. 作为群聊用户,我希望机器人被互动过之后一段时间内,即使别人发的消息没有直接提到它,它也可能有一定 概率随口接一句,就像一个人刚被人搭话后会更愿意继续参与讨论。 18. 作为群聊用户,我希望机器人发的一条消息如果明确在等回应,短时间没人接的话它可能会像人一样追问 一下,但这个行为在群里应该复用它已有的"要不要主动开口"判断,不是另开一套独立通道。 **新用户/陌生群视角:冷启动** 19. 作为一个刚把机器人拉进一个新群的人,我希望它头几天表现得比较克制——话不多、门槛高,而不是 一上来就跟熟人一样到处主动搭话,让人觉得唐突。 20. 作为一个第一次和机器人说话的陌生用户,我希望叫它时它会做一个轻量的自我介绍,而不是完全没有 过渡地直接聊起来。 21. 作为一个新部署的机器人的第一批用户,我希望随着我们互动增多、它对这个群/这个人的了解积累,它 的主动性会自然、渐进地放开,而不是某个时间点突然"性情大变"。 22. 作为一个刚认识机器人的用户,我希望即使在冷启动期,只要我直接找它说话,它也几乎一定会回应我 ——冷启动的保守只体现在"主动"上,不该体现成"叫不应"。 **老朋友/熟人视角:关系网** 23. 作为和机器人认识很久、聊了很多次的用户,我希望它表现出来的熟络程度和一个刚认识几天的人不一样 ——更愿意主动找我、语气更放松。 24. 作为一个和机器人聊过一些私密话题的用户,我希望它对我的自我披露深度会随信任积累而自然加深, 而不是对谁都一个尺度。 25. 作为一个某天一口气和机器人聊了很久很久的用户,我不希望这一次长聊就让它把我当成"多年老友"—— 熟悉度的增长应该更看重"我们经常聊"而不是"我们这次聊了很久"。 26. 作为群里的用户,我希望机器人多少能感知到"谁和谁关系好""谁刚一起参与过同一件事"这类关系线索, 即使这不是它直接问出来的。 **Host 部署者/运维者视角:安全与可控** 27. 作为部署者,我希望机器人的自我学习(反思闭环)只会调整"这个群适不适合开玩笑""该不该多话"这类 分寸感参数,且这些调整是有界的、会随时间衰减回基线,不会无限跑偏。 28. 作为部署者,我希望反思闭环给画像/技能写的任何内容,在真正生效前都会先过一道"是否偏离人设"的 审核,偏离了就直接不落库,而不是等我事后发现机器人性格跑偏了才能补救。 29. 作为部署者,我希望"变安静"这个方向的自我调整比"变话痨"更容易发生——如果一定要在"偶尔漏答一个 问题"和"刷屏惹人烦"之间选一个更小的风险,我希望系统默认偏向前者。 30. 作为部署者,我希望自发的主动开口/追问永远可以被真人的正常聊天打断/抢占,不会有"机器人非要把 这句话说出来"的执念场景。 31. 作为部署者,我希望某个群/某个用户的关系轴、情感态出现异常(比如一直很低落且没有恢复迹象)时, 这些状态本身仍然是有界、可解释的数值,而不是我完全看不懂的黑箱。 32. 作为部署者,我希望群里没有配置 `@event_postprocessor` 环境信号推送时,机器人的环境感知能力 整体优雅静默降级,不影响其它已有功能正常运行。 33. 作为部署者,我希望我可以整体关闭自发目标/环境感知 tier-2 反应这类"额外主动性"功能(灰度开关), 只保留最基础的反应式 + Recall,用于我还不确定要不要开放更多主动性的过渡期。 **维护者/贡献者视角:可测性** 34. 作为维护者,我希望情感态的三轴更新方程是纯函数(时钟/随机可注入),可以直接写性质测试断言 "衰减最终收敛""数值不会越过上下界""重复同类刺激会被打折",不需要真实等待时间流逝或接入真实 LLM 才能验证。 35. 作为维护者,我希望两级门控的级一启发式打分同样是可以脱离真实消息批次直接单测的纯函数。 36. 作为维护者,我希望反思闭环和人设漂移守护的测试可以用脚本化的假 LLM 客户端跑通"产出候选→独立 判断→落库或丢弃"整条链路,不需要真实网络请求,且能覆盖"判断调用失败时候选被丢弃"这条 fail-closed 路径。 37. 作为维护者,我希望渐进解锁的每一档解锁条件都可以用一组固定的互动量/画像丰度输入直接断言解锁 状态,不需要真的跑几天数据。 38. 作为维护者,我希望某次真实(或构造的)触发批次可以被录制下来,回放到测试里断言门控的最终裁决 与当时一致,用于后续调参时防回归。 39. 作为维护者,我希望新增的"私聊主动重连"机制在代码里有一个和既有『三因子召回』模块清晰区分的 命名,不会因为都叫"recall"而在代码评审/搜索时被搞混。 **机器人行为验收视角** 40. 作为验收标准,我希望同一批消息触发的两级门控级二判断,其"回哪几条/不回哪几条"的裁决结果会被 完整记入决策快照,供后续排查"为什么没回那条"使用。 41. 作为验收标准,我希望 Drive Tick 在没有任何到期任务时,整轮跳过、不产生任何 LLM 调用。 42. 作为验收标准,我希望反思闭环写入 per-chat 画像/技能/门控阈值 offset 这三类目标中的任意一类时, 都经过同一道漂移守护判断,不存在某条写入路径绕过了这道闸。 43. 作为验收标准,我希望群聊场景下,快情感态的回摆目标只读该群自己的 per-group 慢情感态,不会读取 任何个人的 per-user 慢情感态。 44. 作为验收标准,我希望机器人在"忙"(比如正被真人频繁互动)的时候,Drive Tick 的主动开口评估会 让路,不与真人抢时间线,而是顺延到下一次评估。 ## Implementation Decisions **范围边界(先说清楚"不做什么")**:本阶段不实现深挖任务委托(ADR-0020)、习得贴纸(ADR-0024)、 跨平台资料拉取(ADR-0027)、记忆深度搜索(ADR-0031)、mood_congruence 接入三因子召回(ADR-0009 更新)、 环境遥测 Ambient Telemetry(ADR-0014 2026-07-11 更新)、以及 ADR-0010 完整运营面(`/cost`/`/why`/ `/why_query`/`/diagnose`、六池成本治理、系统自检信号层)——只交付决策快照的**写入**这一个最小必要 切片,供本阶段自身测试与未来 `/why` 消费,不交付任何聊天管理命令。详见 Out of Scope。 ### 统一触发路径与两级门控(ADR-0029) - 所有触发源(话题强相关/私聊/interaction 命中本人/`EnvironmentSignal` tier-2 显著信号/drive-tick 周期 评估)统一走同一套两级门控判定代码;**注入策略按触发源分流,决策逻辑不分流**——事件触发注入全量 对话上下文,周期触发注入 isolated/light context(persona+情感态+未决意图+近期摘要+距上次交互+ 时段字段)。 - 沉默预算(衰减令牌桶)**覆盖全部触发源**,不再是"只管主动开口";被直接搭话的评估也计入同一个桶, 预算耗尽时可能被压下,这是明确接受的行为。 - 冷启动期 `floor=1` 的适用范围从"选择性回应"扩为"共享预算本身"——事件触发的评估预算下限强制 ≥1, 周期触发不设下限。 - 原"选择性回应"(ADR-0017)作为独立判定机制退场,"回哪几条/不回哪几条"并入两级门控级二判断, `addressed_message_ids`/`skipped_message_ids` 字段保留,产出方改为统一级二判定。 - 已读延迟窗(Phase 3 已交付)不受影响,继续作为事件触发路径批次就绪后的独立前置计时层。 - **沉默窗口**(CONTEXT.md):级二判定"主动开口"后不立即发,先排一个短延迟 job;窗口内任何人发言 即撤销这次主动开口(补位而非抢话)。 - **慢中断**(CONTEXT.md):被交互后一段时间窗内,对消息按时间衰减概率接话,建模为情感态短时 高 energy 窗口的自然结果,不是独立判定分支。 - 决策快照:每次触发评估写一条结构化记录(门控级一/级二得分与裁决、`addressed`/`skipped_message_ids`、 注入的记忆条目、情感态三轴、沉默预算余量、命中意图),供 Testing Decisions 的录制回放使用。 ### 情感态(ADR-0005) - 三轴 `(valence, energy, dominance)`,双时间尺度:**快情感态**(per-chat,分钟级)+ **慢情感态** (per-user + per-group 对称三轴,天级,连续衰减、无硬重置边界)。 - 快情感态各轴独立输入源,衰减项退向**同一 chat 当前的慢情感态**(而非固定值或零点): - `valence`:互动极性驱动,**负性偏差**——为负时向慢层回摆比为正时更慢。 - `energy`:互动极性 + 资源态推送 + 群氛围传染 EMA(仅速率无内容,来自 `EnvironmentSignal` tier-1) + 昼夜节律 nudge(深夜额外下调)+ 未获回应升级信号。 - `dominance`:共享结局分类器(`landed`/`fell-flat`/`annoyed`)驱动,专管房间级进取性/主动开口 门槛基值,**不介入自我披露**。 - 慢情感态:per-group 低通滤波该 chat 快层(零新输入源);per-user 按发言人个人归属独立累积同一套 输入表;**群聊场景下快情感态只读 per-group 慢情感态,从不读取任何个人的 per-user 慢情感态**。 慢情感态自身衰减向中性零点。 - 抗溢出:按当前值动态压缩新增量(越接近上下界,同一原始 delta 产生的实际变化越小),高位区间抑制 负向冲击、低位区间抑制正向冲击(非对称锁定区)。 - 抗刷:短时间窗内同一分类标签的重复刺激,后续 delta 按衰减系数打折。 - **人设不进数值方程**:persona port 内容只影响 LLM 如何解读/表达这些数字,不提供任何数值锚点/基线 ——不新增 persona port 数值配置面。 - 是全部拟人参数的唯一中央调节器:打字速度(**接入 Phase 1 已交付的 base+per-char 静态公式,新增 情绪抖动项,不重建整个打字节奏机制**)、linger 概率、门控阈值基值、自我披露倾向(`valence` 倾向 + `trust` 封顶,`dominance` 明确不参与)、兴趣门阈值。 - 三轴/双层全部为 clamp 过的确定性纯函数(时钟/随机可注入);单次更新单一 DB 事务,失败整体不提交。 > _正文过长,Codeberg/`fj` 单次写入有长度限制,续接下方评论。_
KumaAgent commented 2026-07-11 07:07:58 +00:00 (Migrated from codeberg.org)

(续正文)

能动性:Drive Tick + Recall + 自发目标 + 反思闭环(ADR-0006)

  • Drive Tick:跑在 isolated/light context;无 due 任务整轮跳过、零 API;决定沉默时输出静默令牌;
    开工先读状态防重复关心;不与真人抢 lane(busy 时 defer 到下一 tick)。群事件驱动 / 私聊冷场定时;
    事件触发复用同一入口但改用全量上下文(见"统一触发路径")。
  • Recall(私聊唯一主动出口):冷场计时触发;冷却计时两段式——己方主动发送触发部分缓解
    ("确实努力了"),只有对方真实回复才触发全量重置("连接达成"),复用既有 Sent Log + 回复归属检测
    判定"是否已被回复"。命名提醒:不与既有『三因子召回』模块混淆,须使用独立的模块/标识符命名
    (如"主动重连"而非任何形式的裸 "recall")。
  • 自发目标:core 本地启发式触发候选(熟人久未联系/话题新进展/冒出不懂的梗);主模型轮内
    决定是否成 context 模式 pending intent,走既有 inject_intents + Recall 单一出口消费,不新起
    循环、不新增独立出口;默认低优先 + 强衰减 + 可被真人抢占 + fail-closed + 灰度可一键关。
  • 离线反思闭环:离线、廉价 auxiliary 模型,复用 Delta 管线;消费双向弱反馈(正:主动后有人接/
    话题延续/energy 升;负:被无视/被"别烦"/冷场/被追问)产自然语言教训(带证据指针);目标 = 主动
    尝试逐次得体率(hit-rate)
    ,明确不是"最小化负反馈"(沉默坍缩退化解)也不是"最大化净参与"(噪声
    坍缩退化解);自主写三处——门控阈值 offset(对称有界 [floor, ceiling]步长不对称:抬静默阈值
    快于降
    ,无信号衰减朝安静,offset 本身锚回基值)、per-chat 画像、技能——全部 fail-closed + 可回溯
    可撤销 + 灰度;profile/skill/Knowledge 写入路径全部先过人设漂移守护否决闸才落库;在线反思绝
    不做。
  • 共享结局分类器(landed/fell-flat/annoyed)为同一份分类逻辑,三路消费:dominance 快路(同轮)、
    反思 hit-rate 慢路(沉淀 offset)、per-user 慢情感态.dominance(更慢路),不重复写分类代码。
  • 反思对技能的写入复用 Knowledge 查重合并模式(按向量相似度查是否与现有技能语义重叠,命中融入/
    精炼现有条目,不命中才新建)。

冷启动与渐进解锁(ADR-0007,被 ADR-0029 更新为单轴)

  • 解锁顺序:(统一门控,沉默预算/兴趣门连续收紧) → 三因子召回(Phase 2 已交付)→ 关系网注入 → 自发目标;不存在"反应式已解锁但主动开口未解锁"的中间态。
  • 冷启动期门控收紧(沉默预算下限收紧、兴趣门阈值抬高),被提及时可触发轻量自我介绍。
  • 该解锁顺序同时是上线灰度轴,与已交付的 read_delay scope_ceiling 冷启动收紧共用同一条轴线。

关系网与关系多轴(ADR-0008)

  • 保留既有两层关系网结构(显式声明边 + 隐式同群/同事件共现查询时派生,不上图,1-hop 主力 + 递归
    CTE ≤2 或 lookup_relation 按需)、知情-gate(敏感数据私聊例外 ⇔ current 是某知情者的私聊)。
  • agent↔user 扩为四轴,per-persona + per-user 作用域:familiarity(互动次数/时长客观派生,
    零 LLM)、trust(复用 Delta 压缩管线已有的 sensitive 打标作为"自我展露深度"代理信号,命中
    sensitive 的内容对 trust 正向贡献权重更高,不新增专门的 LLM 分类调用)、affinity(≈旧
    warmth,注入排序键)、tension(近期冲突,自然衰减防记仇)。4 轴各自独立封顶。
  • familiarity 客观派生增量按自然日分桶——同一天内互动的边际贡献递减,不同天始终满额计;零 LLM、
    零新状态字段(用现有互动时间戳分桶计算)。

环境感知(ADR-0014)

  • EnvironmentSignal:前处理 port 与 ConversationInput 并列的独立类型
    {plugin, action, outcome?, subject_id?, actor_id?, chat_id, time};源 = host @event_postprocessor
    实时 push(真 group_id + 真 user_id);subject_id 可空(无主体事件如文件上传/群公告则空);
    actor_id 可空,专用于第三方 poke/reaction 场景记录发起方。
  • tier-1 氛围恒感:所有环境信号仅以速率/热闹度(无内容)喂 per-chat 情感态传染 EMA,常开,受
    有界传染封顶,冷启动仍受 ADR-0007 高阈值压制。
  • tier-2 显著反应:仅显著信号成 drive-tick 反应候选,走既有群聊主动路径(drive-tick → 两级门控
    → 主动开口),不新开输出出口;级一本地启发式(零 LLM)筛候选,级二主模型决定反应/沉默。
  • 易逝:不自动写 episodic;tier-1 速率并入 EMA(无新存储);tier-2 原始信号当轮用完即弃;若
    真反应,反应本身走正常对话记忆路径(send + 他人回复自然沉淀)。
  • 渐进解锁:tier-1 全程常开;tier-2 晚解锁(挂"主动开口"解锁之后)。
  • 能力门控:host 不发环境信号则整特性静默降级,core 无环境感知照常运行。

时间感(ADR-0018)

  • 距上次交互:per-user(非 per-chat),挂进冻结快照,复用 Recall 冷场计时 / 自发目标"久未联系"
    启发式已经在追踪的数据源,只加一层文本暴露;低于阈值不注入。reactive 与 Drive Tick 两条路径都持有。
  • 时段字段(深夜/清晨/白天/晚上):仅 Drive Tick 的 light context 新增——这条路径没有用户消息
    可锚定"现在几点";reactive 路径不重复注入(模型已能从消息自带时间戳读出)。
  • 两者均为纯声明性文本,不驱动任何数值方程,与 ADR-0005 情感态的昼夜节律 nudge(数值输入)是两条
    平行但不冲突的墙钟接入点。

人设漂移守护(ADR-0021)

  • 写入前否决闸(pre-commit gate):反思产出 profile/skill/Knowledge 候选后,同一次离线批处理
    紧跟一次独立(不承接产出候选那条推理链的新鲜调用)LLM-as-judge 判断——喂 persona port 完整
    结构化人设(persona/backstory/speech_patterns/sample_dialogue)+ 候选内容,做二元判断"是否
    与人设基线冲突" + 简短理由。
  • 通过才真正落库;判否或调用失败均 fail-closed 丢弃候选,记入决策快照标注"判断失败",反思下轮
    可重新尝试产出(非永久拉黑对应教训)。
  • 容许带 = 纯静态 config,判断 prompt 与基线内容不受反思-offset/情感态调制影响——监督者的准绳
    不能被被监督对象动手脚。
  • 管辖范围 = profile + skill + Knowledge 三类自主写入;不管辖沉默预算/门控阈值 offset(那是
    ADR-0006 自己已有的反坍缩护栏)。

即刻追问(ADR-0025)

  • send_message 新增可选参数 expects_reply: bool——模型显式声明这条消息是否在等待回应,
    文本启发式(问号结尾等)推断。
  • 私聊:复用 Recall 单一出口,短窗口未获回应触发本次冷场计时临时缩短,决策仍走 Recall 既有门控。
  • 群聊:复用 drive-tick,短窗口未获回应成为该 chat 下一次 drive-tick 评估的事件驱动触发源,走既有
    两级门控 → 主动开口决策链。
  • 不新增独立主动出口,不设熟悉度专属硬门槛(两级门控级二读得到关系多轴快照 + 渐进解锁硬门槛已双重
    覆盖)。

实时状态感知(ADR-0026,私聊专属)

  • 在线状态变化:host push(来源机制类似 poke),触发本次 Recall 冷场计时临时缩短(复用即刻追问
    同一接入点),不设熟悉度硬门槛。
  • 输入状态:纯被动参考事实,不触发任何主动性评估,落地为可读的活状态事实供模型自行参考
    发送时机,不接入已读延迟窗(避免神经质地对每次"对方开始打字"都跑一遍门控)。
  • 能力位按字段拆细:read_online_statusread_typing_status 独立开位,某平台缺哪项即整字段在
    对应机制里缺席,优雅降级。

Testing Decisions

  • 好测试的标准:只测外部可观察行为,不测实现细节——门控最终裁决、情感态数值轨迹、Recall 是否
    真的发出了消息,而不是内部某个中间变量的取值。
  • 纯函数优先:情感态三轴更新方程、两级门控级一启发式打分、沉默预算令牌桶、Recall 两段式冷却
    计时器、渐进解锁阈值曲线、familiarity 自然日分桶——全部设计为无 IO 纯函数(时钟/随机可注入),
    比照既有 recall.py::recency_decay()read_delay.pyf(energy) 风格独立单测,不需要接入
    RuntimeLoop 或真实 LLM。
  • 性质测试:情感态做衰减收敛(最终趋于慢层/零点)、单调性(同向刺激不产生反向变化)、有界性
    (不越过 clamp 上下界,非对称锁定区在边界附近生效)的性质测试,而非仅断言几个具体数值。
  • 录制回放:两级门控的决策比照 ADR-0010"可测性"既定doctrine——用固定的触发批次 + ScriptedLLMClient
    跑一遍,断言决策快照(级一/级二裁决、addressed/skipped_message_ids)与预期一致;后续调参时
    同一批固定输入重放,防回归。
  • 顶层集成seam复用RuntimeLoop 保持为 Phase 1-3 沿用至今的唯一集成级测试入口——本阶段只是
    新增一个 Drive Tick 触发入口(与既有的消息触发入口共享同一套门控代码),继续用
    tests/runtime_loop_helpers.py::make_loop() + ScriptedLLMClienttests/fake_llm.py)+
    FakeClock/FakeEgresstests/fake_egress.py)驱动,不引入新的集成测试框架。
  • 离线批处理 seam 复用:反思闭环 + 人设漂移守护的测试比照既有 delta.py(DeltaCompressor)的
    离线任务测试形状——注入 FakeClock + 两个独立的 ScriptedLLMClient 脚本(一个产出反思候选、一个
    扮演漂移守护判断)+ 假存储,覆盖"候选通过→落库""候选被否决→丢弃""判断调用失败→fail-closed 丢弃"
    三条路径。
  • LLM 触达路径一律走 fixture:门控级二、反思候选产出、漂移守护判断、共享结局分类器——均通过
    ScriptedLLMClient 驱动,测试中不发起真实网络请求。
  • 回归重点self_recall/三因子召回等 Phase 1-3 既有行为在两级门控接入后不能变化(比如三因子
    召回本身的评分公式本阶段不改动)——沿用既有测试文件,只在集成点补充断言"门控裁决为'回应'之后,
    下游行为与 Phase 3 一致"。

Out of Scope

  • 深挖任务委托ADR-0020):用户请求触发(非主动性
    决策)、完成投递刻意不过两级门控、用主力模型、独立成本池——架构上与本阶段的决策引擎正交,留待
    单独一个 phase。
  • 习得贴纸ADR-0024):依赖对他人发送贴纸的多模态识别,
    与主动性/情感态无耦合。
  • 跨平台资料拉取ADR-0027):执行形状复用深挖
    任务委托(ADR-0020),需等其先落地;且涉及 per-user 显式同意流程,属独立隐私议题。
  • 记忆深度搜索ADR-0031):纯记忆/工具增强,模型
    主动调用检索,不依赖情感态/门控。
  • mood_congruence 接入三因子召回ADR-0009 本轮更新):
    需要本阶段交付的情感态数值作为输入源,但把它接进 recall.py 评分公式属于对 Phase 2 已交付模块
    的增量修改,留给下一个触碰记忆管线的 phase 处理——本阶段只保证情感态数值本身可被外部读取。
  • 环境遥测 Ambient Telemetry(ADR-0014 2026-07-11 更新,per-user 常驻感知流):依赖 host 侧
    尚未设计的 LLM/VLM 预筛选基础设施,EnvironmentSignal tier-1/tier-2 本身不受影响。
  • ADR-0010 完整运营面/cost//why//why_query//diagnose 等聊天管理命令、六池成本治理
    (分池预算 + 熔断)、系统自检信号层、Prompt Cache 命中率遥测、"忘记我"命令——均为运营/可观测性
    打磨,非本阶段决策引擎的阻塞项;本阶段只交付决策快照的写入这一个最小必要切片。
  • TTS(语音合成):独立能力 port,与本阶段无耦合。

Further Notes

  • docs/design.md"上线路线"需要一次刷新:其第 4/5 阶段("真人感"/"能动性")的划分早于
    ADR-0029 的 reactive/主动开口合一决策,"主动开口三件套"与 drive-tick 分属两阶段的表述已经过时;
    该文档把深挖任务委托也归进第 5 阶段"能动性",但如上所述其触发/投递语义与本阶段的决策引擎正交。
    建议本阶段落地后顺手把路线图这两节合并改写,避免继续误导后来者。
  • 命名冲突提醒recall.py 目前是"三因子记忆召回"(ADR-0009),本阶段新增的"私聊主动重连"
    机制(CONTEXT.md 里同样叫"Recall",源自 ADR-0006)是完全不同的概念,只是英文都习惯叫 recall——
    实现期务必用不同的模块/类型名区分(比如"主动重连"/"reconnect"一类,避免与既有召回模块混淆),
    这条在 Implementation Decisions 里也提了一遍,这里再强调一次因为踩坑代价(一次不小心的 grep 改错
    模块)比较高。
  • 体量预期:本阶段体量约为 Phase 3 的两倍(10 条 ADR vs Phase 3 的约 6 条),预计在后续实现期
    规划(对应 Phase 1-3 "PRD issue → 拆 slice issue"的既有模式)会被拆成 6-8 个 slice issue,这不
    属于本 PRD 阶段的工作。
  • 本 PRD 里提到的所有具体数值(沉默预算容量/令牌桶 refill 速率、情感态衰减系数、抗溢出压缩系数、
    familiarity 分桶阈值、渐进解锁各档具体门槛、距上次交互的"低阈"数字、时段划分粒度等)均按
    ADR-0011 阈值三层分类推迟到真实 QQ 场景数据标定,保守
    默认起步,Testing Decisions 里的"录制回放"机制正是为这条标定路径准备的。
> _(续正文)_ ### 能动性:Drive Tick + Recall + 自发目标 + 反思闭环(ADR-0006) - **Drive Tick**:跑在 isolated/light context;无 due 任务整轮跳过、零 API;决定沉默时输出静默令牌; 开工先读状态防重复关心;不与真人抢 lane(busy 时 defer 到下一 tick)。群事件驱动 / 私聊冷场定时; 事件触发复用同一入口但改用全量上下文(见"统一触发路径")。 - **Recall(私聊唯一主动出口)**:冷场计时触发;**冷却计时两段式**——己方主动发送触发部分缓解 ("确实努力了"),只有对方真实回复才触发全量重置("连接达成"),复用既有 Sent Log + 回复归属检测 判定"是否已被回复"。**命名提醒**:不与既有『三因子召回』模块混淆,须使用独立的模块/标识符命名 (如"主动重连"而非任何形式的裸 "recall")。 - **自发目标**:core 本地启发式触发候选(熟人久未联系/话题新进展/冒出不懂的梗);主模型**轮内** 决定是否成 context 模式 pending intent,走既有 `inject_intents` + Recall 单一出口消费,不新起 循环、不新增独立出口;默认低优先 + 强衰减 + 可被真人抢占 + fail-closed + 灰度可一键关。 - **离线反思闭环**:离线、廉价 auxiliary 模型,复用 Delta 管线;消费双向弱反馈(正:主动后有人接/ 话题延续/energy 升;负:被无视/被"别烦"/冷场/被追问)产自然语言教训(带证据指针);**目标 = 主动 尝试逐次得体率(hit-rate)**,明确不是"最小化负反馈"(沉默坍缩退化解)也不是"最大化净参与"(噪声 坍缩退化解);自主写三处——门控阈值 offset(对称有界 `[floor, ceiling]`,**步长不对称:抬静默阈值 快于降**,无信号衰减朝安静,offset 本身锚回基值)、per-chat 画像、技能——全部 fail-closed + 可回溯 可撤销 + 灰度;**profile/skill/Knowledge 写入路径全部先过人设漂移守护否决闸才落库**;在线反思绝 不做。 - 共享结局分类器(`landed`/`fell-flat`/`annoyed`)为同一份分类逻辑,三路消费:dominance 快路(同轮)、 反思 hit-rate 慢路(沉淀 offset)、per-user 慢情感态.dominance(更慢路),不重复写分类代码。 - 反思对技能的写入复用 Knowledge 查重合并模式(按向量相似度查是否与现有技能语义重叠,命中融入/ 精炼现有条目,不命中才新建)。 ### 冷启动与渐进解锁(ADR-0007,被 ADR-0029 更新为单轴) - 解锁顺序:`(统一门控,沉默预算/兴趣门连续收紧) → 三因子召回(Phase 2 已交付)→ 关系网注入 → 自发目标`;不存在"反应式已解锁但主动开口未解锁"的中间态。 - 冷启动期门控收紧(沉默预算下限收紧、兴趣门阈值抬高),被提及时可触发轻量自我介绍。 - 该解锁顺序同时是上线灰度轴,与已交付的 `read_delay` scope_ceiling 冷启动收紧共用同一条轴线。 ### 关系网与关系多轴(ADR-0008) - 保留既有两层关系网结构(显式声明边 + 隐式同群/同事件共现查询时派生,不上图,1-hop 主力 + 递归 CTE ≤2 或 `lookup_relation` 按需)、知情-gate(敏感数据私聊例外 ⇔ current 是某知情者的私聊)。 - agent↔user 扩为四轴,**per-persona + per-user** 作用域:`familiarity`(互动次数/时长客观派生, 零 LLM)、`trust`(复用 Delta 压缩管线已有的 `sensitive` 打标作为"自我展露深度"代理信号,命中 sensitive 的内容对 trust 正向贡献权重更高,**不新增专门的 LLM 分类调用**)、`affinity`(≈旧 warmth,注入排序键)、`tension`(近期冲突,自然衰减防记仇)。4 轴各自独立封顶。 - `familiarity` 客观派生增量按**自然日分桶**——同一天内互动的边际贡献递减,不同天始终满额计;零 LLM、 零新状态字段(用现有互动时间戳分桶计算)。 ### 环境感知(ADR-0014) - `EnvironmentSignal`:前处理 port 与 `ConversationInput` 并列的独立类型 `{plugin, action, outcome?, subject_id?, actor_id?, chat_id, time}`;源 = host `@event_postprocessor` 实时 push(真 `group_id` + 真 `user_id`);`subject_id` 可空(无主体事件如文件上传/群公告则空); `actor_id` 可空,专用于第三方 poke/reaction 场景记录发起方。 - **tier-1 氛围恒感**:所有环境信号仅以速率/热闹度(无内容)喂 per-chat 情感态传染 EMA,常开,受 有界传染封顶,冷启动仍受 ADR-0007 高阈值压制。 - **tier-2 显著反应**:仅显著信号成 drive-tick 反应候选,走既有群聊主动路径(drive-tick → 两级门控 → 主动开口),**不新开输出出口**;级一本地启发式(零 LLM)筛候选,级二主模型决定反应/沉默。 - **易逝**:不自动写 episodic;tier-1 速率并入 EMA(无新存储);tier-2 原始信号当轮用完即弃;若 真反应,反应本身走正常对话记忆路径(send + 他人回复自然沉淀)。 - 渐进解锁:tier-1 全程常开;tier-2 晚解锁(挂"主动开口"解锁之后)。 - 能力门控:host 不发环境信号则整特性静默降级,core 无环境感知照常运行。 ### 时间感(ADR-0018) - **距上次交互**:per-user(非 per-chat),挂进冻结快照,复用 Recall 冷场计时 / 自发目标"久未联系" 启发式已经在追踪的数据源,只加一层文本暴露;低于阈值不注入。reactive 与 Drive Tick 两条路径都持有。 - **时段字段**(深夜/清晨/白天/晚上):仅 Drive Tick 的 light context 新增——这条路径没有用户消息 可锚定"现在几点";reactive 路径不重复注入(模型已能从消息自带时间戳读出)。 - 两者均为纯声明性文本,不驱动任何数值方程,与 ADR-0005 情感态的昼夜节律 nudge(数值输入)是两条 平行但不冲突的墙钟接入点。 ### 人设漂移守护(ADR-0021) - **写入前否决闸(pre-commit gate)**:反思产出 profile/skill/Knowledge 候选后,同一次离线批处理 紧跟一次**独立**(不承接产出候选那条推理链的新鲜调用)LLM-as-judge 判断——喂 persona port 完整 结构化人设(`persona`/`backstory`/`speech_patterns`/`sample_dialogue`)+ 候选内容,做二元判断"是否 与人设基线冲突" + 简短理由。 - 通过才真正落库;判否或调用失败均 **fail-closed** 丢弃候选,记入决策快照标注"判断失败",反思下轮 可重新尝试产出(非永久拉黑对应教训)。 - 容许带 = 纯静态 config,判断 prompt 与基线内容**不受反思-offset/情感态调制影响**——监督者的准绳 不能被被监督对象动手脚。 - 管辖范围 = profile + skill + Knowledge 三类自主写入;**不管辖**沉默预算/门控阈值 offset(那是 ADR-0006 自己已有的反坍缩护栏)。 ### 即刻追问(ADR-0025) - `send_message` 新增可选参数 `expects_reply: bool`——模型显式声明这条消息是否在等待回应,**不**用 文本启发式(问号结尾等)推断。 - 私聊:复用 Recall 单一出口,短窗口未获回应触发本次冷场计时**临时缩短**,决策仍走 Recall 既有门控。 - 群聊:复用 drive-tick,短窗口未获回应成为该 chat 下一次 drive-tick 评估的事件驱动触发源,走既有 两级门控 → 主动开口决策链。 - 不新增独立主动出口,不设熟悉度专属硬门槛(两级门控级二读得到关系多轴快照 + 渐进解锁硬门槛已双重 覆盖)。 ### 实时状态感知(ADR-0026,私聊专属) - **在线状态变化**:host push(来源机制类似 poke),触发本次 Recall 冷场计时临时缩短(复用即刻追问 同一接入点),不设熟悉度硬门槛。 - **输入状态**:纯被动参考事实,**不触发任何主动性评估**,落地为可读的活状态事实供模型自行参考 发送时机,不接入已读延迟窗(避免神经质地对每次"对方开始打字"都跑一遍门控)。 - 能力位按字段拆细:`read_online_status`、`read_typing_status` 独立开位,某平台缺哪项即整字段在 对应机制里缺席,优雅降级。 ## Testing Decisions - **好测试的标准**:只测外部可观察行为,不测实现细节——门控最终裁决、情感态数值轨迹、Recall 是否 真的发出了消息,而不是内部某个中间变量的取值。 - **纯函数优先**:情感态三轴更新方程、两级门控级一启发式打分、沉默预算令牌桶、Recall 两段式冷却 计时器、渐进解锁阈值曲线、`familiarity` 自然日分桶——全部设计为无 IO 纯函数(时钟/随机可注入), 比照既有 `recall.py::recency_decay()`、`read_delay.py` 的 `f(energy)` 风格独立单测,不需要接入 `RuntimeLoop` 或真实 LLM。 - **性质测试**:情感态做衰减收敛(最终趋于慢层/零点)、单调性(同向刺激不产生反向变化)、有界性 (不越过 clamp 上下界,非对称锁定区在边界附近生效)的性质测试,而非仅断言几个具体数值。 - **录制回放**:两级门控的决策比照 ADR-0010"可测性"既定doctrine——用固定的触发批次 + `ScriptedLLMClient` 跑一遍,断言决策快照(级一/级二裁决、`addressed`/`skipped_message_ids`)与预期一致;后续调参时 同一批固定输入重放,防回归。 - **顶层集成seam复用**:`RuntimeLoop` 保持为 Phase 1-3 沿用至今的唯一集成级测试入口——本阶段只是 新增一个 Drive Tick 触发入口(与既有的消息触发入口共享同一套门控代码),继续用 `tests/runtime_loop_helpers.py::make_loop()` + `ScriptedLLMClient`(`tests/fake_llm.py`)+ `FakeClock`/`FakeEgress`(`tests/fake_egress.py`)驱动,不引入新的集成测试框架。 - **离线批处理 seam 复用**:反思闭环 + 人设漂移守护的测试比照既有 `delta.py`(DeltaCompressor)的 离线任务测试形状——注入 `FakeClock` + 两个独立的 `ScriptedLLMClient` 脚本(一个产出反思候选、一个 扮演漂移守护判断)+ 假存储,覆盖"候选通过→落库""候选被否决→丢弃""判断调用失败→fail-closed 丢弃" 三条路径。 - **LLM 触达路径一律走 fixture**:门控级二、反思候选产出、漂移守护判断、共享结局分类器——均通过 `ScriptedLLMClient` 驱动,测试中不发起真实网络请求。 - **回归重点**:`self_recall`/三因子召回等 Phase 1-3 既有行为在两级门控接入后不能变化(比如三因子 召回本身的评分公式本阶段不改动)——沿用既有测试文件,只在集成点补充断言"门控裁决为'回应'之后, 下游行为与 Phase 3 一致"。 ## Out of Scope - **深挖任务委托**([ADR-0020](docs/adr/0020-deep-task-delegation.md)):用户请求触发(非主动性 决策)、完成投递刻意不过两级门控、用主力模型、独立成本池——架构上与本阶段的决策引擎正交,留待 单独一个 phase。 - **习得贴纸**([ADR-0024](docs/adr/0024-learned-stickers.md)):依赖对他人发送贴纸的多模态识别, 与主动性/情感态无耦合。 - **跨平台资料拉取**([ADR-0027](docs/adr/0027-cross-platform-profile-pull.md)):执行形状复用深挖 任务委托(ADR-0020),需等其先落地;且涉及 per-user 显式同意流程,属独立隐私议题。 - **记忆深度搜索**([ADR-0031](docs/adr/0031-on-demand-memory-search.md)):纯记忆/工具增强,模型 主动调用检索,不依赖情感态/门控。 - **mood_congruence 接入三因子召回**([ADR-0009](docs/adr/0009-memory-engineering.md) 本轮更新): 需要本阶段交付的情感态数值作为输入源,但把它接进 `recall.py` 评分公式属于对 Phase 2 已交付模块 的增量修改,留给下一个触碰记忆管线的 phase 处理——本阶段只保证情感态数值本身可被外部读取。 - **环境遥测 Ambient Telemetry**(ADR-0014 2026-07-11 更新,per-user 常驻感知流):依赖 host 侧 尚未设计的 LLM/VLM 预筛选基础设施,`EnvironmentSignal` tier-1/tier-2 本身不受影响。 - **ADR-0010 完整运营面**:`/cost`/`/why`/`/why_query`/`/diagnose` 等聊天管理命令、六池成本治理 (分池预算 + 熔断)、系统自检信号层、Prompt Cache 命中率遥测、"忘记我"命令——均为运营/可观测性 打磨,非本阶段决策引擎的阻塞项;本阶段只交付决策快照的**写入**这一个最小必要切片。 - **TTS(语音合成)**:独立能力 port,与本阶段无耦合。 ## Further Notes - **`docs/design.md`"上线路线"需要一次刷新**:其第 4/5 阶段("真人感"/"能动性")的划分早于 ADR-0029 的 reactive/主动开口合一决策,"主动开口三件套"与 drive-tick 分属两阶段的表述已经过时; 该文档把深挖任务委托也归进第 5 阶段"能动性",但如上所述其触发/投递语义与本阶段的决策引擎正交。 建议本阶段落地后顺手把路线图这两节合并改写,避免继续误导后来者。 - **命名冲突提醒**:`recall.py` 目前是"三因子记忆召回"(ADR-0009),本阶段新增的"私聊主动重连" 机制(CONTEXT.md 里同样叫"Recall",源自 ADR-0006)是完全不同的概念,只是英文都习惯叫 recall—— 实现期务必用不同的模块/类型名区分(比如"主动重连"/"reconnect"一类,避免与既有召回模块混淆), 这条在 Implementation Decisions 里也提了一遍,这里再强调一次因为踩坑代价(一次不小心的 grep 改错 模块)比较高。 - **体量预期**:本阶段体量约为 Phase 3 的两倍(10 条 ADR vs Phase 3 的约 6 条),预计在后续实现期 规划(对应 Phase 1-3 "PRD issue → 拆 slice issue"的既有模式)会被拆成 6-8 个 slice issue,这不 属于本 PRD 阶段的工作。 - 本 PRD 里提到的所有具体数值(沉默预算容量/令牌桶 refill 速率、情感态衰减系数、抗溢出压缩系数、 familiarity 分桶阈值、渐进解锁各档具体门槛、距上次交互的"低阈"数字、时段划分粒度等)均按 [ADR-0011](docs/adr/0011-technology-selection.md) 阈值三层分类推迟到真实 QQ 场景数据标定,保守 默认起步,Testing Decisions 里的"录制回放"机制正是为这条标定路径准备的。
Yushu closed this issue 2026-07-24 03:12:53 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ProjectKuma/arise#33
No description provided.