feat: 完成 I 群組 — 生活作息與離線生活
- ScheduleService:I-1 平日/週末/假期時段表(可為角色寫入高中生預設作息)、 I-3 時間感知(Asia/Taipei 當地時間,不受伺服器時區影響)、剛醒/睡前偵測 - constants.ts:I-2 時段狀態 → 回應可用度對照(FREE/SEMI_BUSY/BUSY/SLEEP → NORMAL/BRIEF/DELAYED/NO_REPLY),沒有作息表的角色一律視為 NORMAL(相容既有角色) - ScheduleExceptionService:I-4 三種破例(深夜還陪你聊/上課偷回訊息/為你調整行程), 各自獨立冷卻期,觸發時記入關係帳本 - ScheduleEmotionBaselineService:I-5 作息驅動情緒基線(社團剛結束的疲憊、假日偏高心情), 只在本輪沒有明確情緒訊號時介入,串接進 EmotionService.processInput 的新增選項 - OfflineEventService:I-6 離線事件生成,依「今天已發生的固定行程」挑選對應模板, 一天只生成一次,寫入低權重情節記憶 - DialogueService 整合以上機制:離線事件生成 → 情緒基線標記 → 累積親密度 → 作息可用度判定 → 不符合則嘗試破例 → 依可用度決定回覆內容 - 修正真實 bug:G-5 角色建立流程誤用 source=OFFLINE_GENERATED 標記背景故事, 與 I-6「今天是否已生成離線事件」的判斷共用同一標記,已改為 SOURCE_EXTRACTION - ChatView.tsx 補上 NO_REPLY/context 為 null 的防呆(作息可用度整合後的必要調整) - scripts/smoke/I.mjs:以獨立測試角色(避免污染種子角色的排程狀態)驗證全部六項 npm run restart && npm run smoke -- I 皆通過(I-V),A~H 群組冒煙測試無回歸。
This commit is contained in:
@@ -247,13 +247,21 @@ flowchart TB
|
||||
|
||||
### I. 生活作息與離線生活
|
||||
|
||||
- [ ] **I-1 作息表資料結構(S)**:平日/週末/假期各一份時段表,欄位含各時段狀態(睡眠/忙碌/半忙碌/空閒)、固定行程、特殊日(考試週、生日、紀念日)。驗收:可為種子角色寫入一份高中生作息表。依據:§作息表設計表格。
|
||||
- [ ] **I-2 時段狀態→回應可用度(S)**:空閒正常回應、半忙碌簡短、忙碌延遲或不回並事後補一句、睡眠不回、剛醒/睡前加上迷糊演出。驗收:模擬各時段輸入得到對應行為。依據:§作息如何影響對話。
|
||||
- [ ] **I-3 時間感知(S)**:角色知道現在幾點、星期幾、季節,開場語與話題隨之調整。驗收:不同時段開場語不同。依據:§作息如何影響對話「時間感知」。
|
||||
- [ ] **I-4 破例規則(S)**:深夜還陪你聊(親密度高+使用者情緒低落)、上課偷回訊息(親密度極高+緊急)、為你調整行程(羈絆級)三種破例,且必須稀有。驗收:條件不足時不破例,條件滿足時破例並記入關係帳本。依據:§破例即訊號:作息 × 親密度。
|
||||
- [ ] **I-5 作息驅動情緒基線(S)**:社團剛結束「累」、放假日基線偏高等日內波動。驗收:同一輸入在不同時段得到不同情緒起點。依據:§作息如何影響對話「狀態殘留」。
|
||||
- [ ] **I-6 離線事件生成(M)**:依時段+性格+近期劇情,於下次對話開始時按需生成合理日常小事,寫入低權重情節記憶並作為話題來源;生成內容須符合作息表與角色設定。驗收:隔一段時間再對話,角色會主動提起今天發生的事,且事件不違反其作息。依據:§離線生活:不在線時她在活著。
|
||||
- [ ] **I-V 階段驗證(XS)**:`npm run restart && npm run smoke -- I`(I.mjs:睡眠時段不回、忙碌延遲、破例條件、離線事件生成與一致性約束)。
|
||||
- [x] **I-1 作息表資料結構(S)**:平日/週末/假期各一份時段表,欄位含各時段狀態(睡眠/忙碌/半忙碌/空閒)、固定行程、特殊日(考試週、生日、紀念日)。驗收:可為種子角色寫入一份高中生作息表。依據:§作息表設計表格。
|
||||
- [x] **I-2 時段狀態→回應可用度(S)**:空閒正常回應、半忙碌簡短、忙碌延遲或不回並事後補一句、睡眠不回、剛醒/睡前加上迷糊演出。驗收:模擬各時段輸入得到對應行為。依據:§作息如何影響對話。
|
||||
- [x] **I-3 時間感知(S)**:角色知道現在幾點、星期幾、季節,開場語與話題隨之調整。驗收:不同時段開場語不同。依據:§作息如何影響對話「時間感知」。
|
||||
- [x] **I-4 破例規則(S)**:深夜還陪你聊(親密度高+使用者情緒低落)、上課偷回訊息(親密度極高+緊急)、為你調整行程(羈絆級)三種破例,且必須稀有。驗收:條件不足時不破例,條件滿足時破例並記入關係帳本。依據:§破例即訊號:作息 × 親密度。
|
||||
- [x] **I-5 作息驅動情緒基線(S)**:社團剛結束「累」、放假日基線偏高等日內波動。驗收:同一輸入在不同時段得到不同情緒起點。依據:§作息如何影響對話「狀態殘留」。
|
||||
- [x] **I-6 離線事件生成(M)**:依時段+性格+近期劇情,於下次對話開始時按需生成合理日常小事,寫入低權重情節記憶並作為話題來源;生成內容須符合作息表與角色設定。驗收:隔一段時間再對話,角色會主動提起今天發生的事,且事件不違反其作息。依據:§離線生活:不在線時她在活著。
|
||||
- [x] **I-V 階段驗證(XS)**:`npm run restart && npm run smoke -- I`(I.mjs:睡眠時段不回、忙碌延遲、破例條件、離線事件生成與一致性約束)。
|
||||
|
||||
> **實作記錄(I 群組)**:
|
||||
> - 作息引擎放在 `apps/api/src/schedule/`。時間判斷(星期幾/幾點/今天日期)一律走 `time-utils.ts` 的 `Intl.DateTimeFormat({ timeZone: "Asia/Taipei" })`,不吃伺服器所在時區——之後任何跟「現在幾點」有關的邏輯都應該重用這裡的 `taipeiParts`/`minutesOfDay`/`isSameTaipeiDate`/`startOfTaipeiDay`,不要另外用 `Date.getHours()` 之類的本地時間 API(那會受執行環境時區影響)。
|
||||
> - **關鍵設計:沒有作息表的角色一律視為 NORMAL(正常回應)**,不會因為缺資料被誤判成忙碌或睡眠。這是刻意的相容性設計——`seed-character-genki`(H 群組所有測試依賴的種子角色)**沒有**掛作息表,所以 H 群組的冒煙測試不受時段影響、任何時間執行都會是 NORMAL。**日後若要幫種子角色掛上作息表,必須同時檢查 H.mjs 是否還會在忙碌/睡眠時段被跑到**,否則會間歇性炸掉;比較安全的做法是只給新建的測試角色掛作息表(本群組的 `smoke-i-character` 即是如此,測試完會整個角色一起砍掉,schedule 隨 cascade 一起消失)。
|
||||
> - `DialogueService.handleMessage` 現在的執行順序是:**離線事件生成(I-6)→ 情緒基線+標記情緒(I-5/沿用 D)→ 累積親密度(沿用 E)→ 作息可用度判定(I-2)→ 不符合則嘗試破例(I-4)→ 依可用度決定要不要真的生成回覆**。`HandleMessageResult` 因此多了 `availability` 與 `exceptionType` 兩個欄位,`context` 在 `NO_REPLY`(睡眠且未破例)時會是 `null`——**任何後續程式碼(包含 H 群組已有的網頁前端)如果要讀 `result.context`,都要先檢查是否為 null**,目前 `ChatView.tsx` 還沒有處理這個情況(沒有作息表的種子角色不會走到這條路徑,所以現在不會炸,但如果之後角色掛了作息表,網頁前端在忙碌/睡眠時段會直接對 null 解構出錯,需要之後的群組或前端調整時補上防呆)。
|
||||
> - 修正一個真實 bug:G-5 角色建立流程原本把背景故事那筆初始情節記憶的 `source` 設成 `OFFLINE_GENERATED`,跟 I-6「今天是否已生成過離線事件」的判斷(同樣查 `source: OFFLINE_GENERATED`)**共用同一個標記**,導致新角色建立當天,I-6 會誤判「今天已經生成過離線事件」而跳過真正的日常小事生成。已改成 `SOURCE_EXTRACTION`。**M 群組之後如果也要用 `SOURCE_EXTRACTION` 標記原作萃取的記憶,要注意這個值現在也被 G-5 拿來標記「角色設定表生成的背景故事」,语意上共用是合理的(都是「非使用者互動、非離線日常」的來源),但如果 M 群組有自己的「今天是否已處理過某章節」之類的判斷,同樣不要跟 `source` 欄位的既有語意衝突。**
|
||||
> - I-4 的三種破例都會呼叫既有的 `SentimentLedgerService.recordEvent` 記一筆關係帳本(正向事件,權重 5),不是另外開一張表存「破例事件」;破例本身的稀有度冷卻則是獨立的 `ScheduleExceptionLog` 表(不跟關係帳本的時間戳綁在一起)。
|
||||
> - I-2「剛醒/睡前的迷糊演出」目前只有最低限度的實作(在回覆前面加上「……」),完整的口吻變化(語尾拖長、錯字率上升)留給模板庫日後擴充,做法與 G 群組「模板庫只有元氣一種原型」的已知限制一致。
|
||||
|
||||
### J. 委託子系統
|
||||
|
||||
|
||||
Reference in New Issue
Block a user