docs(06-09): complete save/load independent system plan

This commit is contained in:
unanmed 2026-09-14 19:01:01 +08:00
parent 502d87ba26
commit f74646ab0c
3 changed files with 220 additions and 13 deletions

View File

@ -210,7 +210,7 @@ Plans:
3. 测试在本地可运行且全部通过
4. 测试由 AI 编写并运行,通过验证后可提交
**Plans**: 7/9 plans executed replanned (D-28;旧 06-01/06-02 执行结果标记 superseded,按同号重跑;数据端切片,非数据 render/legacy 覆盖延后)
**Plans**: 8/9 plans executed replanned (D-28;旧 06-01/06-02 执行结果标记 superseded,按同号重跑;数据端切片,非数据 render/legacy 覆盖延后)
Plans:
@ -222,7 +222,7 @@ Plans:
- [x] 06-06-PLAN.md — Map ALL interfaces, emphasis static/dynamic tiles + static arrays (data-base/src/map;无 save/load)
- [ ] 06-07-PLAN.md — Top-level integration: damage combos + map+replay play + second-play re-record equality; error 2001–2008 (BLOCKED: pre-execution user confirmation)
- [x] 06-08-PLAN.md — Flag full surface + common (utils/indexer/faceManager+face/mover) (无 save/load)
- [ ] 06-09-PLAN.md — Save/load independent system: every saveState/loadState class + CoreState top-level (BLOCKED: pre-execution user confirmation)
- [x] 06-09-PLAN.md — Save/load independent system: every saveState/loadState class + CoreState top-level (BLOCKED: pre-execution user confirmation)
**Wave 1** *(independent test-writing plans; no shared production edits)*
@ -232,7 +232,7 @@ Plans:
- [x] 06-04-PLAN.md
- [x] 06-05-PLAN.md
- [x] 06-06-PLAN.md
- [ ] 06-08-PLAN.md
- [x] 06-08-PLAN.md
**Wave 2** *(blocked on Wave 1 + user confirmation)*
@ -251,4 +251,4 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6
| 3. 数据端完成 | 19/19 | Complete | 2026-09-12 |
| 4. 渲染适配与双布局 | 0/TBD | Not started | - |
| 5. Legacy 移植 | 0/TBD | Not started | - |
| 6. 单元测试 | 7/9 | In Progress| |
| 6. 单元测试 | 8/9 | In Progress| |

View File

