mirror of
https://github.com/motajs/template.git
synced 2026-10-21 14:50:26 +08:00
docs(04): create 04-02 勇士移动接口探索 plan (只读, D-17)
This commit is contained in:
parent
41616833b2
commit
4a1e9b36f8
@ -181,11 +181,12 @@ Plans:
|
||||
3. 移动端(窄屏)布局下,同一场景正常显示且可操作
|
||||
4. 数据端与渲染端保持双端分离——数据端无 DOM,仍可在 Node 环境跑回放验证
|
||||
|
||||
**Plans**: 1/1 plans executed(第一步·只读对账;本阶段增量规划,后续适配实施与双布局待对账结果出来后另行规划 — 04-CONTEXT D-01/D-02)
|
||||
**Plans**: 1/2 plans executed(第一步·只读对账已完成;第二步·勇士移动接口探索(只读)已规划 — 04-CONTEXT D-01/D-02/D-13/D-17/D-18;后续适配实施与双布局待探索结果与缺失候选裁决后另行规划)
|
||||
|
||||
Plans:
|
||||
|
||||
- [x] 04-01-PLAN.md — 渲染端 ↔ 数据端接口对账(只读清点,产出 `04-RENDER-INTERFACE-AUDIT.md`;按 ① 错配 / ② 数据端缺失 / ③ 多余旧路径 三类登记)
|
||||
- [ ] 04-02-PLAN.md — 勇士移动接口探索(只读,D-17):产出 `04-HERO-MOVER-INTERFACE.md`(数据端现行接口 / 渲染端现状 / 逐成员三态对账 / 缺失接口候选 / 未确定 / 处置;排除 `HeroRendering`(D-18)与 `core.*`(D-12);不改任何代码,适配(04-03+)未规划)
|
||||
|
||||
**UI hint**: yes
|
||||
|
||||
@ -380,7 +381,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. 渲染适配与双布局 | 1/1 | In Progress| |
|
||||
| 4. 渲染适配与双布局 | 1/2 | In Progress| |
|
||||
| 5. Legacy 移植 | 0/TBD | Not started | - |
|
||||
| 6. 单元测试 | 18/18 | In Progress| |
|
||||
| 7. 数据端缺陷修复 | 15/16 | 暂缓 (Deferred) | - |
|
||||
|
||||
295
.planning/phases/04-render-adaptation/04-02-PLAN.md
Normal file
295
.planning/phases/04-render-adaptation/04-02-PLAN.md
Normal file
@ -0,0 +1,295 @@
|
||||
---
|
||||
phase: 04-render-adaptation
|
||||
plan: 2
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on:
|
||||
- 04-01
|
||||
files_modified:
|
||||
- .planning/phases/04-render-adaptation/04-HERO-MOVER-INTERFACE.md
|
||||
autonomous: true
|
||||
requirements:
|
||||
- REND-01
|
||||
- REND-02
|
||||
estimate:
|
||||
tokens: 58000
|
||||
raw_tokens: 58000
|
||||
tasks: 3
|
||||
confidence: low
|
||||
must_haves:
|
||||
truths:
|
||||
- "`.planning/phases/04-render-adaptation/04-HERO-MOVER-INTERFACE.md` 存在,含 7 个二级标题:`## 背景` / `## 数据端现行接口` / `## 渲染端现状` / `## 逐成员对账(匹配 / 渲染端需改 / 数据端缺失)` / `## 缺失接口候选` / `## 未能从阅读确定(未猜测)` / `## 处置`;全文为 CRLF 换行(dev.md「换行使用 CRLF 格式」)"
|
||||
- "逐成员对账表每条 `#04-02-R-N` 精确到接口/成员名,同行同时含渲染端 `client-base|client-modules` 与数据端 `data-common|data-base|data-state` 两侧 `file:line` 锚点(数据端无对位时写「无对位,最接近:<file:line>」),结论取 匹配 / 渲染端需改 / 数据端缺失 三态之一"
|
||||
- "带 `// @ts-expect-error 需要重构` 的 import 一律先归「渲染端需改」(用户规则,见 04-RENDER-INTERFACE-AUDIT.md 处置口径),不归「数据端缺失」"
|
||||
- "「缺失接口候选」独立成节,每条 `### #04-02-G-N:标题` 含 `**渲染端需求**` / `**数据端现状**` / `**待确认**` 三段,数据端现状引用最接近的现行成员 `file:line`;候选只记录、不设计、不修复(D-13),未经用户裁决不视为最终缺失清单"
|
||||
- "`HeroRendering` 相关(alpha / 贴图 / 渲染粒度钩子)与 legacy `core.*` 为显式排除项(D-18 / D-12):文中不出现针对它们的对账行或缺失候选,仅在「处置」与范围排除说明中登记排除理由"
|
||||
- "全部生产代码零改动:`git status --porcelain -- packages-user/client-base packages-user/client-modules` 为空;本次只新增交付文档与 `04-02-PLAN.md`,不新增任何适配计划(04-03+ 未规划)"
|
||||
- "无法从静态阅读定论的链路进入「未能从阅读确定(未猜测)」而非写成缺失或错配;文档引用的生产路径均为 tracked 源码路径(可被 `git ls-files` 命中)"
|
||||
artifacts:
|
||||
- path: .planning/phases/04-render-adaptation/04-HERO-MOVER-INTERFACE.md
|
||||
provides: "勇士移动子系统的只读接口探索账本:数据端现行接口清单 + 渲染端现状清单 + 逐成员三态对账(匹配 / 渲染端需改 / 数据端缺失) + 缺失接口候选 + 未确定项 + 处置;供用户裁决缺失候选并据此规划后续适配(D-17/D-13)"
|
||||
key_links:
|
||||
- "渲染端 `render/map/extension/hero.ts:81` 的 `hero.addHook(new MapHeroHook(this))` ↔ 数据端 `IHookable`(经 `data-common/src/common/mover.ts:235` 的 `IObjectMover<T> extends IHookable<...>` 承接)与 `IHeroLocationHooks.onSetPos`(`data-base/src/hero/types.ts:283`)/ `IObjectMoverHooks.onSetPos`(`data-common/src/common/mover.ts:216`)"
|
||||
- "渲染端 `action/move.ts:4` 的 `{ HeroMover, IMoveController } from '@user/data-state'` ↔ 数据端 `data-base/src/hero/mover.ts:22` 的 `HeroMover` 与 `data-common/src/common/mover.ts:142` 的 `IMoverController`(`data-state` barrel 无该导出)"
|
||||
- "渲染端 `render/map/extension/manager.ts:18` 的 `heroMap: Map<IHeroMoveController, ...>` ↔ 数据端 `IHeroLocation`/`IHeroMover`(`data-base/src/hero/types.ts:303,399`)与 `IHeroState.location`(`:894`)"
|
||||
- "「缺失接口候选」段 ↔ 用户增量裁决(D-13):本步只登记候选与数据端现状,是否新增接口由用户在适配开始时逐条确认"
|
||||
- "「处置」/范围排除说明 ↔ D-12(`core.*` 属第五阶段)与 D-18(`HeroRendering` 先改数据端后处理)"
|
||||
assumptions:
|
||||
- "**FLAGGED ASSUMPTION(specless fallback)— REND-01 edge unresolved:** 未提供 REND-01(渲染端适配新数据层接口)的验收边界;本计划**不发明**阈值,只交付勇士移动子系统的只读接口探索账本,供其适配阶段消费。用户须在规划适配工作前补齐边界判据。"
|
||||
- "**FLAGGED ASSUMPTION(specless fallback)— REND-02 edge unresolved:** 未提供 REND-02(移动端与桌面端双布局)的验收边界;本计划不涉及双布局实现,也不发明其验收阈值。"
|
||||
- "数据端接口签名在规划后可能仍被用户并行修改**实现**但不改签名(D-05);本计划以执行当日基准文件的现行签名为准,若发现签名已变,以当日文件为准并在「未能从阅读确定(未猜测)」记录该变化。"
|
||||
- "数据端包(`data-common` / `data-base` / `data-state`)工作树可能因用户并发重构而非空;只读门禁只对渲染端两包(`client-base` / `client-modules`)与计划文件范围做机器断言,不对数据端工作树状态做断言(否则会与用户的进行中工作冲突)。"
|
||||
prohibitions:
|
||||
- "不得修改或新建任何生产代码(`packages-user/client-base`、`packages-user/client-modules`、`packages-user/data-common`、`packages-user/data-base`、`packages-user/data-state`)——本步是只读接口探索(D-17)。"
|
||||
- "不得规划、设计或实施勇士移动适配工作(04-03+ 适配计划不在本 run)。"
|
||||
- "不得把 `HeroRendering` 相关(alpha / 勇士贴图 image / 渲染粒度钩子)纳入对账行或缺失候选(D-18)。"
|
||||
- "不得把 legacy `core.*`(含 `client.*` 以外的旧全局)纳入对账行或缺失候选(D-12,属第五阶段)。"
|
||||
- "不得为缺失接口候选设计解决方案,也不得新增或改写数据端接口(D-13)。"
|
||||
- "不得写入缺少两侧 `file:line` 锚点的对账行;静态阅读无法定论的链路只能进「未能从阅读确定(未猜测)」。"
|
||||
- "不得把带 `// @ts-expect-error 需要重构` 的 import 归为「数据端缺失」——它们一律是「渲染端需改」。"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Phase 4 第二个增量(D-17):对**勇士移动子系统**做**只读接口探索**,产出 `.planning/phases/04-render-adaptation/04-HERO-MOVER-INTERFACE.md`,逐成员对账「渲染端现行期望 ↔ 数据端现行接口」,并把渲染端需要而数据端未提供的接口登记为**缺失接口候选**(D-13:只记录、不设计、不修复)。
|
||||
|
||||
**本 run 只做探索,不改任何代码。** 探索面 = 勇士移动子系统的数据端现行接口(`data-common/src/common/mover.ts` 的 `IObjectMover` / `IObjectMovable` / `IMoverController` / `IObjectMoverHooks` / `ObjectAnimDirection` 与 `data-base/src/hero/types.ts` 的 `IHeroState` / `IHeroLocation` / `IHeroMover` / `IHeroLocationHooks` / `IHeroFollowersControllerHooks` / `IHeroStateHooks`,以及各包 barrel 的实际导出,D-05)与渲染端使用面(`render/map/extension/{hero,types,manager}.ts`、`action/move.ts`,及相关移动器契约参考 `render/map/{moving,status,renderer}.ts`)。
|
||||
|
||||
对账结论固定三态:**匹配 / 渲染端需改 / 数据端缺失**。带 `// @ts-expect-error 需要重构` 的 import 一律先归「渲染端需改」(不归数据端缺失)。
|
||||
|
||||
**显式排除:** `HeroRendering` 相关(alpha / 贴图 / 渲染粒度钩子)按 D-18 排除(用户先改数据端,之后再处理);legacy `core.*` 按 D-12 排除(属第五阶段)。二者不产生任何对账行或候选。
|
||||
|
||||
**后续适配(04-03+)在本 run 不规划**:适配依赖本探索输出,且需用户先裁决缺失候选(D-13/D-17)。
|
||||
|
||||
Purpose: 勇士移动是本次对账暴露的主要失配点(D-17)。在动适配代码前先把「数据端到底提供什么、渲染端到底需要什么、差在哪」钉死到接口成员级,避免按旧形状直接改渲染端。
|
||||
|
||||
Output: `04-HERO-MOVER-INTERFACE.md`(本 run 唯一新增交付物;零生产代码改动)。
|
||||
|
||||
**Artifacts this phase produces(本计划产出物)**:
|
||||
|
||||
- **文件**:`.planning/phases/04-render-adaptation/04-HERO-MOVER-INTERFACE.md`(新建,唯一写入目标)。
|
||||
- **章节**(7 个二级标题,下游验证按标题名核对):`## 背景` / `## 数据端现行接口` / `## 渲染端现状` / `## 逐成员对账(匹配 / 渲染端需改 / 数据端缺失)` / `## 缺失接口候选` / `## 未能从阅读确定(未猜测)` / `## 处置`。
|
||||
- **元信息块**(标题下 5 行,对照 04-RENDER-INTERFACE-AUDIT.md:3-6):`**日期:**` / `**范围:**`(勇士移动子系统;排除 HeroRendering 与 core.*) / `**性质:**`(只读接口探索,未修改任何生产代码) / `**接口基准:**`(`data-common/src/common/mover.ts`、`data-base/src/hero/{types,mover}.ts` 及 barrel 现行导出) / `**输入账本:**`(`04-RENDER-INTERFACE-AUDIT.md` 的 `#04-01-M-01..05`)。
|
||||
- **逐成员对账表列**(固定顺序):`| ID | 成员 | 渲染端锚点 | 数据端锚点 | 对账结论 | 说明 |`。
|
||||
- **记录 ID 前缀**(下游按前缀检索):`#04-02-R-N` —— 逐成员对账行(结论 ∈ 匹配 / 渲染端需改 / 数据端缺失);`#04-02-G-N` —— 缺失接口候选(独立节,`### #04-02-G-N:标题` + `**渲染端需求**` / `**数据端现状**` / `**待确认**`)。
|
||||
- **缺失候选节结论行**(固定写法,必须出现):`**候选结论:** 本步登记 N 项缺失接口候选(未经用户裁决,不视为最终缺失清单,见 D-13)`。
|
||||
- **`## 处置` 必备内容**:本步只读、零生产代码改动;适配工作(04-03+)未在本 run 规划、由用户在本探索结果与缺失候选裁决后另行规划;`HeroRendering`(D-18)与 `core.*`(D-12)为显式排除项;缺失接口按 D-13 增量确认。
|
||||
|
||||
## Source Audit(多源覆盖审计)
|
||||
|
||||
| SOURCE | ID | Feature/Requirement | Plan | Status | Notes |
|
||||
|--------|----|---------------------|------|--------|-------|
|
||||
| GOAL | — | Phase 4:「渲染端通过新数据层接口驱动,并同时支持移动端与桌面端布局」 | 04-02 | COVERED(增量·探索) | D-17 增量:本 run 只做勇士移动的接口探索;适配实施与双布局属后续增量,未在本 run 规划 |
|
||||
| REQ | REND-01 | 渲染端适配新数据层接口 | 04-02 | COVERED(仅探索) | 本 run 交付 REND-01 勇士移动子集的差异账本,不实施适配;验收边界未提供 → 见 assumptions 的 FLAGGED ASSUMPTION |
|
||||
| REQ | REND-02 | 渲染端同时支持移动端与桌面端布局 | 04-02 | COVERED(不涉及) | 本 run 范围不含双布局;REND-02 验收边界未提供 → 见 assumptions 的 FLAGGED ASSUMPTION |
|
||||
| CONTEXT | D-05 | 以接口为准,不受数据端实现变动影响 | 04-02 | COVERED | 数据端锚点引用现行签名与 barrel 导出;签名变动记入「未能从阅读确定」 |
|
||||
| CONTEXT | D-09 | 允许只读子代理扫描 | 04-02 | COVERED | Task 2 派只读子代理;子代理仅回传文本,不得写文件 |
|
||||
| CONTEXT | D-11 | `getHeroStatusOn` 等裸函数多为待删除 | 04-02 | COVERED(边界) | 该裸函数属 UI 属性读取,非勇士移动接口;只在「处置」说明其不属本增量范围,不登记为缺失 |
|
||||
| CONTEXT | D-12 | `core.*` 属旧引擎适配,归第五阶段 | 04-02 | COVERED | `core.*` 为显式排除项,不产生对账行/候选 |
|
||||
| CONTEXT | D-13 | 缺失接口待改时逐步确认,不一次定死 | 04-02 | COVERED | 「缺失接口候选」节只登记候选 + 数据端现状,不设计、不修复、不视为最终清单 |
|
||||
| CONTEXT | D-17 | 下一步=勇士移动适配;先接口探索再适配 | 04-02 | COVERED | 本计划即「先接口探索」的一半;适配半未规划 |
|
||||
| CONTEXT | D-18 | `HeroRendering` 暂不处理,用户先改数据端 | 04-02 | COVERED | `HeroRendering`(alpha/贴图/渲染粒度钩子)为显式排除项 |
|
||||
| RESEARCH | — | (本阶段无 RESEARCH.md) | — | N/A | Phase 4 未产出 RESEARCH.md,无研究项需覆盖 |
|
||||
|
||||
## Estimate Basis(估算依据)
|
||||
|
||||
`estimate-calibration` 返回 `factor: 1`、`sample_count: 0`、`confidence: low`(项目无历史样本),故 `tokens == raw_tokens`,并如实标注 `confidence: low`。本计划按「执行者实际触及量」估算:Task 1 读交付文档结构范式 + 两个基准切开面 + 写骨架(约 14k);Task 2 数据端/渲染端两侧清单(约 22k,重型整文件读取按 D-09 委派只读子代理);Task 3 对账、缺失候选、未确定、处置与门禁(约 18k);固定开销约 4k;合计约 58k,落在 smart-zone 预算内。
|
||||
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@C:/Users/book/.config/opencode/gsd-core/workflows/execute-plan.md
|
||||
@C:/Users/book/.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-01-SUMMARY.md
|
||||
@.planning/phases/04-render-adaptation/04-RENDER-INTERFACE-AUDIT.md
|
||||
@.planning/phases/04-render-adaptation/04-PATTERNS.md
|
||||
@.planning/phases/07-data-fixes/07-LOADSTATE-AUDIT.md
|
||||
@.planning/phases/02-pathfinding/02-INTERFACE-DRAFT.md
|
||||
@AGENTS.md
|
||||
@dev.md
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="tracer">
|
||||
<name>Task 1(tracer):交付文档骨架 + 勇士移动一条端到端对账切片 —— 7 段结构 + `#04-02-R-01` 双锚点实测 + 结构/CRLF 门禁转绿</name>
|
||||
<files>.planning/phases/04-render-adaptation/04-HERO-MOVER-INTERFACE.md</files>
|
||||
<read_first>
|
||||
- .planning/phases/07-data-fixes/07-LOADSTATE-AUDIT.md:1-14(元信息块 + 背景/方法骨架)
|
||||
- .planning/phases/02-pathfinding/02-INTERFACE-DRAFT.md:1-10(「接口事实源」声明块写法)
|
||||
- .planning/phases/04-render-adaptation/04-RENDER-INTERFACE-AUDIT.md:1-23(元信息块/方法段写法)与 :30-34(`#04-01-M-01..05` 勇士移动既有登记,作为本计划的输入账本)
|
||||
- .planning/phases/04-render-adaptation/04-CONTEXT.md(D-11 / D-12 / D-13 / D-17 / D-18)
|
||||
- packages-user/client-modules/src/render/map/extension/hero.ts:76-132(构造器、`hero.addHook`、`hero.x`/`hero.y`/`hero.direction`/`hero.image` 使用点)与 :452-517(`MapHeroHook` 全部钩子方法名)
|
||||
- packages-user/client-modules/src/render/map/extension/types.ts:13-40,63-159(`IMapExtensionManager` / `IMapHeroRenderer` 契约)
|
||||
- packages-user/client-modules/src/action/move.ts:1-40(`// @ts-expect-error 需要重构` 与 `HeroMover` / `IMoveController` import)
|
||||
- packages-user/data-common/src/common/mover.ts:40-64,100-164,166-233,235-351(`ObjectAnimDirection` / `IMoverController` / `IObjectMoverHooks` / `IObjectMover`)
|
||||
- packages-user/data-base/src/hero/types.ts:275-322,399-417(`IHeroLocationHooks` / `IHeroLocation` / `IHeroMover`)
|
||||
- packages-user/data-base/src/hero/mover.ts:22-76(`HeroMover` 类公开面)
|
||||
- dev.md(「双端分离」「命名规则」「注释规范」;交付文档换行 CRLF)
|
||||
</read_first>
|
||||
<action>
|
||||
(1) 新建 `04-HERO-MOVER-INTERFACE.md`,先写标题与 5 行元信息块:`**日期:** 2026-09-18`;`**范围:**` 勇士移动子系统(渲染端使用点 → 数据端现行接口),排除 `HeroRendering` 与 `core.*`(D-18/D-12);`**性质:**` 只读接口探索,未修改任何生产代码(D-17);`**接口基准:**` `packages-user/data-common/src/common/mover.ts`、`packages-user/data-base/src/hero/{types,mover}.ts` 及各自 barrel 现行导出(D-05);`**输入账本:**` `04-RENDER-INTERFACE-AUDIT.md` 的 `#04-01-M-01..05`。**全文使用 CRLF 换行**(dev.md「换行使用 CRLF 格式」);Task 2/3 追加内容同样保持 CRLF,不得出现孤立 `LF`。
|
||||
(2) 写 `## 背景`:D-17(对账暴露的主要失配点在勇士移动;下一步先接口探索并找出缺失接口,再适配)、本步只读、明确本步不实施适配、不裁决缺失接口(D-13)、不涉 `HeroRendering`(D-18)与 `core.*`(D-12)。
|
||||
(3) 写 `## 方法`:枚举两个面 ——(a)**数据端现行接口面** = `data-common` 移动器族(`IObjectMovable` / `IObjectMover` / `IObjectMoverHooks` / `IMoverController` / `ObjectMoveStep` 各族 / `ObjectAnimDirection`)+ `data-base/hero` 位置移动族(`IHeroState` / `IHeroLocation` / `IHeroMover` / `IHeroLocationHooks` / `IHeroFollowersControllerHooks` / `IHeroStateHooks` / `HeroMover`)+ 各 `index.ts` barrel 实际导出;(b)**渲染端勇士移动使用面** = `render/map/extension/{hero,types,manager}.ts` + `action/move.ts` + `client.ts` 接线点,`render/map/{moving,status,renderer}.ts` 仅作移动器契约参考(不登记为独立对账对象)。判定三态固定为 **匹配 / 渲染端需改 / 数据端缺失**;带 `// @ts-expect-error 需要重构` 的 import 一律先归「渲染端需改」,不归「数据端缺失」。证据纪律:每条含 `接口/成员名 + 两侧 file:line`;静态阅读不能定论者进「未能从阅读确定(未猜测)」,不写成缺失或错配。允许按 D-09 派只读子代理(仅回传文本、不得写文件)。
|
||||
(4) 写 7 个二级标题占位:`## 背景` / `## 数据端现行接口` / `## 渲染端现状` / `## 逐成员对账(匹配 / 渲染端需改 / 数据端缺失)` / `## 缺失接口候选` / `## 未能从阅读确定(未猜测)` / `## 处置`(Task 2/3 在同一骨架上横向补齐,不再改结构)。
|
||||
(5) **端到端切片(本任务唯一实测对账行)**:以 `MapHeroRenderer` 构造期的钩子注册为对象,从渲染端 `packages-user/client-modules/src/render/map/extension/hero.ts:81`(`hero.addHook(new MapHeroHook(this))`)与 :457-516(`MapHeroHook implements Partial<IHeroMoveControllerHooks>`:`onSetImage` / `onSetPosition` / `onTurnHero` / `onStartMove` / `onMoveHero` / `onEndMove` / `onJumpHero` / `onSetAlpha` / `onAddFollower` / `onRemoveFollower` / `onRemoveAllFollowers` / `onSetFollowerAlpha`)出发,打开数据端基准核对:`addHook` 来自 `IHookable`(经 `packages-user/data-common/src/common/mover.ts:235` 的 `IObjectMover<T> extends IHookable<...>` 承接),`onSetPos` 在 `IHeroLocationHooks`(`packages-user/data-base/src/hero/types.ts:283`)与 `IObjectMoverHooks`(`packages-user/data-common/src/common/mover.ts:216`)各有对位,而 `onSetPosition`/`onStartMove`/`onEndMove`/`onMoveHero`/`onJumpHero`/`onTurnHero`/`onAddFollower`/`onRemoveFollower`/`onRemoveAllFollowers`/`onSetFollowerAlpha` 在数据端无同名对位。据此在 `## 逐成员对账(...)` 下写表头 `| ID | 成员 | 渲染端锚点 | 数据端锚点 | 对账结论 | 说明 |` 与 `#04-02-R-01` 一行:成员=`IHeroMoveControllerHooks` 钩子族;渲染端锚点=hero.ts:81,457-516;数据端锚点=`data-common/src/common/mover.ts:166,216` 与 `data-base/src/hero/types.ts:277,283`(逐项写「有对位」或「无对位,最接近:<file:line>」);结论=`渲染端需改`(随 `IHeroMoveControllerHooks` 整体重构)。同时在 `## 数据端现行接口` 与 `## 渲染端现状` 各写至少 1 条带 `file:line` 的最小条目,证明三段相互可达。
|
||||
(6) 写 `## 处置` 初稿:本步只读、未改任何生产代码;适配工作(04-03+)不在本 run 规划;明确 `HeroRendering`(D-18)与 `core.*`(D-12)为排除项;缺失接口候选须经用户逐步裁决(D-13);`getHeroStatusOn` 类裸函数(D-11)不属本增量范围。
|
||||
(7) 全程不得修改任何被查源码;本任务只写该交付文档一个文件。
|
||||
</action>
|
||||
<reversibility rating="reversible">交付文档是只读探索的记录,可随时修订或废弃;它不引入生产代码、公共接口或契约约束,因此这一步的任何取舍都不难回退。</reversibility>
|
||||
<verify>
|
||||
<automated>node -e "const fs=require('fs');const p='.planning/phases/04-render-adaptation/04-HERO-MOVER-INTERFACE.md';const t=fs.readFileSync(p,'utf8');const need=['## \u80cc\u666f','## \u6570\u636e\u7aef\u73b0\u884c\u63a5\u53e3','## \u6e32\u67d3\u7aef\u73b0\u72b6','## \u9010\u6210\u5458\u5bf9\u8d26\uff08\u5339\u914d / \u6e32\u67d3\u7aef\u9700\u6539 / \u6570\u636e\u7aef\u7f3a\u5931\uff09','## \u7f3a\u5931\u63a5\u53e3\u5019\u9009','## \u672a\u80fd\u4ece\u9605\u8bfb\u786e\u5b9a\uff08\u672a\u731c\u6d4b\uff09','## \u5904\u7f6e'];const miss=need.filter(h=>t.indexOf(h)<0);if(miss.length>0){console.error('MISSING HEADINGS '+miss.length);process.exit(1)}const rows=t.split(/\r?\n/).filter(l=>/^\|\s*#04-02-R-\d+\s*\|/.test(l));if(rows.length<1){console.error('NO RECON ROWS');process.exit(1)}const bad=rows.filter(l=>!/client-(base|modules)\/[^\s|]*:\d+/.test(l)||!/data-(common|base|state)\/[^\s|]*:\d+/.test(l));if(bad.length>0){console.error('ROW MISSING TWO-SIDED ANCHOR '+bad.length);process.exit(1)}if(t.indexOf('HeroRendering')<0||t.indexOf('core.*')<0){console.error('MISSING SCOPE EXCLUSION');process.exit(1)}console.log('OK headings 7 recRows '+rows.length)"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "MISSING HEADINGS" / "NO RECON ROWS" / "ROW MISSING TWO-SIDED ANCHOR" / "MISSING SCOPE EXCLUSION"</fails_when>
|
||||
<automated>node -e "const fs=require('fs');const s=fs.readFileSync('.planning/phases/04-render-adaptation/04-HERO-MOVER-INTERFACE.md','utf8');const lf=(s.match(/\n/g)||[]).length;const crlf=(s.match(/\r\n/g)||[]).length;if(lf!==crlf){console.error('NON-CRLF LINE ENDINGS '+(lf-crlf));process.exit(1)}console.log('OK CRLF lines '+crlf)"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "NON-CRLF LINE ENDINGS"(交付文档出现非 CRLF 换行,违反 dev.md「换行使用 CRLF 格式」)</fails_when>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- 交付文档存在于约定路径,7 个二级标题逐字存在(`## 背景` / `## 数据端现行接口` / `## 渲染端现状` / `## 逐成员对账(匹配 / 渲染端需改 / 数据端缺失)` / `## 缺失接口候选` / `## 未能从阅读确定(未猜测)` / `## 处置`)
|
||||
- 元信息块 5 行齐备(日期 / 范围 / 性质 / 接口基准 / 输入账本),且「范围」明写排除 `HeroRendering` 与 `core.*`
|
||||
- `## 逐成员对账(...)` 表列序为 `ID | 成员 | 渲染端锚点 | 数据端锚点 | 对账结论 | 说明`,至少含 1 条 `#04-02-R-*`,同行两侧均有 `file:line` 锚点,结论取自三态
|
||||
- `#04-02-R-01` 的钩子族判定来自实际打开基准文件核对(hero.ts 的钩子方法名与 `data-common`/`data-base` 现行 hooks 逐项比对),而非照抄 04-RENDER-INTERFACE-AUDIT.md
|
||||
- `## 数据端现行接口` 与 `## 渲染端现状` 各至少 1 条带 `file:line` 条目,三段(数据端 / 渲染端 / 对账)相互可达
|
||||
- `## 处置` 含 D-12 / D-13 / D-17 / D-18 的明确表述;全文 CRLF;无生产代码改动
|
||||
</acceptance_criteria>
|
||||
<done>交付文档骨架与一条勇士移动端到端对账切片贯通,7 段结构 + 双锚点对账行 + CRLF 门禁转绿;Task 2/3 只需在同一模板上横向补齐</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2:数据端现行接口 + 渲染端现状两侧清单 —— 成员级 `file:line` 清点 + barrel 实际导出核对 + `@ts-expect-error` 标记清单</name>
|
||||
<files>.planning/phases/04-render-adaptation/04-HERO-MOVER-INTERFACE.md</files>
|
||||
<read_first>
|
||||
- .planning/phases/04-render-adaptation/04-HERO-MOVER-INTERFACE.md(Task 1 产出的现有内容,在同一模板上追加)
|
||||
- .planning/phases/04-render-adaptation/04-RENDER-INTERFACE-AUDIT.md:30-34,82-88,110-127(`#04-01-M-01..05` 与「未能从阅读确定」中与勇士移动相关条目,作为输入与对照)
|
||||
- packages-user/data-common/src/common/mover.ts:12-45,47-140,142-164,166-233,235-351,357-731(移动器族接口与基类)
|
||||
- packages-user/data-base/src/hero/types.ts:275-322,327-349,351-388,390-417,455-506,508-571,845-956(位置/移动/跟随者/顶层状态)
|
||||
- packages-user/data-base/src/hero/mover.ts:1-100(`HeroMover` 公开面与 `IHeroMoveTopImpl` 用法)
|
||||
- packages-user/data-common/src/index.ts、packages-user/data-common/src/common/index.ts、packages-user/data-base/src/index.ts、packages-user/data-base/src/hero/index.ts、packages-user/data-state/src/index.ts、packages-user/data-state/src/hero/index.ts、packages-user/data-state/src/ins.ts(barrel 实际导出核对)
|
||||
- packages-user/client-modules/src/render/map/extension/hero.ts(整文件;构造器 / `addHeroMoving` / `updateHeroTexture` / `moveEntity` / `jumpEntity` / `move` / `jumpTo` / `addFollower` / `removeFollower` / `removeAllFollowers` / `setFollowerAlpha` / `setHeroAnimateDirection` / `turn` / `MapHeroHook`)
|
||||
- packages-user/client-modules/src/render/map/extension/types.ts:13-40,63-159 与 packages-user/client-modules/src/render/map/extension/manager.ts:1-44
|
||||
- packages-user/client-modules/src/action/move.ts:1-183(`HeroKeyMover` 全类)
|
||||
- packages-user/client-modules/src/client.ts:143-154(注释掉的 `addHero` 接线)与 packages-user/client-modules/src/render/map/{moving,status,renderer}.ts(仅移动器契约参考锚点,如 `addMovingBlock` / `IMovingBlock` / 图层更新钩子)
|
||||
- dev.md(「双端分离」「不转发导出」「无类型导入」)
|
||||
</read_first>
|
||||
<action>
|
||||
(1) **数据端现行接口段**:逐成员登记并给 `file:line` —— `data-common/src/common/mover.ts` 的 `ObjectMoveType` / `ObjectSpecialStep` / `ObjectAnimDirection` / `IObjectMovable` / 各 `IObjectMoveStep*` / `ObjectMoveStep` / `IMoverController` / `IObjectMoverHooks` / `IObjectMover`(含每个方法名与签名,如 `start(): Readonly<IMoverController> | null`、`step/stepFace/forward/backward/speed/face/animDir/tp/jump/push/clear/setPos/setFaceDir/setMoveDir`),以及 `data-base/src/hero/types.ts` 的 `HeroMoveCode` / `IHeroMoveTopHandler` / `IHeroMoveTopImpl` / `IHeroMoverConfig` / `IHeroMover` / `IHeroLocationHooks` / `IHeroLocation` / `IHeroFollower` / `IHeroFollowersControllerHooks` / `IHeroFollowersController` / `IHeroStateHooks` / `IHeroState` 与 `data-base/src/hero/mover.ts` 的 `HeroMover` 公开面(`config` / `getConfig` / `useTopImplementation`)。另单列一条 **barrel 实际导出核对**:写明 `IHeroMover` / `IHeroLocation` / `HeroMover` 等符号实际可经哪个包取得(例如 `HeroMover` 在 `@user/data-base`,`IMoverController` 在 `@user/data-common`,`@user/data-state` barrel 未导出 `HeroMover`/`IMoveController`),每条给 barrel `file:line`。
|
||||
(2) **渲染端现状段**:逐使用点登记并给 `file:line` —— `extension/hero.ts`(构造器 `:76-102` 的 `hero.addHook`/`hero.x`/`hero.y`/`hero.direction`/`hero.image`、`addHeroMoving :110-132`、`updateHeroTexture :138-163`、`tick :165-189`、`setImage :191-196`、`setAlpha :198-200`、`setPosition :202-207`、`moveEntity :215-238`、`jumpEntity :264-280`、`startMove :282-286`、`waitMoveEnd :295-298`、`stopMove :300-305`、`move :307-314`、`jumpTo :316-339`、`addFollower :341-376`、`removeFollower :378-422`、`removeAllFollowers :424-429`、`setFollowerAlpha :431-435`、`setHeroAnimateDirection :437-439`、`turn :441-450`、`MapHeroHook :457-517`);`extension/types.ts`(`heroMap` 键类型 `:15`、`addHero`/`removeHero` `:26-35`、`IMapHeroRenderer` `:63-159`);`extension/manager.ts`(`:2` import 源、`:18` heroMap、`:26-44` addHero/removeHero);`action/move.ts`(`:3-4` 重构标记与 import、`:11` 类、`:19` `IMoveController`、`:29,:33` `HeroMover` 类型、`:66-67` 全局门控、`:97,:123,:156` `core.status.lockControl`、`:125-127` `oneStep`+`startMove(...)`、`:130-134` `controller.onEnd`、`:137` `on('stepEnd')`、`:169-171` `controller.queue`+`push({type:'dir',value})`、`:180` `off('stepEnd')`);`client.ts:148-153`(被注释的 `addHero(this.hero.mover, layer)` 接线)。段末单列 **`// @ts-expect-error 需要重构` 清单**(文件 + 行号)。`render/map/{moving,status,renderer}.ts` 仅作移动器契约参考,写明其与勇士移动的触点即可,不逐成员展开。
|
||||
(3) **重型整文件读取按 D-09 委派只读子代理**(`hero.ts`、`extension/types.ts`、`action/move.ts`、`data-common/src/common/mover.ts`、`data-base/src/hero/types.ts`、`render/map/moving.ts`/`status.ts`/`renderer.ts`)。子代理只回传事实表(每行:成员名 + 所属 `file:line` + 签名或使用形态),**不得写文件、不贴大段源码**;主执行者据事实表登记并在存疑处按 `file:line` 切片复核。
|
||||
(4) 只修改交付文档;不得改动任何生产源码,不得新增计划文件。
|
||||
</action>
|
||||
<verify>
|
||||
<automated>node -e "const fs=require('fs');const t=fs.readFileSync('.planning/phases/04-render-adaptation/04-HERO-MOVER-INTERFACE.md','utf8');const seg=(h)=>{const i=t.indexOf(h);if(i<0)return '';const rest=t.slice(i+h.length);const j=rest.search(/\r?\n## /);return j<0?rest:rest.slice(0,j)};const d=seg('## \u6570\u636e\u7aef\u73b0\u884c\u63a5\u53e3');const r=seg('## \u6e32\u67d3\u7aef\u73b0\u72b6');const cnt=(s,re)=>(s.match(re)||[]).length;const dA=cnt(d,/data-(common|base|state)\/[^\s|)]*:\d+/g);const rA=cnt(r,/client-(base|modules)\/[^\s|)]*:\d+/g);if(dA<8){console.error('DATA SECTION ANCHORS '+dA);process.exit(1)}if(rA<12){console.error('RENDER SECTION ANCHORS '+rA);process.exit(1)}if(t.indexOf('@ts-expect-error')<0){console.error('NO TSEXEPECT MARKER SURVEY');process.exit(1)}if(!/index\.ts:\d+/.test(t)){console.error('NO BARREL EXPORT CHECK');process.exit(1)}console.log('OK dataAnchors '+dA+' renderAnchors '+rA)"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "DATA SECTION ANCHORS" / "RENDER SECTION ANCHORS" / "NO TSEXEPECT MARKER SURVEY" / "NO BARREL EXPORT CHECK"</fails_when>
|
||||
<automated>node -e "const fs=require('fs');const s=fs.readFileSync('.planning/phases/04-render-adaptation/04-HERO-MOVER-INTERFACE.md','utf8');const lf=(s.match(/\n/g)||[]).length;const crlf=(s.match(/\r\n/g)||[]).length;if(lf!==crlf){console.error('NON-CRLF LINE ENDINGS '+(lf-crlf));process.exit(1)}console.log('OK CRLF lines '+crlf)"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "NON-CRLF LINE ENDINGS"(追加内容未保持 CRLF)</fails_when>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- `## 数据端现行接口` 覆盖 `IObjectMover` / `IObjectMoverHooks` / `IMoverController` / `IObjectMovable` / `ObjectAnimDirection` / `IHeroMover` / `IHeroLocation` / `IHeroLocationHooks` / `IHeroFollowersControllerHooks` / `IHeroStateHooks` / `IHeroState` / `HeroMover`,每条带 `data-*` `file:line`
|
||||
- 该段含 barrel 实际导出核对(明确 `HeroMover` / `IMoveController` / `IMoverController` 等符号的实际来源包),并带 `index.ts:line` 锚点
|
||||
- `## 渲染端现状` 覆盖 `extension/hero.ts`(构造器 + 移动/跳跃/跟随者/朝向/动画方向/钩子注册与回调)、`extension/types.ts`(heroMap 与 `IMapHeroRenderer`)、`extension/manager.ts`(addHero/removeHero/heroMap)、`action/move.ts`(`HeroKeyMover` 全类)、`client.ts` 接线点,每条带 `client-*` `file:line`
|
||||
- 段末列出全部 `// @ts-expect-error 需要重构` 出现位置(文件 + 行号)
|
||||
- 相关渲染文件 `render/map/{moving,status,renderer}.ts` 仅作为移动器契约参考登记,未被当作独立对账对象
|
||||
- 被查两渲染端包零改动;未新增任何计划文件;全文 CRLF
|
||||
</acceptance_criteria>
|
||||
<done>数据端现行接口与渲染端现状两侧清单成员级落位,每条可追溯到 `file:line`,barrel 导出与 `@ts-expect-error` 标记清单齐备</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3:逐成员三态对账 + 缺失接口候选 + 未确定/处置定稿 + 只读与范围门禁</name>
|
||||
<files>.planning/phases/04-render-adaptation/04-HERO-MOVER-INTERFACE.md</files>
|
||||
<read_first>
|
||||
- .planning/phases/04-render-adaptation/04-HERO-MOVER-INTERFACE.md(Task 1/2 产出,做定稿而非重写)
|
||||
- .planning/phases/04-render-adaptation/04-CONTEXT.md(D-11 / D-12 / D-13 / D-17 / D-18;Deferred Ideas)
|
||||
- .planning/phases/04-render-adaptation/04-RENDER-INTERFACE-AUDIT.md:30-34(`M-01..05` 归类口径)与 :110-127(「未能从阅读确定」第 2、3、4 条:渲染粒度钩子、`hero.image`、无对位旧状态读)
|
||||
- packages-user/data-common/src/common/mover.ts:142-233,235-351(`IMoverController` / `IObjectMoverHooks` / `IObjectMover` 逐方法签名,用于三态判定)
|
||||
- packages-user/data-base/src/hero/types.ts:277-322,399-417,486-506,858-872,889-954(hooks 与 `IHeroState` 成员,用于三态判定)
|
||||
- packages-user/data-base/src/hero/mover.ts:22-76(`HeroMover` 与 `config`/`getConfig`/`useTopImplementation`)
|
||||
- packages-user/client-modules/src/action/move.ts:118-182(`HeroKeyMover.tryStartMove`/`onStepEnd`/`endMove` 的移动器期望:`oneStep` / `startMove(false,false,false,true)` / `controller.onEnd` / `controller.queue` / `controller.push` / `stepEnd` 事件)
|
||||
- packages-user/data-state/src/ins.ts(`state` 单例)与 packages-user/data-base/src/hero/types.ts:889-904(`IHeroState.location` 可达性参考)
|
||||
- dev.md(「双端分离」「其他要求」)
|
||||
</read_first>
|
||||
<action>
|
||||
(1) **逐成员对账段定稿**:为每个渲染端使用成员写一行 `#04-02-R-N`(N 从 2 递增,`R-01` 由 Task 1 占用),结论取 匹配 / 渲染端需改 / 数据端缺失 三态之一,两侧均给 `file:line`(数据端无对位时写「无对位,最接近:<file:line>」)。至少覆盖:`HeroMover` / `IMoveController` 的 import 源与类型名(`action/move.ts:4` vs `data-base/src/hero/mover.ts:22`、`data-common/src/common/mover.ts:142`)→ 渲染端需改;`HeroAnimateDirection`(hero.ts:6,53,97,170,372,437;types.ts:5,147)→ 渲染端需改(改 `ObjectAnimDirection`,`data-common/src/common/mover.ts:40`);`IHeroMoveController`(hero.ts:8,79;types.ts:7,15,27,35;manager.ts:2,18,27,39)→ 渲染端需改(拆为 `IHeroLocation` `data-base/src/hero/types.ts:303` / `IHeroMover` `:399`);`IHeroMoveControllerHooks`(hero.ts:10,61,457)→ 渲染端需改(拆为 `IObjectMoverHooks` `data-common/src/common/mover.ts:166` / `IHeroLocationHooks` `data-base/src/hero/types.ts:277` / `IHeroFollowersControllerHooks` `:486`);`hero.x`/`hero.y`(hero.ts:87-88,117,122,127,129)→ 匹配(`IObjectMovable.x/y` `data-common/src/common/mover.ts:48-51`);`hero.direction`(hero.ts:89,125,193)→ 渲染端需改(`IObjectMover.faceDirection`/`moveDirection` `:243,245`);`hero.image`(hero.ts:115,119,121,143)→ 按既有口径随 `IHeroMoveController` 归「渲染端需改」,并在「未能从阅读确定」交叉引用其与 D-18 的边界;`hero.addHook`(hero.ts:81)→ 匹配(`IHookable`,经 `IObjectMover extends IHookable` `data-common/src/common/mover.ts:235`);`HeroKeyMover` 移动器期望(`action/move.ts:125-127,130-134,137,169-171,180`)逐成员对到 `IObjectMover.step/start`(`:293,350`)与 `IMoverController.push(...ObjectMoveStep[])`(`:152`)、`done`(`:144`)、`onEnd`(`:146`)→ 渲染端需改;`manager.ts:18` `heroMap` 键类型 → 渲染端需改。
|
||||
(2) **缺失接口候选段**:把渲染端需要而数据端无对位的成员(例如按方向/时长的渲染粒度移动钩子 `onMoveHero(direction, time)` / `onJumpHero(x, y, time, waitFollower)` / `onTurnHero` / `onStartMove` / `onEndMove`,以及 `HeroKeyMover` 依赖的 `oneStep` 与 `controller.queue`)逐条登记为 `### #04-02-G-N:标题` + `- **渲染端需求**:` / `- **数据端现状**:` / `- **待确认**:`;数据端现状必须引用最接近的现行成员 `file:line`(例如 `data-common/src/common/mover.ts:166-233` 的 hooks 方法集 / `:142-164` 的控制器成员集)。**只记录候选**:不设计、不修复、不改数据端接口(D-13)。节末写固定结论行 `**候选结论:** 本步登记 N 项缺失接口候选(未经用户裁决,不视为最终缺失清单,见 D-13)`。
|
||||
(3) **未能从阅读确定段**:逐条登记无法静态定论项,例如 `hero.image` 贴图别名归属与 D-18 边界、`controller.queue`(`action/move.ts:169`)的运行时形状与 `IMoverController` 的可达性、`state.hero.location` 是否为当前渲染端可取的入口、渲染粒度钩子候选与 04-RENDER-INTERFACE-AUDIT.md 第 2 条候选的重叠关系。不得写成缺失或错配。
|
||||
(4) **处置段定稿**:本步只读、零生产代码改动;适配工作(04-03+)由用户在本探索结果与候选裁决后另行规划(D-17/D-13);显式排除 `HeroRendering`(D-18)与 `core.*`(D-12);`getHeroStatusOn` 类裸函数(D-11)不属本增量。
|
||||
(5) **门禁与提交**:运行只读门禁、CRLF 门禁、范围门禁(无 04-03+ 计划文件);随后以 `docs(04-02): 勇士移动接口探索(只读,D-17)` 提交**仅**该交付文档与 `04-02-PLAN.md`,不得提交任何生产源码改动。
|
||||
</action>
|
||||
<verify>
|
||||
<automated>node -e "const fs=require('fs');const t=fs.readFileSync('.planning/phases/04-render-adaptation/04-HERO-MOVER-INTERFACE.md','utf8');const rows=t.split(/\r?\n/).filter(l=>/^\|\s*#04-02-R-\d+\s*\|/.test(l));if(rows.length<10){console.error('TOO FEW RECON ROWS '+rows.length);process.exit(1)}const bad=rows.filter(l=>!/client-(base|modules)\/[^\s|]*:\d+/.test(l)||!/data-(common|base|state)\/[^\s|]*:\d+/.test(l));if(bad.length>0){console.error('ROW MISSING TWO-SIDED ANCHOR '+bad.length);process.exit(1)}for(const v of ['\u5339\u914d','\u6e32\u67d3\u7aef\u9700\u6539','\u6570\u636e\u7aef\u7f3a\u5931']){if(t.indexOf(v)<0){console.error('MISSING VERDICT VOCAB '+v);process.exit(1)}}const lines=t.split(/\r?\n/);const gh=lines.map((l,i)=>({l,i})).filter(o=>/^### #04-02-G-\d+/.test(o.l));for(const g of gh){const body=lines.slice(g.i+1,g.i+8).join('\n');if(body.indexOf('\u6e32\u67d3\u7aef\u9700\u6c42')<0||body.indexOf('\u6570\u636e\u7aef\u73b0\u72b6')<0||body.indexOf('\u5f85\u786e\u8ba4')<0){console.error('GAP CANDIDATE MISSING FIELDS');process.exit(1)}}if(t.indexOf('\u5019\u9009\u7ed3\u8bba')<0){console.error('GAP SECTION WITHOUT CONCLUSION');process.exit(1)}console.log('OK recRows '+rows.length+' gapCandidates '+gh.length)"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "TOO FEW RECON ROWS" / "ROW MISSING TWO-SIDED ANCHOR" / "MISSING VERDICT VOCAB" / "GAP CANDIDATE MISSING FIELDS" / "GAP SECTION WITHOUT CONCLUSION"</fails_when>
|
||||
<automated>node -e "const fs=require('fs');const s=fs.readFileSync('.planning/phases/04-render-adaptation/04-HERO-MOVER-INTERFACE.md','utf8');const lf=(s.match(/\n/g)||[]).length;const crlf=(s.match(/\r\n/g)||[]).length;if(lf!==crlf){console.error('NON-CRLF LINE ENDINGS '+(lf-crlf));process.exit(1)}console.log('OK CRLF lines '+crlf)"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "NON-CRLF LINE ENDINGS"(交付文档出现非 CRLF 换行)</fails_when>
|
||||
<automated>git status --porcelain -- packages-user/client-base packages-user/client-modules</automated>
|
||||
<fails_when>stdout 非空(任一被查渲染端包出现改动/新增行)—— 违反只读约束</fails_when>
|
||||
<automated>node -e "const fs=require('fs');const dir='.planning/phases/04-render-adaptation';const plans=fs.readdirSync(dir).filter(f=>/-PLAN\.md$/.test(f)).sort();const allowed=['04-01-PLAN.md','04-02-PLAN.md'];const extra=plans.filter(p=>allowed.indexOf(p)<0);if(extra.length>0){console.error('UNEXPECTED PLAN FILES '+extra.join(','));process.exit(1)}console.log('OK plan scope '+plans.join(','))"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "UNEXPECTED PLAN FILES"(出现了 04-03+ 适配计划文件,即提前规划了未授权的适配工作)</fails_when>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- 逐成员对账行 ≥ 10 条,每条含两侧 `file:line`;三态词表(匹配 / 渲染端需改 / 数据端缺失)在文档中出现
|
||||
- `HeroMover`/`IMoveController`、`HeroAnimateDirection`、`IHeroMoveController`、`IHeroMoveControllerHooks`、`hero.x/y/direction/image/addHook`、`HeroKeyMover` 的移动器期望、`manager.ts` heroMap 键类型均已逐成员落位
|
||||
- 「缺失接口候选」独立成节,每条 `### #04-02-G-*` 含 `渲染端需求` / `数据端现状` / `待确认`,数据端现状带 `file:line`;节末含固定结论行;候选未设计/未修复(D-13)
|
||||
- 「未能从阅读确定(未猜测)」非空,且 `hero.image`、`controller.queue` 等不确定项只登记不判定
|
||||
- `## 处置` 含 D-11 / D-12 / D-13 / D-17 / D-18 的明确表述,并明写适配工作(04-03+)未规划
|
||||
- `git status --porcelain -- packages-user/client-base packages-user/client-modules` 为空;`.planning/phases/04-render-adaptation` 下计划文件仅 `04-01-PLAN.md` 与 `04-02-PLAN.md`;全文 CRLF
|
||||
- 交付文档已以 `docs(04-02)` 提交,提交内容仅含该文档与 `04-02-PLAN.md`
|
||||
</acceptance_criteria>
|
||||
<done>逐成员三态对账、缺失接口候选、未确定与处置全部定稿;只读/CRLF/范围门禁全绿;交付文档已提交,用户可据此裁决缺失候选并规划后续勇士移动适配</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<threat_model>
|
||||
## Trust Boundaries
|
||||
|
||||
| Boundary | Description |
|
||||
|----------|-------------|
|
||||
| 数据端接口基准 → 探索文档 | 只读引用 `data-common` / `data-base` / `data-state` 的接口与 barrel;基准不变,仅记录差异 |
|
||||
| 渲染端源码 → 探索文档 | 只读引用 `client-base` / `client-modules`;不得产生任何写回 |
|
||||
| 执行者 → 仓库工作树 | 本 run 唯一允许写入的交付文件是探索文档;被查渲染端包必须保持零改动 |
|
||||
| 缺失接口候选 → 用户裁决/后续适配 | 候选被下游用户与适配计划消费;把「渲染端需改」误报为「数据端缺失」会诱导错误的数据端改动(D-13) |
|
||||
| 探索范围 → Phase 5 / 后续增量 | 把 `HeroRendering`(D-18)或 `core.*`(D-12)混入本增量会扩大范围并污染阶段边界 |
|
||||
|
||||
## STRIDE Threat Register
|
||||
|
||||
| Threat ID | Category | Component | Severity | Disposition | Mitigation Plan |
|
||||
|-----------|----------|-----------|----------|-------------|-----------------|
|
||||
| T-04-02-01 | Tampering | 被查渲染端包 `packages-user/client-base` / `client-modules` | high | mitigate | Task 1–3 均为只读;Task 3 门禁 `git status --porcelain -- packages-user/client-base packages-user/client-modules` 必须为空,非空即失败 |
|
||||
| T-04-02-02 | Repudiation | 对账行(无锚点则不可追溯) | medium | mitigate | 每条 `#04-02-R-*` 强制含两侧 `file:line`;由 Task 1/3 的 `<verify>` 门禁机器判定(两侧锚点正则) |
|
||||
| T-04-02-03 | Spoofing | 「缺失接口候选」段 | high | mitigate | 每条候选必须含 `渲染端需求` / `数据端现状` / `待确认` 三段且数据端现状带 `file:line`;节末固定结论行;门禁机器判定;明写「未经用户裁决不视为最终清单」(D-13) |
|
||||
| T-04-02-04 | Elevation of Privilege | 探索范围(`HeroRendering` / `core.*` / 双布局 / legacy 移植) | medium | mitigate | D-12/D-18 为显式排除项;文中排除说明与「处置」必须出现 `HeroRendering` 与 `core.*`;范围门禁禁止产生 04-03+ 计划文件 |
|
||||
| T-04-02-05 | Information Disclosure | 探索文档引用的源码行与接口名 | low | accept | 记录只含接口名、文件行号与成员签名,不含凭据/密钥 |
|
||||
| T-04-02-06 | Denial of Service | 只读子代理越权写入(D-09) | low | mitigate | Task 2 明确子代理仅回传事实表、不写文件、不贴大段源码;最终由主执行者只读门禁统一验证 |
|
||||
| T-04-02-SC | Tampering | npm / pnpm 依赖安装 | high | mitigate | 本计划零依赖变更、不修改任何 `package.json`;出现安装需求即暂停并要求用户确认包合法性(blocking human checkpoint),不得自动继续 |
|
||||
|
||||
</threat_model>
|
||||
|
||||
<verification>
|
||||
1. 结构门禁(Task 1):探索文档 7 个二级标题逐字存在;至少 1 条 `#04-02-R-*` 双锚点对账行;文档含 `HeroRendering` 与 `core.*` 排除说明。
|
||||
2. CRLF 门禁(Task 1/2/3):文档无孤立 `LF`,全文 CRLF(dev.md「换行使用 CRLF 格式」)。
|
||||
3. 两侧清单门禁(Task 2):数据端段 ≥ 8 个 `data-*` `file:line` 锚点;渲染端段 ≥ 12 个 `client-*` `file:line` 锚点;含 `@ts-expect-error` 标记清单与 `index.ts:line` barrel 导出核对。
|
||||
4. 对账完整性门禁(Task 3):`#04-02-R-*` ≥ 10 条且每条两侧锚点;三态词表齐备;每条 `### #04-02-G-*` 含 `渲染端需求` / `数据端现状` / `待确认`;`候选结论` 行存在。
|
||||
5. 只读门禁(Task 3):`git status --porcelain -- packages-user/client-base packages-user/client-modules` 输出为空。
|
||||
6. 范围门禁(Task 3):`.planning/phases/04-render-adaptation` 下计划文件仅 `04-01-PLAN.md` 与 `04-02-PLAN.md`(未规划 04-03+ 适配)。
|
||||
7. 人工核对:「未能从阅读确定(未猜测)」的逐条理由;`## 处置` 对 D-11/D-12/D-13/D-17/D-18 的表述;缺失候选是否确实只记录未设计。
|
||||
8. 提交:`docs(04-02)` 仅含探索文档与 `04-02-PLAN.md`。
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- `.planning/phases/04-render-adaptation/04-HERO-MOVER-INTERFACE.md` 按 7 段骨架产出,成员级覆盖数据端现行接口与渲染端现状,逐成员三态对账(匹配 / 渲染端需改 / 数据端缺失)每条两侧 `file:line` 可追溯(D-05/D-17)。
|
||||
- 缺失接口候选独立成节、含「渲染端需求 / 数据端现状 / 待确认」,且只记录不设计不修复、未经用户裁决不视为最终清单(D-13)。
|
||||
- `HeroRendering`(D-18)与 `core.*`(D-12)被显式排除,未产生对账行或候选;`getHeroStatusOn` 类裸函数(D-11)不属本增量。
|
||||
- 被查两个渲染端包零改动;本 run 只新增探索文档一个交付文件,未规划、未实施任何适配工作(04-03+)。
|
||||
- 静态阅读无法定论的项进入「未能从阅读确定(未猜测)」而非写成缺失/错配;全文 CRLF。
|
||||
- 用户可据此裁决缺失候选并规划后续勇士移动适配。
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
Create `.planning/phases/04-render-adaptation/04-02-SUMMARY.md` when done
|
||||
</output>
|
||||
Loading…
Reference in New Issue
Block a user