mirror of
https://github.com/motajs/template.git
synced 2026-09-26 04:30:16 +08:00
docs(04): plan TextureManager interface adaptation step 2 (04-09)
This commit is contained in:
parent
c225fbe100
commit
93ed3115fc
@ -181,8 +181,9 @@ Plans:
|
||||
3. 移动端(窄屏)布局下,同一场景正常显示且可操作
|
||||
4. 数据端与渲染端保持双端分离——数据端无 DOM,仍可在 Node 环境跑回放验证
|
||||
|
||||
**Plans**: 8/8 plans executed planned — 04-01..04-07 已执行(04-06 = material 接口影响范围清点·只读;04-07 = material 接口适应实施·第二步);**04-08(TextureManager 新接口影响范围清点·只读,D-38/D-39/D-40/D-41/D-42 第一步)已规划待执行**;渲染适配与移动端/桌面端双布局(REND-01/REND-02)整体仍未完成
|
||||
**Plans**: 8 已执行 + 1 已规划待执行(04-09) — 04-01..04-07 已执行(04-06 = material 接口影响范围清点·只读;04-07 = material 接口适应实施·第二步);04-08(TextureManager 新接口影响范围清点·只读,D-38/D-39/D-40/D-41/D-42 第一步)已执行;**04-09(TextureManager 新接口适应实施·第二步·代码改动,D-43..D-50)已规划待执行**(执行前须 Task 0 汇报关卡等待用户「可以执行」);渲染适配与移动端/桌面端双布局(REND-01/REND-02)整体仍未完成
|
||||
**Plan register note (2026-09-21):** 第五个增量 `04-05`(收口 `#04-01-M-06` / `#04-01-M-09`:状态栏 9 个数值属性改经 `client.hero.attribute.getFinalAttribute(...)` 读取 + 逐图层钩子类 `RendererLayerHook`,2026-09-20 执行)此前未登记进本路线图,本次一并补登;第六个增量 `04-06` = material 接口适应(D-30/D-31/D-32)**第一步·只读影响清点**,产出 `04-MATERIAL-INTERFACE-IMPACT.md`,第二步(实施)待用户审阅后另行规划。第七个增量 `04-07` = material 接口适应实施(**第二步·代码改动**,D-33..D-37),2026-09-22 已执行(10 文件原子提交)。**第八个增量 `04-08` = TextureManager 新接口适应(D-38..D-42)第一步·只读影响清点**,产出 `04-TEXTURE-INTERFACE-IMPACT.md`;第二步(实施)待用户审阅后另行规划。
|
||||
**Plan register note (2026-09-23):** 第九个增量 `04-09` = TextureManager 新接口适应**第二步(实施·代码改动)**(用户裁定 D-43..D-50:`renderWithoutCheck` 三处调用点改新 `render(tile, connection)`;`BlockCls` / `cls` 判定改为 `tileType === TileType.Autotile`、不做映射表;`extension/hero.ts` 勇士字面量填 `tileType: TileType.Unknown`;`MapRenderer` 不再自建 `AutotileProcessor` 而取 `manager.autotile`、保留 `readonly autotile` 字段与 `IMapRenderer` 签名;不改 `material/**` 与加载面;不考虑 legacy 兼容)。对象 = `packages-user/client-modules/src/render/map/{vertex.ts,renderer.ts,extension/hero.ts}` 的 **13 条** texture 归属 TS 诊断(vertex 6 / renderer 5 / hero 2),目标归零;`moving.ts` 与 `render/map/types.ts` 经核实无需改动。**已规划待执行**,执行前须 Task 0 汇报关卡等待用户「可以执行」;`REND-01` / `REND-02` 仍 Pending(本步仅为 REND-01 的 texture 子切片)。
|
||||
|
||||
Plans:
|
||||
**Wave 1**
|
||||
@ -214,6 +215,10 @@ Plans:
|
||||
|
||||
- [x] 04-08-PLAN.md — TextureManager 新接口影响范围清点(**只读**,D-38/D-39/D-40/D-41/D-42 第一步):以 `d36ea69`(`refactor: 贴图存储方式`)后的 `client-base/src/{types.ts,material/types.ts,material/manager.ts,material/autotile.ts,material/index.ts}` 为基准,清点 `packages-user` 消费者面对改名(`MaterialManager`→`TextureManager` 与构造器)、移除(`BlockCls` 枚举 / `IMaterialFramedData.cls`→`tileType` / `IAutotileProcessor` 三方法合一 / `renderAnimatedWith`→`renderAnimated` / `getIdentifierByAlias` / `getAliasByIdentifier` / `getBlockCls(ByAlias)` / `IClientBase.autotile` / `create()` 与 `createMaterial()`)与新增收紧(`tiles` / `autotile` / `tilesetReserve` / `tilesetUnit` / `getFrameCount` / 四个 `add*` 参数 / `flatten` / `AutotileType` / `IClientCoreConfig` 两个必填字段)的引用,按 A 符号改名与移除 / B 成员与签名变化 / C 地图渲染消费者定位索引 / D 被删且无替代(需用户反馈)/ E 加载相关与添加素材(仅报告,D-39/D-41)/ F 未确定 六类分组,每行精确到符号 + `file:line` 且 ≥2 锚点;产出 `04-TEXTURE-INTERFACE-IMPACT.md`,生产代码零改动(`material/` 按 D-42 只登记),第二步实施待用户审阅后另行规划
|
||||
|
||||
**Wave 8** *(blocked on Wave 7 completion)*
|
||||
|
||||
- [ ] 04-09-PLAN.md — TextureManager 新接口适应实施(**第二步·代码改动**,D-43..D-50):`renderWithoutCheck` 的三处调用点(`render/map/vertex.ts:461`、`render/map/vertex.ts:874`、`render/map/renderer.ts:1253`)改新 `render(tile, connection)` 且不保留跳过检查入口(D-43);自动元件判定与解构(`render/map/renderer.ts:1252` / `:1263`、`render/map/vertex.ts:517` / `:561` / `:872` 与 `:852`)改 `tileType === TileType.Autotile`,不做映射表、不用 `AutotileType` 分类(D-44);`render/map/extension/hero.ts:167` 填 `tileType: TileType.Unknown`(D-45,D-18 不排除该文件);`MapRenderer` 保留 `readonly autotile: IAutotileProcessor` 字段与 `IMapRenderer` 签名、构造器改取 `manager.autotile`、不再自建 `AutotileProcessor`(D-46);只做接口适应不重设计 `textures` / `tileStore` / `tiles`(D-47)、`material/**` 零改动(D-48)、不考虑 legacy 兼容(D-49)、`IBlockIdentifier` 零出现(D-50);`moving.ts` 与 `render/map/types.ts` 无需改动;门禁 = 三文件 texture 归属诊断 13→0 + eslint / prettier / CRLF / 符号零命中 / 基线与禁用路径;`autonomous: false`(Task 0 汇报关卡);`REND-01` / `REND-02` 仍 Pending
|
||||
|
||||
**UI hint**: yes
|
||||
|
||||
### Phase 5: Legacy 移植
|
||||
@ -407,7 +412,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7
|
||||
| 1. 事件系统 | 13/13 | In Progress| |
|
||||
| 2. 寻路系统 | 5/5 | In Progress| |
|
||||
| 3. 数据端完成 | 19/19 | Complete | 2026-09-12 |
|
||||
| 4. 渲染适配与双布局 | 8/8 | In Progress| |
|
||||
| 4. 渲染适配与双布局 | 8/9 | In Progress| |
|
||||
| 5. Legacy 移植 | 0/TBD | Not started | - |
|
||||
| 6. 单元测试 | 18/18 | In Progress| |
|
||||
| 7. 数据端缺陷修复 | 15/16 | 暂缓 (Deferred) | - |
|
||||
|
||||
@ -4,15 +4,15 @@ milestone: v1.0
|
||||
current_phase: 04
|
||||
current_phase_name: 渲染适配与双布局
|
||||
status: executing
|
||||
stopped_at: Completed 04-08-PLAN.md(TextureManager 新接口影响范围清点·只读:交付 04-TEXTURE-INTERFACE-IMPACT.md(11 节 / A13 B8 C8 D9 E7 F8 / 每行双 file:line 锚点);旧名 5 个源码面 0 引用;texture 归属错误 23 不变、总错误 263;生产代码零改动;REND-01/REND-02 保持 Pending,第二步未规划)
|
||||
last_updated: "2026-09-23T05:20:00.000Z"
|
||||
stopped_at: "Completed 04-08-PLAN.md(TextureManager 新接口影响范围清点·只读:交付 04-TEXTURE-INTERFACE-IMPACT.md(11 节 / A13 B8 C8 D9 E7 F8 / 每行双 file:line 锚点);旧名 5 个源码面 0 引用;texture 归属错误 23 不变、总错误 263;生产代码零改动;REND-01/REND-02 保持 Pending,第二步未规划)"
|
||||
last_updated: "2026-09-23T06:46:17.171Z"
|
||||
last_activity: 2026-09-23
|
||||
last_activity_desc: Completed 04-08-PLAN.md(TextureManager 新接口影响范围清点·只读)
|
||||
state_head: e47c34c6b0152217d4f20630d89c5297b5336e80
|
||||
last_activity_desc: Planned 04-09-PLAN.md(TextureManager 新接口适应·第二步;通过 checker)
|
||||
state_head: c225fbe100c71247e4de9d0bff103cad2fabc773
|
||||
progress:
|
||||
total_phases: 7
|
||||
completed_phases: 1
|
||||
total_plans: 79
|
||||
total_plans: 80
|
||||
completed_plans: 78
|
||||
milestone_name: milestone
|
||||
---
|
||||
@ -28,10 +28,10 @@ See: .planning/PROJECT.md (updated 2026-09-17)
|
||||
|
||||
## Current Position
|
||||
|
||||
Phase: 04 (渲染适配与双布局) — IN PROGRESS
|
||||
Plan: 8 of 8
|
||||
Status: 04-08 完成(TextureManager 新接口影响范围只读清点);Phase 4 整体未完成 — REND-01/REND-02 仍 Pending,第二步(texture 接口适应实施)待用户审阅后另行规划
|
||||
Last activity: 2026-09-23 — Completed 04-08-PLAN.md(TextureManager 新接口影响范围清点·只读)
|
||||
Phase: 04 (渲染适配与双布局) — READY TO EXECUTE
|
||||
Plan: 8/9 已执行;04-09(TextureManager 新接口适应·第二步)已规划待执行(Wave 8)
|
||||
Status: 04-09 已规划并通过 checker(0 blocker / 0 warning / 3 info-advisory);待用户回复「可以执行」后执行;Phase 4 整体仍未完成 — REND-01/REND-02 保持 Pending
|
||||
Last activity: 2026-09-23 — Planned 04-09-PLAN.md(TextureManager 新接口适应·第二步)
|
||||
|
||||
Progress: [█████░░░░░] 50%
|
||||
|
||||
|
||||
404
.planning/phases/04-render-adaptation/04-09-PLAN.md
Normal file
404
.planning/phases/04-render-adaptation/04-09-PLAN.md
Normal file
@ -0,0 +1,404 @@
|
||||
---
|
||||
phase: 04-render-adaptation
|
||||
plan: 9
|
||||
type: execute
|
||||
wave: 8
|
||||
depends_on:
|
||||
- 04-01
|
||||
- 04-02
|
||||
- 04-03
|
||||
- 04-04
|
||||
- 04-05
|
||||
- 04-06
|
||||
- 04-07
|
||||
- 04-08
|
||||
files_modified:
|
||||
- packages-user/client-modules/src/render/map/vertex.ts
|
||||
- packages-user/client-modules/src/render/map/renderer.ts
|
||||
- packages-user/client-modules/src/render/map/extension/hero.ts
|
||||
autonomous: false
|
||||
requirements:
|
||||
- REND-01
|
||||
- REND-02
|
||||
estimate:
|
||||
tokens: 52000
|
||||
raw_tokens: 52000
|
||||
tasks: 4
|
||||
confidence: low
|
||||
must_haves:
|
||||
truths:
|
||||
- "**本计划的第一个 block 点是 Task 0 的 `blocking-human` 汇报关卡(AGENTS.md 硬要求)**:Task 0 必须先向用户汇报「要解决的问题(`d36ea69` 重写贴图存储层后,地图渲染端 13 条 texture 归属 TS 错误未跟上新接口)、大致解决方案(按 D-43..D-50 逐条把消费者改成新接口;对象仅 `render/map/{vertex,renderer,extension/hero}.ts`)、逐条裁定编码、验证方式与范围禁令」,并**同时呈报命名审批结论**(本计划不新增、不改名任何公共 / 受保护 / 私有成员或字段),然后必须**停下等待**用户明确回复「可以执行」四个字;收到前不得执行任何任务、不得派发任何执行子代理。无论触发方式(`/gsd-execute-phase`、`/gsd-manager`、`/gsd-autonomous`、子代理 / 执行器派发)或配置(`mode: yolo`、`workflow.auto_advance`)如何,均不得自动放行。"
|
||||
- "**范围内自动元件渲染不再经过被删除的「跳过检查」入口,三处调用点全部改调新 `render(tile, connection)`,且不保留、不新增任何「跳过检查」入口(D-43 精确落地)** —— 三处 = `render/map/vertex.ts:461`(`updateAutotile`,`autotile.render(tile, connection)`)、`render/map/vertex.ts:874`(`updateMoving` 动态自动元件分支,`this.renderer.autotile.render(block.texture, 0b0000_0000)`)、`render/map/renderer.ts:1253`(`useTileBackground` 单帧分支,`this.autotile.render(tex, 0b1111_1111)!`);除方法名外调用形态、实参与非空断言一律保持不变。"
|
||||
- "**范围内自动元件判定不再依赖旧 `BlockCls`,统一由 `tileType === TileType.Autotile`(`TileType` 来自 `@user/data-common`)决定,且不出现 `BlockCls`→`TileType` 映射、不用 `AutotileType` 做布局分类(D-44 精确落地)** —— 五处判定 = `render/map/renderer.ts:1252`、`render/map/renderer.ts:1263`、`render/map/vertex.ts:517`、`render/map/vertex.ts:561`、`render/map/vertex.ts:872`;`render/map/vertex.ts:852` 的对象解构键 `cls` 同步改为 `tileType`(仍为多键解构,符合 dev.md 解构规范)。"
|
||||
- "**勇士贴图字面量不再携带旧 `cls` 成员,改以 `tileType: TileType.Unknown` 构造,其 `BlockCls` import 移除、`TileType` 并入既有的 `@user/data-common` 导入块(D-45 精确落地)** —— 落点 `render/map/extension/hero.ts:167`;该文件是本步工作项(D-18 的排除只针对数据层 `HeroRendering`,不覆盖渲染端 `extension/hero.ts`)。"
|
||||
- "**`MapRenderer` 不再自建自动元件处理器,其 `autotile` 直接取自 `manager.autotile`,字段声明与接口签名一字不变(D-46 精确落地)** —— `render/map/renderer.ts:234` 的自建构造调用改为 `this.autotile = manager.autotile;`,`AutotileProcessor` import 随之移除(该 import 已无使用点);`render/map/renderer.ts:71` 的 `readonly autotile: IAutotileProcessor` 逐字保留、`render/map/types.ts:334` 的 `IMapRenderer.autotile` 与 `render/map/types.ts:329` 的 `manager: ITextureManager` 一字不动。"
|
||||
- "**改动边界未被扩大:范围外零改动、不新增 legacy 兼容相关内容、被删标识符零出现(D-47 / D-48 / D-49 / D-50 硬边界全部满足)** —— 不重新设计 `textures` / `tileStore` / `tiles` 的职责边界(地图背景继续走现有 `manager.getTile`,`ITextureGetter` 不变);`packages-user/client-base/src/material/` 下零改动;加载面(`client-modules/src/fallback/load.ts`、`client-base/src/load/**`)零改动;不添加任何 legacy 兼容相关任务、约束或验收项;`IBlockIdentifier` 在 `render/map/**` 内零出现。`packages/` 与 `src/` 零改动。"
|
||||
- "**目标达成:三份范围内文件上 texture 归属 TS 诊断由 13 条归零**(vertex 6 + renderer 5 + hero 2 = 13),且不新增任何范围内诊断;`vue-tsc` 全仓错误总行数不因本计划上升(范围内 3 文件诊断数 = 0);`eslint`、`prettier --check`、CRLF 三文件全绿。"
|
||||
- "**项目硬规则满足**:不修改任何既有 jsDoc / 注释文本;不新增注释中的低价值内容;不新增公共 / 受保护 / 私有成员或字段(Task 0 已呈报「无新命名」并获得批准);全部为普通 import(无 `import type`);import 仍集中在文件首部连续块、无注释 / 空行插入;不新增依赖、不动 `package.json` / `pnpm-lock.yaml` / `tsconfig.json`;`moving.ts` 与 `render/map/types.ts` 经核实无需改动(二者不含 `cls` 读写,仅承载类型面)。"
|
||||
- "**只读基线以「状态零漂移 + 目标内容已变」方式断言,判据与提交状态无关**:Task 1 起始把 `git status --porcelain -- packages packages-user src` 与三份目标文件的内容 SHA-256 原样落盘到临时目录(`%TEMP%/opencode/04-09-baseline.txt` / `%TEMP%/opencode/04-09-baseline-hashes.txt`,均不在仓库内),Task 3 断言 ① 三份目标文件当前内容哈希均不同于基线(即确已被本计划改动,无论是否已被每任务提交协议提交),② 当前 `git status` 相对该基线除三份目标文件外无新增 / 消失 / 状态变化;用户对数据包的并发改动一律不被回滚 / 暂存 / 提交 / 修改。"
|
||||
artifacts:
|
||||
- path: packages-user/client-modules/src/render/map/vertex.ts
|
||||
provides: "自动元件顶点生成器消费新接口:`updateAutotile` / `updateMoving` 改调 `IAutotileProcessor.render`;`checkAutotileConnectionAround` / `updateVertexArray` / `updateMoving` 的自动元件判定改走 `tileType === TileType.Autotile`;`BlockCls` import 移除、`TileType` 从 `@user/data-common` 引入"
|
||||
- path: packages-user/client-modules/src/render/map/renderer.ts
|
||||
provides: "`MapRenderer` 组合根:`readonly autotile: IAutotileProcessor` 字段保留并从 `manager.autotile` 赋值(D-46);`useTileBackground` 的背景自动元件分支改走 `render` + `tileType`;`AutotileProcessor` / `BlockCls` import 移除、`TileType` 引入"
|
||||
- path: packages-user/client-modules/src/render/map/extension/hero.ts
|
||||
provides: "勇士贴图 `IMaterialFramedData` 字面量以 `tileType: TileType.Unknown` 构造(D-45);`BlockCls` import 移除、`TileType` 并入既有 `@user/data-common` 导入块"
|
||||
- path: .planning/phases/04-render-adaptation/04-09-SUMMARY.md
|
||||
provides: "本增量的执行簿记:逐条 D-43..D-50 落点、三文件诊断 13→0 的门禁输出、并发基线保持证据、无新命名声明、REND-01 / REND-02 仍 Pending 的声明"
|
||||
key_links:
|
||||
- "`packages-user/client-base/src/material/types.ts:148-151`(`IAutotileProcessor.render(tile: IMaterialFramedData, connection: number): ITextureRenderable | null`)↔ 三处调用点 `packages-user/client-modules/src/render/map/vertex.ts:461`、`render/map/vertex.ts:874`、`render/map/renderer.ts:1253`(原 `renderWithoutCheck` 调用全部改 `render`,D-43)"
|
||||
- "`packages-user/client-base/src/material/types.ts:79`(`IMaterialFramedData.tileType: TileType`)与 `packages-user/data-common/src/store/types.ts:6-25`(`TileType.Autotile`)↔ 五处判定 `render/map/renderer.ts:1252`、`render/map/renderer.ts:1263`、`render/map/vertex.ts:517`、`render/map/vertex.ts:561`、`render/map/vertex.ts:872` 与一处解构 `render/map/vertex.ts:852`(D-44)"
|
||||
- "`packages-user/client-base/src/material/manager.ts:38` + `:90`(`TextureManager` 持有 `readonly autotile` 并在构造器内 `new AutotileProcessor(state)`)↔ `packages-user/client-modules/src/render/map/renderer.ts:71`(`readonly autotile: IAutotileProcessor` 保留)与 `:234`(改为 `manager.autotile`)↔ `packages-user/client-modules/src/render/map/types.ts:334`(`IMapRenderer.autotile` 签名不变)(D-46)"
|
||||
- "`packages-user/client-modules/src/render/map/extension/hero.ts:164-170`(勇士贴图字面量)↔ `packages-user/client-modules/src/render/map/moving.ts:31` / `render/map/types.ts:204`(`IMaterialFramedData` 经 `IMovingBlock.texture` 流向 `vertex.ts:852` 的解构)(D-45 + 类型面)"
|
||||
- "`git status --porcelain -- packages packages-user src` 状态基线 + 三份目标文件的内容 SHA-256 基线(Task 1 (0a)/(0b) 落盘,均在仓库外)↔ Task 3 的「状态零漂移 + 目标内容已变」断言(与每任务提交协议是否已提交无关)↔ 用户数据包改动零触碰证据"
|
||||
- "`pnpm exec vue-tsc --noEmit` 的范围内三文件诊断数(Task 1 记录 13,Task 2 后应为 0)↔ Task 3 的范围内归零门禁 ↔ REND-01 texture 子切片完成证据(REND-01 / REND-02 仍 Pending)"
|
||||
assumptions:
|
||||
- "**FLAGGED ASSUMPTION(specless fallback)— REND-01 edge unresolved:** REND-01(渲染端适配新数据层接口)的整体验收边界未提供;本计划只完成其 texture 子切片,不发明整体阈值。"
|
||||
- "**FLAGGED ASSUMPTION(specless fallback)— REND-02 edge unresolved:** REND-02(移动端与桌面端双布局)验收边界未提供;本计划不涉及双布局,也不发明其阈值。"
|
||||
- "**无运行时渲染验证可得(诚实降级):** 仓库渲染端无运行时测试设施(04-07 已如实声明)。本计划的端到端可运行门禁为「范围内 TS 诊断归零 + eslint + prettier + CRLF + 符号零命中 + 基线增量」的静态组合,配合人工复核;**不得**以任何无法运行的运行时门禁冒充通过,也不得新增测试文件。"
|
||||
- "**并发基线可能非空:** 用户持续手工改数据端(`data-base` / `data-common` / `data-system`),Task 1 起始的 `git status --porcelain -- packages packages-user src` 可能非空;本计划一律以当日实测为基线,**不回滚 / 不暂存 / 不提交 / 不修改**用户任何改动;断言只要求基线之外恰好新增三份目标文件。"
|
||||
- "**行号以当日实测为准:** 本计划引用的 `file:line` 为规划日(2026-09-23,HEAD `c225fbe`,工作树干净)实测锚点;执行时若偏移,按符号名定位(`renderWithoutCheck`、`cls`、`BlockCls`、`AutotileProcessor`、`tileType`)并在 SUMMARY 记录实际行号。"
|
||||
prohibitions:
|
||||
- "不得在用户明确回复「可以执行」四个字之前执行本计划任何任务或派发任何执行子代理(AGENTS.md 第一个 block 点;不因触发方式或 `yolo` / `auto_advance` 放宽)。"
|
||||
- "不得修改 `packages-user/client-base/src/material/` 下任何内容(D-42 / D-48);不得修改 `packages-user/client-base/src/types.ts`、`packages-user/client-modules/src/{client.ts,core.ts,types.ts}`。"
|
||||
- "不得修改加载面:`packages-user/client-modules/src/fallback/load.ts`、`packages-user/client-base/src/load/**`(D-39 / D-41),其既有诊断(含 9 条 TS2554)一律只报告、不修复。"
|
||||
- "不得修改 `packages/**`、`src/**`(D-33 / D-32 沿用);不得试图追平仓库既有无关类型错误。"
|
||||
- "不得引入 legacy 兼容改动,也不得把「是否破坏 legacy 插件面」写成任务、约束或验收项(D-49;对应 04-08 台账 `#04-08-D-08` / `#04-08-F-07` 作废)。"
|
||||
- "不得使用 `IBlockIdentifier`,也不得为其保留兼容分支(D-50);`render/map/**` 内该标识符必须零出现。"
|
||||
- "不得新建 `BlockCls` → `TileType` 的映射表,也不用 `AutotileType` 做自动元件布局分类(D-44)。"
|
||||
- "不得保留或新增「跳过检查」入口;三处调用点一律用 `render`(D-43)。"
|
||||
- "不得新增 / 改名任何公共 / 受保护 / 私有成员、字段或方法名;不得新增依赖;不得修改 `package.json` / `pnpm-lock.yaml` / `tsconfig.json`。"
|
||||
- "不得修改任何既有 jsDoc / 注释文本;不得新增 `// @ts-expect-error`,不得删除既有 `// @ts-expect-error`(`hero.ts` 的既有标注逐字保留)。"
|
||||
- "不得改写 / 覆盖 / 改号 `04-01`..`04-08` 的既有 `*-PLAN.md` 与 `*-SUMMARY.md`。"
|
||||
- "不得新增、删除或修改任何测试文件;不得把 `moving.ts` / `render/map/types.ts` 列入改动(经核实无需改动)。"
|
||||
- "每条 `<automated>` 必须紧跟 `<fails_when>`;无法运行的运行时门禁必须显式声明不可得并降级,不得伪造绿。"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Phase 4 第九个增量(用户裁定 2026-09-23 · D-43..D-50 **第二步·实施**)—— **TextureManager 新接口适应实施(代码改动)**。
|
||||
|
||||
**要解决的问题:** 用户以 `d36ea69 refactor: 贴图存储方式` 重写了贴图存储层,`04-TEXTURE-INTERFACE-IMPACT.md`(04-08 只读清点)确认地图渲染端仍有 **13 条** texture 归属 TS 诊断未跟上新接口(`render/map/vertex.ts` 6 条、`render/map/renderer.ts` 5 条、`render/map/extension/hero.ts` 2 条);同时台账 D 类 / F 类的未决项已由用户逐条裁定(D-43..D-50),本步即为按裁定落地的实施。
|
||||
|
||||
**大致解决方案:** 仅改三份地图渲染文件,按裁定做四类替换 —— ① `renderWithoutCheck` 的三处调用点改用新 `render(tile, connection)`(D-43);② `BlockCls` / `cls` 的判定与解构改用 `tileType === TileType.Autotile`(`TileType` 来自 `@user/data-common`,D-44);③ `hero.ts:167` 的勇士贴图字面量填 `tileType: TileType.Unknown`(D-45);④ `MapRenderer` 自建 `AutotileProcessor` 改为从 `manager.autotile` 取值(`AutotileProcessor` import 随之移除),`readonly autotile` 字段与 `IMapRenderer` 签名不变(D-46)。`moving.ts` / `render/map/types.ts` 经核实不含 `cls` 读写、无需改动;`material/`、加载面、`packages/`、`src/` 一律零改动(D-39 / D-41 / D-42 / D-48)。
|
||||
|
||||
**逐条裁定编码(本步的验收锚点):**
|
||||
|
||||
| 裁定 | 落点 | 要求 |
|
||||
|---|---|---|
|
||||
| D-43 | `render/map/vertex.ts:461`、`render/map/vertex.ts:874`、`render/map/renderer.ts:1253` | 改调 `render(tile, connection)`;不得保留 / 新增「跳过检查」入口 |
|
||||
| D-44 | `render/map/renderer.ts:1252`、`:1263`、`render/map/vertex.ts:517`、`:561`、`:872`(判定)与 `render/map/vertex.ts:852`(解构键) | `tileType === TileType.Autotile`;不做映射表;`AutotileType` 不参与分类 |
|
||||
| D-45 | `render/map/extension/hero.ts:167` | `tileType: TileType.Unknown`;该文件在范围内 |
|
||||
| D-46 | `render/map/renderer.ts:71`(保留字段)、`:234`(改 `manager.autotile`)、`render/map/types.ts:334`(签名不动) | 不再自建处理器 |
|
||||
| D-47 | 地图背景 `manager.getTile` 路径 | 只做接口适应,不重设计 `textures` / `tileStore` / `tiles` |
|
||||
| D-48 | `packages-user/client-base/src/material/**` | AI 零改动(写入侧归用户加载系统) |
|
||||
| D-49 | 全计划 | 不考虑 legacy 兼容,不设相关任务 / 约束 / 验收项 |
|
||||
| D-50 | `render/map/**` | `IBlockIdentifier` 零出现;其消费点属加载面、归用户 |
|
||||
|
||||
**目标:** 三份文件上 13 条 texture 归属诊断归零(`vue-tsc` 范围内 3 文件诊断数 = 0),`eslint` / `prettier --check` / CRLF 全绿;`REND-01` / `REND-02` 保持 **Pending**(本步仅为 REND-01 的 texture 子切片)。
|
||||
|
||||
**第一步是强制汇报关卡(AGENTS.md):** 本计划以 `checkpoint:decision` + `gate="blocking-human"` 的 Task 0 开头,`autonomous: false`;未收到用户「可以执行」四个字前不得执行任何步骤。
|
||||
|
||||
## Source Audit(多源覆盖审计)
|
||||
|
||||
| SOURCE | ID | Feature/Requirement | Plan | Status | Notes |
|
||||
|--------|----|---------------------|------|--------|-------|
|
||||
| GOAL | — | Phase 4:「渲染端通过新数据层接口驱动,并同时支持移动端与桌面端布局」 | 04-09 | COVERED(增量·texture 实施子切片) | 只闭合地图渲染的 texture 接口适配;双布局属后续增量(见 assumptions) |
|
||||
| REQ | REND-01 | 渲染端适配新数据层接口 | 04-09 | COVERED(子切片;需求保持 Pending) | texture / 素材接口是渲染端素材公共面;本步只做地图渲染消费者适配;整体验收边界未提供 → FLAGGED ASSUMPTION |
|
||||
| REQ | REND-02 | 渲染端同时支持移动端与桌面端布局 | 04-09 | COVERED(不涉及) | 本步不含双布局;验收边界未提供 → FLAGGED ASSUMPTION |
|
||||
| RESEARCH | — | (本阶段无 `04-RESEARCH.md`) | — | N/A | 等价输入 = `04-TEXTURE-INTERFACE-IMPACT.md`(A13/B8/C8/D9/E7/F8)与 `d36ea69` 接口基准 |
|
||||
| CONTEXT | D-43 | `renderWithoutCheck` 的替代 = 直接用新 `render(tile, connection)`,3 处调用点全改 | 04-09 | COVERED | Task 1(1 处)+ Task 2(2 处),逐处双锚点门禁 |
|
||||
| CONTEXT | D-44 | `BlockCls` 的替代 = `TileType`;判定走 `tileType === TileType.Autotile`;不做映射表 | 04-09 | COVERED | Task 1(动态路径 1 解构 + 1 判定)+ Task 2(4 处判定 + import 清理) |
|
||||
| CONTEXT | D-45 | `extension/hero.ts:167` 用 `tileType: TileType.Unknown`;D-18 不排除该文件 | 04-09 | COVERED | Task 1 |
|
||||
| CONTEXT | D-46 | `MapRenderer` 不再自建 `AutotileProcessor`;保留字段签名,构造器取 `manager.autotile` | 04-09 | COVERED | Task 1 |
|
||||
| CONTEXT | D-47 | `textures` / `tileStore` / `tiles` 职责边界不在本步;背景继续 `manager.getTile` | 04-09 | COVERED(边界) | 无任务改动背景取值路径 |
|
||||
| CONTEXT | D-48 | `material/` 零改动,写入侧归用户 | 04-09 | COVERED(禁止) | prohibitions + forbidden-path 门禁 |
|
||||
| CONTEXT | D-49 | 不考虑 legacy 兼容 | 04-09 | COVERED(禁止) | prohibitions 明列;无相关任务 / 约束 / 验收项 |
|
||||
| CONTEXT | D-50 | `IBlockIdentifier` 用法删除;本步范围内不得出现 | 04-09 | COVERED | 符号零命中门禁含该标识符;消费点 `fallback/load.ts` 属加载面不纳入 |
|
||||
| CONTEXT | D-33 | 范围外一律不改;不追求解决全部类型错误 | 04-09 | COVERED(边界) | forbidden-path 门禁 + 只断言范围内 3 文件 |
|
||||
| CONTEXT | D-23 | 不使用 `client` / `state` 全局单例(仅约束新增 / 后续) | 04-09 | COVERED | 本步零新增代码;`state` 注入不属本步;不因存量单例阻塞 |
|
||||
| CONTEXT | D-01..D-22, D-24..D-42 | 前序决策与已执行增量 | 04-01..04-08 | COVERED(前序计划) | `04-TEXTURE-INTERFACE-IMPACT.md` 是本步的权威输入 |
|
||||
| CONTEXT | Deferred Ideas | 阶段 4 后续步骤(双布局实现);`packages` 全部、`entry-client`、`legacy-plugin-*`、`data-fallback` | — | DEFERRED | 未写入任何任务 |
|
||||
| AUDIT | #04-08-C-01/C-02/C-03 | 地图渲染三文件定位索引(texture 归属 13 条) | 04-09 | COVERED | Task 1/2 逐处落地;C-04/C-05 经核实无需改动 |
|
||||
|
||||
## Estimate Basis(估算依据)
|
||||
|
||||
`estimate-calibration` 无历史样本(`factor: 1`、`confidence: low`),故 `tokens == raw_tokens` 并如实标注 `confidence: low`。按执行者实际触及量估算:Task 0 只读汇报并等待确认(约 4k);Task 1(tracer)三文件共 8 处编辑 + 首次 `vue-tsc` 全量(约 1–3 分钟)+ 基线落盘(约 20k);Task 2 两文件剩余 8 处编辑与 import 清理(约 15k);Task 3 六道门禁重跑 + 人工复核 + `04-09-SUMMARY.md` 落盘提交(约 10k);固定开销约 3k;合计约 52k。
|
||||
|
||||
</objective>
|
||||
<execution_context>
|
||||
@C:/Users/13194/.config/opencode/gsd-core/workflows/execute-plan.md
|
||||
@C:/Users/13194/.config/opencode/gsd-core/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/STATE.md
|
||||
@.planning/REQUIREMENTS.md
|
||||
@.planning/phases/04-render-adaptation/04-CONTEXT.md
|
||||
@.planning/phases/04-render-adaptation/04-TEXTURE-INTERFACE-IMPACT.md
|
||||
@.planning/phases/04-render-adaptation/04-08-SUMMARY.md
|
||||
@.planning/phases/04-render-adaptation/04-07-PLAN.md
|
||||
@AGENTS.md
|
||||
@dev.md
|
||||
</context>
|
||||
|
||||
## Artifacts this phase produces
|
||||
|
||||
| Artifact | Path | Purpose |
|
||||
|---|---|---|
|
||||
| 自动元件顶点生成器(改) | `packages-user/client-modules/src/render/map/vertex.ts` | 消费 `IAutotileProcessor.render` 与 `TileType.Autotile`;移除 `BlockCls` import,引入 `TileType` |
|
||||
| 地图渲染器组合根(改) | `packages-user/client-modules/src/render/map/renderer.ts` | `autotile` 取自 `manager.autotile`(D-46);背景自动元件分支改 `render` + `tileType`;import 清理 |
|
||||
| 勇士渲染扩展(改) | `packages-user/client-modules/src/render/map/extension/hero.ts` | 贴图字面量填 `tileType: TileType.Unknown`(D-45);import 清理 |
|
||||
| 执行簿记(新) | `.planning/phases/04-render-adaptation/04-09-SUMMARY.md` | 逐条裁定落点、13→0 门禁输出、基线保持证据、无新命名声明 |
|
||||
| 路线图登记(改) | `.planning/ROADMAP.md` | Phase 4 Wave 8 的 `04-09-PLAN.md` 条目与登记说明 |
|
||||
| 本计划(新) | `.planning/phases/04-render-adaptation/04-09-PLAN.md` | 本文件 |
|
||||
|
||||
<!-- planner-discipline-allow: BlockCls -->
|
||||
<!-- planner-discipline-allow: renderWithoutCheck -->
|
||||
<!-- planner-discipline-allow: IBlockIdentifier -->
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="checkpoint:decision" gate="blocking-human">
|
||||
<name>Task 0: 预执行汇报关卡 —— 汇报 TextureManager 新接口适应实施(D-43..D-50)的对象、逐条裁定编码、四类替换方案与命名审批结论,等待用户回复「可以执行」</name>
|
||||
<precondition>用户裁定 D-43..D-50 已写入 `.planning/phases/04-render-adaptation/04-CONTEXT.md`(以文件内实际存在该区间为准);`d36ea69` 是当日 HEAD 的祖先(`git merge-base --is-ancestor d36ea69 HEAD` 退出码 0);`04-TEXTURE-INTERFACE-IMPACT.md` 存在且含 A/B/C/D/E/F 六类台账</precondition>
|
||||
<files>(只读汇报,不修改任何文件)</files>
|
||||
<read_first>
|
||||
- AGENTS.md(第一个 block 点必须汇报并等待;只有「可以执行」四个字后才允许执行;命名必须先反馈;发现问题须经确认)
|
||||
- .planning/phases/04-render-adaptation/04-CONTEXT.md(D-43..D-50 裁定原文;D-33 / D-42 / D-23)
|
||||
- .planning/phases/04-render-adaptation/04-TEXTURE-INTERFACE-IMPACT.md(A13/B8/C8/D9/E7/F8;D 类 3 处调用点与 `material/utils.ts` 用户自有面;E 类加载面;F 类未决项)
|
||||
- .planning/phases/04-render-adaptation/04-09-PLAN.md(本计划全文:objective 的裁定编码表、tasks、禁令、门禁)
|
||||
- packages-user/client-base/src/material/types.ts:75-86,148-151(`IMaterialFramedData.tileType`;`IAutotileProcessor.render`)
|
||||
- packages-user/client-base/src/material/manager.ts:37-94(`TextureManager.autotile` 与构造器赋值)
|
||||
- packages-user/data-common/src/store/types.ts:6-25(`TileType.Autotile`)
|
||||
- packages-user/client-modules/src/render/map/renderer.ts:8-15,71,234,1243-1271(待改点)
|
||||
- packages-user/client-modules/src/render/map/vertex.ts:24-29,446-479,510-528,537-582,846-913(待改点)
|
||||
- packages-user/client-modules/src/render/map/extension/hero.ts:1-19,144-173(待改点)
|
||||
- dev.md(「无类型导入」「引入位置」「命名规则」「换行使用 CRLF」)
|
||||
</read_first>
|
||||
<action>
|
||||
**停下并向用户汇报,等待明确回复后才继续;汇报本身只读,不写任何文件、不改任何代码、不派发子代理。**
|
||||
|
||||
① **要解决的问题**:`d36ea69` 重写贴图存储层后,地图渲染端 13 条 texture 归属 TS 诊断未跟上新接口(`render/map/vertex.ts` 6 条、`render/map/renderer.ts` 5 条、`render/map/extension/hero.ts` 2 条)。04-08 只读台账的 D 类 / F 类未决项已由用户逐条裁定为 D-43..D-50,本步按裁定落地。
|
||||
|
||||
② **逐条裁定编码(须原样汇报 objective 的编码表)**:D-43(三处调用点改 `render(tile, connection)`,不保留跳过检查入口);D-44(五处判定与一处解构改 `tileType === TileType.Autotile`,不做映射表、不用 `AutotileType` 分类);D-45(`extension/hero.ts:167` 填 `tileType: TileType.Unknown`,该文件在范围内);D-46(`MapRenderer` 保留 `readonly autotile` 字段与 `IMapRenderer` 签名,构造器改取 `manager.autotile`,不再自建处理器);D-47(不重设计 `textures` / `tileStore` / `tiles`,背景继续 `manager.getTile`);D-48(`material/` 零改动);D-49(不考虑 legacy 兼容,相关顾虑作废);D-50(`IBlockIdentifier` 零出现,其消费点属加载面归用户)。
|
||||
|
||||
③ **大致解决方案与对象**:只改 `packages-user/client-modules/src/render/map/vertex.ts`、`render/map/renderer.ts`、`render/map/extension/hero.ts` 三份文件,做四类替换(方法名 `render`、判定 / 解构 `tileType`、勇士字面量 `tileType: TileType.Unknown`、`manager.autotile` 取值),并清理随之失去使用点的 `BlockCls` / `AutotileProcessor` import、在需要处引入 `TileType`(`@user/data-common`)。**`renderer.ts` 的 `AutotileProcessor` import 必须与 `:234` 的替换在同一步内完成**(替换后该 import 再无使用点,而 eslint 的 `@typescript-eslint/no-unused-vars` 为 `error`,留着必然使该步 eslint 门禁失败);`BlockCls` import 则在其各自文件最后一次使用被替换掉时同步移除。经核实 `render/map/moving.ts` 与 `render/map/types.ts` 不含 `cls` 读写,**无需改动**,不列入改动清单。
|
||||
|
||||
④ **明确不做的事(须原样告知)**:不改 `material/**`、不改加载面(`fallback/load.ts`、`client-base/src/load/**`)、不改 `packages/**` 与 `src/**`、不追平仓库既有无关类型错误、不加 legacy 兼容、不加 / 删 `// @ts-expect-error`、不改任何既有 jsDoc / 注释、不新增依赖、不动 `package.json` / `pnpm-lock.yaml` / `tsconfig.json`、不新增或修改测试、不新增 / 改名任何成员或字段;**范围外已知余留(只报告、不修改)**:`packages-user/client-modules/src/client.ts:14` 的 `IAutotileProcessor` 与 `:16` 的 `AutotileProcessor` 是 `d36ea69` 删除 `IClientBase.autotile` 后遗留的孤立未使用 import,属 D-33 范围外,本计划不改动,仅在 `04-09-SUMMARY.md` 如实记录。
|
||||
|
||||
⑤ **命名审批(AGENTS.md 要求,须明确呈报并请求批准)**:本计划**不新增、不改名任何公共 / 受保护 / 私有成员、字段或方法名**;唯一的标识符变化是 `vertex.ts` 内一处**局部对象解构绑定**由 `cls` 改为 `tileType`(绑定名取自既有接口成员 `IMaterialFramedData.tileType`,非新命名),以及引入既有枚举 `TileType`。请用户确认该结论;若用户要求任何命名调整,按 ⑧ 退出修订。
|
||||
|
||||
⑥ **验证方式(须原样告知)**:`pnpm exec vue-tsc --noEmit`(断言三份范围内文件诊断数 = 0,规划日 13 条);`pnpm exec eslint <三文件>`;`pnpm exec prettier --check <三文件>`;CRLF 三文件门禁;`git grep` 符号零命中(`render/map/**` 内 `BlockCls`、`renderWithoutCheck`、`IBlockIdentifier` 均 0);基线门禁 = 状态零漂移 + 三份目标文件内容哈希已变(**与每任务提交协议是否已提交无关**)+ 禁用路径零改动;人工复核。**渲染端无运行时测试设施,运行时 UAT 不可得**,如实声明,不以无法运行的门禁冒充通过。
|
||||
|
||||
⑦ **编号与 wave(须原样告知)**:本计划为 **04-09**(第九个增量),`wave: 8`,`depends_on` 列 `04-01`..`04-08`;phase 目录内既有 `04-01`..`04-08` 的 `*-PLAN.md` 与 `*-SUMMARY.md` 一律不得改写 / 覆盖 / 改号。
|
||||
|
||||
⑧ **关卡性质与失败语义(须原样告知)**:无论触发方式或配置模式(`mode: yolo`、`workflow.auto_advance`)如何,执行者 / 子代理都必须在此停下并等待用户明确回复「可以执行」四个字;未收到即继续、或回复其它内容(含修订意见、沉默、自动模式推进、子代理自行放行),一律视为未通过本关卡,必须立即停止、保持只读、不写任何文件。若用户给出修订意见(不同意替换范围 / 命名结论 / 裁定编码),退出本计划、修订 `04-09-PLAN.md` 后重新汇报,不得自行改道执行。
|
||||
</action>
|
||||
<decision>是否按本计划开始执行 TextureManager 新接口适应实施(对象 = `render/map/{vertex,renderer,extension/hero}.ts`;按 D-43..D-50 做四类替换;`material/`、加载面、`packages/`、`src/` 零改动;不新增 / 改命名;`autonomous: false`)</decision>
|
||||
<context>AGENTS.md 要求任何计划的第一个 block 点必须是向用户汇报并等待确认;本次涉及接口适应与局部绑定调整,须先确认命名结论无新命名。`.planning/config.json` 的 `mode: yolo` 会使执行默认自动推进,故必须显式置 `blocking-human` 且 `autonomous: false`。</context>
|
||||
<options>
|
||||
<option id="execute">
|
||||
<name>可以执行</name>
|
||||
<pros>按本计划落地四类替换,三文件 texture 归属诊断 13→0;无新命名;范围与禁令明确</pros>
|
||||
<cons>无(改动集中于三份渲染文件,可编译 / lint / 静态门禁验证)</cons>
|
||||
</option>
|
||||
<option id="revise">
|
||||
<name>修订裁定编码 / 范围 / 命名结论后再执行</name>
|
||||
<pros>避免带着错误的替换方案落地</pros>
|
||||
<cons>退出本计划并修订 PLAN.md 后重新汇报,增加一轮往返</cons>
|
||||
</option>
|
||||
</options>
|
||||
<resume-signal>回复「可以执行」四个字(修订意见请按 action ⑧ 处理)</resume-signal>
|
||||
<verify>
|
||||
<human-check>用户在对话中明确回复「可以执行」四个字(人工核对回复原文;本关卡为人工关卡,失败语义写在 Task 0 的 action ⑧ 与 acceptance_criteria 中)</human-check>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- 用户回复中明确包含「可以执行」四个字
|
||||
- 汇报涵盖:要解决的问题(13 条范围内诊断)、大致解决方案(三文件四类替换)、逐条裁定编码(D-43..D-50)、明确不做的事、验证方式、编号与 wave
|
||||
- 汇报中已呈报命名审批结论(本计划无新命名;仅一处局部解构绑定 `cls`→`tileType` 与既有枚举 `TileType` 引入)并请求确认
|
||||
- 汇报中已声明范围外已知余留(`packages-user/client-modules/src/client.ts:14` / `:16` 的孤立未使用 import)只报告、不处置
|
||||
- 汇报中已声明运行时 UAT 不可得(渲染端无运行时测试设施)
|
||||
- 汇报中已声明关卡性质:不因触发方式或 `yolo` / `auto_advance` 自动放行
|
||||
</acceptance_criteria>
|
||||
<done>用户明确回复「可以执行」;在此之前未执行任何任务、未修改任何文件、未派发任何执行子代理</done>
|
||||
</task>
|
||||
|
||||
<task type="tracer">
|
||||
<name>Task 1(tracer):一条端到端路径 —— 勇士贴图字面量(`tileType: TileType.Unknown`)→ 移动图块 `IMaterialFramedData` → 顶点动态分支(`tileType` 判定 + `render`)→ `MapRenderer.autotile` 取自 `manager.autotile`</name>
|
||||
<precondition>Task 0 已闭环:用户在对话中明确回复「可以执行」四个字(未收到则不得开始本任务)</precondition>
|
||||
<files>packages-user/client-modules/src/render/map/extension/hero.ts, packages-user/client-modules/src/render/map/vertex.ts, packages-user/client-modules/src/render/map/renderer.ts</files>
|
||||
<read_first>
|
||||
- packages-user/client-modules/src/render/map/extension/hero.ts:1-19,144-173(`@user/data-common` 导入块、`@user/client-base` 的 `BlockCls` / `IMaterialFramedData` 导入、`updateHeroTexture` 的对象字面量)
|
||||
- packages-user/client-modules/src/render/map/vertex.ts:24-29,846-913(`BlockCls` / `IMaterialFramedData` 导入;`updateMoving` 的解构与自动元件分支)
|
||||
- packages-user/client-modules/src/render/map/renderer.ts:8-15,217-240(`@user/client-base` 导入块;构造器与 `autotile` 赋值点)
|
||||
- packages-user/client-base/src/material/types.ts:75-86,148-151(`IMaterialFramedData` 现行成员;`render(tile, connection)` 签名)
|
||||
- packages-user/client-base/src/material/manager.ts:37-40,84-94(`TextureManager.autotile` 成员与构造器赋值)
|
||||
- packages-user/data-common/src/store/types.ts:6-25(`TileType.Autotile` / `TileType.Unknown`)
|
||||
- packages-user/client-modules/src/render/map/moving.ts:26-107(`IMovingBlock.texture` 与本路径的类型面;本任务不改该文件)
|
||||
- packages-user/client-modules/src/render/map/types.ts:195-230,320-345,525-545(`IMovingBlock.texture` / `IMapRenderer.manager` / `IMapRenderer.autotile` / `addMovingBlock` 签名;本任务不改该文件)
|
||||
- dev.md(「无类型导入」「引入位置」「命名规则」「对象解构」;「换行使用 CRLF」)
|
||||
</read_first>
|
||||
<action>
|
||||
(0a) **只读起始基线(先做)**:执行 `git status --porcelain -- packages packages-user src`,把输出**原样逐行**写入临时文件 `%TEMP%/opencode/04-09-baseline.txt`(不存在则创建该目录;文件内容保留原始 BOM 与行序;输出为空则写入零字节并在汇报中记「(无)」)。**不得回滚 / 暂存 / 提交 / 修改**任何既有改动;该文件位于仓库外,不进入 `git status`。同时执行 `pnpm exec vue-tsc --noEmit` 并把完整输出存到 `%TEMP%/opencode/04-09-tsc-before.txt`,记录**范围内三文件**的诊断行数与逐行内容(规划日实测 = 13 条:`vertex.ts` 6 / `renderer.ts` 5 / `hero.ts` 2),供 Task 3 对比。
|
||||
|
||||
(0b) **三份目标文件的内容哈希基线(与 (0a) 同为改动前、必须先做)**:用 Node 的 `crypto` 计算三份目标文件**改动前**内容的 SHA-256,写入 `%TEMP%/opencode/04-09-baseline-hashes.txt`,每行格式 `<sha256> <相对路径>`(两空格分隔,路径用正斜杠,行序 = `vertex.ts` / `renderer.ts` / `hero.ts`),例如 `crypto.createHash('sha256').update(fs.readFileSync(f)).digest('hex')`。**原因(必须遵守)**:执行器按每任务提交协议会在 Task 1 / Task 2 结束时分别提交这三份文件,Task 3 不得再以「`git status` 是否仍显示它们为已修改」判断目标是否被改动;内容哈希是与提交状态无关的判据。该文件同样位于仓库外,不得回滚 / 暂存 / 提交 / 修改任何既有改动。
|
||||
|
||||
(1) **`extension/hero.ts`(D-45)**:把 `TileType` 并入既有的 `@user/data-common` 导入块(该块当前以 `ObjectMoveType` 结尾,`TileType` 追加为该块最后一项,保持 import 连续块、不插入注释或空行);从 `@user/client-base` 的导入中仅移除 `BlockCls`、保留 `IMaterialFramedData`;把 `:167` 的对象字面量成员 `cls: BlockCls.Unknown,` 改为 `tileType: TileType.Unknown,`(其余 `offset` / `texture` / `frames` / `defaultFrame` 逐字保留;不改动该文件既有的 `// @ts-expect-error` 标注与 `state` 存量用法)。
|
||||
|
||||
(2) **`vertex.ts` 动态路径(D-43 / D-44)**:在导入块中加入 `import { TileType } from '@user/data-common';`(置于既有 `@user/data-base` 导入之后、连续块内、无空行);在 `updateMoving` 中把对象解构的键 `cls` 改为 `tileType`(保持多键解构形态);把紧随其后的自动元件判定由读取 `cls` 比较改为 `tileType === TileType.Autotile`;把该分支内的自动元件渲染调用由旧的「跳过检查」方法改为 `this.renderer.autotile.render(block.texture, 0b0000_0000)`(连接常量与后续 `ITextureRenderable` 判空逻辑保持不变)。**本任务暂不移除 `vertex.ts` 的 `BlockCls` 导入**(`:517` / `:561` 仍在使用,同 Task 2 一并清理)。
|
||||
|
||||
(3) **`renderer.ts` 组合根(D-46)**:把构造器内自建自动元件处理器的赋值(`:234`)改为 `this.autotile = manager.autotile;`;**并在同一编辑内从 `@user/client-base` 导入块移除 `AutotileProcessor`** —— 该 import 在 `:234` 被替换后已无任何使用点,而 `eslint.config.js` 的 `@typescript-eslint/no-unused-vars` 为 `error`,若留着会使本任务的 eslint 门禁必然失败(本任务不得留下任何未使用 import)。`readonly autotile: IAutotileProcessor;` 字段声明(`:71`)与 `render/map/types.ts` 的 `IMapRenderer.autotile`(`:334`)**一字不动**(`IAutotileProcessor` 类型 import 仍被 `:71` 使用,必须保留);`BlockCls` 导入本任务**保留**(`:1252` / `:1263` 仍在使用,Task 2 随判定替换一并移除);构造器其余语句、`manager` 参数的 `readonly` 形态、`vertex` / `viewport` / `tileAnimater` 初始化顺序保持不变。
|
||||
|
||||
(4) 本任务只改上述三份文件;不得改 `moving.ts` / `render/map/types.ts`、不得改 `material/**`、不得改加载面、不得新增测试;不得修改任何既有注释文本。
|
||||
</action>
|
||||
<reversibility rating="reversible">三处改动都是把消费者指向新接口的机械替换(方法名、成员名、取值来源),可用一次 git 操作整体回退;不引入新契约、不改公共签名。</reversibility>
|
||||
<verify>
|
||||
<automated>node -e "const fs=require('fs'),path=require('path'),{execSync}=require('child_process');let o='';try{o=execSync('pnpm exec vue-tsc --noEmit',{encoding:'utf8',maxBuffer:1<<28,stdio:['ignore','pipe','pipe']})}catch(e){o=(e.stdout||'')+(e.stderr||'')}const scoped=['packages-user/client-modules/src/render/map/vertex.ts','packages-user/client-modules/src/render/map/renderer.ts','packages-user/client-modules/src/render/map/extension/hero.ts'];const cnt=t=>t.split(/\r?\n/).map(l=>l.replace(/\\/g,'/')).filter(l=>/error TS\d+/.test(l)&&scoped.some(f=>l.indexOf(f)>=0)).length;const bp=path.join(process.env.TEMP||process.env.TMP,'opencode','04-09-tsc-before.txt');if(!fs.existsSync(bp)){console.error('MISSING TSC BEFORE FILE');process.exit(1)}const before=cnt(fs.readFileSync(bp,'utf8')),after=cnt(o);if(before-after!==5){console.error('TRACER DELTA WRONG before='+before+' after='+after);process.exit(1)}console.log('OK tracer delta -5 (before '+before+' after '+after+')')"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "MISSING TSC BEFORE FILE" / "TRACER DELTA WRONG"(未落盘 (0a) 的类型基线,或 tracer 未恰好消解范围内 5 条诊断 —— 改动缺失或改错)</fails_when>
|
||||
<automated>node -e "const{execSync}=require('child_process');const files=['packages-user/client-modules/src/render/map/vertex.ts','packages-user/client-modules/src/render/map/renderer.ts','packages-user/client-modules/src/render/map/extension/hero.ts'];try{execSync('pnpm exec eslint '+files.join(' '),{encoding:'utf8',stdio:['ignore','pipe','pipe']});console.log('OK eslint')}catch(e){console.error('ESLINT FAILED :: '+(e.stdout||'')+(e.stderr||''));process.exit(1)}"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "ESLINT FAILED"(三份文件 eslint 报错,通常是未使用 import 或导入顺序问题)</fails_when>
|
||||
<automated>node -e "const fs=require('fs'),path=require('path');const dir=path.join(process.env.TEMP||process.env.TMP,'opencode');const bp=path.join(dir,'04-09-baseline.txt'),hp=path.join(dir,'04-09-baseline-hashes.txt');if(!fs.existsSync(bp)||!fs.existsSync(hp)){console.error('MISSING BASELINE FILE');process.exit(1)}const target=['packages-user/client-modules/src/render/map/vertex.ts','packages-user/client-modules/src/render/map/renderer.ts','packages-user/client-modules/src/render/map/extension/hero.ts'];const lines=fs.readFileSync(hp,'utf8').split(/\r?\n/).map(l=>l.trim()).filter(Boolean);const miss=target.filter(t=>!lines.some(l=>l.replace(/\\/g,'/').endsWith(t)));if(miss.length){console.error('BASELINE HASH MISSING '+miss.join(' ; '));process.exit(1)}const s=fs.readFileSync('.planning/phases/04-render-adaptation/04-09-PLAN.md','utf8');if(s.indexOf('tileType: TileType.Unknown')<0){console.error('D-45 LITERAL MISSING IN PLAN');process.exit(1)}console.log('OK baseline + hash baseline present ('+lines.length+' targets) + D-45 literal declared')"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "MISSING BASELINE FILE" / "BASELINE HASH MISSING" / "D-45 LITERAL MISSING IN PLAN"(未落盘 (0a) 的状态基线或 (0b) 的三份目标文件内容哈希基线,Task 3 无法断言增量)</fails_when>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- `hero.ts`:`BlockCls` 不再出现在该文件;`TileType` 位于既有 `@user/data-common` 导入块内;`:167` 字面量为 `tileType: TileType.Unknown`;既有 `// @ts-expect-error` 与 `state` 用法逐字保留
|
||||
- `vertex.ts`:`updateMoving` 解构键为 `tileType`,判定为 `tileType === TileType.Autotile`,调用为 `this.renderer.autotile.render(block.texture, 0b0000_0000)`;已加入 `@user/data-common` 的 `TileType` 导入;`BlockCls` 导入本任务保留待 Task 2 清理
|
||||
- `renderer.ts`:构造器为 `this.autotile = manager.autotile;`;`AutotileProcessor` 已从 `@user/client-base` 导入移除(`:234` 替换后已无使用点,否则 eslint `no-unused-vars` 必然报错);`BlockCls` 导入本任务保留待 Task 2 清理;`readonly autotile: IAutotileProcessor;` 与 `IMapRenderer.autotile` 签名未改
|
||||
- `moving.ts`、`render/map/types.ts`、`material/**`、加载面、`packages/**`、`src/**` 零改动;无新增测试;无既有注释改动;无新增依赖
|
||||
- 只读起始基线已落盘至仓库外(`%TEMP%/opencode/04-09-baseline.txt` 与 `%TEMP%/opencode/04-09-baseline-hashes.txt`),且未触碰用户任何改动
|
||||
</acceptance_criteria>
|
||||
<done>tracer 路径闭环:勇士贴图 → 移动图块 → 顶点动态分支 → `manager.autotile` 全部走新接口;该路径 **5** 个诊断行转绿(`hero.ts:15` / `hero.ts:167` / `vertex.ts:852` / `vertex.ts:874` / `renderer.ts:234`;`vertex.ts:872` 的 `cls` 来自 `:852` 的解构,TS 只在 `:852` 报错,故本任务消解 5 条而非 6 条);eslint 三文件通过;状态基线与三份目标文件内容哈希基线均已落盘</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2:补齐剩余转换 —— `vertex.ts` 静态判定与 `updateAutotile` 调用、`renderer.ts` 背景自动元件分支与 import 清理</name>
|
||||
<files>packages-user/client-modules/src/render/map/vertex.ts, packages-user/client-modules/src/render/map/renderer.ts</files>
|
||||
<precondition>Task 1 已闭环:tracer 路径的 5 个诊断行转绿、状态基线与内容哈希基线均已落盘</precondition>
|
||||
<read_first>
|
||||
- packages-user/client-modules/src/render/map/vertex.ts:24-29,440-479,510-582(`BlockCls` / `IMaterialFramedData` 导入;`updateAutotile` 的自动元件渲染调用;`checkAutotileConnectionAround` 与 `updateVertexArray` 的判定)
|
||||
- packages-user/client-modules/src/render/map/renderer.ts:8-15,1231-1271(`@user/client-base` 导入块;`useTileBackground` 的单帧 / 多帧分支)
|
||||
- packages-user/client-base/src/material/types.ts:148-162(`render` 与 `renderAnimated` 现行签名;`renderAnimated` 是已适配点、本任务不得改动)
|
||||
- packages-user/data-common/src/store/types.ts:6-25(`TileType.Autotile`)
|
||||
- dev.md(「无类型导入」「引入位置」「命名规则」「换行使用 CRLF」)
|
||||
</read_first>
|
||||
<action>
|
||||
(1) **`vertex.ts` 静态路径(D-43 / D-44 / import 清理)**:把 `updateAutotile` 内的自动元件渲染调用由「跳过检查」方法改为 `autotile.render(tile, connection)`(传入参数与返回值处理不变,`const renderable = ...` 的判空与后续 `updateTileVertex` 调用逐字保留);把 `checkAutotileConnectionAround` 的判定改为 `if (!tile || tile.tileType !== TileType.Autotile) return;`;把 `updateVertexArray` 的自动元件判定改为 `if (tile.tileType === TileType.Autotile) {`;最后从 `@user/client-base` 导入中移除 `BlockCls`(仅保留 `IMaterialFramedData`)。`:852` / `:872` 已于 Task 1 处理,本任务不得回改。`render/map/renderer.ts:1264` 的 `renderAnimated` 调用是已适配点,**不得改动**。
|
||||
|
||||
(2) **`renderer.ts` 背景分支与 import 清理(D-43 / D-44)**:把 `useTileBackground` 单帧分支的判定改为 `if (tex.tileType === TileType.Autotile) {`,其内调用改为 `this.autotile.render(tex, 0b1111_1111)!`(保留末尾非空断言与返回值直返形态);把多帧分支的判定改为 `if (tex.tileType === TileType.Autotile) {`(其后 `this.autotile.renderAnimated(tex, 0b1111_1111)` 保持不变);在导入块中加入 `import { TileType } from '@user/data-common';`(置于既有 `@user/data-base` 导入块之后、连续块内);从 `@user/client-base` 导入中移除 `BlockCls`(`AutotileProcessor` 已于 Task 1 随 `:234` 替换一并移除,本任务不得回加;保留 `IAutotileProcessor` / `IMaterialFramedData` / `ITextureManager` / `ITrackedAssetData` —— 四者仍有使用点)。
|
||||
|
||||
(3) **完成后自检**:确认 `render/map/**` 内已无 `cls` 成员读写、无「跳过检查」调用、无 `BlockCls` 记号、无 `IBlockIdentifier`;确认 `moving.ts` / `render/map/types.ts` 未被修改;确认 CRLF 未被破坏。
|
||||
|
||||
(4) 本任务只改 `vertex.ts` 与 `renderer.ts`;不得改 `hero.ts` 既有结论、不得改 `material/**`、不得改加载面、不得新增测试、不得修改既有注释文本。
|
||||
</action>
|
||||
<reversibility rating="reversible">与 Task 1 同类机械替换,整体可回退;不改任何公共签名或存储设计(D-47)。</reversibility>
|
||||
<!-- plan-criteria-allow: R4 - 各门禁脚本均由 node 的 execSync 承载,git 命令的退出状态被显式捕获并判定(status 0/1 区分命中与无命中,其它状态视为失败),不构成被吞掉的中间管道阶段 -->
|
||||
<verify>
|
||||
<automated>node -e "const{execSync}=require('child_process');let o='';try{o=execSync('pnpm exec vue-tsc --noEmit',{encoding:'utf8',maxBuffer:1<<28,stdio:['ignore','pipe','pipe']})}catch(e){o=(e.stdout||'')+(e.stderr||'')}const scoped=['packages-user/client-modules/src/render/map/vertex.ts','packages-user/client-modules/src/render/map/renderer.ts','packages-user/client-modules/src/render/map/extension/hero.ts'];const hits=o.split(/\r?\n/).map(l=>l.replace(/\\/g,'/')).filter(l=>/error TS\d+/.test(l)&&scoped.some(f=>l.indexOf(f)>=0));if(hits.length){console.error('SCOPED TS ERRORS '+hits.length+' :: '+hits.slice(0,8).join(' @ '));process.exit(1)}console.log('OK zero scoped TS errors ('+scoped.length+' files)')"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "SCOPED TS ERRORS"(三份范围内文件仍有 TS 诊断,13→0 未达成)</fails_when>
|
||||
<automated>node -e "const fs=require('fs');const files=['packages-user/client-modules/src/render/map/vertex.ts','packages-user/client-modules/src/render/map/renderer.ts','packages-user/client-modules/src/render/map/extension/hero.ts'];const bad=files.filter(f=>{const s=fs.readFileSync(f,'utf8');const lf=(s.match(/\n/g)||[]).length,crlf=(s.match(/\r\n/g)||[]).length;return lf!==crlf});if(bad.length){console.error('NON-CRLF '+bad.join(' ; '));process.exit(1)}console.log('OK CRLF 3 files')"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "NON-CRLF"(三份文件出现非 CRLF 换行,违反 dev.md「换行使用 CRLF 格式」)</fails_when>
|
||||
<automated>node -e "const{execSync}=require('child_process');const names=['BlockCls','renderWithoutCheck','IBlockIdentifier'];const bad=[];for(const n of names){let o='',st=0;try{o=execSync('git grep -n -- '+n+' -- packages-user/client-modules/src/render',{encoding:'utf8',stdio:['ignore','pipe','pipe']})}catch(e){o=(e.stdout||'')+(e.stderr||'');st=e.status}const lines=o.replace(/\s+$/,'').length?o.replace(/\s+$/,'').split(/\r?\n/):[];if(lines.length)bad.push(n+' => '+lines.slice(0,3).join(' ; '));else if(st!==0&&st!==1)bad.push(n+' grep status '+st)}if(bad.length){console.error('SCOPE SYMBOL STILL PRESENT: '+bad.join(' || '));process.exit(1)}console.log('OK zero scoped symbols ('+names.length+')')"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "SCOPE SYMBOL STILL PRESENT"(`render/map/**` 内仍命中旧符号 / 被删标识符,替换未彻底)</fails_when>
|
||||
<automated>node -e "const fs=require('fs');const t=fs.readFileSync('packages-user/client-modules/src/render/map/vertex.ts','utf8')+fs.readFileSync('packages-user/client-modules/src/render/map/renderer.ts','utf8');const bad=[];if(/\bcls\b/.test(t.replace(/\/\/[^\n]*/g,'')))bad.push('cls residual');if(t.indexOf('tileType === TileType.Autotile')<0)bad.push('no tileType comparison');if(t.indexOf(\"from '@user/data-common'\")<0)bad.push('TileType import missing');if(bad.length){console.error('CONVERSION INCOMPLETE '+bad.join(' | '));process.exit(1)}console.log('OK conversion markers present')"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "CONVERSION INCOMPLETE"(`cls` 成员读写残留,或缺少 `tileType` 判定,或未引入 `TileType`)</fails_when>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- `vertex.ts`:三处旧的「跳过检查」/ `BlockCls` 使用全部转为 `render` / `tileType`;`@user/client-base` 导入仅剩 `IMaterialFramedData`;`TileType` 已引入
|
||||
- `renderer.ts`:`useTileBackground` 两处判定为 `tex.tileType === TileType.Autotile`,单帧分支调用为 `this.autotile.render(tex, 0b1111_1111)!`,多帧分支 `renderAnimated` 未改;`BlockCls` 已从导入移除(`AutotileProcessor` 已于 Task 1 移除,未回加);`TileType` 已引入
|
||||
- `render/map/**` 内 `BlockCls` / 旧的「跳过检查」调用 / `IBlockIdentifier` 全部零命中;`cls` 成员读写零残留
|
||||
- 三份范围内文件 `vue-tsc` 诊断数 = 0;CRLF 保持;`moving.ts` / `render/map/types.ts` 零改动
|
||||
</acceptance_criteria>
|
||||
<done>剩余转换完成,范围内三文件 texture 归属诊断由 13 归零;符号零命中与 CRLF 门禁转绿;未触碰 `material/`、加载面与范围外文件</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3:Phase 增量收口 —— 六道门禁(范围诊断归零 / eslint / prettier / CRLF / 符号零命中 / 基线增量与禁用路径)+ 人工复核 + `04-09-SUMMARY.md` 落盘与提交</name>
|
||||
<files>.planning/phases/04-render-adaptation/04-09-SUMMARY.md</files>
|
||||
<precondition>Task 1 / Task 2 已闭环:范围内三文件诊断归零、符号零命中、CRLF 通过、基线文件仍可读</precondition>
|
||||
<read_first>
|
||||
- .planning/phases/04-render-adaptation/04-07-SUMMARY.md:1-40,120-200(既有 SUMMARY 的元信息块、「执行前核对」「门禁输出摘要」「人工复核」「运行时 UAT 不可得声明」写法,可对齐版式)
|
||||
- .planning/phases/04-render-adaptation/04-TEXTURE-INTERFACE-IMPACT.md(A13/B8/C8/D9/E7/F8;本步是其 D 类 / F 类未决项经 D-43..D-50 裁定后的落地)
|
||||
- .planning/phases/04-render-adaptation/04-CONTEXT.md(D-43..D-50 原文)
|
||||
- .planning/phases/04-render-adaptation/04-09-PLAN.md(本计划门禁与禁令)
|
||||
- dev.md(「其他要求」CRLF;「双端分离」)
|
||||
</read_first>
|
||||
<action>
|
||||
(1) **重跑全部门禁并原样记录输出**:**门禁顺序为硬要求 —— ①..⑥ 全部在提交之前执行;本 action 内不得出现任何 `git commit`**(三份源文件由 Task 1 / Task 2 的每任务提交协议各自提交,本任务产物由本任务提交协议在 `<verify>` 六道门禁全绿之后提交)。① `pnpm exec vue-tsc --noEmit` —— 断言范围内三文件诊断数 = 0,并与 `%TEMP%/opencode/04-09-tsc-before.txt` 记录的前值(规划日 13)对比,确认全仓错误总行数**未因本计划新增**(范围内为 0;范围外既有诊断只记录不处置,D-33);② `pnpm exec eslint` 三文件;③ `pnpm exec prettier --check` 三文件;④ CRLF 三文件;⑤ `git grep` 符号零命中(`render/map/**` 内 `BlockCls`、`renderWithoutCheck`、`IBlockIdentifier`);⑥ 基线增量 + 禁用路径门禁 —— 三份目标文件当前内容哈希均**不同于** `%TEMP%/opencode/04-09-baseline-hashes.txt` 的基线(即确已被本计划改动;该判据**与文件是否已被每任务提交协议提交无关**,不得改用「`git status` 是否仍显示为已修改」),`git status --porcelain -- packages packages-user src` 相对 `%TEMP%/opencode/04-09-baseline.txt` 除三份目标文件外零新增 / 零消失 / 零状态变化,且 `material/**`、加载面、`packages/**`、`src/**` 零改动。
|
||||
|
||||
(2) **人工复核(不可自动化的部分)**:逐处比对 objective 的裁定编码表与代码实际形态 —— D-43 三处调用形态与实参、D-44 五处判定与一处解构键、D-45 勇士字面量、D-46 字段与取值来源;确认未新增 / 改名任何成员或字段、未改既有 jsDoc / 注释、未加 / 删 `// @ts-expect-error`、未引入 `import type`、未动 `package.json` / `pnpm-lock.yaml` / `tsconfig.json`、未新增测试;确认 `packages-user/client-modules/src/client.ts` 与 `render/map/moving.ts` / `render/map/types.ts` 零改动(范围外已知余留一律只报告、不处置)。
|
||||
|
||||
(3) **写 `.planning/phases/04-render-adaptation/04-09-SUMMARY.md`**(CRLF、与既有 SUMMARY 版式对齐):元信息块(日期 / 计划号 04-09 / wave 8 / 性质:代码改动·第二步实施 / 基准:`04-TEXTURE-INTERFACE-IMPACT.md` + `d36ea69`);逐条 D-43..D-50 的实际落点与实际行号;范围内诊断 13→0 的门禁输出摘要;全仓错误总行数前后对比(范围外既有诊断不归因本步);六道门禁输出摘要;人工复核结论;**无新命名声明**(仅一处局部解构绑定改名与既有枚举引入);**运行时 UAT 不可得声明**(渲染端无运行时测试设施,端到端验证为静态组合);**范围外已知余留(只报告、不处置)**:`packages-user/client-modules/src/client.ts:14` 的 `IAutotileProcessor` 与 `:16` 的 `AutotileProcessor` 是 `d36ea69` 删除 `IClientBase.autotile` 后遗留的孤立未使用 import,属 D-33 范围外、本计划未改动,须在 SUMMARY 中如实记录;**REND-01 / REND-02 仍保持 Pending** 的声明(本步仅为 REND-01 的 texture 子切片)。
|
||||
|
||||
(4) **提交(由每任务提交协议在 `<verify>` 六道门禁全绿之后执行;本 action 内不得出现任何 `git commit`,否则 `<verify>` 的基线门禁会在「已提交」的树上评估而失去意义)**:三份源文件已由 Task 1 / Task 2 的每任务提交协议各自提交,本任务只需提交本任务产物 `.planning/phases/04-render-adaptation/04-09-SUMMARY.md`(如路线图登记尚未随规划提交则一并包含);提交信息按仓库既有风格(如 `docs(04-09): record texture interface adaptation`);**不得**提交用户的任何并发改动(只 `git add` 本计划明确产出的路径)。
|
||||
|
||||
(5) 本任务只新增 `04-09-SUMMARY.md` 一个文件(提交动作由本任务提交协议在 `<verify>` 全绿后执行);不得改写 `04-01`..`04-08` 的任何产物。
|
||||
</action>
|
||||
<reversibility rating="reversible">收口任务只产出簿记与提交,代码改动可整体回退;不引入契约或存储变更。</reversibility>
|
||||
<verify>
|
||||
<automated>node -e "const{execSync}=require('child_process');let o='';try{o=execSync('pnpm exec vue-tsc --noEmit',{encoding:'utf8',maxBuffer:1<<28,stdio:['ignore','pipe','pipe']})}catch(e){o=(e.stdout||'')+(e.stderr||'')}const scoped=['packages-user/client-modules/src/render/map/vertex.ts','packages-user/client-modules/src/render/map/renderer.ts','packages-user/client-modules/src/render/map/extension/hero.ts'];const hits=o.split(/\r?\n/).map(l=>l.replace(/\\/g,'/')).filter(l=>/error TS\d+/.test(l)&&scoped.some(f=>l.indexOf(f)>=0));if(hits.length){console.error('SCOPED TS ERRORS '+hits.length+' :: '+hits.slice(0,8).join(' @ '));process.exit(1)}console.log('OK zero scoped TS errors; total error-TS lines '+(o.match(/error TS\d+/g)||[]).length)"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "SCOPED TS ERRORS"(范围内诊断未归零)</fails_when>
|
||||
<automated>node -e "const{execSync}=require('child_process');const files=['packages-user/client-modules/src/render/map/vertex.ts','packages-user/client-modules/src/render/map/renderer.ts','packages-user/client-modules/src/render/map/extension/hero.ts'];try{execSync('pnpm exec eslint '+files.join(' '),{encoding:'utf8',stdio:['ignore','pipe','pipe']});execSync('pnpm exec prettier --check '+files.join(' '),{encoding:'utf8',stdio:['ignore','pipe','pipe']});console.log('OK eslint + prettier')}catch(e){console.error('QUALITY GATE FAILED :: '+(e.stdout||'')+(e.stderr||''));process.exit(1)}"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "QUALITY GATE FAILED"(eslint 或 prettier 未通过)</fails_when>
|
||||
<automated>node -e "const{execSync}=require('child_process'),fs=require('fs'),path=require('path'),crypto=require('crypto');const dir=path.join(process.env.TEMP||process.env.TMP,'opencode');const bp=path.join(dir,'04-09-baseline.txt'),hp=path.join(dir,'04-09-baseline-hashes.txt');if(!fs.existsSync(bp)||!fs.existsSync(hp)){console.error('MISSING BASELINE FILE');process.exit(1)}const target=['packages-user/client-modules/src/render/map/vertex.ts','packages-user/client-modules/src/render/map/renderer.ts','packages-user/client-modules/src/render/map/extension/hero.ts'];const sha=f=>crypto.createHash('sha256').update(fs.readFileSync(f)).digest('hex');const rec={};for(const l of fs.readFileSync(hp,'utf8').split(/\r?\n/).map(s=>s.trim()).filter(Boolean)){const i=l.indexOf(' ');rec[l.slice(i+2).replace(/\\/g,'/')]=l.slice(0,i)}const missing=target.filter(t=>!rec[t]);if(missing.length){console.error('BASELINE HASH MISSING '+missing.join(' ; '));process.exit(1)}const unchanged=target.filter(t=>sha(t)===rec[t]);if(unchanged.length){console.error('TARGET NOT CHANGED '+unchanged.join(' ; '));process.exit(1)}const base=fs.readFileSync(bp,'utf8').replace(/\s+$/,'');const rows=base.length?base.split(/\r?\n/).map(s=>s.replace(/\s+$/,'')):[];const now=execSync('git status --porcelain -- packages packages-user src',{encoding:'utf8'}).replace(/\s+$/,'');const cur=now.length?now.split(/\r?\n/).map(s=>s.replace(/\s+$/,'')):[];const added=cur.filter(l=>rows.indexOf(l)<0);const removed=rows.filter(l=>cur.indexOf(l)<0);const badAdded=added.filter(l=>!target.some(t=>l.endsWith(t)));const badRemoved=removed.filter(l=>!target.some(t=>l.endsWith(t)));if(badAdded.length||badRemoved.length){console.error('BASELINE DRIFT added=['+badAdded.join(' ; ')+'] removed=['+badRemoved.join(' ; ')+']');process.exit(1)}console.log('OK 3 targets differ from recorded hashes (commit-state independent) + baseline status preserved (dirty delta added '+added.length+' / removed '+removed.length+')')"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "MISSING BASELINE FILE" / "BASELINE HASH MISSING" / "BASELINE DRIFT" / "TARGET NOT CHANGED"(未落盘基线、目标文件未被本计划改动,或除三份目标文件外出现状态漂移 —— 注意本门禁以内容哈希判「目标已改」,与文件是否已被每任务提交协议提交无关)</fails_when>
|
||||
<automated>node -e "const{execSync}=require('child_process');const raw=execSync('git status --porcelain -- packages packages-user src',{encoding:'utf8'});const rows=raw.replace(/\s+$/,'').length?raw.replace(/\s+$/,'').split(/\r?\n/):[];const forbidden=['packages-user/client-base/src/material/','packages-user/client-modules/src/fallback/','packages-user/client-base/src/load/','packages-user/client-base/src/types.ts','packages-user/client-modules/src/client.ts','packages-user/client-modules/src/core.ts','packages-user/client-modules/src/types.ts'];const bad=rows.filter(l=>{const p=l.slice(3).replace(/\\/g,'/');return p.indexOf('packages/')===0||p.indexOf('src/')===0||forbidden.some(f=>p.indexOf(f)===0)});if(bad.length){console.error('FORBIDDEN PATH TOUCHED '+bad.join(' ; '));process.exit(1)}console.log('OK no forbidden paths touched ('+rows.length+' entries)')"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "FORBIDDEN PATH TOUCHED"(`material/`、加载面、`packages/`、`src/` 或用户自有的客户端组合文件被改动)</fails_when>
|
||||
<automated>node -e "const fs=require('fs');const p='.planning/phases/04-render-adaptation/04-09-SUMMARY.md';if(!fs.existsSync(p)){console.error('MISSING SUMMARY');process.exit(1)}const s=fs.readFileSync(p,'utf8');const need=['D-43','D-44','D-45','D-46','D-47','D-48','D-49','D-50','REND-01','REND-02','Pending','13','0','client.ts','IAutotileProcessor','余留'];const miss=need.filter(k=>s.indexOf(k)<0);if(miss.length){console.error('SUMMARY MISSING '+miss.join('|'));process.exit(1)}const lf=(s.match(/\n/g)||[]).length,crlf=(s.match(/\r\n/g)||[]).length;if(lf!==crlf){console.error('SUMMARY NON-CRLF');process.exit(1)}console.log('OK summary content + CRLF')"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "MISSING SUMMARY" / "SUMMARY MISSING" / "SUMMARY NON-CRLF"(SUMMARY 未产出、缺裁定编号或需求状态声明、或非 CRLF)</fails_when>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- 六道门禁全部转绿并输出已原样记录:范围内诊断 = 0、eslint、prettier、CRLF、符号零命中、基线增量 + 禁用路径;六道门禁均在提交之前执行,且「目标文件已改动」以内容哈希断言(与是否已被每任务提交协议提交无关)
|
||||
- 全仓错误总行数与 `04-09-tsc-before.txt` 对比后,范围内为 0 且范围外诊断未被本计划改动(只记录不处置)
|
||||
- 人工复核逐条确认 D-43..D-50 的实际落点、无新命名、无注释改动、无 `@ts-expect-error` 增删、无 `import type`、无依赖 / 清单改动、无测试改动、`client.ts` 与 `moving.ts` / `render/map/types.ts` 零改动
|
||||
- `04-09-SUMMARY.md` 落盘(CRLF),含逐条裁定落点、13→0 门禁摘要、基线保持证据、无新命名声明、运行时 UAT 不可得声明、范围外已知余留(`client.ts:14` / `:16` 孤立未使用 import)只报告记录、`REND-01` / `REND-02` 保持 Pending 声明
|
||||
- 三份源文件已由 Task 1 / Task 2 的每任务提交协议提交,`04-09-SUMMARY.md` 已在 `<verify>` 全绿后提交;未提交任何用户并发改动;`04-01`..`04-08` 产物未被改写
|
||||
</acceptance_criteria>
|
||||
<done>Phase 4 第九个增量收口:三份地图渲染文件完成 TextureManager 新接口适应,范围内 texture 归属诊断由 13 归零;六道门禁(全部在提交之前执行)转绿;`04-09-SUMMARY.md` 落盘并在 `<verify>` 全绿后提交,其中记录范围外已知余留(`client.ts:14` / `:16`);`REND-01` / `REND-02` 仍 Pending</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<threat_model>
|
||||
## Trust Boundaries
|
||||
|
||||
| Boundary | Description |
|
||||
|----------|-------------|
|
||||
| 渲染端消费者 → `@user/client-base` 素材接口 | 本步把消费者从旧形状 / 被删符号迁到现行接口;边界在编译期(`vue-tsc`)而非运行时,无不可信输入跨入 |
|
||||
| 构建期依赖 → 仓库 | 本步不新增依赖,`package.json` / `pnpm-lock.yaml` / `tsconfig.json` 零改动 |
|
||||
|
||||
## STRIDE Threat Register
|
||||
|
||||
| Threat ID | Category | Component | Severity | Disposition | Mitigation Plan |
|
||||
|-----------|----------|-----------|----------|-------------|-----------------|
|
||||
| T-04-09-01 | Tampering | `render/map/vertex.ts` / `renderer.ts` / `extension/hero.ts` 消费者 | medium | mitigate | 旧成员 `cls` / 被删方法残留会导致「静默取到 undefined / 类型伪装」;由 `vue-tsc` 范围内诊断归零门禁 + `git grep` 符号零命中门禁双重点验(D-43 / D-44) |
|
||||
| T-04-09-02 | Tampering | `MapRenderer.autotile` 取值来源 | medium | mitigate | 若仍自建处理器会导致与 `manager.autotile` 状态分裂;D-46 强制改为 `manager.autotile`,并以「构造器无自建调用 + 字段声明与 `IMapRenderer` 签名未变」的人工复核确认 |
|
||||
| T-04-09-03 | Elevation of Privilege | 范围外文件(`material/`、加载面、`packages/`、`src/`) | high | mitigate | 禁令 + `git status` 禁用路径门禁 + 基线增量门禁:除三份目标文件外零 delta;发现越界即失败 |
|
||||
| T-04-09-04 | Denial of Service | 构建期类型门禁 | low | accept | 仓库既有无关诊断大量存在(D-33),门禁只断言范围内三文件;范围外诊断按既有基线记录,不由本计划处置 |
|
||||
| T-04-09-05 | Information Disclosure | 本步触及的贴图 / 素材元数据 | low | accept | 改动仅接口成员名与判定条件,不新增数据出口、不记录敏感信息 |
|
||||
| T-04-09-06 | Repudiation | 变更可追溯性 | low | mitigate | 原子提交三份源文件 + `04-09-SUMMARY.md`;SUMMARY 逐条记录裁定落点与实际行号 |
|
||||
| T-04-09-SC | Tampering | npm/pnpm 安装(供应链) | high | mitigate | 本步零依赖新增;`package.json` / `pnpm-lock.yaml` 列入禁用路径门禁;如出现安装需求即暂停并告知用户(计划禁令) |
|
||||
</threat_model>
|
||||
|
||||
<verification>
|
||||
- 范围内(`render/map/vertex.ts` + `render/map/renderer.ts` + `render/map/extension/hero.ts`)texture 归属 TS 诊断:13 → 0。
|
||||
- `pnpm exec vue-tsc --noEmit` 全仓错误总行数不因本计划上升(范围内为 0;范围外既有诊断只记录,D-33)。
|
||||
- `pnpm exec eslint <三文件>` 与 `pnpm exec prettier --check <三文件>` 通过。
|
||||
- CRLF 三文件门禁通过。
|
||||
- `render/map/**` 内旧符号(`BlockCls`、旧「跳过检查」调用)与被删标识符(`IBlockIdentifier`)零命中。
|
||||
- `git status --porcelain -- packages packages-user src` 相对 Task 1 状态基线除三份目标文件外零漂移,且三份目标文件内容 SHA-256 均已不同于 Task 1 记录的内容哈希(判据与提交状态无关);`material/**`、加载面、`packages/**`、`src/**` 零改动。
|
||||
- 人工复核:D-43..D-50 逐条落点、无新命名、无既有注释改动、无 `@ts-expect-error` 增删、无 `import type`、无依赖 / 清单 / 测试改动。
|
||||
- 运行时 UAT 不可得(渲染端无运行时测试设施)—— 如实声明,不以无法运行的门禁冒充通过。
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- 13 条范围内 texture 归属诊断归零,且三份文件不新增任何诊断。
|
||||
- D-43 / D-44 / D-45 / D-46 精确落地(逐处可核);D-47 / D-48 / D-49 / D-50 的边界全部满足。
|
||||
- 无新命名、无既有注释改动、无依赖 / 清单 / 测试改动、无范围外改动。
|
||||
- `04-09-SUMMARY.md` 落盘并提交;`REND-01` / `REND-02` 保持 Pending。
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
Create `.planning/phases/04-render-adaptation/04-09-SUMMARY.md` when done
|
||||
</output>
|
||||
@ -82,6 +82,19 @@
|
||||
- **D-41:** 「加载相关」的排除边界(用户界定):**加载本身**,以及**向 `TextureManager` 中添加素材的内容**(均由用户自行适配新加载系统)。
|
||||
- **D-42:** `packages-user/client-base/src/material/` 文件夹已由用户**重构完毕**;AI **只修改消费者**(如地图渲染)。**若某接口被删除且无替代,必须向用户反馈**,不得自行发明替代方案。
|
||||
|
||||
### 下一个目标:TextureManager 新接口适应·**第二步(实施)**(用户裁定,2026-09-23;待规划)
|
||||
> 本步的输入 = 第一步只读清点产物 `.planning/phases/04-render-adaptation/04-TEXTURE-INTERFACE-IMPACT.md`(A13 / B8 / C8 / D9 / E7 / F8)。以下 D-43..D-50 为用户对该台账 D / F 两类未决项的逐条裁决。
|
||||
|
||||
- **D-43:** `renderWithoutCheck` 的替代 = **直接用新 `render(tile, connection)`**。用户原话:现在 `render` 已经进行了简化,性能比原本的 `renderWithoutCheck` 更好。3 处调用点(`render/map/vertex.ts:461`、`render/map/vertex.ts:874`、`render/map/renderer.ts:1253`)**全部改为 `render`**,不得保留或新增「跳过检查」入口。
|
||||
- **D-44:** `BlockCls` 的替代 = **`TileType`(`@user/data-common`)**。自动元件判定(`render/map/renderer.ts:1252`/`:1263`、`render/map/vertex.ts:517`/`:561`/`:872`)统一走 `tileType === TileType.Autotile`;**自动元件不需要做布局类型(`AutotileType`)判断**。用户明确:**不为旧 `BlockCls` 值做一一映射**——该类型尚未完全定稿、后续还会改,不得为了凑齐对应关系而发明映射表。
|
||||
- **D-45:** `render/map/extension/hero.ts:167` 的 `tileType` 取值 = **`TileType.Unknown`**。用户澄清:**D-18 指的是数据层的 `HeroRendering` 对象,不是渲染端的勇士渲染代码**,故 `render/map/extension/hero.ts` **不受 D-18 排除**,属本步范围。
|
||||
- **D-46:** `MapRenderer` **不再自建 `AutotileProcessor`**;**保留** `readonly autotile: IAutotileProcessor` 字段(`render/map/types.ts`,`IMapRenderer` 签名不变),**构造器内赋值为 `manager.autotile`**(用户原话:「全换成 manager 上的」)。
|
||||
- **D-47:** `ITextureManager.textures` / `tileStore` / `tiles` 的职责边界**不在本步解决**——地图背景已走现有 `manager.getTile`(`ITextureGetter` 未变),本步**只做接口适应**,不重新设计存储取值。
|
||||
- **D-48:** `textures` 的**写入侧归用户自行处理的加载系统**;**AI 不得修改 `packages-user/client-base/src/material/` 下的任何内容**(沿用并再次确认 D-42)。
|
||||
- **D-49:** **不考虑 legacy 兼容**——本次大重构的目的就是删除 legacy。凡「是否破坏 legacy 插件面」一类顾虑(对应 04-08 台账 `#04-08-D-08` / `#04-08-F-07`)**一律作废,不作为本步约束或验收项**。
|
||||
- **D-50:** `IBlockIdentifier` 已被用户删除,**其所有用法一并删除;本步范围内不得出现该接口**(其消费点 `packages-user/client-modules/src/fallback/load.ts` 属加载面,归用户)。
|
||||
- **本步范围(据 D-38..D-50 与 D-33 收敛):** AI 渲染端适配对象 = `packages-user/client-modules/src/render/map/vertex.ts`、`render/map/renderer.ts`、`render/map/extension/hero.ts`(台账中 texture 归属 13 条错误),连带 `render/map/moving.ts` / `render/map/types.ts` 的类型面;**排除**加载面(`fallback/load.ts`、`client-base/src/load/**`)、`packages-user/client-base/src/material/**`、`packages/`、`src/`、legacy 兼容。目标:texture 归属 23 条中属 AI 面的 13 条归零;**不追平全仓既有类型错误**(D-33)。`REND-01` / `REND-02` 仍 Pending——本步仅为 REND-01 的 texture 子切片。
|
||||
|
||||
### the agent's Discretion
|
||||
- D-07 的「影响」字段具体写法、「多余旧路径」是否需要进一步细分,交由 AI 在对账执行时按实际情况把握,但不得据此扩大范围。
|
||||
|
||||
|
||||
@ -44,5 +44,5 @@
|
||||
"label": "Advance to the next step",
|
||||
"reason": "Phase 04 of 7 · executing"
|
||||
},
|
||||
"updated_at": "2026-09-23T04:55:40.008Z"
|
||||
"updated_at": "2026-09-23T06:46:17.246Z"
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user