@ -4,16 +4,16 @@ milestone: v1.0
current_phase: 06
current_phase_name: unit-tests
status: executing
stopped_at: Completed 06-08-PLAN.md
last_updated: "2026-09-14T09:03:12.315Z"
stopped_at: Completed 06-09-PLAN.md
last_updated: "2026-09-14T10:59:52.055Z"
last_activity: 2026-09-14
last_activity_desc: Phase 06 execution started
state_head: 6699df9eeed82f39879d68aa58ee1f978b442ab0
state_head: 502d87ba260989fe2018a5139c5f9729d82a2275
progress:
total_phases: 6
completed_phases: 0
total_plans: 46
completed_plans: 44
completed_plans: 45
milestone_name: milestone
---
@ -29,9 +29,9 @@ See: .planning/PROJECT.md (updated 2026-09-10)
## Current Position
Phase: 06 (unit-tests) — EXECUTING
Plan: 9 of 9
Status: Ready to execute
Last activity: 2026-09-14 — Phase 06 execution started
Plan: 9 of 9 (06-09 complete; 06-07 outstanding — no SUMMARY)
Status: 06-09 save/load tests complete; D-44(c) blocked by pre-existing test:ci regression
Last activity: 2026-09-14 — Completed 06-09-PLAN.md
Progress: [█████░░░░░] 50%
@ -85,6 +85,7 @@ Progress: [█████░░░░░] 50%
| Phase 06 P05 | 22min | 3 tasks | 10 files |
| Phase 06 P06 | 24min | 3 tasks | 8 files |
| Phase 06 P08 | 21min | 3 tasks | 6 files |
| Phase 06 P09 | 42min | 3 tasks | 9 files |
## Accumulated Context
@ -170,6 +171,8 @@ Recent decisions affecting current work:
- [Phase 06]: 06-08:flag + common 按 D-43 三阶段(构件→组合/流水线→完整/集成)以 6 个行为单测覆盖,每阶段聚焦跑绿并过 D-44 门禁后提交
- [Phase 06]: 06-08:FlagSystem 全公开表面(码 111)、FaceManager + Dir4/Dir8 handler、RoleFaceBinder(码 43/44)、utils 朝向纯函数、MapLocIndexer、ObjectMover 全公开方法均覆盖;D-32 不测 saveState/loadState(flag 往返归 06-09)
- [Phase 06]: 06-08:疑似缺陷 #06-08-1(ObjectMover.backward(count>1) 因 Special 步翻转 moveDirection 而方向摆动、净位移为零),按 D-05 以正确预期 it.skip 登记,不修改核心代码
- [Phase 06]: 06-09:存读档独立系统按 D-43 三阶段执行,6 个测试文件 41 通过 / 6 跳过;11 个可达码 55/58/59/112/113/119/120/122/124/177/178 全部触发;CoreState 顶层经公开 saveState/loadState 对 5 saveable × 3 压缩档整体往返
- [Phase 06]: 06-09:按 D-05 登记 5 处疑似缺陷 #06-09-1..5(EquipmentState 数值表读档错误 / HeroEquipment 存档未深拷贝 / DynamicTile 不恢复 num / ReplayArray 不恢复 length / 码 178 语义与文案相反),并以正确预期 it.skip 记录;另记录既有 test:ci 回归阻断项(commit cee8439)
### Pending Todos
@ -182,6 +185,7 @@ None yet.
- eventStore circular paths are explicitly preserved as the Phase 01 baseline; the revised 01-08 regression does not require those paths to disappear.
- Plan 01-12 leaves the repository-wide type gate blocked only by pre-existing diagnostics outside the plan-owned files; these are recorded in the phase deferred-items ledger.
- Plan 01-13 records the same repository-wide type gate diagnostics outside its implementation and test files in the phase deferred-items ledger.
- 06-09 阻断项:`pnpm test:ci` 存在先于本计划的既有回归(commit `cee8439` 将录像记录接入 `data-base/src/hero/{equipment,items,mover}.ts`,4 个既有 data-base 测试与 2 个 data-state 文件共 6 文件 / 15 用例失败)。本计划硬约束禁止修改这些越界文件,故 D-44(c) 无法全绿;本计划未新增失败(新增 41 通过 / 6 跳过)。详见 `06-TEST-FINDINGS.md` `#06-09` 阻断项。
### Quick Tasks Completed
@ -198,6 +202,6 @@ None yet.
## Session Continuity
Last session: 2026-09-14T09:03:12.081Z
Stopped at: Completed 06-08-PLAN.md
Last session: 2026-09-14T10:59:39.690Z
Stopped at: Completed 06-09-PLAN.md
Resume file: None

View File

