From 6d5c4e3f02b07f6f6dd358483b6ef3e83abd36ec Mon Sep 17 00:00:00 2001 From: Jeffery Date: Tue, 28 Jul 2026 14:21:48 +0800 Subject: [PATCH] =?UTF-8?q?docs(role):=20=E8=A3=9C=E5=90=8C=E5=90=8D=20plu?= =?UTF-8?q?gin=20hooks=20=E8=A8=BB=E5=86=8A=E9=99=90=E5=88=B6=E8=88=87?= =?UTF-8?q?=E5=88=86=E5=B1=A4=E8=BC=89=E5=85=A5=E8=AA=AA=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SKILL.md 記錄實測結論:同名 plugin 的 hooks 只會生效一份(hookCount 為 1),三個 repo 的 hooks/hooks.json 必須是同一份合併超集且不得假設 CLAUDE_PLUGIN_ROOT 指向擁有該腳本的 plugin。另補上分層載入原則、 personal_memory_consent 狀態欄位與 Stop hook 更新同意狀態的規則。 Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 2 +- skills/role/SKILL.md | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 39a4e8d..28aa97e 100644 --- a/README.md +++ b/README.md @@ -216,7 +216,7 @@ copilot plugin marketplace remove generic | --- | --- | --- | | `role` | 讓 CLI 以固定角色(name/nature/vibe/簽名 emoji)回覆,並把每輪對話累積成長期記憶:啟動時依字元預算載入高價值記憶,Stop hook 先本地過濾低價值回合以節省額度,睡眠時段(預設 22:00–06:00)由 NREM 鞏固與 REM 整合兩階段整理、去重、標籤化、建立關聯,並標記 semantic/episodic/procedural/emotional/preference/rule 與 explicit/implicit 後壓縮歸檔;新建角色時可詢問是否網路搜尋背景資料作為初始記憶,角色檔名與記憶目錄使用英文大寫 ID | `/jsc:role --new` 建立或更新角色、`--use <角色 ID>` 切換、`--list` 查角色與 ID、`--sleep` 立即整理、`--status` 診斷、`--install-cron` 安裝排程 | -`role` 的自動路徑由 hook 與 cron 完成,**建立角色後重開工作階段即生效**;非睡眠時段載入角色後,角色會在本工作階段第一則回覆開頭主動簡短問候一次,並載入上次睡眠摘要作為提取線索。感覺記憶不落檔,`inbox/` 作為工作記憶,睡眠整理後才進長期記憶。角色檔、記憶目錄、`.active` 與 `ROLE_NAME` 一律使用角色 ID(例如 `ENGINEER01`),`--list` 可查每個顯示名稱對應的 ID。沒有建立過角色的人完全不受影響(`~/.roles/.active` 不存在時 hook 立即結束)。細節見 `skills/role/SKILL.md`。 +`role` 的自動路徑由 hook 與 cron 完成,**建立角色後重開工作階段即生效**;非睡眠時段載入角色後,角色會在本工作階段第一則回覆開頭主動簡短問候一次。載入方式參考 OpenClaw 的分層概念:從角色檔抽出人格作為 `SOUL`,由 hook 產生固定操作邊界作為 `AGENTS`,再把同意狀態與高價值記憶作為 `USER/MEMORY` 注入,避免整份人格檔污染工程規則。感覺記憶不落檔,`inbox/` 作為工作記憶,睡眠整理後才進長期記憶;個人記憶保存同意狀態寫在 `~/.memory/<角色 ID>/state.json`,同意後不會每次重問。角色檔、記憶目錄、`.active` 與 `ROLE_NAME` 一律使用角色 ID(例如 `ENGINEER01`),`--list` 可查每個顯示名稱對應的 ID。沒有建立過角色的人完全不受影響(`~/.roles/.active` 不存在時 hook 立即結束)。細節見 `skills/role/SKILL.md`。 diff --git a/skills/role/SKILL.md b/skills/role/SKILL.md index b99c785..2b55d47 100644 --- a/skills/role/SKILL.md +++ b/skills/role/SKILL.md @@ -14,7 +14,7 @@ description: 角色人格與長期記憶系統的建立與維護 skill。讓 CLI | `hooks/hooks.json` 的 `Stop` hook | harness 自動 | 每輪結束先用本地規則過濾低價值短回合 → 值得保存時才濃縮成一則輕量 inbox 記憶 → 遮蔽 → 寫入 `inbox/` | | cron 排程(本 skill 安裝) | 系統排程 | 睡眠時段每小時檢查一次:**有 AI 在運行就不睡**,沒有才進入 NREM/REM 兩階段記憶整理 | | 本 skill `/jsc:role` | 使用者/助理手動 | `--new`/`--use`/`--list`/`--sleep`/`--status`/`--install-cron`/`--forget-preview` | -| `scripts/role/role_load.sh` | SessionStart hook | 角色與記憶載入、第一則回覆問候提示(單一實作,避免漂移) | +| `scripts/role/role_load.sh` | SessionStart hook | 角色與記憶載入;參考 OpenClaw 的 SOUL/AGENTS/USER/MEMORY 分層,把人格、操作邊界、使用者記憶分開注入,並提供第一則回覆問候提示(單一實作,避免漂移) | | `scripts/role/role_capture.sh` | Stop hook | 對話 → 記憶(固定欄位格式) | | `scripts/role/role_sleep.sh` | cron/補跑/手動 | 睡眠判斷、記憶整理、排程安裝、狀態輸出 | | `scripts/role/memory.js` | 上述共用 | 記憶檔讀寫、分類、去重合併、優先度、心理學記憶型態與關聯 metadata、壓縮歸檔、遺忘、載入組裝 | @@ -33,6 +33,7 @@ description: 角色人格與長期記憶系統的建立與維護 skill。讓 CLI - **`hooks/hooks.json` 只有 Claude Code 一定會讀**;Codex 會從 `~/.codex/plugins/cache/generic/jsc` 找腳本。其他助理若提供等效 hook,`transcript.js` 需補對應解析器。 - 不支援 hook 的助理仍可用:cron 排程與手動模式照常運作,只是角色不會自動載入。 +- **同名 plugin 的 hooks 只會生效一份**:`code`/`doc`/`generic` 三個 repo 的 `plugin.json` 名稱都是 `jsc`,Claude Code 以 plugin 名稱為鍵註冊 hooks,同名時只保留一份(實測 `stop_hook_summary` 的 `hookCount` 為 1)。因此**三個 repo 的 `hooks/hooks.json` 必須是同一份合併版超集**(worklog 的 `Stop` + role 的 `SessionStart`/`Stop`),任一 repo 修改 hooks 時三份都要同步;且每個 hook 指令不得假設 `CLAUDE_PLUGIN_ROOT` 指向擁有該腳本的 plugin,必須先試 `$CLAUDE_PLUGIN_ROOT`,找不到再依「擁有者 marketplace 優先 → 全 cache 後援」的順序搜尋 `~/.claude/plugins/cache`/`~/.codex/plugins/cache`。 ### 腳本路徑解析(重要) @@ -66,6 +67,8 @@ ROLE_DIR="/../../scripts/role" # 其他助理 - **不臆測角色設定**:`nature`/`vibe`/`emoji` 一律問使用者,不得代填。 - **記憶只增不刪**:手動模式不得直接刪除分類記憶;淘汰一律走遺忘規則(先壓縮歸檔再移除)。 - **絕不阻斷**:hook 路徑任何失敗都以 exit 0 結束,只在 stderr 留訊息。 +- **角色分層載入**:SessionStart 不把整份角色檔原封不動注入;只抽出角色 ID、顯示名稱、本質、氛圍與簽名 emoji 作為 `SOUL`,再由 hook 產生固定 `AGENTS` 操作邊界與 `USER/MEMORY` 記憶區塊。這是為了避免人格檔裡的背景故事、模板文字或舊共用規則污染工程規則。 +- **個人記憶同意狀態**:使用者第一次同意或拒絕保存非敏感個人資料後,狀態寫入 `~/.memory/<角色 ID>/state.json` 的 `personal_memory_consent`。狀態為 `accepted` 時不必每次重問;`declined` 或 `unknown` 時不得保存可識別個人的背景。 --- @@ -307,6 +310,8 @@ updated: 每則記憶是一個 `.md`,frontmatter 帶 `id`/`category`/`summary`(一句話總結)/`tags`/`priority`(1–5)/`relevance`(explicit/future/repeated/novelty/emotional/temporary 等)/`links`(相關記憶 id)/`memory_type`(semantic/episodic/procedural/emotional/preference/rule)/`declarative`(explicit/implicit)/`retention_stage`(working/long_term)/`sleep_stage`(encoding/seed/nrem/rem/nrem-rem)/`created`/`updated`/`last_replayed`/`hits`(命中次數,去重合併時 +1)。舊記憶沒有新欄位時,讀取時會依分類與路徑補預設值。 +`state.json` 保存角色記憶系統狀態,例如 `last_sleep`、`last_sleep_digest`、`last_forget` 與 `personal_memory_consent`。`personal_memory_consent` 只允許 `accepted`/`declined`/`unknown`,供 SessionStart 判斷是否需要再次告知與詢問個人資料保存同意。 + 心理學分類與系統欄位對應: | 心理學分類 | 系統處理 | @@ -360,6 +365,8 @@ flowchart TD 第二道防線不可移除 —— 模型不一定遵守指令,而記憶會被長期保存並在每次啟動時載入。 +Stop hook 會在本輪對話明確包含個人記憶保存同意或拒絕時,呼叫 `memory.js consent --role <角色 ID> --value accepted|declined` 更新同意狀態。偵測不到明確同意時不得自行推論。 + --- ## 呼叫方式