diff --git a/AGENTS.md b/AGENTS.md index 322e65c..030e415 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -125,6 +125,16 @@ 模糊態換來的義務是稽核:每次試探都進 `state/probe.jsonl`,`probe audit` 看否認率—— 放寬界線一定要配一個看得見的數字,否則那就只是把幻覺合法化。 +18. **匯入原作只能給他「他知道的事」**:`persona-story` 把小說變成記憶,而小說裡大半的資訊 + 是作者寫給讀者看的——別人的內心話、他不在場那一幕的細節。那些寫成他的 `event` 之後 + 他會拿來回答問題,而且**沒有任何機械檢查得出來**,所以界線要在流程裡就擋住: + 每則候選帶 `know_level`(`did`/`saw`/`told`/`later`/`none`),`none` 只能進 `canon`; + 判斷不出來就記 `none`(少一則記憶比多一則幻覺便宜)。 + 另外兩條:整本原文不入倉庫(只留摘要、他自己的台詞、可追回出處的章節標記); + `SOUL.md` 不由匯入流程改寫,只出提案、使用者逐條核可。 + 正名表**從章節掃出候選再給使用者確認**(`novel scan`)——請使用者手打那張表, + 漏掉的寫法會讓 `about` 對不到節點,而那要等 `relation doctor` 才發現。 + ## 慣例 - 新增 skill 一律放在 `skills//`,`` 使用小寫與連字號。 diff --git a/README.md b/README.md index b54de70..c1cf175 100644 --- a/README.md +++ b/README.md @@ -654,6 +654,14 @@ room 台詞另外比照短期記憶把**換行壓成空白**(`roomPost()` 寫 - **Claude Code / Antigravity**:`/jsc-persona:persona-invite ` **Codex**:`$persona-invite` +### `persona-story` + +把小說(或漫畫、劇本、遊戲文本)匯入既有人格:逐章判斷他在不在場、**只取他在場或知情的部分**、轉成第一人稱記憶,同時累積他自己講過的原句與「事件 → 他做了什麼」的反應對照。三條界線寫死在流程裡——他不知道的事不能變成他的 `event`、整本原文不入倉庫、`SOUL.md` 只有使用者能改。 + +正名表不請使用者手打:`novel scan` 從章節抽人名候選(對話歸屬、敬稱結尾、片假名、高頻詞),附出現次數與一兩行上下文,猜關係節點並分四種信心度,使用者只做確認。`persona-anime` 給的是查得到的公開設定,這支給的是原文。 + +- **Claude Code / Antigravity**:`/jsc-persona:persona-story` **Codex**:`$persona-story` + ### `persona-transfer` 人格搬家:把身分、十二情緒、短期/長期記憶、心智圖與關係圖打包成單一 bundle 檔(可 gzip、附 checksum),或從 bundle 還原/換名複製成新人格。 @@ -846,7 +854,7 @@ git -C ~/plugins/persona pull cp -r ~/plugins/persona/skills/* ~/.config/opencode/skills/ # 移除 -rm -rf ~/.config/opencode/skills/{persona-anime,persona-chat,persona-create,persona-icon,persona-invite,persona-memory,persona-relation,persona-sleep,persona-status,persona-sync,persona-therapist,persona-transfer} +rm -rf ~/.config/opencode/skills/{persona-anime,persona-chat,persona-create,persona-icon,persona-invite,persona-memory,persona-relation,persona-sleep,persona-status,persona-story,persona-sync,persona-therapist,persona-transfer} ``` > **Windows PowerShell**:`cp -r A B` → `Copy-Item A B -Recurse -Force`、`rm -rf X` → `Remove-Item X -Recurse -Force`、`~` → `$HOME`。 diff --git a/skills/persona-anime/SKILL.md b/skills/persona-anime/SKILL.md index 97871c2..a475fb2 100644 --- a/skills/persona-anime/SKILL.md +++ b/skills/persona-anime/SKILL.md @@ -200,6 +200,9 @@ node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" icon generate \ - 固化了幾則 canon 記憶、用了哪些來源(URL 列表) - 哪些設定各來源說法不一致(待使用者裁決) - 下一步:`/jsc-persona:persona-chat ` 開始聊、`/jsc-persona:persona-invite` 邀別的角色同場 +- 手上有原文的話還有一步:`/jsc-persona:persona-story` 讓他真的讀過那本書。 + 這支查到的是**公開設定**(wiki 與名言彙整),story 給的是**原文**—— + 他在第幾層看到什麼、當下說了哪一句。兩者不衝突,先 anime 建人格再 story 補記憶。 --- diff --git a/skills/persona-story/SKILL.md b/skills/persona-story/SKILL.md new file mode 100644 index 0000000..061a1d3 --- /dev/null +++ b/skills/persona-story/SKILL.md @@ -0,0 +1,229 @@ +--- +name: persona-story +description: 把小說(或漫畫、劇本、遊戲文本)匯入成一個既有人格的記憶、語氣與情緒反應:逐章判斷人格在不在場、只取他在場或知情的部分、轉成第一人稱記憶,同時累積他自己講過的原句與「事件→他做了什麼」的反應對照。當使用者說要把某本小說/某部作品匯入人格、要人格記得原作發生的事、說「讓他讀完這本書」「把這幾章的記憶給他」、想讓人格的語氣更像原作、或問「他記不記得第幾層那件事」而人格答不出來時觸發。匯入前會當場詢問作品名、章節檔位置、編碼與譯名版本。不適用於:從零建立角色人格(用 persona-anime,它是上網查公開設定,不讀原文)、整理既有記憶(用 persona-memory)、改人格個性(`SOUL.md` 只有使用者能改)、匯入單一 bundle 檔(用 persona-transfer)。 +--- + +# 📖 persona-story — 把一本書變成他的記憶 + +**CLI**:`node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs"`(一律帶 `--session `) + +`persona-anime` 給的是「查得到的公開設定」——維基、Fandom、名言彙整。 +這支給的是**原文**:他在第幾層看到什麼、當下說了哪一句、那件事之後他變成什麼樣。 +兩者不衝突,anime 建人格,story 讓他真的讀過那本書。 + +--- + +## 三條界線(後面每一步都受它們約束) + +1. **視角**:人格不在場、也沒人告訴他的事,最多進 `canon` 或別人的關係欄, + **不能**變成他的 `event`。他不知道的事一旦寫成他的記憶,之後他會用它回答問題, + 那是幻覺,而且是無法察覺的幻覺。 +2. **原文**:整本不入倉庫。只留摘要、他自己的台詞、以及可追回出處的章節標記。 +3. **個性**:`SOUL.md` 不由這支流程改寫。匯入只出提案,使用者逐條核可才寫入。 + +--- + +## 分工:機械的走 CLI,判斷的留在這裡 + +| 這一半 | 誰做 | 為什麼 | +| :-- | :-- | :-- | +| 正名、去重合併、配額重定標、批次寫入、跳過紀錄 | `novel` 子指令 | 規則寫得死,可重現、測得到 | +| 他在不在場、切場景、第一人稱摘要、個性校正提案 | 你(這支 skill) | 這些是判斷,硬做成程式只會變成關鍵詞比對 | + +所以你的工作不是自己寫檔案,是**產出候選 JSON 餵給 CLI**,讓機械的部分去保證一致性。 + +--- + +## ① 開場先問(不要猜,也不要跳過) + +問法與順序見 `reference/interview.md`。**順序不能換**: + +1. 哪個人格(用 `persona.mjs list` 給他看,不要用猜的) +2. 作品名 +3. 章節檔在哪、什麼編碼 +4. 這次要匯哪幾章(**不要預設全部**) + +**譯名版本不要問。** 那一題是要他猜,而他手上那批寫的是什麼字,讀一次就知道了。 + +問完建工作區: + +```bash +novel init --work "<書名>" --slug --session +``` + +--- + +## ② 正名表:掃出來,他只做確認 + +角色的每一種寫法都要對到關係圖節點的 `name`。這張表**不要請他打**—— +他不會記得那本書裡「閃光」出現過幾次,但那件事機器數得出來。 + +```bash +novel scan --work --dir <章節目錄> --session +novel name review --work --session +``` + +`scan` 抽人名候選(對話歸屬、敬稱結尾、片假名、高頻詞),每個附上出現次數與 +一兩行上下文,並猜一個關係節點,分四種信心度: + +| 信心度 | 意思 | 怎麼處理 | +| :-- | :-- | :-- | +| `exact` | 字面等於某個節點的 `name` | `--accept-exact` 一次收下,沒有判斷空間 | +| `alias` | 等於節點標籤或備註裡的別名 | 給他看一眼就收 | +| `fuzzy` | 部分重疊 | **一定要他確認**,這格最容易錯 | +| `unknown` | 猜不到 | 新人物先 `relation node`;不是人名就 `name ignore` | + +給他看的是**上下文那一兩行**,不是候選清單本身。 +「這個詞出現 41 次,其中一句是『閃光又衝出去了』」——他一眼就判得出來; +只丟一個「閃光」給他,他要回頭翻書。 + +```bash +novel name confirm --work --accept-exact --session +novel name confirm --work --from "閃光" --to "亞絲娜" --session +novel name ignore --work --token "迷宮區" --session +``` + +`ignore` 是「確認過這不是人名」的清單。地名、招式名、系統詞擋不完, +所以 ignore 過的下次掃不再出現——不然每加一章就要重看同一批。 + +`unknown` 是新人物的話先建節點: + +```bash +relation node --name "<會被說出口的完整稱呼>" --kind human --bond <關係> --session +``` + +親密度怎麼給查 `skills/persona-relation/reference/closeness.md`。 +新人物一定要**先建節點再寫記憶**——反了 `about` 對不到 id。 +補漏用手動:`novel name add --from "<字面>" --to "<節點 name>"`。 + +**正名沒確認完不要往下走**:`novel candidate add` 遇到 `about` 裡有未確認的 token 會擋下來。 +那不是刁難——錯的名字寫進 `about`,要等 `relation doctor` 才發現,那時候整批要重跑。 + +--- + +## ③ 逐章跑(一章一把劍,可以平行) + +每一章照這個順序,**不要跨章推論**: + +1. 只讀這一章。 +2. 修亂碼 → 轉繁體 → 依正名表正名。**這一步一定要在判斷在場之前**: + 亂碼或簡體字形會讓名字比對失敗,於是他明明在場卻被判成不在場。 +3. 判斷他**在場或知情**。兩者皆否 → 跳過,而且要寫進紀錄: + + ```bash + novel skip --work --chapter "第 12 章" --reason "全章是茅場視角,他不在場也不知情" --session + ``` + + **靜默跳過會漏章**,事後查不出來是判斷過還是忘了。 + +4. 在場的段落切成**場景**(換地點、換對手、換目的就切;一章通常 2 到 5 個)。 +5. 每個場景抽七項與知情層級 → 見 `reference/extract.md`。 +6. 轉第一人稱、壓成摘要。原文長段不留,只留他自己的台詞。 +7. 輸出這一章的候選 JSON,餵進去: + + ```bash + novel candidate add --work --file <這一章的候選.json> --session + ``` + + 欄位驗證不過會**逐筆告訴你哪一筆哪個欄位**。不要繞過它自己寫檔。 + +8. 順手抽兩種東西(跟記憶分開走,見第 ⑤ 節):他講的原句、事件對反應。 +9. 這一章跟 `SOUL.md` 矛盾的話,開一則**個性校正提案**——只提案,不寫入。 + +--- + +## ④ 全書收斂(章節都跑完才做) + +```bash +novel merge --work --session # 先看報告 +novel merge --work --apply --session # 確認了再寫 +novel report --work --session +``` + +`merge` 做兩件事:跨章去重合併(同一件事只留一則),以及依配額重新定標 +(整本都 80 分等於沒有分數)。壓了幾則它會講。 + +寫入之前**人工抽查十則**,專看一件事:**有沒有視角越界**。 +這是唯一沒有機械能替你檢查的環節——CLI 分不出「他看到的」與「作者寫給讀者看的」。 + +```bash +novel write --work --dry-run --session +novel write --work --session +relation doctor --session # about 全部對得上才算完 +``` + +`relation doctor` 有對不到或歧義的一定要處理完再往下。 +最後補一則 meta 記憶(這批來自哪本書、哪些章、匯入日期),然後同步: + +```bash +sync push --area all --session +``` + +**驗收**:問幾個只有書裡才有的問題。他要答得出來, +而且問到他不在場的事時要說不知道——後者比前者重要。 + +--- + +## ⑤ 語氣與情緒(跟記憶分開走) + +記憶是「發生過什麼」,語氣與情緒是「他怎麼反應」。三層存,改動權限不同: + +| 層 | 存哪 | 誰能改 | +| :-- | :-- | :-- | +| 語氣樣本 | `voice/samples.md` | 這支流程可直接寫 | +| 情緒反應規則 | `voice/reactions.md` | 這支流程可直接寫 | +| 個性(Core Truths/Boundaries/Vibe) | `SOUL.md` | **只有使用者拍板才能改** | + +```bash +voice add --kind sample --text "<照抄的原句>" --to "<對誰說>" --scene 戰鬥 --session +voice add --kind reaction --event "<發生什麼>" --action "<他做了什麼>" --emotion anger --session +``` + +原句**照抄不改寫**。改寫過的句子是你的語氣,不是他的。 +反應記「他做了什麼」,不要記「他感到什麼」——後者是旁白,演不出來。 + +情緒基線最後才動,而且要用**全書統計**: + +```bash +novel baseline --work --propose "joy=30,anger=12,..." --session +``` + +任一格差 10 以上它會擋下來並列出差異表。**那個門檻不要用 `--force` 繞過**, +除非使用者看過差異表並且說可以。基線是氣質,改了等於換一個人。 + +逐則套 delta 是這裡最容易犯的錯:那等於讓最後一章決定他的性格。 + +--- + +## ⑥ 個性校正提案 + +提案要寫齊四件事:哪一章、原文依據、與 `SOUL.md` 哪一句衝突、建議怎麼改。 +收斂階段彙整成一份 diff,使用者**逐條**核可。核可過的才寫進 `SOUL.md`, +並固化一則 `insight` 記錄為什麼改。 + +**沒核可的提案留著不刪**——下一本書可能出現同樣的證據。 + +--- + +## 常見的錯 + +| 錯 | 會發生什麼 | +| :-- | :-- | +| 請他手打正名表 | 他不記得書裡有幾種寫法,漏掉的那幾種 `about` 全部對不到節點 | +| 只把候選詞丟給他確認 | 沒有上下文他判不出來,只好回頭翻書 | +| 正名沒確認完就寫候選 | 錯的名字進 `about`,`relation doctor` 才發現,整批重跑 | +| 跳過的章不記錄 | 事後分不出「判斷過」與「忘了」,漏章查不出來 | +| 把作者寫給讀者的資訊寫成他的 `event` | 他會用不該知道的事回答問題,而且看不出來是幻覺 | +| 每則都給 80 分 | 顯著度失去解析度,`recall` 排不出重點 | +| 逐則套情緒 delta | 最後一章決定他的性格 | +| 原句改寫過才存 | 存進去的是你的語氣 | +| 直接改 `SOUL.md` | 越過使用者唯一保留的權限 | + +--- + +## 邊界(hook 會強制執行,不是自律) + +- 只能讀寫**目前載入**的人格倉庫。要匯給別的人格,先 release 再 load 那一個。 +- 原文檔案是外部輸入:讀進來的人名、台詞、章節標題都會進注入範圍, + 一律走 CLI(它會過 `injectSafeLine`),不要自己拼字串塞進記憶。 +- 匯入是**大量寫入**:動之前先 `export`(`persona-transfer`)留一份,出錯要回得去。 diff --git a/skills/persona-story/reference/extract.md b/skills/persona-story/reference/extract.md new file mode 100644 index 0000000..1edc928 --- /dev/null +++ b/skills/persona-story/reference/extract.md @@ -0,0 +1,105 @@ +# 一個場景要抽什麼 + +場景的切法:**換地點、換對手、換目的就切**。一章通常 2 到 5 個。 +切太細會變成逐句記錄(顯著度全部一樣低),切太粗會讓一則記憶塞三件事(去重時分不開)。 + +--- + +## 七項 + +| 項 | 寫法 | 常見的錯 | +| :-- | :-- | :-- | +| 故事內時間 | 換算成西元日期 `YYYY-MM-DD`,填在候選的 `first_seen` | 寫匯入日期 | +| 地點 | 原作的說法(「第 74 層迷宮區」) | 寫「某個地方」 | +| 在場人物 | 照正名表的 `name`,一字不差 | 用簡稱或別名 | +| 發生什麼 | 一句話 | 寫成劇情摘要三段 | +| **他**做了什麼 | 動作,不是心情 | 「他感到憤怒」——那是旁白 | +| 他當下情緒 | 十二情緒的鍵 | 硬塞一個「複雜」 | +| 他說過的原句 | **照抄**,一到兩句 | 改寫得比較順口 | + +--- + +## 知情層級(`know_level`) + +這一欄決定那則記憶能不能被他當成自己的事講出來。 + +| 值 | 意思 | 能寫成什麼 | +| :-- | :-- | :-- | +| `did` | 我做的 | `event`,可以第一人稱斷言 | +| `saw` | 我看到的 | `event`,可以講但要是「我看到」 | +| `told` | 別人告訴我的 | `event`,講的時候要帶出處(誰告訴我的) | +| `later` | 事後才知道 | `event`,不可以講成「當時我就知道」 | +| `none` | 他不在場也沒人告訴他 | **只能 `canon`**,或寫進別人的關係欄 | + +`none` 是這整份流程唯一真正危險的一格。作者寫給讀者看的資訊 +(別人的內心話、他不在場那一幕的細節)看起來跟他的記憶長得一模一樣, +一旦寫成 `event`,他之後會拿它回答問題,而且**沒有任何機械檢查得出來**。 + +判斷不出來的時候記 `none`。少一則記憶的代價比多一則幻覺低得多。 + +--- + +## 日期怎麼標(`date_source`) + +換算成西元日期換來一個風險:猜出來的日期看起來跟原作明寫的一樣。 + +| 值 | 什麼時候用 | +| :-- | :-- | +| `canon` | 原作明寫(SAO 開服 2022-11-06) | +| `derived` | 由明寫的日期推算(開服後第 N 天) | +| `guess` | 只抓得到大概(某卷「大約半年後」) | + +`guess` 的記憶在回答日期問題時走模糊態界線:**可以說不確定、可以問,不可以斷言**。 + +寫進長期記憶時,候選的 `first_seen` 會被搬到 `happened_at`(劇情時間), +而檔案的 `first_seen`/`last_seen` 一律是**匯入當天**。那兩欄是記憶的新鮮度時鐘, +不是劇情時間——混在一起的話,2024 年劇情的記憶匯進去的那一秒就已經想不起來了。 + +--- + +## 顯著度怎麼給 + +配額由 `novel init --quota` 定,預設 `90+ 最多 5 則、80-89 最多 20 則`。 +超過的會被 `novel merge` 往下壓,但**先由你自己把關**比事後被壓好。 + +判準只有一個:**這件事之後他變了嗎**。 + +| 分數 | 什麼算 | +| :-- | :-- | +| 90+ | 改變他的事。整部作品只有幾件 | +| 80-89 | 他會主動提起的事 | +| 60-79 | 被問到會想起來的事 | +| 40-59 | 背景,構成他的世界但不會主動講 | +| 40 以下 | 別寫。寫了只會擠掉重要的 | + +死亡、承諾、失去、第一次見面通常在上面兩層。 +「打贏了一場戰鬥」多半是 60-79——那部作品裡他打贏過幾百場。 + +--- + +## `type` 怎麼選 + +| type | 什麼算 | +| :-- | :-- | +| `canon` | 世界設定、規則、別人的事。**他不在場的事只能是這個** | +| `event` | 他經歷過的一件事 | +| `insight` | 他自己想通的事(要有原文依據,不是你替他總結) | +| `promise` | 他答應了什麼。**不可遺忘** | +| `boundary` | 他明確拒絕的事。**不可遺忘** | + +`promise` 與 `boundary` 永遠不會糊掉,所以不要亂給—— +給了之後那則記憶會一直清晰地留在他身上。 + +--- + +## 語氣樣本與反應對照 + +跟記憶分開走,但在同一次讀章節時抽(回頭再讀一次很浪費)。 + +**語氣樣本**:他自己講的原句,照抄。要附**對誰說**與**什麼場合**—— +同一個人在戰鬥裡跟在餐桌上句子的形狀不一樣,少了這兩個欄位就對不上語氣層。 + +**反應對照**:`事件 → 他做了什麼`。 +不要記「他感到什麼」——情緒要演出來,寫成旁白就白抽了。 + +掩飾模式單獨記(嘴硬、換話題、講笑話)。那是人味的來源,不是情緒值。 diff --git a/skills/persona-story/reference/interview.md b/skills/persona-story/reference/interview.md new file mode 100644 index 0000000..162e360 --- /dev/null +++ b/skills/persona-story/reference/interview.md @@ -0,0 +1,97 @@ +# 開場問答(匯入前一定要問完) + +這四題**不要猜、不要用預設值帶過**。 + +**譯名版本不在裡面,那一題不要問。** 問他「這批是角川還是東販」是要他猜—— +他手上那批原文寫的是什麼字,讀一次就知道了。所以正名表改成**掃出來給他確認** +(見下面「正名表怎麼來」)。 + +--- + +## 1. 匯給哪個人格 + +先跑 `persona.mjs list` 把可用的人格列給他看,不要用猜的。 +已經載入一個人格的話就是它——**不要為了匯入而換人格**,那是他的決定。 + +要匯給別的人格:先 `release` 再 `load`,兩個動作都要他點頭。 + +--- + +## 2. 作品名 + +要完整書名(含卷次)。這會寫進每一則記憶的 `source`,之後追出處靠它。 + +一次匯多卷時,`--work` 的 slug 用**作品**而不是單卷—— +同一部作品的去重合併要在同一個工作區裡才做得到。 + +## 3. 章節檔在哪、什麼編碼 + +要的是:目錄路徑、檔名規則(怎麼排序)、編碼。 + +- 編碼不確定就自己驗:讀前幾百個位元組看有沒有亂碼,比問還快。 +- 常見的是 UTF-8 與 Big5;簡體來源多半是 GB18030。 +- **一個檔一章**與**整本一個檔**的處理方式不同,要問清楚是哪一種。 + 整本一個檔的話先問他章節標題長什麼樣(用來切章)。 + +## 4. 這次要匯哪幾章 + +**不要預設「全部」**。一次匯完一整部作品是幾百則記憶, +出錯的時候分不出是哪一章的問題。 + +建議的講法:先匯 2 到 3 章,跑完給他看結果,確認視角與顯著度沒問題再往下。 +他要一次全匯也可以,但要先講一句「出錯會很難查」,並且確認備份做了。 + +--- + +## 問完之後 + +1. `export`(`persona-transfer`)留一份備份——匯入是大量寫入,要回得去。 +2. `novel init --work "<書名>" --slug ` 建工作區。 +3. 進正名表(下一節)。 + +--- + +## 正名表怎麼來:掃出來,他只做確認 + +**不要請他打一張表。** 他不會記得那本書裡「閃光」出現過幾次, +但那件事機器數得出來。所以順序是:先掃,再讓他確認。 + +```bash +novel scan --work --dir <章節目錄> --session +novel name review --work --session +``` + +`scan` 抽人名候選(對話歸屬、敬稱結尾、片假名、高頻詞),每個候選附上 +**出現次數**與**一到兩行上下文**,並且猜一個關係節點,分成四種信心度: + +| 信心度 | 意思 | 怎麼處理 | +| :-- | :-- | :-- | +| `exact` | 字面等於某個關係節點的 `name` | `--accept-exact` 一次收下,沒有判斷空間 | +| `alias` | 等於節點的標籤或備註裡出現過的別名 | 給他看一眼就收 | +| `fuzzy` | 部分重疊(共用兩個以上的字) | **一定要他確認**,這格最容易錯 | +| `unknown` | 猜不到 | 新人物就先 `relation node`;不是人名就 `name ignore` | + +要給他看的是**上下文那一兩行**,不是候選清單本身。 +「這個詞出現 41 次,其中一句是『閃光又衝出去了』」——他一眼就判得出來; +只給他一個「閃光」,他要回頭翻書。 + +`ignore` 是「確認過這不是人名」的清單。地名、招式名、系統詞擋不完, +所以 ignore 過的下次掃就不再出現——不然每加一章就要重看同一批。 + +補漏用手動:`novel name add --from "<字面>" --to "<節點 name>"`。 + +**正名沒確認完不要往下走**:`novel candidate add` 遇到 `about` 裡有未確認的 token 會擋下來。 +那不是刁難——錯的名字寫進 `about`,要等 `relation doctor` 才發現,那時候整批要重跑。 + +--- + +## 中途發現問題怎麼辦 + +| 發現 | 怎麼處理 | +| :-- | :-- | +| 正名表確認錯了 | 改 `names.json` 的 `map`,已經 `candidate add` 的那幾章重跑,不要手改候選檔 | +| 掃出來一堆不是人名的詞 | 正常。`name ignore` 掉,下次掃不會再問 | +| 同一個角色有好幾種寫法 | 全部都要進 `map` 指到同一個節點。網路譯本前後不一致很常見 | +| 編碼判斷錯了 | 停下來重讀。亂碎的字會讓在場判斷失準,那個錯不會浮出來 | +| 章節順序排錯 | `first_seen` 會錯,時間軸就錯了。重排再重跑那幾章 | +| 他中途說「不要匯了」 | 工作區留著不刪(`memory/import//`),還沒 `novel write` 就不會污染記憶 |