docs(06): update 06-09 for CoreState save/load entry (D-45)

This commit is contained in:
unanmed 2026-09-14 18:19:28 +08:00
parent 82205a9dc1
commit 0c1b1555cb
3 changed files with 76 additions and 37 deletions

View File

@ -23,15 +23,15 @@ must_haves:
truths:
- "TEST-01 由数据端行为单测满足,门禁为固定非 watch 命令 `pnpm test:ci` 全绿(D-08)。"
- "存读档集中:本计划是唯一测试 `saveState`/`loadState` 的计划;其它计划一律不测(D-32 / D-42)。"
- "接口全覆盖:所有覆盖系统内含 `saveState`/`loadState` 的类(Enemy/special、EnemyManager、HeroAttribute/modifier、HeroLocation、HeroState、HeroEquipment、EquipmentState/HeroEquipsStore、HeroItems、HeroFollower、HeroRendering、MapState、GameMap、MapLayer、StaticTile、DynamicTile、ReplayArray、FlagSystem)的这两个方法至少一条正常用例;名称含 legacy 的接口/方法排除(D-30 / D-42)。"
- "code 全覆盖:本计划可达的码 55(MapStore load 缺 reference)、58(equipment store load 找不到 maxUid)、59(equipment load 找不到 item raw data)、112(重复 saveable id)、113(bindSaveableExecuter 目标未添加)、119(loadState 缺 prefab)、120(loadState 缺 special)、122(MapStore load 楼层缺失)、124(MapLayer load 引用缺失)各至少一条触发断言(D-31 / D-42)。"
- "接口全覆盖:所有覆盖系统内含 `saveState`/`loadState` 的类(Enemy/special、EnemyManager、HeroAttribute/modifier、HeroLocation、HeroState、HeroEquipment、EquipmentState/HeroEquipsStore、HeroItems、HeroFollower、HeroRendering、MapState、GameMap、MapLayer、StaticTile、DynamicTile、ReplayArray、FlagSystem)的这两个方法至少一条正常用例;`CoreState` 的公开 `saveState`/`loadState` 亦经顶层入口覆盖(D-45);名称含 legacy 的接口/方法排除(D-30 / D-42)。"
- "code 全覆盖:本计划可达的码 55(MapStore load 缺 reference)、58(equipment store load 找不到 maxUid)、59(equipment load 找不到 item raw data)、112(重复 saveable id)、113(bindSaveableExecuter 目标未添加)、119(loadState 缺 prefab)、120(loadState 缺 special)、122(MapStore load 楼层缺失)、124(MapLayer load 引用缺失)、177(CoreState.loadState 存档缺 saveable key)、178(CoreState.loadState 存档含未加载的 key)各至少一条触发断言(D-31 / D-42 / D-45)。"
- "往返形式为**同实例恢复**:对可存档对象 `saveState` → 继续修改状态 → `loadState` → 关键字段回到存档点(D-12)。"
- "压缩档全覆盖:`NoCompression`/`LowCompression`/`HighCompression` 三档(按各 `saveState`/`loadState` 签名适用者)(D-11 / D-42)。"
- "「状态相同」只用**关键字段显式断言**,不比较派生字段/缓存/序列化容器结构,也不做整体深度相等(D-13)。"
- "推导并写出**排除清单**(存档无关/元数据字段,如最后存档时间、dirty、缓存),落到 `06-SAVE-EXCLUSIONS.md`(D-42)。"
- "CoreState 顶层验证:`getSaveableContent(id)` 对 4 个已注册 id(`@system/hero`/`flags`/`maps`/`enemy`)逐个往返(D-11),并验证 `addSaveableContent`/`bindSaveableExecuter` 守卫(112/113);若用户已新增公开 save/load 入口,则一并经该入口验证。"
- "执行前必须先向用户确认(依赖用户调整 CoreState 可存档内容并新增公开 save/load 入口,例如录像存档目前未计入但应计入)(D-42)。"
- "测试形态(D-01):本计划经 `CoreState` 集成路径(`getSaveableContent`)与各类同实例往返验证存读档,属混合测试形态的跨系统集成一侧。"
- "CoreState 顶层验证(D-45):主路径经**公开入口** `CoreState.saveState(compression)` / `loadState(state, compression)` 对 5 个已注册 id(`@system/hero`/`flags`/`maps`/`enemy`/`replay`)做整体往返(D-11),并以 `getSaveableContent(id)` 作为辅助逐 id 校验;同时断言守卫码 112/113 与 `loadState` 新增码 177/178。"
- "执行前必须先向用户确认(D-42 / D-45):公开 `saveState`/`loadState` 入口已就绪,且 5 个 saveable(含 `@system/replay`)均已注册;若 `@system/replay` 未注册即为阻断,须记录并暂停,不得静默通过。"
- "测试形态(D-01):本计划经 `CoreState` 集成路径(公开 `saveState`/`loadState`,辅以 `getSaveableContent`)与各类同实例往返验证存读档,属混合测试形态的跨系统集成一侧。"
- "疑似缺陷按正确预期编写并标记 `it.skip`/`it.todo`,并按 D-06 的格式登记到共用的 `06-TEST-FINDINGS.md`(模块/接口、现象、最小复现、疑似原因、影响面、建议修复方向、关联 skip 用例、严重度)。"
- "执行节奏(D-33):本计划执行前先向用户确认;执行完成后暂停,用中文分条简要汇报验证结果,详细结果写入共用的 `06-TEST-FINDINGS.md`。"
- "阶段化(D-43):计划按 构件→组合→完整 三阶段组织,每阶段跑绿后进入下一阶段;阻断性 bug 暂停等确认。"
@ -48,11 +48,11 @@ must_haves:
- path: packages-user/data-base/src/flag/saveLoad.test.ts
provides: FlagSystem 存读档覆盖
- path: packages-user/data-state/test/saveablesRoundTrip.test.ts
provides: CoreState 顶层 4 saveables × 3 压缩档往返(112/113)
provides: CoreState 顶层 5 saveables × 3 压缩档经公开 `saveState`/`loadState` 往返(112/113/177/178)
- path: .planning/phases/06-unit-tests/06-SAVE-EXCLUSIONS.md
provides: 存读档排除清单(存档无关/元数据字段)
key_links:
- "saveablesRoundTrip.test.ts 经 `CoreState.getSaveableContent(id)`(`data-state/src/core.ts:486`)进入,对应 `core.ts:237-240` 注册的 4 个 id;不接触 `saveSystem.init`/IndexedDB(D-10)"
- "saveablesRoundTrip.test.ts 以**公开入口** `CoreState.saveState(compression)` / `loadState(state, compression)`(`data-state/src/core.ts:509-538`,D-45)为主路径,对应 `core.ts:237-241` 注册的 5 个 id(`@system/hero`/`flags`/`maps`/`enemy`/`replay`);并以 `getSaveableContent(id)`(`core.ts:487-490`)作辅助逐 id 校验;不接触 `saveSystem.init`/IndexedDB(D-10)"
- "各 saveLoad.test.ts 用 inline 合成对象/小地图/小录像数组;三档压缩循环参照 `data-base/src/map/mapLifecycle.test.ts:203-234` 的显式关键字段形状"
- "`06-COVERAGE-MAP.md` 为共享 create-or-append 文件:写 06-09 小节前先检查表头(`| code | 模块 | 用例 | 计划 |`)是否存在,不存在则先创建,再只追加/更新本小节;幂等且与其它计划顺序无关,不重写他节"
prohibitions:
@ -66,13 +66,13 @@ must_haves:
---
<objective>
存读档独立系统(D-42):覆盖所有含 `saveState`/`loadState` 的类逐类同实例往返 + `CoreState` 顶层验证;仅断言关键状态字段,排除存档无关/元数据字段;压缩档全覆盖。按 D-43 的阶段化测试组织:阶段 1 构件级(enemy + hero 各类同实例往返)→ 阶段 2 组合/流水线(map + replay + flag 各类同实例往返)→ 阶段 3 完整/集成(CoreState 顶层 saveables 往返)。
存读档独立系统(D-42 / D-45):覆盖所有含 `saveState`/`loadState` 的类逐类同实例往返 + `CoreState` 顶层验证;仅断言关键状态字段,排除存档无关/元数据字段;压缩档全覆盖。按 D-43 的阶段化测试组织:阶段 1 构件级(enemy + hero 各类同实例往返)→ 阶段 2 组合/流水线(map + replay + flag 各类同实例往返)→ 阶段 3 完整/集成(经公开 `CoreState.saveState`/`loadState` 对 5 个 saveable 往返)。
**执行前必须先向用户确认**(D-42:依赖用户调整 CoreState 可存档内容,例如录像存档目前未计入但应计入,并新增公开 save/load 入口)。
**执行前必须先向用户确认**(D-42 / D-45:公开 `saveState`/`loadState` 入口已就绪,且 5 个 saveable 均已注册,含 `@system/replay`;`@system/replay` 未注册即为阻断)。
Output: 6 个 `*.test.ts` 与 `06-SAVE-EXCLUSIONS.md`。
阶段结构(D-43):每阶段跑绿后再进入下一阶段;阶段 3 为 CoreState 顶层验证。
阶段结构(D-43):每阶段跑绿后再进入下一阶段;阶段 3 为经公开入口的 CoreState 顶层验证。
</objective>
<execution_context>
@ -105,7 +105,7 @@ Output: 6 个 `*.test.ts` 与 `06-SAVE-EXCLUSIONS.md`。
- fixture 内联且最小(D-02/D-03);用 `SaveCompression` 三档。
- 警告/错误路径经 `logger.catch` / `vi.spyOn(logger, ...)`。
- 疑似 bug:正确预期 + `it.skip`/`it.todo` + 中文注释锚定 `#06-09-N`;`pnpm test:ci` 保持全绿。
- **执行前必须先向用户确认(D-42)CoreState 可存档内容与公开 save/load 入口已就绪;未确认前不得开始。**
- **执行前必须先向用户确认(D-42 / D-45)公开 `CoreState.saveState`/`loadState` 入口与 5 个已注册 saveable(含 `@system/replay`)均已就绪;未确认前不得开始;`@system/replay` 未注册即阻断并记录,不得静默通过。**
- `06-COVERAGE-MAP.md` 为共享 create-or-append 文件(幂等、顺序无关):写 06-09 小节前先检查表头(`| code | 模块 | 用例 | 计划 |`)是否存在,不存在则先创建,再只追加/更新本小节,绝不重写他节。
- **执行协议(D-33):执行前向用户确认;执行后暂停并用中文分条汇报。**
- **阶段门禁(D-43):本计划按 构件 → 组合/流水线 → 完整/集成 三阶段顺序执行,每阶段跑绿后才进入下一阶段;若某阶段发现阻断性 bug 使后续阶段无法运行,暂停并按 D-05/D-07 向用户汇报、等确认,不得跳过或弱化。**
@ -115,25 +115,27 @@ Output: 6 个 `*.test.ts` 与 `06-SAVE-EXCLUSIONS.md`。
<tasks>
<task type="checkpoint:human-verify" gate="blocking-human">
<name>Task 1: 执行前门禁 — 用户确认 CoreState 可存档内容与公开入口已调整</name>
<name>Task 1: 执行前门禁 — 用户确认公开 save/load 入口与 5 个 saveable(含 @system/replay)已就绪</name>
<files>packages-user/data-state/test/saveablesRoundTrip.test.ts(尚未创建,仅作占位说明)</files>
<what-built>调整后的 CoreState 可存档内容(含录像存档计入)与新增的公开 save/load 入口。</what-built>
<what-built>CoreState 公开存档入口 `saveState(compression)` / `loadState(state, compression)`(D-45),以及 5 个已注册 saveable:`@system/hero`/`@system/flags`/`@system/maps`/`@system/enemy`/`@system/replay`。</what-built>
<how-to-verify>
1) 确认 4 个 saveable(`@system/hero`/`flags`/`maps`/`enemy`)及其新增内容已就绪。
2) 确认是否提供公开 save/load 入口(有则一并验证,无则仅走 `getSaveableContent(id)` 的 saveables 层)。
3) 确认录像存档是否已计入。
1) 确认公开入口 `CoreState.saveState(compression)` / `loadState(state, compression)` 已就绪(`ICoreState extends IStateSystem, ISaveableContent<ReadonlyMap<string, unknown>>`)。
2) 确认 5 个 saveable 均已注册:`@system/hero`/`@system/flags`/`@system/maps`/`@system/enemy` + **`@system/replay`**(核对 `core.ts` 的 `addSaveableContent` 调用)。
3) 若 `@system/replay` 未注册,则本计划在阶段 3 前阻断:记录到 `06-TEST-FINDINGS.md` 并暂停等待用户补注册,不得静默通过。
</how-to-verify>
<resume-signal>用户回复「存读档入口已就绪,可以开始」则继续 Task 2/3;否则暂停本计划等待用户改代码。</resume-signal>
<read_first>
.planning/phases/06-unit-tests/06-CONTEXT.md(D-42)
packages-user/data-state/src/core.ts(saveables 注册与 saveableContent 入口)
packages-user/data-common/src/save/types.ts(ISaveableContent/ISaveSystem 契约)
.planning/phases/06-unit-tests/06-CONTEXT.md(D-42 / D-45)
packages-user/data-state/src/core.ts(saveables 注册:`core.ts:237-241`;公开 `saveState`/`loadState`:`core.ts:509-538`)
packages-user/data-state/src/types.ts(`ICoreState extends IStateSystem, ISaveableContent<ReadonlyMap<string, unknown>>`)
packages-user/data-common/src/save/types.ts(`ISaveableContent` / `SaveCompression` 契约)
packages/common/src/logger.json(112/113/177/178)
</read_first>
<action>
本计划依赖用户先调整 CoreState 的可存档内容(例如录像存档目前未计入但应计入),并新增公开 save/load 入口(D-42)。开始前向用户展示并确认:
- 4 个 saveable(`@system/hero`/`flags`/`maps`/`enemy`)及其新增内容是否已就绪;
- 是否已提供公开 save/load 入口(若有,本计划将一并经该入口验证;若无,则仅走 `getSaveableContent(id)` 的 saveables 层);
- 录像存档是否已计入。
本计划依赖已落地的公开存档入口(D-45)。开始前向用户展示并确认:
- 公开入口 `CoreState.saveState(compression)` / `loadState(state, compression)` 是否已就绪;
- 5 个 saveable(`@system/hero`/`@system/flags`/`@system/maps`/`@system/enemy` + `@system/replay`)是否均已注册(核对 `core.ts:237-241` 的 `addSaveableContent` 调用);
- **`@system/replay` 注册状态必须显式确认**:若未注册,则记录为阻断(写入 `06-TEST-FINDINGS.md`)并按 D-05/D-07 暂停等待用户补注册,不得以仅 4 个 id 静默通过。
用户确认后再继续 Task 2/3;若未就绪,暂停本计划等待用户改代码,不得自行修改核心代码。
</action>
<verify>
@ -141,8 +143,9 @@ Output: 6 个 `*.test.ts` 与 `06-SAVE-EXCLUSIONS.md`。
</verify>
<acceptance_criteria>
- 用户给出明确开始确认;否则本计划保持暂停状态。
- `@system/replay` 注册状态已显式确认;未注册即记录为阻断,不得静默通过。
</acceptance_criteria>
<done>CoreState 可存档内容与入口就绪得到用户确认,或计划暂停等待用户改代码。</done>
<done>公开 save/load 入口与 5 个 saveable(含 @system/replay)就绪得到用户确认,或计划暂停等待用户改代码。</done>
</task>
<task type="auto">
@ -235,7 +238,7 @@ Output: 6 个 `*.test.ts` 与 `06-SAVE-EXCLUSIONS.md`。
</task>
<task type="auto">
<name>阶段 3(完整/集成):CoreState 顶层 saveables 往返(4 id × 3 压缩档,码 112/113)</name>
<name>阶段 3(完整/集成):CoreState 顶层 5 saveables × 3 压缩档经公开 saveState/loadState 往返(码 112/113/177/178)</name>
<files>packages-user/data-state/test/saveablesRoundTrip.test.ts</files>
<read_first>
packages-user/data-state/src/core.ts
@ -246,25 +249,27 @@ Output: 6 个 `*.test.ts` 与 `06-SAVE-EXCLUSIONS.md`。
</read_first>
<action>
D-43 阶段 3(完整/集成):在阶段 1/2 跑绿后,测 `CoreState` 顶层完整验证。
`saveablesRoundTrip.test.ts`:经 `CoreState.getSaveableContent(id)`:
- 对 4 个 id(`@system/hero`/`flags`/`maps`/`enemy`)× 3 档 `SaveCompression`:设已知关键字段 → `saveState` → 改字段 → `loadState` → 只断言关键字段(hero base 属性、flag 字段、map 层块/点位事件、enemy prefab 属性)。不做整体深度相等。
- 断言快照分离:save 后改活对象不影响快照关键字段。
`saveablesRoundTrip.test.ts`:**主路径经公开入口** `CoreState.saveState(compression)` / `loadState(state, compression)`(D-45):
- 对 5 个 id(`@system/hero`/`flags`/`maps`/`enemy`/`replay`)× 3 档 `SaveCompression`:设已知关键字段 → `core.saveState(compression)` → 改字段 → `core.loadState(snapshot, compression)` → 只断言关键字段(hero base 属性、flag 字段、map 层块/点位事件、enemy prefab 属性、replay 命令与参数)。不做整体深度相等(D-13)。
- 断言快照形状:`saveState` 返回的映射以 5 个已注册 id 为键,且与活对象分离(save 后改活对象不影响快照关键字段)。
- 辅助逐 id 校验:`getSaveableContent(id)` 对上述 5 个 id 各返回非 null,且其 `saveState`/`loadState` 与顶层入口结果一致。
- `loadState` 新增码:构造缺某 saveable key 的快照触发码 177(经 `logger.catch`);构造含未加载 key 的快照触发码 178。
- 未知 id 返回 null。
- 守卫:重复 `addSaveableContent` 经 `logger.catch` 观测码 112;对未添加对象 `bindSaveableExecuter` 观测码 113。
- 若用户已提供公开 save/load 入口,则经该入口再跑一遍等价往返。
- Node-safe `createCoreState()`;不 `saveSystem.init`、不加 `fake-indexeddb`(D-10)。
</action>
<verify>
<automated>pnpm exec vitest run packages-user/data-state/test/saveablesRoundTrip.test.ts</automated>
<fails_when>运行失败,或 112/113 中任一码未被观测,或 4×3 往返矩阵缺失某组合</fails_when>
<fails_when>运行失败,或 112/113/177/178 中任一码未被观测,或 5×3 往返矩阵缺失某组合,或顶层往返未经公开 `saveState`/`loadState` 驱动</fails_when>
</verify>
<acceptance_criteria>
- `saveablesRoundTrip.test.ts` 零非跳过失败。
- 覆盖 4 id × 3 压缩档,显式关键字段 + 快照分离 + 未知 id null + 码 112/113。
- 主路径经公开 `CoreState.saveState`/`loadState` 覆盖 5 id × 3 压缩档;`getSaveableContent(id)` 作辅助逐 id 校验。
- 显式关键字段 + 快照分离 + 未知 id null + 码 112/113/177/178。
- 每个 `it` 前有单行中文注释。
- D-44 门禁通过:改动文件 `eslint --fix` 后 `eslint <改动文件>` 0 错误;本计划改动的测试文件在 `pnpm exec vue-tsc --noEmit` 输出中按文件路径过滤 0 类型错误;`pnpm test:ci` 全绿。
</acceptance_criteria>
<done>阶段 3(完整/集成)的 CoreState 顶层 saveables 往返在阶段 1/2 跑绿的基础上全部跑绿。若本阶段发现阻断性 bug,暂停并按 D-05/D-07 向用户汇报、等确认;不得跳过或弱化。完成后以 create-or-append 方式将本计划的 code→模块→用例行(55/58/59/112/113/119/120/122/124)写入 `06-COVERAGE-MAP.md` 的 06-09 小节:先检查表头,不存在则先创建,再只追加本小节,不重写他节。</done>
<done>阶段 3(完整/集成)的 CoreState 顶层 saveables 往返在阶段 1/2 跑绿的基础上全部跑绿。若本阶段发现阻断性 bug(含 `@system/replay` 未注册),暂停并按 D-05/D-07 向用户汇报、等确认;不得跳过或弱化。完成后以 create-or-append 方式将本计划的 code→模块→用例行(55/58/59/112/113/119/120/122/124/177/178)写入 `06-COVERAGE-MAP.md` 的 06-09 小节:先检查表头,不存在则先创建,再只追加本小节,不重写他节。</done>
</task>
</tasks>
@ -290,15 +295,15 @@ Output: 6 个 `*.test.ts` 与 `06-SAVE-EXCLUSIONS.md`。
- 六个测试文件聚焦运行通过;`pnpm test:ci` 全量绿。
- `git status` 仅新增 `*.test.ts` 与 `06-SAVE-EXCLUSIONS.md`;无核心文件改动。
- 任何 `it.skip`/`it.todo` 均有 `#06-09-N` 条目。
- 以 create-or-append 方式写入 `06-COVERAGE-MAP.md` 06-09 小节(9 个码);表头不存在则先创建;幂等、顺序无关,不重写他节。
- **执行协议**:执行前必须先向用户确认 CoreState 可存档内容与入口就绪;执行后暂停并用中文分条汇报。
- 以 create-or-append 方式写入 `06-COVERAGE-MAP.md` 06-09 小节(11 个码:55/58/59/112/113/119/120/122/124/177/178);表头不存在则先创建;幂等、顺序无关,不重写他节。
- **执行协议**:执行前必须先向用户确认公开 save/load 入口与 5 个 saveable(含 `@system/replay`)就绪;执行后暂停并用中文分条汇报。
</verification>
<success_criteria>
- 6 个存读档测试文件存在并通过(在用户确认入口就绪之后)。
- 每个含 `saveState`/`loadState` 的类至少一条同实例往返;4 saveable × 3 压缩档覆盖。
- 6 个存读档测试文件存在并通过(在用户确认公开入口与 5 个 saveable 就绪之后)。
- 每个含 `saveState`/`loadState` 的类至少一条同实例往返;5 saveable × 3 压缩档经公开 `CoreState.saveState`/`loadState` 覆盖。
- 排除清单 `06-SAVE-EXCLUSIONS.md` 落盘。
- 9 个可达码全部触发断言。
- 11 个可达码全部触发断言。
</success_criteria>
<artifacts_this_plan_produces>

