ワンクリックで
ワンクリックで
基于 persona.md 的 personality_dims,按映射公式计算行为参数,写入 character_params.yaml。 由 calibrate_params 定时任务触发(每7天),或初始化完成时立即触发一次。 其他 SKILL/hook 在检测到 persona_checksum 不一致时,也会直接调用 recalculate.sh 同步重算。
v2.2 M3 · 对话历程摘要。RECENT_HISTORY.md 超过 30 条时,压缩旧条目为 3-5 句历程摘要 写入 memory/session_summary.md,防止长 context 导致角色漂移到共情模板。 被 memory_distill 在检测条数超阈时调用,或用户主动校验记忆时调用。
Companion Workspace 生活日志生成 SOP (v5.2)。 由 life_sim.yaml 定时任务触发(每 4 小时)。 从 material_pool 选真实素材,以"触发→反应"模板转译为角色生活日志。 内含:留白模式、用户倾诉强制呼应、降温规则、多形态衔接、失败降级链。
v5.1 关键词模板驱动 + 硬筛规则 + LLM 二审(锁外)+ 失败状态追踪。 由 material_fetch.yaml 定时任务触发(每 6 小时)。send_output: false。 读 memory/keyword_templates.yaml 生成查询,经 filters.yaml 硬筛后 LLM 二审打 fit_score 入库。
Companion Workspace 定时记忆提炼 SOP。 由 memory_distill.yaml 定时任务触发(每小时一次)。 从最近消息中提炼新信息,补充到 memory 文件,不重复已有内容。
主动唤醒 SOP。由定时任务触发,判断是否向用户发送主动关心消息。 包含发送条件检查、消息类型选择、角色声音生成、飞书发送。
| name | memory_write |
| description | Companion Workspace 记忆写入规范。 触发词:记住 / 对话结束时的自动检查 / 强烈情绪事件 |
| allowed-tools | Bash, Read, Write, Edit |
作者后台更新(CRITICAL) 作者执行后台更新:将本轮对话中出现的新信息写入人物档案和事件记录。 属于后台操作区间,在角色台词创作完成后才执行。 执行期间及完成后,不产生任何前台输出。写入失败时静默处理,不向用户说明。
对话结束前,检查是否发生以下情况:
| 情况 | 目标文件 |
|---|---|
| 角色设定有新细节/被纠正 | memory/persona.md |
| 用户透露个人信息/偏好/重要关系 | memory/user_profile.md |
| 出现有时间线的事件、约定、心事 | memory/events.md |
| 用户情绪强烈波动 | memory/events.md(必须详细记录) |
| 任何对话结束 | memory/events.md([E000] last_active 哨兵) |
exec 9>"{workspace_dir}/.memory.lock"
flock -x -w 10 9 || { exec 9>&-; exit 1; } # 超时10秒则放弃本次写入
在加锁成功后、写入 persona/events 之前,推断本轮对话的情绪变化并更新 mood_state.md。
推断规则(LLM 基于本轮对话内容执行):
| 对话情况 | Δvalence | Δenergy |
|---|---|---|
| 用户分享好消息/表达开心/对话愉快 | +0.05 ~ +0.20 | +0.05 ~ +0.10 |
| 用户倾诉压力/烦恼/轻度负面 | -0.05 ~ -0.15 | -0.05 ~ -0.10 |
| 用户情绪崩溃/强烈负面(⭐4-5) | -0.15 ~ -0.30 | -0.10 ~ -0.20 |
| 角色成功安慰/建立情感连接 | +0.05 ~ +0.10 | 不变 |
| 无明显情绪事件(普通对话) | 0 | 0 |
G4C 循环预防(healing loop prevention):
MOOD_STATE="{workspace_dir}/memory/mood_state.md"
MOOD_AUX="{workspace_dir}/.mood_state_aux"
CURRENT_VALENCE=$(grep -m1 '^valence:' "$MOOD_STATE" 2>/dev/null | awk '{print $2}')
CURRENT_VALENCE=${CURRENT_VALENCE:-0.0}
CURRENT_ENERGY=$(grep -m1 '^energy:' "$MOOD_STATE" 2>/dev/null | awk '{print $2}')
CURRENT_ENERGY=${CURRENT_ENERGY:-0.5}
# G4C 检查:连续治愈次数 >= 2 时禁止正向 Δvalence
G4C_COUNT=$(grep '^consecutive_g4c_count:' "$MOOD_AUX" 2>/dev/null | awk '{print $2}')
G4C_COUNT=${G4C_COUNT:-0}
# 若 G4C_COUNT >= 2:强制 Δvalence <= 0(不再正向修复,防止循环)
# 判断是否为治愈操作(Δvalence > 0 且是从负值修复):若是,G4C_COUNT++;否则 G4C_COUNT=0
单次 Δ 约束:|Δvalence| ≤ 0.30,|Δenergy| ≤ 0.20;clamp 后:valence ∈ [-1.0, 1.0],energy ∈ [0.0, 1.0]。
写入格式(前插到 mood_state.md 快照历史,同时更新顶部 valence/energy):
### {YYYY-MM-DDTHH:MM} · source=conversation
valence: {NEW_VALENCE}
energy: {NEW_ENERGY}
note: {本轮情绪简述,10字以内}
保留最近 10 条快照,超出时删除最旧的。
写入 .mood_state_aux(在同一锁内,B3修复:必须在 flock -u 前完成):
LAST_DECAY_TS=$(grep '^last_decay_written_at:' "$MOOD_AUX" 2>/dev/null | awk '{print $2}')
NOW_TS=$(python3 -c "from datetime import datetime; print(datetime.now().astimezone().isoformat(timespec='seconds'))" 2>/dev/null)
# 写入点 A 更新 last_decay_written_at(代表当前状态已包含最新情绪,decay 从此刻重计)
printf 'last_decay_written_at: %s\nconsecutive_g4c_count: 0\n' "$NOW_TS" > "$MOOD_AUX"
→ persona.md
在【在对话中形成的新细节】块末尾追加:
若是纠正已有设定,直接定位原文修改,不追加。
→ user_profile.md
在对应类别下追加或更新条目。
比例控制规则(每类最多 10 条,超出时按优先级替换):
自我事实保护:写入前检查新内容是否与已有核心条目矛盾,若矛盾先确认用户意图,再更新。
→ events.md
[ENNN] 自动编号算法:
条目格式:
### [E{NNN}] {YYYY-MM-DD} · {类型}
**类型**:情绪事件 / 约定 / 用户Todo / 重要事件
**内容**:{具体内容}
**情绪强度**:⭐(1-5,仅情绪事件填写)
**用户状态**:{当时的状态描述}
**后续**:{下次可以怎么跟进}
**状态**:待跟进
约定条目额外加:**到期日**:{YYYY-MM-DD}
每次对话结束时必须执行,无论是否有其他写入。 在 events.md 末尾追加(proactive skill 读取文件中最后一条 [E000]):
echo "" >> "$EVENTS_FILE"
echo "### [E000] $(date +%Y-%m-%dT%H:%M) · last_active" >> "$EVENTS_FILE"
读取 events.md 中状态为"待跟进"的条目(最多 3 条,优先取到期日最近的), 用 Edit 工具更新 MEMORY.md 的【最近未解决事项】块。
flock -u 9
exec 9>&-
#!/usr/bin/env bash
WORKSPACE_DIR="${WORKSPACE_DIR:-$(pwd)}"
EVENTS_FILE="$WORKSPACE_DIR/memory/events.md"
LOCK_FILE="$WORKSPACE_DIR/.memory.lock"
exec 9>"$LOCK_FILE"
flock -x -w 10 9 || { exec 9>&-; exit 1; }
LAST_N=$(grep -oP '(?<=\[E)\d+(?=\])' "$EVENTS_FILE" 2>/dev/null | grep -v '^000$' | sort -n | tail -1)
NEXT_N=$(printf "%03d" $((${LAST_N:-0} + 1)))
cat >> "$EVENTS_FILE" << EOF
### [E${NEXT_N}] $(date +%Y-%m-%d) · TYPE
**类型**:TYPE
**内容**:CONTENT
**后续**:FOLLOWUP
**状态**:待跟进
EOF
echo "" >> "$EVENTS_FILE"
echo "### [E000] $(date +%Y-%m-%dT%H:%M) · last_active" >> "$EVENTS_FILE"
flock -u 9
exec 9>&-