@ -0,0 +1,203 @@
---
phase: 06-unit-tests
plan: 09
subsystem: testing
tags: [vitest, save/load, saveables, CoreState, compression, round-trip]
# Dependency graph
requires:
- phase: 06-unit-tests
provides: 06-01..06-08 行为单测与既有测试基建(vitest、logger.catch、inline fixture 模式)
provides:
- 6 个存读档测试文件:enemy/hero/map/replay/flag 逐类同实例往返 + CoreState 顶层 5 saveable × 3 压缩档往返
- 06-SAVE-EXCLUSIONS.md:逐类排除清单(存档无关/元数据/派生/缓存字段及依据)
- 06-COVERAGE-MAP.md 06-09 小节:11 个可达码 55/58/59/112/113/119/120/122/124/177/178 的触发断言映射
- 06-TEST-FINDINGS.md `#06-09-1..5` 疑似缺陷 + 阻断项(既有 test:ci 回归)
affects: [07, verify-work, milestone-audit]
# Actuals (#2632) — chars/4 over the realized diff (new test files + appended planning sections)
actuals:
tokens: 16600
tasks: 3
commits: 4
# Tech tracking
tech-stack:
added: []
patterns:
- 存读档同实例往返:saveState → 改关键字段 → loadState → 仅显式断言关键字段(D-12/D-13)
- 三档压缩循环(NoCompression/LowCompression/HighCompression)套用同实例往返
- 错误/警告路径经 logger.catch 观测 code,绝不 expect(...).toThrow
- 每条 it 前单行中文注释;疑似缺陷 it.skip + `#06-09-N` 锚定
key-files:
created:
- packages-user/data-base/src/enemy/saveLoad.test.ts
- packages-user/data-base/src/hero/saveLoad.test.ts
- packages-user/data-base/src/map/saveLoad.test.ts
- packages-user/data-common/src/replay/saveLoad.test.ts
- packages-user/data-base/src/flag/saveLoad.test.ts
- packages-user/data-state/test/saveablesRoundTrip.test.ts
- .planning/phases/06-unit-tests/06-SAVE-EXCLUSIONS.md
modified:
- .planning/phases/06-unit-tests/06-COVERAGE-MAP.md
- .planning/phases/06-unit-tests/06-TEST-FINDINGS.md
key-decisions:
- "D-45 顶层验证经公开 CoreState.saveState/loadState(而非仅 getSaveableContent)驱动,5 saveable × 3 压缩档全绿"
- "StaticTile/DynamicTile 的 saveState/loadState 签名按接口契约传 SaveCompression(实现忽略该参数),以通过类型门禁"
- "EquipmentState 数值加成无法往返等 5 处缺陷按 D-05 写正确预期 it.skip,并注册 #06-09-1..5;经临时取消 skip 验证确为真实失败"
- "cp 码 178 的现行实现按「存档缺失 key」触发,与文案相反;以实际触发路径写正常用例,另以 it.skip 记录正确预期(#06-09-5)"
requirements-completed: [TEST-01]
coverage:
- id: D1
description: "enemy + hero 各含 saveState/loadState 的类同实例往返(3 压缩档),触发码 119/120/58/59;排除清单落盘"
requirement: TEST-01
verification:
- kind: unit
ref: "packages-user/data-base/src/enemy/saveLoad.test.ts#all"
status: pass
- kind: unit
ref: "packages-user/data-base/src/hero/saveLoad.test.ts#all"
status: pass
human_judgment: false
- id: D2
description: "map + replay(ReplaySystem 与 ReplayArray)+ flag 同实例往返,触发码 55/122/124"
requirement: TEST-01
verification:
- kind: unit
ref: "packages-user/data-base/src/map/saveLoad.test.ts#all"
status: pass
- kind: unit
ref: "packages-user/data-common/src/replay/saveLoad.test.ts#all"
status: pass
- kind: unit
ref: "packages-user/data-base/src/flag/saveLoad.test.ts#all"
status: pass
human_judgment: false
- id: D3
description: "CoreState 顶层经公开 saveState/loadState 对 5 saveable × 3 压缩档整体往返;getSaveableContent 辅助校验;触发码 112/113/177/178"
requirement: TEST-01
verification:
- kind: integration
ref: "packages-user/data-state/test/saveablesRoundTrip.test.ts#all"
status: pass
human_judgment: false
- id: D4
description: "D-44 质量门禁:eslint 0 错误、vue-tsc 文件级 0 类型错误、pnpm test:ci 全绿"
requirement: TEST-01
verification:
- kind: other
ref: "pnpm test:ci"
status: fail
human_judgment: true
rationale: "pnpm test:ci 存在先于本计划的既有回归(commit cee8439 将录像记录接入 equipment/items/mover,4 个 data-base 既有测试与 2 个 data-state 文件失败);本计划硬约束禁止修改这些越界文件,故 test:ci 无法全绿。eslint 与 vue-tsc 已通过,本计划未新增失败。"
# Metrics
duration: 42min
completed: 2026-09-14
status: complete
---
# Phase 06 Plan 09: 存档(独立系统)Summary
**26+ 个含 `saveState`/`loadState` 的类逐类同实例往返 + `CoreState` 顶层 5 saveable × 3 压缩档经公开入口整体往返,11 个可达码全部触发,并落盘排除清单与 5 处疑似缺陷**
## Performance
- **Duration:** 42 min
- **Started:** 2026-09-14T18:34:00Z (approx)
- **Completed:** 2026-09-14T19:16:00Z (approx)
- **Tasks:** 3 (Task 1 为已预清关的用户确认门禁)
- **Files modified:** 9(6 新增测试 + 3 规划产物)
## Accomplishments
- **阶段 1(构件级)**:`Enemy`/`CommonSerializableSpecial`/`NonePropertySpecial`/`EnemyManager` 与 hero 全部子系统(modifier/location/rendering/equipment/equipStore/items/follower/state)同实例往返,三档压缩;码 119/120/58/59 触发。
- **阶段 2(组合/流水线)**:`StaticTile`/`DynamicTile`/`MapLayer`/`GameMap`/`MapState`、`ReplayArray`/`ReplaySystem`、`FlagSystem` 同实例往返;码 55/122/124 触发。
- **阶段 3(完整/集成)**:经公开 `CoreState.saveState(compression)` / `loadState(state, compression)` 对 `@system/hero`/`flags`/`maps`/`enemy`/`replay` × 3 压缩档整体往返,辅以 `getSaveableContent(id)`;码 112/113/177/178 触发。
- **排除清单** `06-SAVE-EXCLUSIONS.md` 逐类列出存档无关/元数据/派生/缓存字段与依据(D-42)。
- **11 个可达码** 全部有触发断言:55/58/59/112/113/119/120/122/124/177/178。
- 发现并登记 **5 处疑似缺陷**(`#06-09-1..5`),以正确预期 `it.skip` 记录,并经临时取消 skip 验证确为真实失败。
## Task Commits
Each task was committed atomically:
1. **Task 1: 执行前门禁 — 用户确认公开 save/load 入口与 5 个 saveable** — 无代码提交(用户已预确认「存读档入口已就绪,可以开始」;磁盘核对 `core.ts:237-241` 含 `@system/replay`)
2. **Task 2: 阶段 1(构件级)enemy + hero** - `3e29548` (test)
3. **Task 3: 阶段 2(组合/流水线)map + replay + flag** - `c707c87` (test)
4. **Task 4: 阶段 3(完整/集成)CoreState 顶层** - `502d87b` (test)
**Plan metadata:** `(see final docs commit)` (docs: complete plan)
## Files Created/Modified
- `packages-user/data-base/src/enemy/saveLoad.test.ts` - Enemy/special/EnemyManager 同实例往返,码 119/120
- `packages-user/data-base/src/hero/saveLoad.test.ts` - hero 各子系统同实例往返,码 58/59
- `packages-user/data-base/src/map/saveLoad.test.ts` - map tile/layer/gameMap/mapState 同实例往返,码 55/122/124
- `packages-user/data-common/src/replay/saveLoad.test.ts` - ReplayArray/ReplaySystem 同实例往返
- `packages-user/data-base/src/flag/saveLoad.test.ts` - FlagSystem 同实例往返与存档克隆
- `packages-user/data-state/test/saveablesRoundTrip.test.ts` - CoreState 顶层 5×3 往返,码 112/113/177/178
- `.planning/phases/06-unit-tests/06-SAVE-EXCLUSIONS.md` - 逐类排除清单
- `.planning/phases/06-unit-tests/06-COVERAGE-MAP.md` - 06-09 小节(11 码映射)
- `.planning/phases/06-unit-tests/06-TEST-FINDINGS.md` - `#06-09-1..5` 与阻断项
## Decisions Made
- 顶层验证以**公开入口** `CoreState.saveState/loadState` 为主路径(D-45),`getSaveableContent(id)` 作辅助逐 id 校验(断言同一实例与未知 id 返回 null)。
- `StaticTile`/`DynamicTile` 调用 `saveState(SaveCompression.*)` / `loadState(save, SaveCompression.*)`:其接口契约声明压缩参数(实现忽略),按契约传参以通过类型门禁。
- `EquipmentState` 数值加成无法往返、`HeroEquipment` 存档未深拷贝、`DynamicTile` 不恢复 num、`ReplayArray` 不恢复 length、码 178 语义反转:按 D-05 写正确预期 `it.skip` 并登记为 `#06-09-1..5`。
- 码 178:以现行实现的实际触发路径(存档缺失 saveable key)写正常用例,另以 `it.skip` 记录「存档多出 key」的正确预期。
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 3 - Blocking] hero 测试的道具分类与 modifier 类型门禁**
- **Found during:** Task 2(阶段 1)
- **Issue:** HeroItems 往返用例最初误用 `ItemCategory.Equipment` 道具,导致分表为空;`registerModifier`/`addModifier` 的泛型签名在具体类上产生类型错误。
- **Fix:** 新增 `createPlainItem`(Constant/Consumable);将 `createHeroState` 返回类型改为接口 `IHeroState<IHeroAttr>` 并用 `setModifierSaveEnabled` 表达 save=false 语义。
- **Files modified:** `packages-user/data-base/src/hero/saveLoad.test.ts`
- **Verification:** 聚焦运行全绿;vue-tsc 本文件 0 错误。
- **Committed in:** `3e29548`
**2. [Rule 3 - Blocking] map tile 存读档需按接口契约传压缩参数**
- **Found during:** Task 4(D-44 vue-tsc)
- **Issue:** `IStaticTile`/`IDynamicTile` 经 `ISaveableContent` 声明 `saveState(compression)`/`loadState(state, compression)`,0/1 参调用触发 TS2554。
- **Fix:** 传 `SaveCompression.NoCompression`(实现忽略);测试语义不变。
- **Files modified:** `packages-user/data-base/src/map/saveLoad.test.ts`
- **Verification:** vue-tsc 本文件 0 错误。
- **Committed in:** `c707c87`
---
**Total deviations:** 2 auto-fixed (2 blocking)
**Impact on plan:** 均为类型/分类门禁修正,无范围蔓延;未修改任何生产/核心源码。
## Issues Encountered
**阻断项(超出本计划范围,未修复)**:`pnpm test:ci` 在本计划执行时**已存在**先于本计划的既有回归 —— commit `cee8439` 将 `this.state.replaySystem.route.add(...)` 接入 `data-base/src/hero/{equipment,items,mover}.ts`,但 4 个既有 `data-base` 测试(equipment/follower/items/mover)的假 `IDataCommon` 不含 `replaySystem`,另 2 个 `data-state` 文件因未处理 rejection 计为失败,共 6 文件 / 15 用例失败。本计划硬约束仅允许新增 6 个 `*.test.ts` 与规划产物,**不得修改这些越界文件**,故 D-44(c) 无法全绿。经复核:本计划新增 6 文件 **41 通过 / 6 跳过,未新增任何失败**;失败集合与改动前完全一致。详见 `06-TEST-FINDINGS.md` `#06-09` 阻断项。
## User Setup Required
None - no external service configuration required.
## Next Phase Readiness
- 存读档测试(D-32 唯一承接计划)已完成;`saveState`/`loadState` 接口覆盖与 CoreState 顶层往返就绪。
- **待用户处理**:修复 `cee8439` 引入的既有测试回归(补齐 4 个 `data-base` 测试的假 `replaySystem` 或为生产侧加空值守卫),使 `pnpm test:ci` 恢复全绿;并裁决 `#06-09-1..5` 的修复方案。
- 07/milestone 验证可基于本 SUMMARY 的 coverage 与 `06-COVERAGE-MAP.md` 继续。
---
*Phase: 06-unit-tests*
*Completed: 2026-09-14*
## Self-Check: PASSED
- 6 个 `*.test.ts` + `06-SAVE-EXCLUSIONS.md` + `06-09-SUMMARY.md` 均存在于磁盘。
- 提交 `3e29548`、`c707c87`、`502d87b` 均存在于历史。
- `git status` 仅含规划产物(SUMMARY/STATE/ROADMAP);未改动任何生产/核心源码。