View File

@ -90,6 +90,7 @@
- **D-33:** 执行节奏 —— **每个计划执行前先向用户确认**;执行完暂停,用中文**分条简要汇报**本计划验证结果;详细结果写入共用的 `06-TEST-FINDINGS.md`。
- **D-43:** 阶段化测试(**应用于全部 06-01..06-09**)—— 先做**构件级**测试(单个类/函数/单个光环/单个 effect 等最小单元),再做**组合/流水线**测试,最后做**完整/集成**测试。**取消 tracer-first**;每阶段跑绿后再进入下一阶段。某阶段发现**阻断性 bug**(导致后续阶段无法运行)时,**暂停并向用户汇报、等确认**(D-05/D-07),不得跳过或弱化为通过。原因:这些系统在本次之前从未被测过,直接端到端很可能整链失败且无法定位,必须先分阶段定位。
- **D-44:** 质量门禁(lint + 类型,**文件级**,应用于全部计划)—— 每个计划执行后、提交前必须:(a) 对改动文件运行 `eslint --fix`,并确保 `eslint <改动文件>` **0 错误**;(b) 对**本计划改动的测试文件**运行 `pnpm exec vue-tsc --noEmit`,并确保其输出中**这些文件路径下 0 类型错误**(按输出文件路径过滤判定;因全局 `pnpm check:type` 已有既有无关错误,故按文件级判定);(c) `pnpm test:ci` 全绿。任一不通过则**不得提交**。既有无关错误(`client-modules`/`legacy-plugin-data` 等,属 Phase 4/legacy)不在本门禁范围。原因:vitest 用 esbuild 剥类型,类型/格式错误不会让测试失败,故必须显式门禁。
- **D-45:** CoreState 顶层存档入口(D-42 落地,2026-09-14)—— `ICoreState extends IStateSystem, ISaveableContent<ReadonlyMap<string, unknown>>`,`CoreState.saveState(compression)` / `loadState(state, compression)` 为**公开入口**;06-09 顶层验证经此入口进行(`getSaveableContent(id)` 作为辅助逐 id 校验)。saveables **预期 5 个**:`@system/hero` / `@system/flags` / `@system/maps` / `@system/enemy` + **`@system/replay`**(录像存档由用户补注册;执行前 Task 1 门禁确认)。`CoreState.loadState` 新增可达码 **177**(存档缺 saveable key)与 **178**(存档含未加载的 key),纳入 06-09 码覆盖。录像相关新码 **176**(只能加 up/right/down/left 移动步)归 06-07。
### 各计划边界
- **D-35:** 06-02 只测顶层实现**基本功能**(单分支、按预期输出);属性/加成**组合**后移至 06-07。范围:`MainDamageCalculator` / `MainEnemyFinalEffect` / `MainEnemyComparer` / `CommonAura(+Converter)` / `GuardAura(+Converter)` / `registerSpecials` / mapDamage 五视图 + converter + reducer。

