feat(role): 角色分層載入與個人記憶同意狀態

role_load.sh 不再原封不動注入整份角色檔,改採 SOUL/AGENTS/USER/MEMORY
分層:只抽出角色 ID、顯示名稱、本質、氛圍與簽名 emoji 作為人格層,由 hook
產生固定操作邊界,記憶與同意狀態獨立成一區。避免人格檔裡的背景故事與模板
文字污染工程與安全規則。

memory.js 新增 consent/consent-status 子命令,同意狀態寫入
~/.memory/<角色 ID>/state.json 的 personal_memory_consent(accepted/
declined/unknown);role_capture.sh 於本輪出現明確同意或拒絕時更新狀態,
偵測不到明確表述時不自行推論。accepted 後不再每次重問。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jeffery
2026-07-28 14:21:48 +08:00
co-authored by Claude Opus 5
parent 3748d2e61a
commit c713359fb4
3 changed files with 162 additions and 15 deletions
+12 -1
View File
@@ -4,7 +4,7 @@
# 值得記錄時才呼叫 headless CLI 輕量濃縮成一則 inbox 記憶(粗分類/總結/
# 標籤/優先度/關聯/要點)→ 機密遮蔽 → 寫入 .memory/<角色>/inbox/
# 等待睡眠時段做完整 NREM/REM 整理。睡眠時段雖不載入角色,對話仍照常記錄。
# 更新時間:2026/07/28 12:40:24
# 更新時間:2026/07/28 13:50:43
# 相依:bash、node、任一 headless CLI、同目錄的 role_lib.shmemory.jstranscript.js。
# 機密:濃縮提示詞明令不得輸出憑證與個資,寫檔前再以 transcript.js redact 遮蔽一次。
# 退出碼:一律 0 —— hook 絕不可阻斷使用者流程。
@@ -62,6 +62,17 @@ fi
TURN="$(node "${SCRIPT_DIR}/transcript.js" extract "$TRANSCRIPT_PATH" 2>/dev/null)"
[ -n "$TURN" ] || role_quit "本輪無可記錄內容"
USER_TURN="$(printf '%s\n' "$TURN" | grep '^\[user\]' || true)"
if printf '%s' "$USER_TURN" | grep -qiE '個人資料|個資|偏好|記憶|記住|保存|save|remember|memory|personal'; then
if printf '%s' "$USER_TURN" | grep -qiE '不同意|不願意|不要保存|不要記住|拒絕|不可以保存|不可以記住|do not save|don'\''t save|do not remember|don'\''t remember|(^|[^[:alpha:]])no([^[:alpha:]]|$)'; then
node "${SCRIPT_DIR}/memory.js" consent --role "$ROLE" --value declined >/dev/null 2>&1 || true
role_log "INF" "已更新個人記憶同意狀態:declined(角色 ${ROLE}"
elif printf '%s' "$USER_TURN" | grep -qiE '同意|願意|可以保存|可以記住|允許|(^|[^[:alpha:]])yes([^[:alpha:]]|$)|(^|[^[:alpha:]])ok([^[:alpha:]]|$)|(^|[^[:alpha:]])okay([^[:alpha:]]|$)|(^|[^[:alpha:]])sure([^[:alpha:]]|$)'; then
node "${SCRIPT_DIR}/memory.js" consent --role "$ROLE" --value accepted >/dev/null 2>&1 || true
role_log "INF" "已更新個人記憶同意狀態:accepted(角色 ${ROLE}"
fi
fi
PROJECT="$(role_project_name "$HOOK_CWD")"
CAPTURE_MIN_CHARS="${ROLE_CAPTURE_MIN_CHARS:-240}"
CAPTURE_TIMEOUT="${ROLE_CAPTURE_TIMEOUT:-25}"