diff --git a/.planning/phases/07-data-fixes/07-CONTEXT.md b/.planning/phases/07-data-fixes/07-CONTEXT.md new file mode 100644 index 0000000..c3eea01 --- /dev/null +++ b/.planning/phases/07-data-fixes/07-CONTEXT.md @@ -0,0 +1,152 @@ +# Phase 7: 数据端缺陷修复 - Context + +**Gathered:** 2026-09-15 +**Status:** Ready for planning + + +## Phase Boundary + +修复 Phase 6 单元测试暴露、登记在 `06-TEST-FINDINGS.md` 的**数据端疑似缺陷(20 条)**,使对应的「正确预期 `it.skip`」用例取消 skip 并通过。改动**仅限数据端**(`packages` 与 `packages-user/data-*`),**不含渲染端**(`@user/client-*`)与 legacy 渲染接线。 + +本阶段不新增功能、不扩展接口(除已裁决的契约修正);不以「提升覆盖率」为目标,而是让 Phase 6 已写好的正确预期断言真实通过。 + +**修复清单(20 条,按系统)** + +| 系统 | 条目 | 严重度 | 处置 | +|------|------|--------|------| +| combat `data-system/src/combat` | #06-01-1 `damage.ts` 临界点 info 与 nextValue 不匹配 | 中 | 修复 | +| combat | #06-01-2 `mapDamage.ts` `deleteEnemy` 残留来源伤害 | 中 | 修复 | +| combat | #06-01-3 `combat.ts` `before` 短路语义反 | 中 | 改实现对齐文档(D-03) | +| combat | #06-01-4 `context.ts` 重复 `buildup` 属性累加 | 中 | 修复 | +| combat | #06-15-1 `deleteAura` 后 `buildup` 不回退(与 #06-01-4 同根因) | 中 | 随 #06-01-4 转绿 | +| enemy `data-base/src/enemy` | #06-03-1 `createEnemy`/`createEnemyById` 未走复用映射 | 中 | 改实现接入复用(D-08) | +| replay `data-common/src/replay` | #06-04-1 `array.ts` int64 解码乘数 | 中 | 修复 | +| replay | #06-04-2 `array.ts` 多字节 bigint 编码 | 中 | 修复 | +| replay | #06-04-3 `array.ts` `delete` 索引回退 | 中 | 修复 | +| replay | #06-04-4 `array.ts` `insert` 位移方向 | 中 | 修复 | +| hero `data-base/src/hero` | #06-05-1 `attribute.ts` 无修饰器 final 陈旧 | 中 | 修复 | +| hero | #06-05-2 `equipment.ts` 空槽判断写反 | 中 | 修复 | +| hero | #06-05-3 `equipment.ts` 码 147 不可达 | 低 | 设计如此(D-06) | +| map `data-base/src/map` | #06-06-1 `mapLayer.ts` 越图 `transferToDynamic` 发 131 | 低 | 改发 128(D-04) | +| path `data-system/src/path` | #06-07-1 `CoreState` 未向 finder 注入 maps/layer/predicate | 中 | 用户自行修改(D-07) | +| flag/common `data-common/src/common` | #06-08-1 `mover.ts` `backward(count>1)` 方向摆动 | 低 | 修复 | +| save | #06-09-1 `EquipmentState.loadState` 数值/百分比加成丢失 | 高 | 修复 | +| save | #06-09-2 `HeroEquipment.saveState` 未深拷贝 | 中 | 修复 | +| save | #06-09-3 `DynamicTile.loadState` 不恢复 num | 中 | 修复 | +| save | #06-09-5 `CoreState` 码 178 语义反向 | 低 | 改实现对齐文案(D-05) | + +> `#06-09-4`(ReplayArray 存档)已因 c08f3f8 重构作废,不在本阶段。 + + + + +## Implementation Decisions + +### 修复范围与计划粒度 +- **D-01:** **全部 20 条纳入**本阶段;`#06-09-4` 作废不进,`#06-15-1` 与 `#06-01-4` 同根因合并处理。 +- **D-02:** **按系统切多个 PLAN**(combat / enemy / replay / hero / map / flag+common / save / path),系统内**先高后低**排序;便于逐系统汇报、门禁与回滚。 + +### 契约冲突裁决(4 条,接口事实源 = 文档/码表文案) +- **D-03:** `#06-01-3` **改实现对齐文档**:`ICombatScript.before` 仅当返回 `false` 才停止后续战前脚本并放弃战斗(`combat/types.ts:772` 的 jsdoc 为准)。 +- **D-04:** `#06-06-1` **改实现**:越图 `transferToDynamic` 分支改发码 **128**,与 `transferToStatic` 的越界语义一致。 +- **D-05:** `#06-09-5` **改实现对齐文案**:码 **178** = 存档中出现但未加载(未注册)的 key,即 `loaded.difference(total)`;并**同步更新既有非 skip 用例** `saveablesRoundTrip.test.ts` 中「缺 key 触发 178」的断言(`:321-334`)。 +- **D-06:** `#06-05-3` **保留码 147,生产代码不动、不标记死码**:错误码关注的是语义错误,而非是否可能被触发。对应 `it.skip` 用例(`warns code 147 when no equipment slot is available`)**保留 skip 并加注释**说明「147 为保留错误码,当前不可达,设计如此」,不纳入取消 skip 清单。 + +### 接口/接线缺口 +- **D-07:** `#06-07-1` **由用户自行修改**(`CoreState` → `pathfinding.finder` 注入 `useMapState`/`useMapLayer`/`usePassPredicate`);**AI 不实现该接线**,计划中标注为用户负责项。用户修复后其 `it.skip` 用例(`plays a teleport step without manual finder wiring`)转绿。 +- **D-08:** `#06-03-1` **改实现**:`createEnemy`/`createEnemyById` 接入复用映射(改用 `internalGetPrefab`,或先查 `reuseByCode`/`reuseById` 再取模板),与 `getPrefab` 行为一致。 + +### 修复方式与执行节奏(强约束) +- **D-09:** **每个计划开始执行前暂停并向用户汇报该计划的修复方案,经用户确认后才执行**;若计划方案修复失败,**不得自行探索其他方案**,必须**退出本次修改、修订修复计划后重新执行**。 +- **D-10:** **测试处置**:修复后**仅取消对应 `it.skip` 转绿**,不额外新增用例(Phase 6 已建立正确预期)。 +- **D-11:** **文档/注释同步**:契约修正后同步更新受影响的 jsdoc / 码表注释 / 契约文档,使文档与实现一致(尤其 D-03、D-05)。 + +### 验证与提交 +- **D-12:** **门禁沿用 Phase 6 D-44(文件级)**:(a) 改动文件 `eslint --fix` 后 `eslint <文件>` 0 错误;(b) 本计划改动文件 `pnpm exec vue-tsc --noEmit` 输出路径下 0 类型错误;(c) `pnpm test:ci` 全绿。不追求全仓 `check:type`(既有渲染/legacy 错误不在范围)。 +- **D-13:** **提交粒度:按缺陷/根因原子提交**(例如 `#06-01-4` + `#06-15-1` 合为一个 fix commit),便于逐条回滚与 windows 结清。 +- **D-14:** **WINDOWS.md 收口**:修复转绿且取消 skip 后 `gsd-tools windows fixed `;设计如此(`#06-05-3`)与用户自改(`#06-07-1`)的保留 `open` 并 **waive 注明原因**。 + +### the agent's Discretion +- 每条缺陷的具体修法(**最小修复 vs 必要的内部重构**)、文件切分、用例命名与 `#region` 划分由实现者在上述约束下决定;但**必须按 D-09 在执行前汇报并获用户确认**。若发现新的接口/设计疑问,立即提问,不自行假设。 + + + + +## Canonical References + +**Downstream agents MUST read these before planning or implementing.** + +### 项目与阶段约束 +- `.planning/PROJECT.md` — 数据/渲染分离、协作分工(接口设计由用户主导,AI 仅实现与测试) +- `.planning/REQUIREMENTS.md` — `FIX-01` 与 `TEST-01` 边界 +- `.planning/ROADMAP.md` — Phase 7 goal、成功标准、依赖 Phase 6 +- `.planning/STATE.md` — 既有决策、质量门禁、当前仓库状态 +- `.planning/WINDOWS.md` — Broken Windows 账本(open `skipped-test` 条目 id 19–27 的收口依据) +- `dev.md` — 四层数据架构、Node 独立性、依赖方向、注释与代码规范(CRLF、无副作用、无循环引用) + +### 缺陷与覆盖锚点(本阶段的输入) +- `.planning/phases/06-unit-tests/06-TEST-FINDINGS.md` — **20 条疑似缺陷的权威登记**(现象、复现、疑似原因、影响面、建议方向、关联 skip 用例、严重度) +- `.planning/phases/06-unit-tests/06-COVERAGE-MAP.md` — `code → 模块 → 用例` 映射(受影响可达码) +- `.planning/phases/06-unit-tests/06-CONTEXT.md` — D-05(skip=正确预期)、D-07/D-33(修复需用户确认)、D-43(阶段化)、D-44(文件级门禁)、D-30/D-31(legacy 排除与 code 覆盖) + +### 受影响源码(按系统) +- `packages-user/data-system/src/combat/` — `damage.ts` / `mapDamage.ts` / `combat.ts` / `context.ts` / `types.ts` +- `packages-user/data-base/src/enemy/` — `manager.ts`(复用映射) +- `packages-user/data-common/src/replay/` — `array.ts`(编解码 + 编辑索引) +- `packages-user/data-base/src/hero/` — `attribute.ts` / `equipment.ts` / `equipStore.ts` +- `packages-user/data-base/src/map/` — `mapLayer.ts` / `dynamicTile.ts` +- `packages-user/data-common/src/common/` — `mover.ts` +- `packages-user/data-system/src/path/` — `system.ts`(D-07 用户负责) +- `packages-user/data-state/src/core.ts` — 码 177/178(D-05) + +### 码表与测试约定 +- `packages/common/src/logger.json` — warn code 权威码表(127/128/131、147、176/177/178 等文案) +- `.planning/codebase/TESTING.md` — Vitest、`logger.catch` 断言模式、无覆盖率工具、`pnpm test:ci` +- `.planning/codebase/CONVENTIONS.md` — 命名、注释、类型、模块原则 + + + + +## Existing Code Insights + +### Reusable Assets +- Phase 6 已建立的「正确预期 `it.skip`」用例:修复后取消 skip 即为回归覆盖,无需重复设计断言 +- `logger.catch(fn)`(`packages/common/src/logger.ts`)—— 断言警告码的既有机制(`{ ret, info }`) +- Phase 6 的 inline fixture / `vi.hoisted` stub + dynamic-import harness —— 各系统测试已就绪 + +### Established Patterns +- 依赖方向 `data-common → data-base → data-system → data-state`;数据端 DOM-free、Node 可跑 +- 错误经 `logger.warn/error(code)` 上报,不抛异常;码唯一、不复用 +- `pnpm test:ci` 为非 watch 门禁;测试文件与源码同级 `*.test.ts`(`data-state/test/` 为聚合目录) + +### Integration Points +- `data-state/src/core.ts` `loadState` —— 码 177/178 判定 +- `data-system/src/combat/context.ts` `buildup` / `refreshEnemy` —— 视图 `reset()` 与重复构建 +- `data-common/src/replay/array.ts` —— 参数编解码与索引数组 `indexArray`/`paramArray` +- `data-base/src/hero/{equipStore,equipment}.ts` —— 存档深拷贝与压缩档回退到原始定义 +- `data-base/src/map/mapLayer.ts` —— 越界转换诊断码与事件层绑定 + + + + +## Specific Ideas + +- 用户明确定义本阶段为 Phase 6「测试 / 修复严格分两环节」中的**修复环节**;Phase 6 只分析、只汇报、不擅自改核心代码。 +- **执行节奏强约束(D-09)**:逐计划暂停汇报方案 → 用户确认 → 执行;方案失败即退出并修订计划,**禁止**自行另辟他法。 +- 契约裁决以**文档/码表文案为事实源**(D-03/D-04/D-05);唯一例外 `#06-05-3` 判为设计如此(D-06)。 +- `#06-07-1` 的接线由用户亲自完成(D-07),AI 只在其后验证并取消 skip。 + + + + +## Deferred Ideas + +- Phase 6 非数据端覆盖(渲染 / legacy 相关)仍延后到后续阶段,不在本阶段。 +- Phase 5(Legacy 移植)若改动数据端接口,本阶段修复与测试需同步调整。 + + + +--- + +*Phase: 7-数据端缺陷修复* +*Context gathered: 2026-09-15* diff --git a/.planning/phases/07-data-fixes/07-DISCUSSION-LOG.md b/.planning/phases/07-data-fixes/07-DISCUSSION-LOG.md new file mode 100644 index 0000000..0b13c07 --- /dev/null +++ b/.planning/phases/07-data-fixes/07-DISCUSSION-LOG.md @@ -0,0 +1,151 @@ +# Phase 7: 数据端缺陷修复 - Discussion Log + +> **Audit trail only.** Do not use as input to planning, research, or execution agents. +> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered. + +**Date:** 2026-09-15 +**Phase:** 7-数据端缺陷修复 +**Areas discussed:** 修复范围与优先级, 契约冲突裁决, 接口/接线缺口边界, 验证与提交节奏, 修复方式 + +--- + +## 修复范围与优先级 + +| Option | Description | Selected | +|--------|-------------|----------| +| 全部 20 条纳入 | 含低危死码/文案类,一次清完、WINDOWS.md 全绿 | ✓ | +| 仅高/中严重度 | 低危延后到独立小阶段 | | +| 分两批:先阻塞后其余 | 第一批修阻塞/高,第二批修其余 | | + +**User's choice:** 全部 20 条纳入 +**Notes:** 先更正了条数——登记为 20 条(不是 26),`#06-09-4` 已作废,`#06-15-1` 与 `#06-01-4` 同根因。 + +| Option | Description | Selected | +|--------|-------------|----------| +| 按系统切多个 PLAN | combat/enemy/replay/hero/map/flag+common/save/path,系统内先高后低 | ✓ | +| 单 PLAN 一次修完 | 一次审查面大、出问题难定位 | | +| 按根因依赖排序 | 先根因后严重度 | | + +**User's choice:** 按系统切多个 PLAN + +--- + +## 契约冲突裁决 + +| Option | Description | Selected | +|--------|-------------|----------| +| #06-01-3 改实现对齐文档 | `before` 返回 false 才放弃战斗 | ✓ | +| #06-05-3 补全 147 诊断 | 让 147 可达 | | +| #06-06-1 改发 128 | 越图分支发 128 | ✓ | +| #06-09-5 对齐 178 语义 | 178=多出的 key | (先澄清) | + +**User's choice:** #06-01-3 改实现对齐文档;#06-06-1 改发 128;对 178 提出「按照我的理解应该没有问题」。 +**Notes:** 已核实 core.ts:531-536 的方向反了;177(缺 key)与 178(多 key)当前重复,且既有 `:322` 用例把错误行为固化。 + +| Option | Description | Selected | +|--------|-------------|----------| +| 按文案改实现(178=多出的 key) | `loaded.difference(total)`,并更新 `:322` 用例 | ✓ | +| 保持实现,调整文案/合并 | 视为缺 key 语义 | | +| 我先说我的理解 | — | | + +**User's choice:** 按文案改实现(178=多出的 key) + +| Option | Description | Selected | +|--------|-------------|----------| +| 补全 147 触发路径 | 让 147 可达 | | +| 移除死分支 + 标注保留 | 标为保留未用码 | | +| 保持现状(登记已知死码) | 不改代码 | ✓ | + +**User's choice:** 「不可能触发不等于这个错误码没用,错误码关注的是语义错误,而不是有没有可能被触发,因此保留,什么都不要动,也不要标记死码」 + +| Option | Description | Selected | +|--------|-------------|----------| +| 保留 skip + 注释 | 147 为保留错误码、设计如此 | ✓ | +| 删除该用例 | 不再把 147 当可达码目标 | | +| 改为当前行为断言 | 断言 canEquipTo 返回 CannotEquip | | + +**User's choice:** 保留 skip + 注释 + +--- + +## 接口/接线缺口边界 + +| Option | Description | Selected | +|--------|-------------|----------| +| 本阶段接线(CoreState 注入) | AI 在 CoreState 注入 finder | | +| 客户端层注入,仅明确契约 | 不改 CoreState | | +| 我先给注入方案 | — | | + +**User's choice:**「我自己改这个」 +**Notes:** `#06-07-1` 由用户亲自修改;AI 不实现该接线。 + +| Option | Description | Selected | +|--------|-------------|----------| +| 改实现:接入复用映射 | createEnemy 走 internalGetPrefab | ✓ | +| 保持现状(设计如此) | createEnemy 只认真实 code/id | | + +**User's choice:** 改实现:接入复用映射 + +--- + +## 验证与提交节奏 + +| Option | Description | Selected | +|--------|-------------|----------| +| 沿用 D-44 文件级 | eslint 0 错误 + 文件级 vue-tsc 0 错误 + test:ci 全绿 | ✓ | +| 加严到数据端整包 | 额外要求四包 check:type/check:circular 全绿 | | + +**User's choice:** 沿用 D-44 文件级 + +| Option | Description | Selected | +|--------|-------------|----------| +| 按缺陷/根因原子提交 | 同根因合一个 commit | ✓ | +| 按系统提交 | 系统内多条一起 | | +| 单 commit | 整个 Phase 7 一个提交 | | + +**User's choice:** 按缺陷/根因原子提交 + +| Option | Description | Selected | +|--------|-------------|----------| +| 修复结清 + 其余 waive | windows fixed;设计如此/用户自改的 waive | ✓ | +| 全部清零 | 不留 open | | +| 暂不结清 | 由后续 ship 处理 | | + +**User's choice:** 修复结清 + 其余 waive + +--- + +## 修复方式 + +| Option | Description | Selected | +|--------|-------------|----------| +| 最小修复,不扩大变更面 | 只改缺陷相关实现 | | +| 允许必要内部重构 | 调整内部结构以真正修好 | | + +**User's choice:** 「每个计划开始执行前暂停并向我汇报修复方案,我确认后执行,若计划方案修复失败,不应自行探索其他方案,应退出本次修改并修订修复计划后重新执行」 +**Notes:** 用户以**执行节奏强约束**替代了单纯的最小/重构选择;具体修法留待逐计划汇报确认。 + +| Option | Description | Selected | +|--------|-------------|----------| +| 仅取消 skip 转绿 | 不额外新增用例 | ✓ | +| 取消 skip + 补边界用例 | 补组合/边界回归 | | + +**User's choice:** 仅取消 skip 转绿 + +| Option | Description | Selected | +|--------|-------------|----------| +| 同步更新文档与注释 | jsdoc/码表/契约文档与实现一致 | ✓ | +| 仅改代码 | 文档保持现状 | | + +**User's choice:** 同步更新文档与注释 + +--- + +## the agent's Discretion + +- 每条缺陷的具体修法(最小修复 vs 必要内部重构)、文件切分、用例命名、`#region` 划分由实现者决定,但必须按 D-09 在执行前汇报并获用户确认。 + +## Deferred Ideas + +- Phase 6 非数据端覆盖(渲染 / legacy)仍延后。 +- Phase 5(Legacy 移植)若改动数据端接口,本阶段需同步调整。