View File

@ -74,6 +74,17 @@
| 43 | common/face.ts | `warns code 43 for an unknown main block` | 06-08 |
| 44 | common/face.ts | `warns code 44 when binding the main direction` | 06-08 |
| 111 | flag/field.ts | `warns code 111 when adding to a non-numeric field` | 06-08 |
| 55 | map/saveLoad.test.ts | `warns code 55 when loading a compressed MapState without a reference` | 06-09 |
| 58 | hero/saveLoad.test.ts | `warns code 58 when the max equipment uid cannot be found` | 06-09 |
| 59 | hero/saveLoad.test.ts | `warns code 59 when the item raw data is missing` | 06-09 |
| 112 | data-state/test/saveablesRoundTrip.test.ts | `warns code 112 when adding a duplicate saveable id` | 06-09 |
| 113 | data-state/test/saveablesRoundTrip.test.ts | `warns code 113 when binding an executor to an unadded saveable` | 06-09 |
| 119 | enemy/saveLoad.test.ts | `warns code 119 when the prefab is missing during loadState` | 06-09 |
| 120 | enemy/saveLoad.test.ts | `warns code 120 when a special is missing during loadState` | 06-09 |
| 122 | map/saveLoad.test.ts | `warns code 122 when a floor is missing during loadState` | 06-09 |
| 124 | map/saveLoad.test.ts | `warns code 124 when a floor or its layers are missing in the reference` | 06-09 |
| 177 | data-state/test/saveablesRoundTrip.test.ts | `warns code 177 when the save data misses a saveable key` | 06-09 |
| 178 | data-state/test/saveablesRoundTrip.test.ts | `warns code 178 when the save data has keys that are not loaded` | 06-09 |
## 06-01 战斗系统(packages-user/data-system/src/combat)
@ -201,3 +212,25 @@ D-32:不测任何 `saveState`/`loadState`,flag 存读档往返归 06-09。
D-30:排除名称含 legacy 的接口/方法。
一条疑似缺陷 `#06-08-1`(`backward(count>1)` 因 `Special` 步翻转 `moveDirection` 而方向摆动、
净位移为零)按 D-05 以 `it.skip` 的正确预期用例登记,详见 `06-TEST-FINDINGS.md`。
## 06-09 存档(独立系统)
模块归属:119 / 120 → `data-base/src/enemy/saveLoad.test.ts`(`EnemyManager.loadState` 缺 prefab /
`Enemy.loadState` 缺 special);
58 / 59 → `data-base/src/hero/saveLoad.test.ts`(`HeroEquipsStore.loadState` 缺 maxUid / 缺 item raw data);
55 / 122 / 124 → `data-base/src/map/saveLoad.test.ts`(`MapState.loadState` 缺 reference / 缺楼层 /
`MapLayer.loadState` 引用缺失);
112 / 113 / 177 / 178 → `data-state/test/saveablesRoundTrip.test.ts`(`CoreState.addSaveableContent` 重复 id /
`bindSaveableExecuter` 未添加目标 / 公开 `CoreState.loadState` 存档缺 saveable key / 存档含未加载的 key)。
其余码(warn 114/115 等)不属本计划可达范围,排除。
阶段 1(构件级)完成 `Enemy`/special/`EnemyManager` 与 hero 各子系统同实例往返,观测 119/120/58/59;
阶段 2(组合/流水线)完成 `MapState`/`GameMap`/`MapLayer`/tile、`ReplayArray`、`FlagSystem` 同实例往返,
观测 55/122/124;
阶段 3(完整/集成)经**公开入口** `CoreState.saveState(compression)` / `loadState(state, compression)`(D-45)
对 5 个 saveable(`@system/hero`/`flags`/`maps`/`enemy`/`replay`)× 3 档压缩做整体往返,
并以 `getSaveableContent(id)` 辅助逐 id 校验,观测 112/113/177/178。
D-32:全部 `saveState`/`loadState` 测试集中本计划,其它计划不测(06-07 播放所需状态重置除外)。
D-45:`@system/replay` 须已注册(执行前 Task 1 门禁确认);未注册即阻断。录像新码 176 归 06-07。
排除清单(存档无关/元数据字段)见 `06-SAVE-EXCLUSIONS.md`。