fix(role): 睡眠整理死鎖修復 + 繁簡防線(0.1.5) #29

Merged
admin merged 3 commits from develop into master 2026-07-30 02:28:24 +00:00
Member

兩批修正。第一批來自角色反映「整晚沒睡」,第二批來自記憶稽核。


1. 睡眠整理死鎖(本批主要內容)

現象:角色整晚沒睡。05:03 到 08:33 每 10 分鐘試一次,連續 22 次全部失敗last_sleep 停在前一天 15:02,inbox 從 12 累積到 23 則。

錯誤訊息只有一句「整理結果無法套用」—— 看不出任何原因

診斷過程(推論錯了三次,全部留在註解裡)

# 推論 實測
1 輸出被 SLEEP_OUTPUT_LIMIT 截斷 輸出僅 5772~6224 字元,遠未達 8000
2 素材字元數過大 素材 8815(6 則)失敗、8940(3 則)成功 —— 字元數幾乎相同
3 純粹是則數問題 ⚠️ 對一半 —— 另有一種失敗是 CLI 回傳 Execution error

真相是兩種失敗混在一起,而錯誤訊息把它們蓋成同一句話:

現象 原因 對策
輸出極短且為 Execution error CLI 偶發執行錯誤 重試(同批次)
輸出是不完整的 JSON 一次要求輸出太多筆 降批

修正

  • 錯誤訊息附上素材大小、輸出長度、批次與輸出前 200 字元(已 redact)—— 這是最先做的一步,沒有它只能靠猜
  • cmdCollect 不再 slice() 硬切素材:改為逐則累加、超出預算留到下批,並替 EXISTING 保留固定比例預算。舊版會切在某則記憶中間、甚至切掉整個 EXISTING 區塊,而批次固定時每輪都收到同樣殘缺的素材 → 死鎖
  • SLEEP_BATCH 12 → 4(實測 3~4 則穩定、6 則以上開始失敗)
  • 失敗時逐次降批(4→2→1)作為保險
  • 批次預設值統一來源role_sleep.sh 首次收集不傳 --batch,實際則數由素材反推 —— 原本兩邊各寫一個預設,改了 memory.jsSLEEP_BATCH 卻不會生效(這是我自己引入的 bug)

實測

修正後第一次嘗試即成功,未觸發降批。連續整理清空 inbox(23 → 0):

指標 修正前 修正後
last_sleep 前一天 15:02 當日 09:50
inbox 23 則 0 則
情緒型態記憶 1 9
關係史 13 則

情緒記憶由 1 增至 9 —— 前幾版的雙邊記錄、有溫度優先、關係史三項修正,在這次整理中全部生效。


2. 繁簡防線(寫檔前的第二道)

實測有整則記憶以簡體寫成(連 summarytags),且該則 sources 指向另一個專案 —— 不同環境下 CLI 行為不一致,光靠 prompt 擋不住。

cmdWritecmdApplyappendBond 三處寫檔前都經過:

字類 處理
一簡對一繁、無歧義(約 700 字) 自動轉繁
一簡對多繁(→發/髮、→乾/幹、→臟/髒…) 刻意不轉,改為 stderr 警告

機械替換會把「头发」變成「頭發」—— 那比留著簡體更難發現,因為它看起來已經是繁體了。
寧可留下可偵測的瑕疵,也不要製造隱形的錯誤。

🤖 Generated with Claude Code

