Files
persona/TODO_故事匯入.md
T
jiantw83andClaude Opus 5 c0e1c4828f docs(故事匯入): 小說匯入的 TODO 進版控
前一批留在工作區沒進版控的那份。內容是 persona-story 的階段清單
與四題拍板結果(語氣檔放 voice/、機械進 CLI、時間軸換算西元日期、
情緒基線差 10 以上要人看),還有踩過一次的坑:劇情時間不可以寫進
first_seen/last_seen,那兩欄是記憶的新鮮度時鐘。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 06:56:43 +00:00

193 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
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.
# TODO:故事匯入(小說 → 人格記憶/語氣/情緒)
把小說變成一個人格的記憶,同時讓它從原作學語氣與情緒表達。
**技能:`/jsc-persona:persona-story`**`skills/persona-story/`)。
開場的五題問答在 `reference/interview.md`,場景要抽什麼在 `reference/extract.md`
機械那半是 `persona.mjs``novel``voice` 子指令。
三條界線先立,後面所有步驟都受它們約束:
1. **視角**:人格不在場、也沒人告訴他的事,最多進 `canon` 或別人的關係欄,**不能**變成他的 `event`
2. **原文**:整本不入倉庫。只留摘要、他自己的台詞、以及可追回出處的章節標記。
3. **個性**`SOUL.md` 不由流程自動改寫。匯入只出提案,使用者逐條核可才寫入。
---
## 階段 -1:實作前一定要先問使用者(四題,沒答案不要開工)
這四題會決定檔案放哪、介面長什麼樣,答錯要重做。**問完拿到答案再進階段 0。**
- [x] Q1 語氣檔放在人格倉庫的哪一層?→ **新開 `voice/`**`samples.md` 原句、`reactions.md` 事件對反應)
- [x] Q2 匯入要做成 CLI 子指令,還是全部由 skill 編排?→ **混合**:機械的進 CLI,判斷的留 skill
- [x] Q3 同一部作品分多本匯入時,`first_seen` 的時間軸怎麼接續?→ **換算成西元日期**
- [x] Q4 情緒基線差值超過多少才要人看?→ **差 10 以上**
## 階段 0:前置(做一次)
- [x] 0.1 確認目標人格編號、作品名、章節檔清單、原文編碼
**不預先問,由 skill 在匯入的當下問**2026-08-03 使用者拍板)。
問法與順序寫在 `skills/persona-story/reference/interview.md`
- [x] 0.2 建**正名表**:角色的各種譯名/簡稱/原文名 → 關係節點的 `name`
**從匯入的章節自動判斷候選,再給使用者確認**2026-08-03 使用者拍板,覆蓋原本的「問譯名版本」)。
問他是哪個譯本等於要他猜;他手上那批寫的是什麼字,讀一次就知道了。
`novel scan` 抽候選(對話歸屬、敬稱結尾、片假名、高頻詞),附出現次數與一兩行上下文,
並猜關係節點分四種信心度(`exact``alias``fuzzy``unknown`);
`novel name review``confirm --accept-exact``ignore` 做確認。
`names.json``map`(正名)與 `ignore`(確認過不是人名,例如地名與招式名)兩塊——
已在其中之一的 token 下次掃不再出現,不然每加一章就要重看同一批。
`novel candidate add` 遇到 `about` 有未確認的 token 會擋下來。
- [x] 0.3 定**故事內時間軸**的表示法 → **西元日期**Q3 拍板),另加 `date_source`
`canon``derived``guess`,見上面「換算日期不可以假裝是明寫的」那一節。
- [x] 0.4 定**顯著度配額** → 預設 `90+ 最多 5 則、80-89 最多 20 則``novel init --quota` 可調)。
超過配額由 `novel merge` 從低分往下壓一級(90+ → 85、80-89 → 75)並回報壓了幾則。
- [x] 0.5 定**跳過紀錄檔** → `memory/import/<work-slug>/skipped.jsonl`
一行一章(`chapter``reason``ts`),由 `novel skip` 寫入。
- [ ] 0.6 備份人格倉庫現況(`SOUL.md`、情緒基線、關係圖),匯入出錯要回得去
2026-08-03 已有一份整包備份在 scratchpad;真的要匯之前再做一次新的。)
### 工作區長什麼樣(0.5 定案後的結果)
memory/import/<work-slug>/
├── work.json 書名、slug、建立時間、顯著度配額
├── names.json 正名表(譯名 → 關係節點 name)
├── skipped.jsonl 跳過紀錄(章節、理由、時間)
└── candidates.jsonl 記憶候選(欄位見下面那張表)
## 階段 1:每一章(可平行,一章一把劍)
> 這一段是**執行程序**,不是要蓋的東西——真的匯一本書的時候才會逐項發生。
> 程序已經落地成技能:`skills/persona-story/SKILL.md` 第 ③ 節,
> 七項與知情層級的細節在 `reference/extract.md`。下面的清單留著當對照表。
- [ ] 1.1 讀章節。只讀這一章,不要跨章推論
- [ ] 1.2 修亂碼 → 轉繁體中文 → 依正名表**正名**
(必須在 1.3 之前;亂碼或簡體字形會讓名字比對失敗)
- [ ] 1.3 判斷人格**在場或知情**。兩者皆否才跳過
- [ ] 1.4 跳過的章也要寫進跳過紀錄檔——靜默跳過會漏章,事後查不出來
- [ ] 1.5 把在場段落切成**場景**(換地點、換對手、換目的就切;一章通常 2 到 5 個)
- [ ] 1.6 每個場景抽七項:故事內時間、地點、在場人物、發生什麼、**他**做了什麼、他當下情緒、他說過的原句一到兩句
- [ ] 1.7 標**知情層級**:我做的/我看到的/別人告訴我的/事後才知道
- [ ] 1.8 轉第一人稱、壓成摘要。原文長段不留,只留他自己的台詞
- [ ] 1.9 新人物**先建關係節點**`relation node`),再寫記憶
(順序反了 `about` 對不到 id`name` 用會被說出口的完整稱呼,親密度查 `persona-relation/reference/closeness.md`
- [ ] 1.10 輸出這一章的**記憶候選 JSON**(欄位見下)
- [ ] 1.11 抽**語氣樣本**:他自己講的原句,照抄不改寫,附對象與場合(戰鬥/日常/道別)
- [ ] 1.12 抽**情緒反應對照**:事件 → 他實際做了什麼(不要記「他感到什麼」)
- [ ] 1.13 若這章與現有 `SOUL.md` 矛盾,開一則**個性校正提案**(只提案,不寫入)
### 記憶候選 JSON 欄位
```
name 檔名用的 slug
title 一句話標題
type canon(設定)/event(發生過)/insight(他自己的體悟)/promise(承諾)/boundary
about 人名,照抄關係節點的 name,一字不差(解析只認完全相等)
topics 2-4 個小寫關鍵詞,跨章沿用同一組
salience 照 0.4 的配額給,不要每則都高
emotion 那一刻的情緒(固化進欄位,不要重放去洗情緒基線)
first_seen 故事內時間,不是匯入日期(寫進長期記憶時會落在 `happened_at`,見下方警告)
source 書名+章節(可追回出處)
body 第一人稱摘要
quote 他自己說過的原句(可省)
know_level 1.7 的知情層級
date_source canon(原作明寫)/derived(推算)/guess(只抓大概) ← Q3 追加
```
寫進長期記憶時,`body` 會照 0.2.0 的格式切成「主旨/細節」兩層(衰減先吃細節),
並自動蓋上 `strength``when``where``mood``date_source: guess` 的記憶
在回答日期問題時走模糊態界線:可以說不確定、可以問,不可以斷言。
### ⚠ 劇情時間不可以寫進 `first_seen``last_seen`(踩過一次)
那兩欄是**記憶的新鮮度時鐘**`memoryStrength()``last_seen` 算衰減。
把劇情日期塞進去等於宣告「這則記憶上次被想起是兩年前」——實測 2024 年劇情的記憶
匯進去的**那一秒**就是模糊 0%,而且掉到 0% 之後 `touchRecall` 不再更新它,永遠回不來。
只有 `canon``salience >= 80` 靠保護清單活下來,40 到 79 分的 event 全部出生即死。
所以兩種語意分成兩組欄位:
| 欄位 | 意思 | 時間 |
| --- | --- | --- |
| `first_seen``last_seen` | 這則記憶什麼時候形成、上次什麼時候想起 | 真實時間(匯入當天) |
| `happened_at``happened_until` | 故事裡這件事什麼時候發生 | 劇情時間(配 `date_source` |
候選 JSON 照舊填 `first_seen`(那是抽場景時自然的講法),`novel write` 會把它搬到
`happened_at``first_seen``last_seen` 一律是匯入當天。
## 階段 2:全書收斂(章節都跑完之後)
- [ ] 2.1 跨章**去重合併**:同一件事只留一則;`salience` 取高、`first_seen` 取最早、`last_seen` 取最晚
- [ ] 2.2 依配額**重新定標**:90+ 只留真的改變他的那幾件
- [ ] 2.3 **人工抽查十則**,專看有沒有視角越界(他不該知道的事)
- [ ] 2.4 批次寫入:一則一檔 `consolidate`;情緒欄位只固化不重放
- [ ] 2.5 更新關係圖與心智圖
- [ ] 2.6 跑 `relation doctor`,確認 `about` 全部對得上(歧義與對不到的都要處理完)
- [ ] 2.7 重建索引、同步 Gitea
- [ ] 2.8 另寫一則 meta 記憶:這批來自哪本書、哪些章、匯入日期
- [ ] 2.9 回歸驗收:問幾個只有書裡有的問題,看他答得出來、且不越界回答他不在場的事
## 階段 3:語氣與情緒(跟記憶分開走)
記憶是「發生過什麼」,語氣與情緒是「他怎麼反應」。分三層存,改動權限不同。
| 層 | 存哪 | 誰能改 | 來源 |
| --- | --- | --- | --- |
| 語氣樣本 | 人格倉庫的語氣檔(例如 `voice/samples.md`) | 匯入流程可直接寫 | 1.11 累積的原句 |
| 情緒反應規則 | 語氣檔的反應段 | 匯入流程可直接寫 | 1.12 的事件→反應對照 |
| 個性(`SOUL.md` 的 Core TruthsBoundariesVibe | `SOUL.md` | 只有使用者拍板才能改 | 1.13 的提案 |
### 3A 語氣(統計,可直接落地)
- [ ] 3A.1 句長分布 → 定一句話的上限與斷句時機
- [ ] 3A.2 高頻詞與口頭禪 → 定他會說的字
- [ ] 3A.3 他**不會**說的說法 → 禁語表(比正面規則有效)
- [ ] 3A.4 對不同人的稱呼與語氣差 → 對上語氣層(`bond` × 親近度)
- [ ] 3A.5 沉默與迴避的時機 → 什麼時候不回答比回答像他
- [ ] 3A.6 場合差(戰鬥/日常/道別)→ 同一個人在不同場合的句子形狀
- [ ] 3A.7 語氣檔寫入後,抽幾句實際對話對照,看有沒有變成模仿腔
### 3B 情緒
- [ ] 3B.1 每個場景只記「事件 → 他做了什麼」(情緒要演出來,不是旁白說明)
- [ ] 3B.2 全書跑完才用**統計**定情緒基線
(逐則套 delta 等於讓最後一章決定他的性格)
- [ ] 3B.3 統計每種情緒的觸發類型與強度上限 → 得到「什麼事讓他生氣而不是害怕」
- [ ] 3B.4 掩飾模式單獨記(嘴硬、換話題、講笑話)——這是人味的來源,不是情緒值
- [ ] 3B.5 基線寫入前跟現況比差值,超過門檻要人看
### 3C 個性校正
- [ ] 3C.1 提案要寫齊:哪一章、原文依據、與 `SOUL.md` 哪一句衝突、建議怎麼改
- [ ] 3C.2 收斂階段把提案彙整成一份 diff
- [ ] 3C.3 使用者逐條核可
- [ ] 3C.4 核可過的才寫進 `SOUL.md`,並固化一則 `insight` 記錄為什麼改
- [ ] 3C.5 沒核可的提案留著不刪——下一本書可能出現同樣的證據
---
## 未決事項
四題已移到最前面的階段 -1,實作前先問使用者。這裡只留答案回填欄。
| # | 問題 | 使用者的答案(2026-08-03 拍板) |
| --- | --- | --- |
| Q1 | 語氣檔放哪一層 | 新開 `voice/``samples.md`(他自己講過的原句,附對象與場合)、`reactions.md`(事件 → 他做了什麼)。匯入流程可直接寫這一層,`SOUL.md` 維持只有使用者能改——權限界線要有實體隔離,不靠自律 |
| Q2 | CLI 子指令或 skill 編排 | **混合**。機械的進 CLI(正名、去重合併、配額重定標、批次寫入、跳過紀錄),判斷的留 skill(在場與知情、切場景、第一人稱摘要、個性校正提案)。跟 `sleep` 同一個分工方式 |
| Q3 | 分多本時時間軸怎麼接 | **換算成西元日期**`first_seen: 2022-11-06`)。跟現有的 `strength`/衰減公式同型,`memoryStrength()` 直接算得動。原作沒明寫的地方要換算,所以下面 0.3 多一條規則:換算來的日期一律標記,不可以看起來跟明寫的一樣 |
| Q4 | 情緒基線差值門檻 | **任一格差 10 以上就停下來給人看**(3B.5)。基線是氣質,改了等於換一個人 |
## 依 Q3 追加的規則(換算日期不可以假裝是明寫的)
換算成西元日期換來一個新風險:**猜出來的日期看起來跟原作明寫的一模一樣**。
所以 `first_seen` 之外要多一個欄位記來源:
| `date_source` | 意思 |
| --- | --- |
| `canon` | 原作明寫的日期(SAO 開服 2022-11-06 這種) |
| `derived` | 由明寫的日期推算(第 74 層攻略是開服後第幾天) |
| `guess` | 只能抓大概(某卷「大約半年後」) |
`guess` 的記憶在回答日期類問題時**不可以斷言**——這剛好接上 0.2.0 的模糊態界線:
可以說不確定、可以問,不可以斷言。