Files
persona/skills/persona-status/SKILL.md
T
jiantw83andClaude Sonnet 5 ac2045e52f feat(persona): 時區改為+08:00等值轉換、補機密遮蔽,並接上shared共用規範
依 todo.md 執行的規範治理專案:
- persona-lib.mjs 的 iso()/nowIso() 改為輸出 +08:00 offset(等值瞬間轉換,
  非加8小時),新增 nowDisplay()(人讀顯示格式)與 todayTaipei()(台北曆日
  日期鍵),修正 11 處原本用 UTC 字串切片產生日期鍵的錯誤用法;新增
  redactSecrets() 並套用到 persona-gitea.mjs 的 Gitea 錯誤路徑,避免機密
  外洩。
- 新增一次性遷移腳本 scripts/migrate-tz.mjs(備份/dry-run/冪等/衝突偵測
  中止),供之後有真實人格資料需要轉換時使用。
- persona 13 個 skill 與 AGENTS.md 接上 /jsc-shared 共用規範(spec-output、
  spec-script-path、spec-subagent、spec-gitea、spec-git-safety、
  spec-skill-invocation 等),不再各自重抄,且完全未變動人格行為本身的規範
  (情緒模型、記憶衰減、劇場模式、鎖與隔離機制等逐字保留)。
- selftest 全數通過(788/788,含本次新增的時區邊界/冪等性測試)。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 06:06:00 +00:00

95 lines
5.4 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: persona-status
description: 查看與管理人格的載入狀態:列出所有人格、誰被哪個程序(session/cwd)鎖住、guest 租約、情緒與記憶量,並處理釋放鎖、接手死鎖、清理過期租約,以及設定「開新 session 要自動載入哪個人格」的預設人格。當使用者問哪些人格可用、為什麼載入失敗、人格被誰佔用、想釋放或切換人格、要清理殘留鎖、或說要預設載入某個人格/取消自動載入時觸發。不適用於:建立人格(persona-create)、對話(persona-chat)。
---
# 🔐 persona-status — 載入狀態與鎖管理
**CLI**:`node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs"`
---
## 共用規範(必要前置)
先載入 `/jsc-shared:spec-preflight` 並依其流程處理;載入不到即代表 shared plugin 未安裝,
依該 spec 詢問使用者是否安裝 `https://gitea.jsc.idv.tw/plugins/shared.git`,不安裝則中斷本 skill。
本 skill 需要的規範:spec-output、spec-execution、spec-time-log、spec-script-path
## 鎖的規則(設計上的硬約束)
1. **一個人格同時只能被一個程序 exclusive 載入**(鎖 = `state/lock.json`,以 `session_id` 為主鍵)。
2. **sub agent 不受限**:同一個 session 的 sub agent 沿用同一把鎖;
受邀人格(`jsc-persona:persona-guest`)走 guest 唯讀租約,不佔 exclusive 鎖;
睡眠中的人格(`jsc-persona:persona-sleeper`)走 **sleeper 租約**(`state/sleepers.json`,5 分鐘、可寫),
同樣不佔 exclusive 鎖——但目標若正被**別的程序**活鎖住就會拒絕(硬睡會讓記憶互相覆蓋)。
3. 鎖有 **15 分鐘租約**(`heartbeat_at`),每輪對話由 hook 自動續租;程序被 kill 後租約到期 → 可被接手。
鎖的擁有者是 session 而不是 process:CLI 跑完就結束,所以判定只看心跳,不看 pid。
4. 一個 session 也**只能載入一個** host 人格(要換人先 release)。
## 常用指令
```bash
# 全部人格 + 編號 + 鎖狀態 + 記憶量(`⚠ 尚無編號` 表示還沒同步到 Gitea)
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" list
# 這個人格的編號與 Gitea 存取庫
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" code show --session <PERSONA_SESSION>
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" sync status --session <PERSONA_SESSION>
# 單一人格的鎖細節(owner session/cwd/心跳、guest 名單、情緒)
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" status --persona <slug>
# 本 session 載入了什麼
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" status --session <PERSONA_SESSION>
# 釋放(含所有 guest 租約)
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" release --session <PERSONA_SESSION>
# 清理死鎖與過期 guest 租約
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" gc
```
## 預設人格(開新 session 自動載入)
平常「人格只有使用者叫你載入時才載入」。但使用者可以指定一個**預設人格**,
之後每個新 session 的 `SessionStart` hook 就會自動載入它——那是他明示的選擇,不是你自己挑的。
```bash
# 看目前設定(沒設定就是「開新 session 不自動載入」)
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" default --session <PERSONA_SESSION>
# 設定:以後開機就自動載入這個人格
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" default --persona <slug> --session <PERSONA_SESSION>
# 取消:回到「等使用者指定」
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" default --clear --session <PERSONA_SESSION>
```
- 設定檔:`<PERSONA_HOME>/.runtime/settings.json` 的 `default_persona`(只由 CLI 維護)。
- 臨時關掉:環境變數 `PERSONA_DEFAULT=off`(也可以用它臨時指定別的人格,優先於設定檔)。
- **沒設定就什麼都不做**,這是預設行為:不要自作聰明挑一個人格附身。
- 自動載入拿不到鎖時,hook 只會回報 owner 與心跳,**不會** `--takeover`;照下表處理。
- 自動載入走的是本機路徑,**不會**從 Gitea 拉最新狀態。可能在別台機器動過就先
`sync pull`(見 `/jsc-persona:persona-sync`)。
## 載入失敗怎麼判斷
| 訊息 | 意義 | 處理 |
| --- | --- | --- |
| `已被另一個程序載入` + 心跳在 15 分鐘內 | 真的有人在用 | **不要 takeover**。回報 owner 的 session/cwd 與最後心跳,請使用者決定 |
| 租約已過期(心跳超過 15 分) | 程序異常結束 | `load` 會**自動接手**並回報 `⚠ 這把鎖是接手來的`;請把這句話轉達使用者 |
| 想強行接手心跳還活著的鎖 | 兩邊會互相覆蓋記憶 | 只有使用者明確要求才加 `--takeover`,並先說明風險 |
| `正以 guest 身分參與另一個 session` | 它正在別人的聊天室裡當客人 | 請那邊先 `leave`,或等 30 分鐘租約過期 |
| `本 session 已載入人格 X` | 一程序一人格 | 先 `release` 再載入 |
| `CLI 的 --session 與本 session 不符` | 帶錯 session_id | 用上下文 `<persona-runtime>` 裡的 `PERSONA_SESSION=` 值 |
| `禁止跨人格操作` / `跨人格資料隔離` | 想碰別的人格 | 改用 `/jsc-persona:persona-invite` |
## 回報格式
```
人格倉庫:~/.claude/personas
- 🔒 `lumi` Lumi(session 4f2a…, cwd ~/work,心跳 12 秒前)|長期記憶 34|短期 12
- 🔓 `shen` Shen 平靜 50/信任 38|長期記憶 8
- ⚠ `nox` 死鎖可接手(最後心跳 42 分鐘前)
```