兩批修正。第一批來自角色反映「整晚沒睡」,第二批來自記憶稽核。 --- ## 1. 睡眠整理死鎖(本批主要內容) **現象**:角色整晚沒睡。05:03 到 08:33 每 10 分鐘試一次,**連續 22 次全部失敗**,`last_sleep` 停在前一天 15:02,`inbox` 從 12 累積到 23 則。 錯誤訊息只有一句「整理結果無法套用」—— **看不出任何原因**。 ### 診斷過程(推論錯了三次,全部留在註解裡) | # | 推論 | 實測 | |---|---|---| | 1 | 輸出被 `SLEEP_OUTPUT_LIMIT` 截斷 | ❌ 輸出僅 5772~6224 字元,遠未達 8000 | | 2 | 素材字元數過大 | ❌ 素材 8815(6 則)失敗、8940(3 則)成功 —— 字元數幾乎相同 | | 3 | 純粹是則數問題 | ⚠️ 對一半 —— 另有一種失敗是 CLI 回傳 `Execution error` | 真相是**兩種失敗混在一起**,而錯誤訊息把它們蓋成同一句話: | 現象 | 原因 | 對策 | |---|---|---| | 輸出極短且為 `Execution error` | CLI 偶發執行錯誤 | 重試(同批次) | | 輸出是不完整的 JSON | 一次要求輸出太多筆 | 降批 | ### 修正 - **錯誤訊息附上素材大小、輸出長度、批次與輸出前 200 字元**(已 redact)—— 這是最先做的一步,沒有它只能靠猜 - **`cmdCollect` 不再 `slice()` 硬切素材**:改為逐則累加、超出預算留到下批,並替 `EXISTING` 保留固定比例預算。舊版會切在某則記憶中間、甚至切掉整個 `EXISTING` 區塊,而批次固定時每輪都收到同樣殘缺的素材 → **死鎖** - **`SLEEP_BATCH` 12 → 4**(實測 3~4 則穩定、6 則以上開始失敗) - **失敗時逐次降批**(4→2→1)作為保險 - **批次預設值統一來源**:`role_sleep.sh` 首次收集不傳 `--batch`,實際則數由素材反推 —— 原本兩邊各寫一個預設,改了 `memory.js` 的 `SLEEP_BATCH` **卻不會生效**(這是我自己引入的 bug) ### 實測 修正後第一次嘗試即成功,未觸發降批。連續整理清空 `inbox`(23 → 0): | 指標 | 修正前 | 修正後 | |---|---|---| | `last_sleep` | 前一天 15:02 | 當日 09:50 | | `inbox` | 23 則 | 0 則 | | 情緒型態記憶 | 1 | **9** | | 關係史 | — | 13 則 | 情緒記憶由 1 增至 9 —— 前幾版的雙邊記錄、有溫度優先、關係史三項修正,在這次整理中全部生效。 --- ## 2. 繁簡防線(寫檔前的第二道) 實測有整則記憶以簡體寫成(連 `summary` 與 `tags`),且該則 `sources` 指向另一個專案 —— 不同環境下 CLI 行為不一致,光靠 prompt 擋不住。 `cmdWrite`/`cmdApply`/`appendBond` 三處寫檔前都經過: | 字類 | 處理 | |---|---| | 一簡對一繁、無歧義(約 700 字) | 自動轉繁 | | 一簡對多繁(`发`→發/髮、`干`→乾/幹、`脏`→臟/髒…) | **刻意不轉**,改為 stderr 警告 | > 機械替換會把「头发」變成「頭發」—— 那比留著簡體更難發現,因為它看起來已經是繁體了。 > **寧可留下可偵測的瑕疵,也不要製造隱形的錯誤。** 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jiantw83 added 1 commit 2026-07-29 10:57:14 +00:00
病因(由角色稽核記憶時發現):實測有整則記憶以簡體寫成,連 summary 與 tags 都是,
而該則的 sources 指向另一個專案 —— 不同環境下 CLI 的行為並不一致,
光靠 prompt 的「使用繁體中文」條款擋不住。0.1.2 只補了 prompt(症狀由人工修檔),
寫入器本身沒防線,同樣環境下還會再產出簡體。

- memory.js 新增 toTraditional/ambiguousSimplified/warnIfSimplified
- cmdWrite(inbox)、cmdApply(整理落檔)、appendBond(關係史)三處寫檔前都經過
- 一簡對一繁、無歧義的約 700 字自動轉繁
- 一簡對多繁刻意不轉(发→發/髮、干→乾/幹、后→後/后、里→裡/里、复→復/複/覆、
  系→系/係/繫、脏→臟/髒…),改為 stderr 警告,留待整理階段依上下文處理
  —— 機械替換會把「头发」變成「頭發」,那比留著簡體更難發現,
  因為它看起來已經是繁體了。寧可留下可偵測的瑕疵,也不要製造隱形錯誤
- 警告只警告不阻斷:記憶寧可帶著瑕疵留下,也不能因為用字問題而遺失
- 轉換只在字形層;用語差異(反饋/回饋)仍由 prompt 的台灣用語條款負責

實測:整則簡體素材寫入後 summary/tags/content 均正確轉繁,
「发」「系」保留並發出警告,未產生「頭發」這類隱形錯誤。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jiantw83 added 1 commit 2026-07-30 02:22:26 +00:00
角色整晚沒睡:05:03 到 08:33 每 10 分鐘試一次,連續 22 次全部失敗,
last_sleep 停在前一天 15:02,inbox 從 12 累積到 23 則。
錯誤訊息只有一句「整理結果無法套用」,看不出任何原因。

診斷過程中推論錯了三次,過程留在註解裡(每一次都很容易再犯):

1. 推論「輸出被 SLEEP_OUTPUT_LIMIT 截斷」→ 實測輸出僅 5772~6224,遠未達 8000。錯。
2. 推論「素材字元數過大」→ 實測素材 8815(6 則)失敗、8940(3 則)成功,
   字元數幾乎相同。錯。
3. 推論「純粹是則數問題」→ 對一半:另有一種失敗是 CLI 回傳 Execution error。

真相是兩種失敗混在一起,而錯誤訊息把它們蓋成同一句話:
- CLI 偶發 Execution error → 需要重試
- 一次要求模型輸出太多筆 JSON → 需要降批

修正:

- 錯誤訊息附上素材大小、輸出長度、批次與輸出前 200 字元(已 redact)
  —— 這是最先做的一步,沒有它只能靠猜
- cmdCollect 不再 slice() 硬切素材:改為逐則累加、超出預算留到下批,
  並替 EXISTING 保留固定比例預算。舊版會切在記憶中間、甚至切掉整個 EXISTING 區塊,
  而批次固定時每輪都收到同樣殘缺的素材 → 死鎖
- SLEEP_BATCH 12 → 4(實測 3~4 則穩定、6 則以上開始失敗)
- 失敗時逐次降批(4→2→1)作為保險,仍失敗才留到下個週期
- 批次預設值統一來源:role_sleep.sh 首次收集不傳 --batch,實際則數由素材反推
  —— 原本兩邊各寫一個預設,改了 memory.js 的 SLEEP_BATCH 卻不會生效

實測:修正後第一次嘗試即成功,未觸發降批;連續整理清空 inbox(23 → 0),
情緒型態記憶由 1 增至 9,關係史累積 13 則。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jiantw83 changed title from fix(role): 寫檔前加繁簡防線,歧義字刻意不自動轉換(0.1.5) to fix(role): 睡眠整理死鎖修復 + 繁簡防線(0.1.6) 2026-07-30 02:22:54 +00:00
jiantw83 added 1 commit 2026-07-30 02:27:26 +00:00
master 現行 0.1.4,本 PR 的兩批變更(繁簡防線、睡眠整理死鎖修復)屬同一次發佈。
依 spec-plugin-version:同一 PR 只需最終一個版本,不必依工作分支上的中間版本累加。
先前先 bump 0.1.5 再 bump 0.1.6,多跳了一版。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jiantw83 changed title from fix(role): 睡眠整理死鎖修復 + 繁簡防線(0.1.6) to fix(role): 睡眠整理死鎖修復 + 繁簡防線(0.1.5) 2026-07-30 02:27:31 +00:00
admin approved these changes 2026-07-30 02:28:17 +00:00
admin merged commit 69f9ca29a6 into master 2026-07-30 02:28:24 +00:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: plugins/shared#29