mirror of
https://github.com/motajs/template.git
synced 2026-09-30 07:20:18 +08:00
docs(04-10): register render structural-refactor read-only impact inventory (D-51/D-57 step 1)
This commit is contained in:
parent
3bc37b596d
commit
c3fb5068d1
@ -181,8 +181,9 @@ Plans:
|
||||
3. 移动端(窄屏)布局下,同一场景正常显示且可操作
|
||||
4. 数据端与渲染端保持双端分离——数据端无 DOM,仍可在 Node 环境跑回放验证
|
||||
|
||||
**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)整体仍未完成
|
||||
**Plans**: 9 已执行 + 1 已规划待执行(04-10) — 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)已执行;**04-10(渲染端结构性重构影响范围清点·只读,D-51..D-57 第一步)已规划待执行**(执行前须 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-24):** 第十个增量 `04-10` = 渲染端结构性重构(用户裁定 2026-09-23 · D-51..D-57)**第一步·只读影响清点**:把 `packages-user/client-modules/src/render/` 下的通用内容(`render/components`、`render/elements`、`render/map` 三文件夹 + `render/utils/layout.ts`,规划日实测 **39** 文件)迁往渲染系统层 `packages-user/client-base/src/`(D-51/D-52;目标布局按 D-53:`client-base/src/{components,elements,map}/` + `client-base/src/layout/`,**不新建 `render/` 目录**);不移植 `render/utils/` 其余(`index.ts`/`saves.ts`/`use.ts`)与 `ui`/`fx`/`weather`/`render` 顶层文件(D-54);legacy 一律只报告(D-55);用户并发改动零触碰(D-56)。台账按 A 被移集合内部交叉引用 / B 外部导入点(含 `entry-client` / `entry-data` / `packages/legacy-ui` 经 `@user/client-modules` 公共面的间接依赖)/ C barrel 与导出面 / D 分层与循环依赖风险(`client-base` 不得反向依赖 `client-modules`,含 `package.json` 依赖现状)/ E legacy 命中(仅报告)/ F 未确定 六类分组,每行精确到文件或符号 + `file:line` 且 ≥2 锚点;产出 `04-STRUCTURE-MIGRATION-IMPACT.md`,生产代码零改动且**零命名变更**;**已规划待执行**,执行前须 Task 0 汇报关卡等待用户「可以执行」;第二步(移植实施)待用户审阅后另行规划;`REND-01` / `REND-02` 仍 Pending。
|
||||
**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:
|
||||
@ -219,6 +220,10 @@ Plans:
|
||||
|
||||
- [x] 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
|
||||
|
||||
**Wave 9** *(blocked on Wave 8 completion)*
|
||||
|
||||
- [ ] 04-10-PLAN.md — 渲染端结构性重构影响范围清点(**只读**,D-51..D-57 第一步):把 `packages-user/client-modules/src/render/` 的通用内容(`render/components`、`render/elements`、`render/map` 三文件夹 + `render/utils/layout.ts`,规划日实测 **39** 文件)迁往渲染系统层 `packages-user/client-base/src/`(D-51/D-52),目标布局按 D-53(`client-base/src/{components,elements,map}/` + `client-base/src/layout/`,不新建 `render/`);不移植 `render/utils/` 其余(`index.ts`/`saves.ts`/`use.ts`)与 `ui`/`fx`/`weather`/`render` 顶层文件(D-54);legacy 只报告(D-55)、用户并发改动零触碰(D-56)。台账按 A 被移集合内部交叉引用(8 方向:`components→elements`、`elements→map`、→ `render/renderer`、→ `render/use.ts`、→ `client-modules/src/shared.ts`、→ `@user/client-base` 自包引用、`map/extension/*→map/types`、零命中机器证据)/ B 外部导入点(`client-modules/src/{client.ts,types.ts}`、`render/index.tsx`、`render/ui` 8 文件 10 处含深层导入、`render/utils/{saves.ts,index.ts}`、`fallback/ui.ts`,以及 `entry-client` / `entry-data` / `packages/legacy-ui` 经公共面的间接依赖)/ C barrel 与导出面(7 节点 + 断链判定)/ D 分层与循环依赖风险(`client-base` 不得反向依赖 `client-modules`;`client-base/package.json` 依赖缺口;`?raw` shader;`dev.md` 规则对照)/ E legacy 命中(仅报告)/ F 未确定 六类分组,每行 ≥2 个 `file:line` 锚点;产出 `04-STRUCTURE-MIGRATION-IMPACT.md`,生产代码零改动且零命名变更;门禁 = 只读基线逐条一致 + 11 节结构 / 39 文件清单 / 类别行数与双锚点 / 两处零命中机器证据 / CRLF / 既有产物保护与计划范围 + 人工复核;`autonomous: false`(Task 0 汇报关卡);第二步(移植实施)待用户审阅后另行规划;`REND-01` / `REND-02` 仍 Pending
|
||||
|
||||
**UI hint**: yes
|
||||
|
||||
### Phase 5: Legacy 移植
|
||||
|
||||
539
.planning/phases/04-render-adaptation/04-10-PLAN.md
Normal file
539
.planning/phases/04-render-adaptation/04-10-PLAN.md
Normal file
@ -0,0 +1,539 @@
|
||||
---
|
||||
phase: 04-render-adaptation
|
||||
plan: 10
|
||||
type: execute
|
||||
wave: 9
|
||||
depends_on:
|
||||
- 04-01
|
||||
- 04-02
|
||||
- 04-03
|
||||
- 04-04
|
||||
- 04-05
|
||||
- 04-06
|
||||
- 04-07
|
||||
- 04-08
|
||||
- 04-09
|
||||
files_modified:
|
||||
- .planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.md
|
||||
autonomous: false
|
||||
requirements:
|
||||
- REND-01
|
||||
- REND-02
|
||||
estimate:
|
||||
tokens: 95000
|
||||
raw_tokens: 95000
|
||||
tasks: 4
|
||||
confidence: low
|
||||
must_haves:
|
||||
truths:
|
||||
- "**本计划的第一个 block 点是 Task 0 的 `blocking-human` 汇报关卡(AGENTS.md 硬要求)**:Task 0 必须先向用户汇报「要解决的问题(`packages-user/client-modules/src/render/` 下的通用渲染内容放错层,须下沉到渲染系统层 `packages-user/client-base/src/`)、锁定裁定(D-51..D-57:移植集合 / 目标布局 / 不移植集合 / legacy 不考虑 / 用户并发改动不可触碰 / 第一步交付物)、大致解决方案(只读影响清点,唯一交付物 `04-STRUCTURE-MIGRATION-IMPACT.md`,11 节结构 / A–F 六类分列 / 每行 ≥2 个 `file:line` 锚点)、**本步为只读、不引入任何命名变更**(不新增 / 不改名任何公共、受保护、私有成员或字段,也不裁定 `client-base/src/{components,elements,map,layout}` 下的文件名 / barrel 名)、验证方式与只读证明」,然后必须**停下等待**用户明确回复「可以执行」四个字;收到该回复前不得执行任何任务、不得派发任何执行子代理。无论触发方式(`/gsd-execute-phase`、`/gsd-manager`、`/gsd-autonomous`、子代理/执行器派发)或配置模式(`.planning/config.json` 的 `mode: yolo`、`workflow.auto_advance`)如何,均不得自动放行。"
|
||||
- "**只读硬约束(生产代码零改动)**:本 run 生产源码改动为 **0**——`git status --porcelain -- packages packages-user src` 在 Task 1 步骤 (0a) 起始逐行原样记录进 `## 方法`(规划日 2026-09-24 实测为 ` M packages-user/data-base/src/enemy/types.ts` 单条,属用户并发改动 D-56),Task 1 / Task 3 门禁断言其后**逐条一致**(不新增、不消失、状态码不变);`files_modified` 只含 `04-STRUCTURE-MIGRATION-IMPACT.md` 一个交付物;本 PLAN 与 `04-10-SUMMARY.md` 属计划/执行簿记,不算生产改动。"
|
||||
- "**被移集合清单完整(39 个文件,一个不少、一个不多)**:`## 被移集合清单(39 文件)` 必须逐条列出 D-52 明示的移植集合全部文件并给出各文件职责与 D-53 目标落点——`render/components/` **13** 个(`choices.tsx` / `floorSelect.tsx` / `icons.tsx` / `index.ts` / `input.tsx` / `list.tsx` / `misc.tsx` / `page.tsx` / `scroll.tsx` / `textbox.tsx` / `textboxTyper.ts` / `thumbnail.tsx` / `tip.tsx`)、`render/elements/` **5** 个(`cache.ts` / `index.ts` / `misc.ts` / `props.ts` / `types.ts`)、`render/map/` **20** 个(`block.ts` / `constant.ts` / `element.ts` / `index.ts` / `moving.ts` / `renderer.ts` / `status.ts` / `types.ts` / `vertex.ts` / `viewport.ts` + `extension/{door,hero,index,manager,text,types}.ts` **6** + `shader/{back.frag,back.vert,map.frag,map.vert}` **4**)、`render/utils/layout.ts` **1**;并写明目标落点(三个文件夹直接落 `client-base/src/{components,elements,map}/`,`layout.ts` 单独开 `client-base/src/layout/`,**不新建 `render/` 目录**),且明写本步**不移动、不复制、不预建**任何目标文件。"
|
||||
- "**A 类(被移集合内部交叉引用)逐条给两侧 `file:line` 锚点**:至少覆盖 ① `components → elements`(`tip.tsx:7` / `textbox.tsx:33` / `textboxTyper.ts:5`);② `elements → map`(`elements/index.ts:2` / `elements/props.ts:4`);③ 被移集合 → **留在 `render/` 顶层**的 `renderer`(`elements/index.ts:3` / `components/textboxTyper.ts:6` / `components/misc.tsx:14`);④ 被移集合 → **留在 `render/`** 的 `use.ts`(`components/choices.tsx:8` / `tip.tsx:4` / `scroll.tsx:31` / `input.tsx:14` / `misc.tsx:10`);⑤ 被移集合 → **`client-modules/src/shared.ts`**(`map/vertex.ts:25` / `map/element.ts:5` / `map/renderer.ts:53` / `map/extension/door.ts:9`);⑥ 被移集合 → **`@user/client-base`(自包引用)**(`map/extension/hero.ts:16` / `map/moving.ts:3` / `map/renderer.ts:13` / `map/types.ts:12` / `map/vertex.ts:28`);⑦ `map/extension/*` → `map/types`(`extension/{door.ts:7,hero.ts:13,manager.ts:8,types.ts:4,text.ts:8}`)。**每行须含「导入处 `file:line`」+「被导入符号的声明 / barrel `file:line`」两个锚点。**"
|
||||
- "**B 类(外部导入点)把移出集合之外的每一处 importer 枚举到 `file:line`**:至少覆盖 ① `client-modules/src/types.ts:2`(`./render/map`);② `client-modules/src/client.ts:25`(`./render/map`);③ `client-modules/src/render/index.tsx:5,45,46`(`./elements` / `./components`);④ `render/ui/` **8** 个文件的 **10** 处 `../components` 导入(`main.tsx:9` / `save.tsx:16` / `settings.tsx:16,21` / `statistics.tsx:8` / `statusBar.tsx:3` / `title.tsx:31` / `viewmap.tsx:26,29` / `toolbar.tsx:13,19`);⑤ `render/utils/saves.ts:2`(`../components`);⑥ `render/utils/index.ts:1`(`export * from './layout'`——barrel 引用被移文件);⑦ `fallback/ui.ts:2`(深层导入 `../render/components/tip`);⑧ 其它 monorepo 包经 `@user/client-modules` 公共面**间接**依赖(`entry-client/src/create.ts:10,27`、`entry-data/src/mota.ts:11,32`、`packages/legacy-ui/src/preset/ui.ts:86,96,105`);⑨ 对照扫描的机器证据:`git grep -n -F \"render/components\"` / `-F \"render/elements\"` / `-F \"render/map\"`(同限 `packages` 与 `src`)在 `packages-user` 之外**零命中**。"
|
||||
- "**C 类(barrel 与导出面)逐个登记并给出「现状导出 → 移出后是否断链」的判定**:`render/components/index.ts`(12 条 `export *`)、`render/elements/index.ts`(`createElements()` + `export * from './cache' | './misc' | './props'`,同时 import `../map` 与 `../renderer`)、`render/map/index.ts`(`export * from './extension'` + 9 条)、`render/index.tsx:45,46,51`(`export * from './components' | './elements' | './renderer'`)、`render/utils/index.ts:1`(`export * from './layout'`,**移出即断链**)、`client-modules/src/index.ts:15`(`export * from './render'`——把被移集合再导出给 `@user/client-modules` 消费者)、`client-base/src/index.ts`(现行 `export * from './load' | './material' | './save' | './types'`)。**C 行不得把「是否新增 barrel / 如何补位」写成结论**(属 F 类、由用户裁定)。"
|
||||
- "**D 类(分层与循环依赖风险)非空且逐条给两个锚点**:① 移入后 `client-base` 反向依赖 `client-modules`——`client-modules/src/shared.ts`(A 类 4 处);② 同向——`render/renderer`(3 处);③ 同向——`render/use.ts`(5 处,且 `use.ts:2` 自身 import `../weather`);④ 同向——`render/utils`(1 处);⑤ 自包引用——`@user/client-base` 的 5 处;⑥ `package.json` 依赖缺口——`client-base/package.json:3-9` 现行只声明 `@motajs/audio` / `@motajs/render` / `@motajs/client-base` / `@user/data-base` / `@user/data-state`,而被移集合还用到 `@motajs/render-vue`(12 个组件 + `elements/props.ts:1`)、`@motajs/system`、`@motajs/common`(`elements/index.ts:1`)、`@user/data-common`(`map/renderer.ts:38` / `map/vertex.ts:2` / `map/extension/{hero.ts:11,manager.ts:1,types.ts:2}`);⑦ 反向依赖**现状**机器证据——`git grep -n \"client-modules\" -- packages-user/client-base` 规划日退出码 1(当前零命中),即该风险由本次移植**引入**;⑧ shader 的 `?raw` 导入(`map/renderer.ts:43-46`,`./shader/{map,back}.{vert,frag}?raw`)在换包后是否仍被构建链处理;⑨ `dev.md` 的单向依赖 / 双端分离规则对照。**D 类不得自拟解耦方案(不得写「应下沉 / 应抽类型 / 应保留跨包依赖」),只登记风险与机器证据。**"
|
||||
- "**E 类(legacy 命中·仅报告)与 in-scope 严格分开**:标题下明写「本节仅报告:按 D-55 不考虑任何 legacy 内容,legacy 相关报错一律不管、不修、不登记为待办」。逐条登记被移集合内的 legacy 耦合事实——① `core.*` 命中(`components/choices.tsx:675,715,717,718,719,728,733,770,772,773,774,783,789`、`components/floorSelect.tsx:62,181`、`components/misc.tsx:312`、`components/textboxTyper.ts:906`、`components/thumbnail.tsx:75`、`components/tip.tsx:103`、`elements/cache.ts:11,87,89,131,151,202,206,393,469`、`elements/misc.ts:221,228`);② 全局 `loading` + `Mota.require('@user/data-base')`(`elements/cache.ts:491-492`、`elements/misc.ts:89-94,219-225`,D-14);③ `client.*` 在移出集合内 **0** 命中(须给机器证据命令与原样输出);④ `packages/` 与 `src/` 的对照扫描结论与命令;⑤ `render/elements/cache.ts` 的 legacy 贴图路径现状(对照 04-06 / 04-07 的 big-image 清退面)。"
|
||||
- "**F 类(未能从阅读确定·未猜测)非空且只登记不判定**,至少覆盖:① 目标文件名(`client-base/src/layout/layout.ts` 还是 `layout/index.ts`;`client-base/src/{components,elements,map}/index.ts` 是否沿用同名 barrel)——**命名须用户反馈并获同意后才能使用**(AGENTS.md);② `client-base/src/index.ts` 是否新增 `export * from './{components,elements,map,layout}'`(导出面是否扩张 / 如何补 `render/index.tsx` 的断链);③ 被移集合对留在 `client-modules` 的 `shared.ts` / `renderer` / `use.ts` / `render/utils` 的依赖如何解耦;④ `@user/client-base` 自包引用的改写方式;⑤ `render/utils/index.ts` 在 `layout.ts` 移出后的归属(D-54 明示 `utils/index.ts` 不移植 ⇒ 断链处置);⑥ `client-base/package.json` 的依赖缺口是否在第二步补齐(D-37 有先例,本步不裁定);⑦ shader `?raw` 在 `client-base` 构建链下是否仍可用;⑧ `packages/legacy-ui` 经 `Mota.require('@user/client-modules')` 运行时取 `mainRenderer` / `client` 的插件面影响(legacy);⑨ `render/elements/index.ts` 的 `createElements()` 注册点(`mainRenderer.registerElement(...)`)在 `client-base` 无渲染器实例时如何接线。**不得把本类任何一条写成错配、缺失、残留或待办。**"
|
||||
- "**第二步(移植实施)不被规划**:文档只清点、分类、定位、分组,**不含**移植方案、不含 import 重写方案、不含任何代码改动建议、不产出 `04-11-PLAN.md` 或任何新 `*-PLAN.md`;`## 处置` 明写「第一步只读清点完成;第二步(移植实施)待用户审阅本文件后另行规划」(D-51 / D-57)。"
|
||||
- "**REND-01 / REND-02 在本 run 后仍保持 Pending**:本计划只清点结构性重构(分层纠正)的影响面,既未实施移植,也未实施渲染端接口适配与移动端 / 桌面端双布局(见 assumptions 的两条 FLAGGED ASSUMPTION)。"
|
||||
- "**验证可运行且不臆造通过**:本计划的「运行结果」= 只读门禁(porcelain 基线逐条一致 + 用户 `04-CONTEXT.md` 未提交改动仍在)+ 静态内容门禁(11 节结构、被移集合 39 文件路径齐备、A–F 六类行数下限与关键词、每行 ≥2 个 `file:line` 锚点、F 类条数)+ 机器证据复验(`client-base` 对 `client-modules` 零反向引用、被移集合对 `ui`/`fx`/`weather` 零引用、`packages` / `src` 对 `render/(components|elements|map)` 零命中)+ 既有产物保护门禁(`04-01..04-09-*` 的 porcelain 为空)+ 计划文件范围门禁(phase 目录内不得出现 `04-11+`)+ CRLF 门禁 + 人工代码复核;本步为只读清点,**无运行时行为可观察**,故不得以任何无法运行的门禁冒充通过。"
|
||||
artifacts:
|
||||
- path: .planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.md
|
||||
provides: "渲染端结构性重构(通用内容由 `client-modules/src/render/` 迁往 `client-base/src/`,D-51..D-57)**第一步·只读影响台账**:元信息块 + 背景 / 方法 / 被移集合清单(39 文件,含各文件职责与目标落点)/ A 被移集合内部交叉引用 / B 外部导入点 / C barrel 与导出面 / D 分层与循环依赖风险 / E legacy 命中(仅报告)/ F 未能从阅读确定(未猜测)/ 处置;每行含文件或符号名 + 命中处 `file:line` + 目标锚点 `file:line` + 问题描述 + 影响 + 置信,供用户审阅后裁定第二步的移植方案与 import 重写集"
|
||||
key_links:
|
||||
- "`packages-user/client-modules/src/render/{components,elements,map}/` + `render/utils/layout.ts`(D-52 移植集合,规划日实测 **39** 文件)↔ `packages-user/client-base/src/{components,elements,map}/` + `packages-user/client-base/src/layout/`(D-53 目标布局,**不新建 `render/` 目录**)"
|
||||
- "`packages-user/client-modules/src/render/index.tsx:45,46,51`(留在 `client-modules` 的 `export * from './components' | './elements' | './renderer'`)↔ `packages-user/client-modules/src/index.ts:3,15`(`import { createGameRenderer, createRender } from './render'` 与 `export * from './render'`)↔ `@user/client-modules` 公共面的消费者(`entry-client/src/create.ts:10,27` / `entry-data/src/mota.ts:11,32` / `packages/legacy-ui/src/preset/ui.ts:86,96,105`)—— 移出后前两条断链,公共面收窄"
|
||||
- "`packages-user/client-modules/src/render/utils/index.ts:1`(`export * from './layout'`)↔ `packages-user/client-modules/src/render/utils/layout.ts`(唯一外部入口)—— `layout.ts` 移出而该 barrel 按 D-54 不移植 ⇒ 断链点,第二步必改"
|
||||
- "`packages-user/client-modules/src/shared.ts` ↔ `packages-user/client-modules/src/render/map/{vertex.ts:25,element.ts:5,renderer.ts:53}` 与 `render/map/extension/door.ts:9`(`../../shared` / `../../../shared`)—— 移入 `client-base` 后变成 `client-base` → `client-modules` **反向依赖**,违反 dev.md 单向依赖(D-57 明列的循环依赖风险)"
|
||||
- "`packages-user/client-modules/src/render/{renderer.ts,use.ts}` ↔ `render/elements/index.ts:3` / `render/components/{textboxTyper.ts:6,misc.tsx:14}` / `render/components/{choices.tsx:8,tip.tsx:4,scroll.tsx:31,input.tsx:14,misc.tsx:10}` —— 同上,反向依赖候选(共 8 处);`render/use.ts:2` 自身 import `../weather`,链条可能牵出 `ui` / `fx` / `weather`"
|
||||
- "`packages-user/client-base/package.json:3-9`(现行 deps:`@motajs/audio` / `@motajs/render` / `@motajs/client-base` / `@user/data-base` / `@user/data-state`)↔ 被移集合用到的 `@motajs/render-vue` / `@motajs/system` / `@motajs/common` / `@user/data-common` —— 依赖缺口,第二步若移植必须补声明(本步只登记,不得提出补声明或安装建议)"
|
||||
- "`packages-user/client-modules/src/render/map/renderer.ts:43-46`(`./shader/{map,back}.{vert,frag}?raw`)↔ `render/map/shader/*`(随集合移动,**相对路径不变**)—— `?raw` 由构建链处理,换包后是否仍成立属 F 类"
|
||||
- "`git status --porcelain -- packages packages-user src`(Task 1 步骤 (0a) 逐行记录,规划日实测 ` M packages-user/data-base/src/enemy/types.ts` 单条)↔ Task 1 / Task 3 门禁的逐条一致断言 + `.planning/phases/04-render-adaptation/04-CONTEXT.md` 未提交改动仍在的断言 ↔ 只读(生产代码零改动)与 D-56 证明"
|
||||
- "`git grep -n \"client-modules\" -- packages-user/client-base`(规划日退出码 1、零命中)↔ Task 1 / Task 2 门禁复验 ↔ 「分层规则现状未被破坏」的机器证据"
|
||||
assumptions:
|
||||
- "**FLAGGED ASSUMPTION(specless fallback)— REND-01 edge unresolved:** 未提供 REND-01(渲染端适配新数据层接口)的验收边界;本计划**不发明**阈值,只交付结构性重构(分层纠正)第一步的只读影响台账(D-51 / D-57)。用户须在推进第二步与其余渲染适配前补齐 REND-01 的边界判据。"
|
||||
- "**FLAGGED ASSUMPTION(specless fallback)— REND-02 edge unresolved:** 未提供 REND-02(移动端与桌面端双布局)的验收边界;本计划不涉及双布局,也不发明其验收阈值。"
|
||||
- "**规划日实测数值与口径须用户在审阅时确认:** 规划日 2026-09-24 在 HEAD `3bc37b5 docs: 修正 types.ts 中关于录像参数的描述`(分支 `refine/data-client`)实测:移植集合共 **39** 文件(`components` 13 / `elements` 5 / `map` 20 = 顶层 10 + `extension` 6 + `shader` 4 / `utils/layout.ts` 1);A 类内部交叉引用 **8** 个方向 / 约 **30** 处 import;B 类外部导入点 **8** 个文件族(约 17 处)+ 3 个包间接依赖(`entry-client` / `entry-data` / `packages/legacy-ui`);C 类 barrel **7** 个节点;D 类风险 **9** 条;E 类 legacy 文件 **8** 个(`core.*` 约 **31** 处 + `loading` / `Mota.require` 3 处);F 类未确定 **9** 条。**执行日一律以当日实测为准**(行号可能因用户并发编辑漂移),任一与规划日不同即以当日实测写入文档并在 SUMMARY 说明差异,**不得按本计划的规划日数值硬写**。"
|
||||
- "**执行前必须复核(未确定项,不猜):** Task 1 步骤 (0a) 必须在动手前打开当日 HEAD 的工作树逐条核对:① `render/{components,elements,map}` 的三个目录文件清单与 `render/utils/layout.ts` 是否存在(数量与文件名,规划日 13 / 5 / 20 / 1);② A 类各方向的当日行号;③ B 类 importer 的当日行号与 `packages` / `src` 对照扫描结论;④ C 类各 barrel 的现行导出集合;⑤ D 类 `client-base/package.json` 现行 deps 与 `git grep -n \"client-modules\" -- packages-user/client-base` 的退出码;⑥ E 类 legacy 命中行号;⑦ `git status --porcelain -- packages packages-user src` 基线(含用户并发条目)。"
|
||||
- "**用户可能有执行日的并发未提交改动(D-56):** 规划日实测基线已含 ` M packages-user/data-base/src/enemy/types.ts`(用户正在改数据端 `data-base`);一律以 Task 1 步骤 (0a) 当日实测为基线(逐行原样记录,含 `.planning/phases/04-render-adaptation/04-CONTEXT.md` 的既有未提交改动——该路径不在集合内故不计入 porcellain 基线),**不得回滚 / 暂存 / 提交 / 修改**用户的任何未提交改动;若基线中出现其它 `packages` / `packages-user` / `src` 条目,属清点范围内的既有改动,须一并记录并原样保留。"
|
||||
- "**被移集合在清点期间可能继续变化:** 用户会同步修改其它文件(D-56),且 04-09 刚落地 `render/map/{vertex,renderer,extension/hero}.ts` 的 texture 适配;故行号与成员集合以**当日实测**为准,本计划的规划日行号仅作定位线索。"
|
||||
- "**无运行时验证可得(诚实降级):** 本步为只读清点,不产生任何运行时行为(不启动渲染、不改代码、不新增测试),因此承载体是「只读门禁 + 静态内容门禁 + 机器证据复验 + 人工代码复核」。**不得**以任何无法运行的门禁冒充通过。"
|
||||
- "**`.planning/graphs/*` 是过期工装态:** 其中的分层 / 依赖标签早于本次结构性重构;该文件**不得**作为基准或命中依据,只作对照登记(是否重建由用户决定)。"
|
||||
prohibitions:
|
||||
- "不得在用户明确回复「可以执行」四个字之前执行本计划的任何任务、或派发任何执行子代理(AGENTS.md 的第一个 block 点约束;不因触发方式或 `yolo` / `auto_advance` 模式而放宽)。"
|
||||
- "不得修改任何生产源码:`packages/**`、`packages-user/**`、`src/**` 的生产文件一律零改动;不得新增 / 删除 / 改写任何 `.ts` / `.tsx` / `.frag` / `.vert` 文件;**不得移动、不得复制、不得预建** `client-base/src/{components,elements,map,layout}` 下的任何文件或目录(移植属第二步)。"
|
||||
- "不得改动 `package.json` / `pnpm-lock.yaml` / `tsconfig.json`;不得新增依赖;不得为 D 类的「依赖缺口」提出补声明、安装或改配置的建议(只登记事实,属第二步由用户裁定)。"
|
||||
- "不得修改任何既有 jsDoc / 注释文本(AGENTS.md);不得新增公共 / 受保护 / 私有成员或字段;**不得引入任何命名变更、不得为 `client-base/src/{components,elements,map,layout}` 下的文件 / 目录命名拍板**(命名须先向用户反馈并获同意——`layout.ts` 是否改名 `index.ts`、barrel 是否沿用同名等一律进 F 类)。"
|
||||
- "不得改写 / 覆盖 / 改号 `04-01`..`04-09` 的既有 `*-PLAN.md` 与 `*-SUMMARY.md`;除本 `04-10-PLAN.md`、`04-STRUCTURE-MIGRATION-IMPACT.md` 与 `04-10-SUMMARY.md` 外不得写任何其它文件。"
|
||||
- "不得规划或实施第二步:不得给出移植方案、不得给出 import 重写写法或代码改动建议、不得产出 `04-11+` 或任何新 `*-PLAN.md`;`client-base` 反向依赖的解耦方式一律进 F 类、由用户裁定。"
|
||||
- "不得把任何 legacy 内容当成问题或待办(D-55):`core.*` / 全局 `loading` / `hook` / `Mota.require` 命中一律只报告,不得修复、不得登记为待办、不得写成错配或残留。"
|
||||
- "不得触碰、暂存、提交用户的并发改动(D-56):尤其不得提交 `.planning/phases/04-render-adaptation/04-CONTEXT.md` 的既有未提交改动与 `packages-user/data-base/**` 下的改动。"
|
||||
- "不得把 `packages/` 与 `src/` 的命中写成待修改项、不得为其提出修改建议;该二者只登记事实与核对命令。"
|
||||
- "不得把 A / B / C / D / E 混为一类:A 记被移集合**内部**交叉引用、B 记移出集合**之外**的导入点、C 记 barrel 与导出面、D 记分层与循环依赖风险(含 `package.json` 依赖现状)、E 记 legacy 命中(仅报告);同一事实若跨类,拆条并互相引用,不得互相冒充。"
|
||||
- "不得使用 `import type`(dev.md 项目规则);不得新增、删除或修改任何测试文件与既有测试。"
|
||||
- "不得以「无运行时」为由弱化验证:每条 `<automated>` 必须有 `<fails_when>`;确实无法运行的门禁必须显式声明为不可得并降级为静态 + 人工,不得伪造绿。"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Phase 4 第十个增量(用户裁定 2026-09-23 · D-51..D-57 **第一步**)—— **渲染端结构性重构影响范围清点(只读)**。
|
||||
|
||||
**要解决的问题:**
|
||||
|
||||
1. **通用渲染内容放错层(D-51)**:`packages-user/client-modules/src/render/` 下的**通用内容**(`components` / `elements` / `map` 三个文件夹 + `utils/layout.ts`)本属渲染**系统层**,却放在实现层 / 交互层包 `client-modules` 中;`dev.md` 的双端分离要求 `@user/client-base`(系统层)承载渲染核心系统、`@user/client-modules`(实现层)只保留实现 / 交互内容。分层不纠正,后续 REND-01 / REND-02 的实现会持续往错误的一层堆。
|
||||
2. **移植面未知,不能直接动手(D-57)**:用户裁定走**两步**——第一步只读影响清点(产出影响台账文档),第二步移植实施待用户审阅后另行规划。没有第一手的范围台账就直接搬,会漏改外部导入点、漏发现「移入后反向依赖 `client-modules`」这类分层硬伤。
|
||||
3. **分层 / 循环依赖是硬红线(D-57)**:`client-base` 不得反向依赖 `client-modules`。规划日已实测到 4 个明确的反向依赖候选(`client-modules/src/shared.ts` 4 处、`render/renderer` 3 处、`render/use.ts` 5 处、`render/utils` 1 处)与 1 个自包引用(`@user/client-base` 5 处),必须在台账中逐条落到 `file:line`,让用户据以裁定第二步的解耦方式。
|
||||
4. **legacy 一律不考虑(D-55)**:本次大重构的目的就是删除 legacy。被移集合内仍有大量 `core.*`(约 31 处)与全局 `loading` / `Mota.require('@user/data-base')`(3 处)耦合;这些**只报告**,不得修复、不得登记为待办。
|
||||
5. **用户并发改动不可触碰(D-56)**:用户正在并发修改数据端(规划日基线已含 ` M packages-user/data-base/src/enemy/types.ts`);一律零触碰、零提交。
|
||||
6. **本步零命名变更**:只读清点不引入任何公共 / 受保护 / 私有成员或字段的命名变更,也不裁定目标文件名 / barrel 名(命名须先向用户反馈并获同意,AGENTS.md)。
|
||||
|
||||
**大致解决方案:** 只做**只读清点**,产出唯一交付物 `.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.md`。文档 11 节(外加 6 行元信息块):`## 背景` / `## 方法` / `## 被移集合清单(39 文件)` / `## A 被移集合内部交叉引用` / `## B 外部导入点` / `## C barrel 与导出面` / `## D 分层与循环依赖风险` / `## E legacy 命中(仅报告)` / `## F 未能从阅读确定(未猜测)` / `## 处置`。A–E 每节一张**固定列序**表 `| ID | 文件/符号 | 命中处(源) | 目标锚点 | 问题描述 | 影响 | 置信 |`,**每行至少两个 `file:line` 锚点**(源侧 + 目标 / 基准侧),一条记录只归一类、跨类拆条并互相引用;F 类逐条登记静态阅读无法定论项(只登记不判定)。
|
||||
|
||||
**分列规则(写死,防止类别互相冒充):**
|
||||
|
||||
| 类别 | 含义 | 归属规则 |
|
||||
|---|---|---|
|
||||
| A | **被移集合内部交叉引用** | 移植集合**内部**的互相 import(`components → elements`、`elements → map`、`map/extension/* → map/types`),以及移植集合 → **留在 `client-modules` 的**模块(`client-modules/src/shared.ts`、`render/renderer`、`render/use.ts`、`@user/client-base` 自包引用) |
|
||||
| B | **外部导入点** | 移出集合**之外**的每一处 importer:`client-modules/src/{client.ts,types.ts}`、`render/index.tsx`、`render/ui/*`、`render/utils/{saves.ts,index.ts}`、`fallback/ui.ts`,以及其它 monorepo 包经 `@user/client-modules` 公共面的间接依赖(`entry-client` / `entry-data` / `packages/legacy-ui`) |
|
||||
| C | **barrel 与导出面** | `render/{components,elements,map}/index.ts`、`render/index.tsx`、`render/utils/index.ts`、`client-modules/src/index.ts`、`client-base/src/index.ts` 的现行导出集合与「移出后是否断链」判定(**不得裁定是否新增 barrel / 如何补位**,属 F 类) |
|
||||
| D | **分层与循环依赖风险** | 移入后 `client-base` → `client-modules` 的反向依赖候选、`@user/client-base` 自包引用、`client-base/package.json` 依赖缺口、`?raw` shader 构建链、`dev.md` 规则对照;**只登记风险与机器证据,不得自拟解耦方案** |
|
||||
| E | **legacy 命中(仅报告)** | 被移集合内的 `core.*` / 全局 `loading` / `hook` / `Mota.require('@user/data-base')`(D-55:不考虑、不修、不登记为待办);`packages/` 与 `src/` 对照扫描 |
|
||||
| F | **未能从阅读确定** | 目标文件名与命名、barrel 扩张 / 断链补位、反向依赖解耦方式、`render/utils/index.ts` 归属、依赖缺口补齐、`?raw` 可行性、legacy 插件面、`createElements()` 注册点接线;只登记,不得写成错配 / 缺失 / 残留 / 待办 |
|
||||
|
||||
**规划日实测(2026-09-24,HEAD `3bc37b5`,分支 `refine/data-client`;执行日一律以当日实测为准):**
|
||||
|
||||
| 类别 | 规划日实测结果 |
|
||||
|---|---|
|
||||
| 被移集合 | **39** 文件:`components` 13(含 `index.ts`)+ `elements` 5(含 `index.ts`)+ `map` 20(顶层 10 + `extension` 6 + `shader` 4)+ `utils/layout.ts` 1 |
|
||||
| 目标落点(D-53) | `client-base/src/{components,elements,map}/` + `client-base/src/layout/`;**不新建 `render/` 目录** |
|
||||
| A(内部交叉引用) | **8** 个方向 / 约 **30** 处:`components→elements` 3、`elements→map` 2、→`renderer` 3、→`use.ts` 5、→`client-modules/src/shared.ts` 4、→`@user/client-base`(自包)5、`extension/*→map/types` 5;另记「被移集合 → `ui`/`fx`/`weather` **0** 命中」的机器证据 |
|
||||
| B(外部导入点) | **8** 个文件族 / 约 **17** 处:`client.ts:25`、`types.ts:2`、`render/index.tsx:5,45,46`、`render/ui` 8 文件 10 处、`render/utils/saves.ts:2`、`render/utils/index.ts:1`、`fallback/ui.ts:2`;另 3 个包经 `@user/client-modules` 间接依赖(`entry-client/src/create.ts:10,27`、`entry-data/src/mota.ts:11,32`、`packages/legacy-ui/src/preset/ui.ts:86,96,105`);`packages` / `src` 对 `render/(components\|elements\|map)` **零命中** |
|
||||
| C(barrel / 导出面) | **7** 个节点:`components/index.ts`(12 条)、`elements/index.ts`(`createElements` + 3 条)、`map/index.ts`(`extension` + 9 条)、`render/index.tsx:45,46,51`、`render/utils/index.ts:1`(**移出即断链**)、`client-modules/src/index.ts:15`、`client-base/src/index.ts`(4 条) |
|
||||
| D(分层 / 循环) | **9** 条:反向依赖候选 4 族(`shared.ts` / `renderer` / `use.ts` / `render/utils`,共 13 处)、自包引用 5 处、`client-base/package.json` 依赖缺口(缺 `@motajs/render-vue` / `@motajs/system` / `@motajs/common` / `@user/data-common`)、现状零反向引用机器证据(`git grep -n client-modules -- packages-user/client-base` 退出码 1)、`?raw` shader 4 处、`dev.md` 规则对照 |
|
||||
| E(legacy 仅报告) | **8** 个文件:`core.*` 约 **31** 处(`choices.tsx` 13 / `floorSelect.tsx` 2 / `misc.tsx` 1 / `textboxTyper.ts` 1 / `thumbnail.tsx` 1 / `tip.tsx` 1 / `elements/cache.ts` 9 / `elements/misc.ts` 2);`loading` + `Mota.require('@user/data-base')` 3 处(`elements/cache.ts:491`、`elements/misc.ts:89,219`);`client.*` 在移出集合内 **0** 命中(须给机器证据) |
|
||||
| F(未确定) | ≥ **9** 条(见 must_haves) |
|
||||
|
||||
**范围与硬边界:** 被查对象 = 移植集合(39 文件)与其全部 importer;基准 = 当日工作树(HEAD `3bc37b5`)与 `dev.md` 的单向依赖 / 双端分离规则、`packages-user/client-base/package.json`、`packages-user/client-modules/package.json`;`packages/` 与 `src/` **仅报告**;`client-base` 反向依赖 `client-modules` 的解耦方式由用户裁定(F 类);legacy 一律不考虑(D-55);用户并发改动零触碰(D-56)。生产源码零改动;本步不规划第二步。
|
||||
|
||||
**两步走(D-51 / D-57):** 本 run = **第一步(只读清点)**;**第二步(移植实施)不在本 run 规划**,待用户审阅本文件后另行规划。
|
||||
|
||||
## Source Audit(多源覆盖审计)
|
||||
|
||||
| SOURCE | ID | Feature/Requirement | Plan | Status | Notes |
|
||||
|--------|----|---------------------|------|--------|-------|
|
||||
| GOAL | — | Phase 4:「渲染端通过新数据层接口驱动,并同时支持移动端与桌面端布局」 | 04-10 | COVERED(增量·结构性重构只读清点子切片) | 本 run 只产出「通用内容由 `client-modules` 下沉 `client-base`」的只读影响台账;接口适配与双布局属后续增量(REND-02 见 assumptions) |
|
||||
| REQ | REND-01 | 渲染端适配新数据层接口 | 04-10 | COVERED(子切片·只读;需求保持 Pending) | 分层纠正是 REND-01 实现的前置结构条件(D-51);本 run 只清点影响面,不实施;验收边界未提供 → assumptions 的 FLAGGED ASSUMPTION |
|
||||
| REQ | REND-02 | 渲染端同时支持移动端与桌面端布局 | 04-10 | COVERED(不涉及) | 本 run 范围不含双布局;REND-02 验收边界未提供 → assumptions 的 FLAGGED ASSUMPTION |
|
||||
| RESEARCH | — | (本阶段无 `04-RESEARCH.md`) | — | N/A | Phase 4 未产出 RESEARCH.md;等价输入为 04-01 / 04-02 / 04-06 / 04-08 账本与 `04-TEXTURE-INTERFACE-IMPACT.md` 的版式 |
|
||||
| CONTEXT | D-51 | 目标 = 把 `client-modules/src/render/` 下的通用内容迁移到 `client-base/src/`(渲染系统层),纠正分层 | 04-10 | COVERED(第一步·只读) | 台账的「被移集合清单 + 目标落点」节即该决策的事实化;实施属第二步(未规划) |
|
||||
| CONTEXT | D-52 | 移植集合 = `render/components`、`render/elements`、`render/map` 三文件夹 + `render/utils/layout.ts` | 04-10 | COVERED | 门禁断言 39 个文件路径逐条出现;少一个 / 多一个即失败 |
|
||||
| CONTEXT | D-53 | 目标布局:不新建 `render/`;三文件夹落 `client-base/src/{components,elements,map}/`;`layout.ts` 单独 `client-base/src/layout/` | 04-10 | COVERED | `## 被移集合清单` 逐条写明目标落点;prohibitions 禁预建、禁命名拍板 |
|
||||
| CONTEXT | D-54 | 不移植 `render/utils/` 其余(`index.ts` / `saves.ts` / `use.ts`);`ui` / `fx` / `weather` 与 `render` 顶层文件均不移植 | 04-10 | COVERED(边界) | 台账把 `render/use.ts`、`render/renderer.ts`、`render/utils/index.ts`、`saves.ts`、`fallback/ui.ts` 登记为「留下但被引用」的反向依赖候选 / 第二步必改点 |
|
||||
| CONTEXT | D-55 | 不考虑任何 legacy:legacy 报错不管、不修、不登记为待办;只报告 | 04-10 | COVERED(排除) | `## E legacy 命中(仅报告)` 标题下明写该边界;prohibitions 明列不得把 legacy 写成问题 / 待办 |
|
||||
| CONTEXT | D-56 | 用户会同步进行其它修改;不得触碰、不得提交用户的并发改动 | 04-10 | COVERED | Task 1 步骤 (0a) 逐行记录当日基线(规划日含 ` M packages-user/data-base/src/enemy/types.ts`);Task 1 / Task 3 门禁断言逐条一致并断言 `04-CONTEXT.md` 未提交改动仍在;prohibitions 明列 |
|
||||
| CONTEXT | D-57 | 第一步 = 只读影响清点,至少覆盖:被移文件清单 / 内部交叉引用 / 外部导入点(含其它 monorepo 包)/ barrel 导出现状 / `package.json` 依赖现状 / 分层与循环依赖风险(`client-base` 不得反向依赖 `client-modules`)/ legacy 命中 / 未确定项;生产代码零改动 | 04-10 | COVERED | 11 节结构与 A–F 六类一一对应:清单节 / A / B / C / D(含 `package.json`)/ E / F;Task 3 门禁逐项断言 |
|
||||
| CONTEXT | D-33 | 范围外一律不改;不追求解决全部类型错误 | 04-10 | COVERED(边界) | 本步零代码改动;`packages/` 与 `src/` 仅报告 |
|
||||
| CONTEXT | D-42 / D-49 | `client-base/src/material/` 归用户、AI 不得改;不考虑 legacy 兼容 | 04-10 | COVERED(边界) | 本步不触碰 `material/`;legacy 归 E 类只报告 |
|
||||
| CONTEXT | D-07 / D-09 | 记录精确到符号 + 所属文件;允许派只读子代理扫描 | 04-10 | COVERED(粒度) | 固定列序 + 每行 ≥2 个 `file:line` 锚点 + 门禁机器判定;Task 2 允许只读子代理回传事实表 |
|
||||
| CONTEXT | D-01..D-06, D-08, D-10..D-32, D-34..D-50 | 前序决策与已执行增量 | 04-01..04-09 | COVERED(前序计划) | 已由 04-01..04-09 落地;04-09 = texture 接口适应第二步(`status: complete`) |
|
||||
| CONTEXT | Deferred Ideas | 阶段 4 后续步骤(移植实施、适配实施、双布局);`packages` 全部、`entry-client`、`legacy-plugin-*`、`data-fallback` | — | DEFERRED | 未写入任何任务;`packages/` 仅作 E 类对照扫描 |
|
||||
|
||||
## Estimate Basis(估算依据)
|
||||
|
||||
`estimate-calibration` 返回 `factor: 1`、`applied: false`、`sample_count: 0`、`confidence: low`(项目无历史样本),故 `tokens == raw_tokens` 并如实标注 `confidence: low`。按「执行者实际触及量」估算(`estimate.tasks: 4` = Task 0 汇报关卡 + 三个工作任务):Task 0 只读汇报并等待用户确认(约 5k,不写文件);Task 1(tracer)起始只读基线 + 交付文档骨架 + 39 文件清单 + `## 背景` / `## 方法` + `render/utils/layout.ts` 贯穿 A–F 的端到端切片(约 35k);Task 2 横向补齐 A / B / C 三类(约 30k);Task 3 补齐 D / E / F + `## 处置` + 五道门禁 + 人工复核 + `04-10-SUMMARY.md`(约 20k);固定开销约 5k;合计约 95k。
|
||||
|
||||
</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-MATERIAL-INTERFACE-IMPACT.md
|
||||
@.planning/phases/04-render-adaptation/04-RENDER-INTERFACE-AUDIT.md
|
||||
@.planning/phases/04-render-adaptation/04-08-PLAN.md
|
||||
@.planning/phases/04-render-adaptation/04-09-SUMMARY.md
|
||||
@.planning/phases/04-render-adaptation/04-PATTERNS.md
|
||||
@AGENTS.md
|
||||
@dev.md
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="checkpoint:decision" gate="blocking-human">
|
||||
<name>Task 0: 预执行汇报关卡 —— 汇报渲染端结构性重构(D-51/D-57 第一步)的范围、移植集合与目标布局、A–F 六类分列规则与唯一交付物、D-55/D-56 两条硬边界与「零命名变更」性质、只读证明方式,等待用户回复「可以执行」</name>
|
||||
<precondition>用户对渲染端结构性重构的裁定 D-51 / D-52 / D-53 / D-54 / D-55 / D-56 / D-57 已写入 `.planning/phases/04-render-adaptation/04-CONTEXT.md`(以文件内实际存在 D-51..D-57 为准);移植集合在当日工作树上存在(`packages-user/client-modules/src/render/components`、`render/elements`、`render/map` 三个均为目录,且 `packages-user/client-modules/src/render/utils/layout.ts` 为文件);`packages-user/client-base/src/` 下**尚无** `components` / `elements` / `map` / `layout` 目录(移植尚未发生,本次为第一步只读清点)</precondition>
|
||||
<files>(只读汇报,不修改任何文件)</files>
|
||||
<read_first>
|
||||
- AGENTS.md(「任何计划的执行,其第一个 block 点必须是向我汇报计划内容并等待我确认」;只有明确回复「可以执行」四个字之后才允许开始执行;「如果发现任何问题,永远不要擅自将其视为问题并记录,必须经由我确认」;「任何公共、受保护、私有方法、字段等内容的命名必须先向我反馈」)
|
||||
- .planning/phases/04-render-adaptation/04-CONTEXT.md(D-51 / D-52 / D-53 / D-54 / D-55 / D-56 / D-57 裁定原文;D-33 范围、D-42 / D-49 边界、D-07 粒度、D-09 子代理)
|
||||
- .planning/phases/04-render-adaptation/04-10-PLAN.md(本计划全文:objective 的移植集合 / 分列规则 / 规划日实测表、tasks、禁令、门禁)
|
||||
- .planning/phases/04-render-adaptation/04-09-SUMMARY.md:1-45(前一个已执行增量:texture 接口适应的落点与「REND 仍 Pending」声明;本步是其后的结构性重构增量)
|
||||
- .planning/phases/04-render-adaptation/04-TEXTURE-INTERFACE-IMPACT.md:1-60(既有只读台账的元信息块 / `## 背景` / `## 方法` / 固定列序表的写法,本次对齐版式)
|
||||
- dev.md(「项目结构」的单向依赖 `src → packages-user → packages`;「双端分离」定义 `@user/client-base`(系统层)与 `@user/client-modules`(实现层);「其他要求」的 CRLF)
|
||||
</read_first>
|
||||
<action>
|
||||
**停下并向用户汇报,等待明确回复后才继续;汇报本身只读,不写任何文件、不改任何生产代码、不派发子代理。**
|
||||
|
||||
① **要解决的问题(D-51)**:`packages-user/client-modules/src/render/` 下的**通用渲染内容**(`components` / `elements` / `map` 三个文件夹 + `utils/layout.ts`)放错了层——它们属渲染**系统层**,应由 `packages-user/client-base/src/` 承载;`client-modules` 只应保留实现层 / 交互层内容(`ui` / `fx` / `weather` / `render` 顶层文件 / `action` / `fallback`)。用户裁定走**两步**:第一步只读影响清点(本 run),第二步移植实施待用户审阅后另行规划(D-57)。
|
||||
|
||||
② **锁定裁定(须逐条汇报)**:
|
||||
- **D-52 移植集合(明确)** = `render/components`、`render/elements`、`render/map` 三个文件夹;外加单文件 `render/utils/layout.ts`。规划日实测共 **39** 文件(`components` 13 / `elements` 5 / `map` 20 / `layout.ts` 1)。
|
||||
- **D-53 目标布局**:**不新建 `render/` 目录**;三个文件夹直接放 `client-base/src/{components,elements,map}/`;`layout.ts` 单独开 `client-base/src/layout/`。
|
||||
- **D-54 不移植**:`render/utils/` 的其余内容(`index.ts` / `saves.ts` / `use.ts`);`ui` / `fx` / `weather` 三个文件夹与 `render` 顶层文件(`action.ts` / `index.tsx` / `renderer.ts` / `scene.ts` / `use.ts`)。
|
||||
- **D-55 legacy 不涉及**:legacy 相关报错一律不管、不修、不登记为待办;只报告。
|
||||
- **D-56 用户并发改动**:不得触碰、不得提交用户的任何并发改动(规划日基线已含 ` M packages-user/data-base/src/enemy/types.ts`)。
|
||||
- **D-57 第一步交付物**:只读影响台账,至少覆盖被移文件清单 / 内部交叉引用 / 外部导入点(含其它 monorepo 包)/ barrel 导出现状 / `package.json` 依赖现状 / 分层与循环依赖风险(`client-base` 不得反向依赖 `client-modules`)/ legacy 命中 / 未确定项;生产代码零改动。
|
||||
|
||||
③ **规划日实测的影响面(2026-09-24,HEAD `3bc37b5`,分支 `refine/data-client`;执行日以当日实测为准)**:A 类内部交叉引用 **8** 个方向(约 30 处)——`components→elements` 3(`tip.tsx` / `textbox.tsx` / `textboxTyper.ts`)、`elements→map` 2(`elements/index.ts` / `elements/props.ts`)、→ 留在 `render/` 的 `renderer` 3、→ 留在 `render/` 的 `use.ts` 5、→ `client-modules/src/shared.ts` 4(`map/vertex.ts` / `map/element.ts` / `map/renderer.ts` / `map/extension/door.ts`)、→ `@user/client-base` 自包引用 5、`map/extension/*→map/types` 5;另记「被移集合 → `ui`/`fx`/`weather` **0** 命中」的机器证据。B 类外部导入点 **8** 个文件族(约 17 处)——`client-modules/src/{client.ts:25,types.ts:2}`、`render/index.tsx:5,45,46`、`render/ui` 8 文件 10 处、`render/utils/saves.ts:2`、`render/utils/index.ts:1`(barrel 引用被移文件)、`fallback/ui.ts:2`;另有 3 个包经 `@user/client-modules` 公共面间接依赖(`entry-client/src/create.ts:10,27`、`entry-data/src/mota.ts:11,32`、`packages/legacy-ui/src/preset/ui.ts:86,96,105`);`packages/` 与 `src/` 对 `render/components|elements|map` **零命中**。C 类 barrel **7** 个节点(`components/index.ts` 12 条 / `elements/index.ts` `createElements` + 3 条 / `map/index.ts` `extension` + 9 条 / `render/index.tsx:45,46,51` / `render/utils/index.ts:1` 移出即断链 / `client-modules/src/index.ts:15` / `client-base/src/index.ts` 4 条)。D 类风险 **9** 条(反向依赖候选 4 族共 13 处、自包引用 5 处、`client-base/package.json` 依赖缺口:缺 `@motajs/render-vue` / `@motajs/system` / `@motajs/common` / `@user/data-common`、现状零反向引用机器证据、`?raw` shader 4 处、`dev.md` 规则对照)。E 类 legacy **8** 个文件(`core.*` 约 31 处;`loading` / `Mota.require('@user/data-base')` 3 处;`client.*` 0 命中)。F 类未确定 ≥ **9** 条。
|
||||
|
||||
④ **大致解决方案**:只读清点,唯一交付物 `.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.md`;11 节结构(`## 背景` / `## 方法` / `## 被移集合清单(39 文件)` / `## A 被移集合内部交叉引用` / `## B 外部导入点` / `## C barrel 与导出面` / `## D 分层与循环依赖风险` / `## E legacy 命中(仅报告)` / `## F 未能从阅读确定(未猜测)` / `## 处置`)+ 6 行元信息块;A–E 每节固定列序表(`ID | 文件/符号 | 命中处(源) | 目标锚点 | 问题描述 | 影响 | 置信`),**每行 ≥2 个 `file:line` 锚点**;**分列规则**:A = 被移集合内部交叉引用、B = 外部导入点、C = barrel 与导出面、D = 分层与循环依赖风险(含 `package.json` 依赖现状)、E = legacy 命中(仅报告)、F 类只登记不判定。重型整文件读取可按 **D-09** 派**只读**子代理(仅回传事实表,不得写文件)。
|
||||
|
||||
⑤ **范围与硬边界**:被查 = 移植集合 39 文件与其全部 importer;基准 = 当日工作树 + `dev.md` 单向依赖 / 双端分离规则 + 两个包的 `package.json`;`packages/` 与 `src/` 命中**仅报告、不修改**;**D-55**:legacy 一律只报告,不修、不登记为待办;**D-56**:用户并发改动零触碰。**生产源码零改动**;唯一写入为上述交付文档(外加本 PLAN 与 `04-10-SUMMARY.md` 两份簿记)。
|
||||
|
||||
⑥ **本步性质:零命名变更(须原样告知)**:本计划为**只读清点**,不新增、不改名任何公共 / 受保护 / 私有成员或字段,也不裁定 `client-base/src/{components,elements,map,layout}` 下的文件名 / barrel 名(如 `layout.ts` 是否改名 `index.ts`)——**任何命名一律进 F 类、须先向用户反馈并获同意后才可使用**(AGENTS.md)。
|
||||
|
||||
⑦ **计划号与 wave(须原样告知)**:本计划为 **04-10**(第十个增量),`wave: 9`,`depends_on` 列 `04-01`..`04-09`;phase 目录内既有 `04-01`..`04-09` 的 `*-PLAN.md` 与 `*-SUMMARY.md` **一律不得改写 / 覆盖 / 改号**。
|
||||
|
||||
⑧ **验证方式与只读证明(须原样告知)**:本步为只读清点,**无运行时行为可观察**。证明方式 = ①**只读门禁**:`git status --porcelain -- packages packages-user src` 在 Task 1 起始逐行记录(规划日实测单条 ` M packages-user/data-base/src/enemy/types.ts`),Task 1 / Task 3 断言其后逐条一致;②**静态内容门禁**:11 节结构、被移集合 **39** 文件路径逐条齐备、A–F 行数下限与关键词、每行 ≥2 个 `file:line` 锚点、F 类条数;③**机器证据复验**:`git grep -n -F "client-modules" -- packages-user/client-base` 零命中、`git grep -n -F "render/components"` / `-F "render/elements"` / `-F "render/map"`(同限 `packages` 与 `src`)在 `packages-user` 之外零命中、被移集合对 `ui`/`fx`/`weather` 零引用、`client.*` 在被移集合内零命中;④**既有产物保护 + 计划范围门禁**:`04-01`..`04-09` 的 `*-PLAN.md` / `*-SUMMARY.md` porcelain 为空;phase 目录内 `-PLAN.md` 仅 `04-01`..`04-10`;⑤**CRLF 门禁**;⑥**人工代码复核**。**不冒充任何无法运行的门禁。**
|
||||
|
||||
⑨ **第二步不被规划**:本 run **不含**移植方案、不含 import 重写方案、不产出 `04-11+`;第二步(移植实施)待用户审阅本清点文件后另行规划(D-57)。
|
||||
|
||||
⑩ **关卡性质(必须原样告知用户)**:无论触发方式(`/gsd-execute-phase`、`/gsd-manager`、`/gsd-autonomous`、子代理/执行器派发)或配置模式(`.planning/config.json` 的 `mode: yolo`、`workflow.auto_advance`)如何,**执行者/子代理都必须在此停下并等待**用户明确回复「可以执行」四个字;未收到这四个字前不得执行任何任务、不得派发执行子代理,也不得以「自动化模式」为由自动放行。
|
||||
|
||||
⑪ **失败语义(等同硬门禁,非自动命令)**:用户未回复「可以执行」即继续,或回复的是其它任何内容(含修订意见、沉默、`yolo` / `auto_advance` 模式下的自动推进、或子代理/执行器的自行放行),一律视为**未通过本关卡**:必须立即停止执行,不派发任何执行子代理,保持只读、不写任何文件,直到用户在对话中明确回复「可以执行」四个字后方可继续。本条只以本 `<action>` 与 `<acceptance_criteria>` 表达,不写成 XML 失败声明元素(人工关卡没有可运行的自动命令可与之绑定)。
|
||||
|
||||
⑫ **若用户给出修订意见**(含不同意移植集合 / 目标布局 / A–F 分列规则 / 不同意把某些内容归 E 类只报告 / 希望把命名一并裁定 / 希望调整范围):退出本计划、修订 `04-10-PLAN.md` 后重新汇报,不得自行改道执行。
|
||||
</action>
|
||||
<decision>是否按本计划(渲染端结构性重构·第一步只读影响清点:唯一交付物 `04-STRUCTURE-MIGRATION-IMPACT.md`,11 节 / A–F 六类,被移集合 39 文件,范围含全部 importer 与其它 monorepo 包,`packages/` 与 `src/` 仅报告,legacy 按 D-55 仅报告,生产代码零改动且零命名变更,第二步不规划)开始执行</decision>
|
||||
<context>
|
||||
AGENTS.md 要求任何计划的第一个 block 点必须是向用户汇报计划内容并等待用户确认;本计划虽是只读清点,仍不得例外。`.planning/config.json` 为 `mode: yolo`,因此该关卡必须显式声明为 `blocking-human` 并置 `autonomous: false`,否则计划层面不提供任何 block 点。此外本次存在两条会改变范围归属的用户裁定(D-55 legacy 只报告、D-56 用户并发改动零触碰)与一条会改变权限边界的项目规则(AGENTS.md 的命名须先反馈),必须在关卡中先行澄清,避免 AI 把 legacy 写成待办、或替用户给目标文件命名。
|
||||
</context>
|
||||
<options>
|
||||
<option id="execute">
|
||||
<name>可以执行</name>
|
||||
<pros>按本计划执行:只读清点,零生产代码改动、零命名变更,唯一写入为交付文档 + 两份簿记;产出可供用户审阅并据此裁定第二步的移植方案与 import 重写集</pros>
|
||||
<cons>无(只读;只读性由 Task 1 / Task 3 机器判定)</cons>
|
||||
</option>
|
||||
<option id="revise">
|
||||
<name>修订范围 / 移植集合 / A–F 分列规则后再执行</name>
|
||||
<pros>避免带着错误的范围(如把 `ui` / `fx` / `weather` 纳入、或漏掉其它 monorepo 包的间接依赖)或错误的分类(把反向依赖报成内部引用)落地</pros>
|
||||
<cons>退出本计划并修订 PLAN.md 后重新汇报,增加一轮往返</cons>
|
||||
</option>
|
||||
<option id="renumber">
|
||||
<name>可以执行,但改用其它编号</name>
|
||||
<pros>按用户指定的编号落地,避免后续引用混淆</pros>
|
||||
<cons>需用户先指定文件名;phase 目录内既有 `04-01`..`04-09` 产物不得改写 / 覆盖</cons>
|
||||
</option>
|
||||
</options>
|
||||
<resume-signal>回复「可以执行」四个字(修订意见请按 action ⑫ 处理)</resume-signal>
|
||||
<verify>
|
||||
<human-check>用户在对话中明确回复「可以执行」四个字(人工核对用户回复原文;本关卡为人工关卡,无自动命令,失败语义写在 Task 0 的 action ⑪ 与 acceptance_criteria 中)</human-check>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- 用户回复中明确包含「可以执行」四个字
|
||||
- 汇报内容涵盖:要解决的问题(D-51 分层放错 + D-57 两步走)、锁定裁定(D-52 移植集合 39 文件 / D-53 目标布局 / D-54 不移植 / D-55 legacy / D-56 并发 / D-57 第一步交付物)、规划日实测的影响面(A 8 方向 / B 8 文件族 + 3 包 / C 7 barrel / D 9 风险 / E 8 文件 / F ≥9)、大致解决方案(11 节结构 + 固定列序 + A/B/C/D/E 分列规则 + F 只登记不判定)、范围与硬边界、唯一交付物与两步走
|
||||
- 汇报中已原样告知 **D-55**(legacy 一律只报告,不修、不登记为待办)与 **D-56**(不得触碰 / 提交用户并发改动)
|
||||
- 汇报中已原样告知**本步零命名变更**,且目标文件名 / barrel 名等命名一律进 F 类、须先向用户反馈并获同意
|
||||
- 汇报中已原样告知**编号与 wave**(04-10 / wave 9 / `depends_on` 04-01..04-09)以及既有 `04-01`..`04-09` 产物不得改写 / 覆盖 / 改号
|
||||
- 汇报中已原样告知**验证方式与只读证明**(只读门禁 / 静态内容门禁 / 机器证据复验 / 既有产物保护与计划范围门禁 / CRLF / 人工复核),并声明无运行时行为可观察
|
||||
- 汇报中已原样告知**关卡性质**:执行者/子代理必须停下等待,不因触发方式或 `yolo` / `auto_advance` 模式自动放行
|
||||
</acceptance_criteria>
|
||||
<done>用户明确回复「可以执行」;在此之前未执行任何任务、未修改任何文件、未派发任何执行子代理</done>
|
||||
</task>
|
||||
|
||||
<task type="tracer">
|
||||
<name>Task 1(tracer):交付文档骨架 + 被移集合全量清单 + 一条端到端清点切片 —— 起始只读基线 + 11 节结构 + 元信息块 + `## 背景` / `## 方法` + 39 文件清单(含目标落点)+ `render/utils/layout.ts` 贯穿 A–F 六节的端到端行,结构 / 清单 / 切片双锚点 / CRLF / 只读基线 / 分层基线六道门禁转绿</name>
|
||||
<precondition>Task 0 已闭环:用户在对话中明确回复「可以执行」四个字(未收到则不得开始本任务)</precondition>
|
||||
<files>.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.md</files>
|
||||
<read_first>
|
||||
- .planning/phases/04-render-adaptation/04-TEXTURE-INTERFACE-IMPACT.md:1-60,100-160,245-268(前进量的元信息块 / `## 背景` / `## 方法` / 只读起始基线 / 固定列序表 / `## 处置` 既有写法,本次对齐版式与证据纪律)
|
||||
- .planning/phases/04-render-adaptation/04-08-PLAN.md:251-320(前进量 tracer 任务的结构:只读基线前置 + 骨架 + 端到端切片 + 门禁)
|
||||
- .planning/phases/04-render-adaptation/04-CONTEXT.md(D-51..D-57 原文;D-33 / D-42 / D-49 边界;D-07 粒度;D-09 子代理)
|
||||
- .planning/phases/04-render-adaptation/04-10-PLAN.md(本计划全文:移植集合 / 目标布局 / 分列规则 / 规划日实测表 / 禁令 / 门禁)
|
||||
- packages-user/client-modules/src/render/(三个目录的当日文件清单:`components` / `elements` / `map` 含 `map/extension` 与 `map/shader`)
|
||||
- packages-user/client-modules/src/render/utils/layout.ts(端到端切片对象:整文件;`:1` `import { ElementLocator } from '@motajs/render'`)
|
||||
- packages-user/client-modules/src/render/utils/index.ts:1(`export * from './layout'`——`layout.ts` 的**唯一**外部入口,移出即断链)
|
||||
- packages-user/client-modules/src/render/utils/saves.ts:2(`../components`——`utils/` 内另一个指向被移集合的引用,属 B 类)
|
||||
- dev.md(「项目结构」单向依赖;「双端分离」;「其他要求」的 CRLF)
|
||||
</read_first>
|
||||
<action>
|
||||
(0a) **起始基线快照(只读前置,先做这一步)**:执行 `git status --porcelain -- packages packages-user src`,把输出**原样逐行**记为「只读起始基线」写入 `## 方法`:先写 bullet `- **只读起始基线(packages / packages-user / src)**:`,其后逐行抄录输出(每条一行,行首为两字符状态码;输出为空则写 `(无)`)。规划日 2026-09-24 实测该输出为**单条** ` M packages-user/data-base/src/enemy/types.ts`(用户正在并发修改数据端,D-56)。**不得回滚、暂存、提交或修改**任何既有改动;若当日实测出现其它 `packages` / `packages-user` / `src` 下的条目,逐条记录并原样保留(属清点范围内的既有改动,需在 `## 方法` 注明)。同时记下 `git rev-parse HEAD` 与 `git rev-parse --abbrev-ref HEAD` 的当日值写入元信息块(规划日为 `3bc37b5` / `refine/data-client`)。
|
||||
|
||||
(1) **新建交付文档** `.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.md`,先写标题与元信息块 7 行:`**日期:**`(当日日期);`**范围:**` 被查对象 = 移植集合 39 文件与其全部 importer(`packages-user/client-modules` 内 `render/{ui,fx,weather,index.tsx,renderer.ts,scene.ts,use.ts,action.ts,utils}` 与 `client.ts` / `types.ts` / `fallback`,以及其它 monorepo 包);`packages/` 与 `src/` 命中仅报告、不修改;`**性质:**` 只读清点(D-51 / D-57 第一步),未修改任何生产代码、未引入任何命名变更;`**移植集合:**` D-52 的三文件夹 + `render/utils/layout.ts`(规划日实测 39 文件);`**目标布局:**` D-53 的 `client-base/src/{components,elements,map}/` 与 `client-base/src/layout/`(不新建 `render/`);`**基准:**` 当日 HEAD(规划日 `3bc37b5`,分支 `refine/data-client`)工作树 + `dev.md` 单向依赖 / 双端分离规则;`**下一步:**` 第二步(移植实施)未规划,待用户审阅本文件后另行规划(D-57)。**全文使用 CRLF 换行**(dev.md「换行使用 CRLF 格式」);若写入工具产出 LF,用 `node -e "const fs=require('fs');const p='.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.md';fs.writeFileSync(p,fs.readFileSync(p,'utf8').replace(/\r?\n/g,'\r\n'))"` 统一转换后落盘;Task 2 / Task 3 追加内容同样保持 CRLF,不得出现孤立 LF。
|
||||
|
||||
(2) 写 `## 背景`:D-51(通用渲染内容放错层,须下沉到 `client-base` 系统层)、D-52(移植集合 = 三文件夹 + `layout.ts`)、D-53(目标布局:不新建 `render/`;`layout.ts` 单独 `client-base/src/layout/`)、D-54(不移植 `render/utils/` 其余与 `ui` / `fx` / `weather` / `render` 顶层文件)、D-55(不考虑 legacy,只报告)、D-56(用户并发改动零触碰)、D-57(第一步交付物与覆盖项清单)。并明写本步**只清点、不修改、不规划第二步、零命名变更**。
|
||||
|
||||
(3) 写 `## 方法`((0a) 的「只读起始基线」bullet 也在本节):
|
||||
- **枚举面**:(a)**被移面** = 移植集合 39 文件(D-52);(b)**命中面** = 移出集合之外的全部 importer(`client-modules/src` 全量)与其它 monorepo 包(`entry-client` / `entry-data` / `packages/legacy-ui` 经 `@user/client-modules` 公共面的间接依赖),另对 `packages/` 与 `src/` 做**对照扫描**(只登记、不修改)。
|
||||
- **判定口径固定为六类**(A 被移集合内部交叉引用 / B 外部导入点 / C barrel 与导出面 / D 分层与循环依赖风险 / E legacy 命中(仅报告)/ F 未能从阅读确定),**一条记录只归一类**,跨类拆条并互相引用。
|
||||
- **分列规则写死**:A 记「集合内部互相 import + 集合 → 留在 `client-modules` 的模块(`shared.ts` / `render/renderer` / `render/use.ts` / `@user/client-base` 自包引用)」;B 记「集合之外的 importer(含其它 monorepo 包的间接依赖)」;C 记「barrel / 导出集合现状与移出后是否断链(**不裁定是否新增 barrel**)」;D 记「分层与循环依赖风险 + `package.json` 依赖现状(**只登记,不自拟解耦方案**)」;E 记「`core.*` / `loading` / `hook` / `Mota.require` 等 legacy 耦合(D-55 只报告)」;F 记「静态阅读不能定论(含全部命名问题)」。
|
||||
- **证据纪律**:每行含 `文件/符号 + 命中处 file:line + 目标锚点 file:line + 问题描述 + 影响 + 置信`,**每行至少两个锚点**;静态阅读不能定论者一律进 F 类,**不得写成错配 / 缺失 / 残留 / 待办**。
|
||||
- **只读子代理(D-09)**:重型整文件读取可派**只读**子代理(只回传事实表「文件 + `file:line` + 形态或签名」,**不得写文件、不得贴大段源码**),最终由主执行者按 `file:line` 切片复核。
|
||||
|
||||
(4) **写 `## 被移集合清单(39 文件)`**:四张子表 + 一行单文件 ——(i)`render/components/` **13** 个:`choices.tsx` / `floorSelect.tsx` / `icons.tsx` / `index.ts` / `input.tsx` / `list.tsx` / `misc.tsx` / `page.tsx` / `scroll.tsx` / `textbox.tsx` / `textboxTyper.ts` / `thumbnail.tsx` / `tip.tsx`;(ii)`render/elements/` **5** 个:`cache.ts` / `index.ts` / `misc.ts` / `props.ts` / `types.ts`;(iii)`render/map/` **20** 个:`block.ts` / `constant.ts` / `element.ts` / `index.ts` / `moving.ts` / `renderer.ts` / `status.ts` / `types.ts` / `vertex.ts` / `viewport.ts` + `extension/{door,hero,index,manager,text,types}.ts`(6)+ `shader/{back.frag,back.vert,map.frag,map.vert}`(4);(iv)`render/utils/layout.ts` **1**。每行含 `现路径 | 目标路径(按 D-53) | 职责(一句话,据当日阅读) | 备注`。**目标路径写法**:`components` / `elements` / `map` 三个文件夹内的文件按同名相对路径映射到 `packages-user/client-base/src/{components,elements,map}/…`;`layout.ts` 映射为 `packages-user/client-base/src/layout/…`(**具体文件名是否仍为 `layout.ts` 属 F 类,须写「命名待用户裁定」,不得拍板**)。同时写明「**不新建 `client-base/src/render/` 目录**」与「**本步不移动、不复制、不预建任何目标文件**」。
|
||||
|
||||
(5) **补齐 11 个二级标题**(`## 背景` / `## 方法` / `## 被移集合清单(39 文件)` 已在前几步写入,此处补齐其余 8 个占位,其后 Task 2 / Task 3 在同一骨架上横向补齐,不再改结构):`## A 被移集合内部交叉引用` / `## B 外部导入点` / `## C barrel 与导出面` / `## D 分层与循环依赖风险` / `## E legacy 命中(仅报告)` / `## F 未能从阅读确定(未猜测)` / `## 处置`。**每个类别标题下先写一行记录编号模板**(供后续横向补齐对齐):A 类 `#04-10-A-NN`、B 类 `#04-10-B-NN`、C 类 `#04-10-C-NN`、D 类 `#04-10-D-NN`、E 类 `#04-10-E-NN`,表头固定为 `| ID | 文件/符号 | 命中处(源) | 目标锚点 | 问题描述 | 影响 | 置信 |`;F 类条目形如 `- **#04-10-F-NN**:现象 + 为什么读不出来 + 需要用户裁决的点`。模板行用 `NN` 占位、不含数字,故不计入任何行数门禁。
|
||||
|
||||
(6) **端到端切片:`render/utils/layout.ts` 一条线贯穿 A–F 六节(本任务唯一实测清点对象)**——这是本 tracer 的「一条路径走通全部层」:
|
||||
- **清单节**:已在 (4) 中登记 `render/utils/layout.ts` → `client-base/src/layout/`(文件名待裁定)。
|
||||
- **A 类 `#04-10-A-01`**:集合**内部**无对 `layout.ts` 的 import(须给机器证据:`git grep -n "utils/layout" -- packages-user/client-modules/src` 的原样输出——规划日仅 `render/utils/index.ts:1`,即**集合之外**);锚点 = 命中处 `packages-user/client-modules/src/render/utils/index.ts:1` + 目标锚点 `packages-user/client-modules/src/render/utils/layout.ts:1`(文件首行)/ 其 `export` 声明行(按当日实测)。该行须明写「A 类本方向为 0 命中、证据如下」,**不得凭空造引用**。
|
||||
- **B 类 `#04-10-B-01`**:外部导入点 = `packages-user/client-modules/src/render/utils/index.ts:1`(`export * from './layout'`)—— `layout.ts` 的**唯一**外部入口;锚点 = 该行 + `layout.ts` 的声明行;影响 = 移出后该 barrel 断链(`render/utils/index.ts` 按 D-54 不移植,`render/ui/save.tsx:31` / `settings.tsx:20` / `title.tsx:35` 经 `../utils` 间接依赖它)。
|
||||
- **C 类 `#04-10-C-01`**:barrel 节点 = `render/utils/index.ts:1`(`export * from './layout'`)嵌在 `render/utils/index.ts:1-3`(另两条 `./saves` / `./use` 留在原地)中;现状 = 该 barrel 同时导出被移与非被移内容;判定 = **移出即断链**,第二步必须改指 `client-base`(**改指的具体写法属 F 类**)。该行与 B-01 交叉引用、不重复计数。
|
||||
- **D 类 `#04-10-D-01`**:分层风险 = `layout.ts` 自身只依赖 `@motajs/render`(`layout.ts:1`;`packages-user/client-base/package.json:5` 已声明该依赖)⇒ **本文件不引入新的依赖缺口**;但若 `render/utils/index.ts` 为保持导出面而反向 import `@user/client-base`,则该方向为 `client-modules → client-base`(与 D 类其它条目的反向风险相反,属合法方向);锚点 = `packages-user/client-modules/src/render/utils/layout.ts:1` + `packages-user/client-base/package.json:5`。
|
||||
- **E 类 `#04-10-E-01`**:legacy 命中 = `layout.ts` 内**零** legacy 命中(须给当日实测证据:打开整文件 + 执行 `git grep -n -F "core."` / `-F "hook"` / `-F "loading"` / `-F "Mota.require"`(同限 `packages-user/client-modules/src/render/utils/layout.ts`)四个**独立**检索与原样输出;规划日为无输出 / 退出码 1)。**只报告**(D-55)。
|
||||
- **F 类 `#04-10-F-01`**:目标文件名未确定(`client-base/src/layout/layout.ts` 还是 `client-base/src/layout/index.ts`;D-53 只定「单独开 `layout/` 文件夹」);**命名须先向用户反馈并获同意后才可使用**(AGENTS.md)。另写 `#04-10-F-02`:`render/utils/index.ts` 在 `layout.ts` 移出后的归属(D-54 明示 `utils/index.ts` 不移植 ⇒ 断链处置未裁定)。
|
||||
- 其余 A–F 行由 Task 2 / Task 3 横向补齐;本任务的切片**必须六节各有一行**,以便门禁先验通结构。
|
||||
|
||||
(7) 写 `## 处置` 初稿:本步只读、未改任何生产代码、未引入任何命名变更、`files_modified` 仅本文件;相对 (0a) 记录的只读起始基线零变化;本步**不规划第二步**(D-57);范围含全部 importer 与其它 monorepo 包,`packages/` 与 `src/` 仅报告;legacy 按 D-55 仅报告;`client-base` 反向依赖的解耦方式与全部命名问题进 F 类由用户裁定;`REND-01` / `REND-02` 保持 Pending。
|
||||
|
||||
(8) **本任务只写该交付文档一个文件**;不得改动任何被查源码(含用户既有的未提交改动),不得派发会写文件的子代理,不得新增计划文件、不得预建 `client-base/src/{components,elements,map,layout}`。
|
||||
</action>
|
||||
<reversibility rating="reversible">交付文档是只读清点的记录,可随时修订或废弃;它不引入生产代码、公共接口、契约约束或命名,因此这一步的任何取舍都不难回退。</reversibility>
|
||||
<!-- plan-criteria-allow: R4 - 本任务验证块内的竖线字符全部位于 node 程序的正则分支 / 数组字面量中,不是 shell 管道;所有 git 命令均由 node 的 execSync 调用并在 JS 内捕获 stdout 与 exit status 后自行判定,不经 shell 管道传递状态 -->
|
||||
<verify>
|
||||
<automated>node -e "const fs=require('fs');const p='.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.md';const t=fs.readFileSync(p,'utf8');const heads=(t.match(/^## /gm)||[]).length;if(heads!==11){console.error('HEADING COUNT '+heads);process.exit(1)}const need=['## A ','## B ','## C ','## D ','## E ','## F ','## \u5904\u7f6e'];const miss=need.filter(h=>t.indexOf(h)<0);if(miss.length>0){console.error('MISSING HEADINGS '+miss.join(' ; '));process.exit(1)}if(t.indexOf('\u53ea\u8bfb\u8d77\u59cb\u57fa\u7ebf')<0){console.error('MISSING READONLY BASELINE');process.exit(1)}if(!/\b[0-9a-f]{7,40}\b/i.test(t)){console.error('MISSING BASELINE COMMIT');process.exit(1)}console.log('OK headings '+heads)"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "HEADING COUNT" / "MISSING HEADINGS" / "MISSING READONLY BASELINE" / "MISSING BASELINE COMMIT"(二级标题数不等于 11,或 A–F 与 `## 处置` 任一缺失,或 `## 方法` 未记录只读起始基线 / 元信息块未登记基准 HEAD)</fails_when>
|
||||
<automated>node -e "const fs=require('fs');const t=fs.readFileSync('.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.md','utf8');const f=['components/choices.tsx','components/floorSelect.tsx','components/icons.tsx','components/index.ts','components/input.tsx','components/list.tsx','components/misc.tsx','components/page.tsx','components/scroll.tsx','components/textbox.tsx','components/textboxTyper.ts','components/thumbnail.tsx','components/tip.tsx','elements/cache.ts','elements/index.ts','elements/misc.ts','elements/props.ts','elements/types.ts','map/block.ts','map/constant.ts','map/element.ts','map/index.ts','map/moving.ts','map/renderer.ts','map/status.ts','map/types.ts','map/vertex.ts','map/viewport.ts','map/extension/door.ts','map/extension/hero.ts','map/extension/index.ts','map/extension/manager.ts','map/extension/text.ts','map/extension/types.ts','map/shader/back.frag','map/shader/back.vert','map/shader/map.frag','map/shader/map.vert','utils/layout.ts'];const miss=f.filter(x=>t.indexOf(x)<0);if(miss.length>0){console.error('MOVE-SET MISSING '+miss.length+' :: '+miss.join(' ; '));process.exit(1)}if(t.indexOf('client-base/src/')<0){console.error('MISSING TARGET LAYOUT');process.exit(1)}console.log('OK move-set files '+f.length)"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "MOVE-SET MISSING" / "MISSING TARGET LAYOUT"(39 个被移文件未逐条列出 D-52 的全部路径,或未写明 D-53 的目标落点)</fails_when>
|
||||
<automated>node -e "const fs=require('fs');const t=fs.readFileSync('.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.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 p=[];for(const c of ['A','B','C','D','E']){const s=seg('## '+c+' ');if(!s){p.push('MISSING SECTION '+c);continue}const re=new RegExp('^\\|\\s*#04-10-'+c+'-\\d+\\s*\\|');const rows=s.split(/\r?\n/).filter(l=>re.test(l));if(rows.length<1)p.push('NO ROWS '+c);const bad=rows.filter(l=>((l.match(/[A-Za-z0-9_\-.\\/]+\.(tsx?|frag|vert):\d+/g)||[]).length<2));if(bad.length>0)p.push('ROW WITHOUT TWO-SIDED ANCHOR '+c+' '+bad.length)}const F=seg('## F ');if((F.match(/^- \*\*#04-10-F-\d+/gm)||[]).length<2)p.push('F ITEMS '+(F.match(/^- \*\*#04-10-F-\d+/gm)||[]).length);if(p.length>0){console.error('TRACER SLICE GATE FAILED :: '+p.join(' ;; '));process.exit(1)}console.log('OK tracer slice rows in A-E + F items')"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "TRACER SLICE GATE FAILED"(A–E 任一节无端到端切片行,或某行缺命中处 / 目标锚点之一(不足 2 个 `file:line` 锚点),或 F 类少于 2 条)</fails_when>
|
||||
<automated>node -e "const fs=require('fs');const s=fs.readFileSync('.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.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>
|
||||
<automated>node -e "const fs=require('fs'),{execSync}=require('child_process');const t=fs.readFileSync('.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.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 ms=seg('## \u65b9\u6cd5');if(ms.indexOf('\u53ea\u8bfb\u8d77\u59cb\u57fa\u7ebf')<0){console.error('READONLY BASELINE NOT RECORDED');process.exit(1)}const rec=(ms.match(/^[ MARCUD?!]{2} (?:packages|packages-user|src)[^\r\n]*/gm)||[]).map(s=>s.replace(/\s+$/,''));let raw='';try{raw=execSync('git status --porcelain -- packages packages-user src',{encoding:'utf8'})}catch(e){console.error('GIT STATUS FAILED '+(e.message||''));process.exit(1)}const out=raw.replace(/\s+$/,'');const cur=out.length>0?out.split(/\r?\n/).map(s=>s.replace(/\s+$/,'')):[];const extra=cur.filter(l=>rec.indexOf(l)<0);const gone=rec.filter(l=>cur.indexOf(l)<0);if(extra.length+gone.length>0){console.error('READONLY BASELINE CHANGED extra=['+extra.join(' ; ')+'] missing=['+gone.join(' ; ')+']');process.exit(1)}const actx=execSync('git status --porcelain -- .planning/phases/04-render-adaptation/04-CONTEXT.md',{encoding:'utf8'}).replace(/\s+$/,'');if(actx.length===0){console.error('USER CONTEXT EDIT DISAPPEARED (D-56)');process.exit(1)}console.log('OK read-only baseline verbatim entries '+cur.length)"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "READONLY BASELINE NOT RECORDED" / "READONLY BASELINE CHANGED" / "USER CONTEXT EDIT DISAPPEARED" / "GIT STATUS FAILED"(`## 方法` 未把起始 `git status --porcelain -- packages packages-user src` 输出逐行原样记录,或记录内容与当前状态不一致,或用户的 `04-CONTEXT.md` 未提交改动已消失、被回滚 / 提交 —— 违反只读与 D-56)</fails_when>
|
||||
<automated>node -e "const{execSync}=require('child_process');const sets=[[['../ui','../fx','../weather'],'packages-user/client-modules/src/render/components packages-user/client-modules/src/render/elements packages-user/client-modules/src/render/map packages-user/client-modules/src/render/utils/layout.ts'],[['client-modules'],'packages-user/client-base'],[['render/components','render/elements','render/map'],'packages src']];const bad=[];for(const s of sets){for(const pat of s[0]){let o='',st=0;try{o=execSync('git grep -n -F \"'+pat+'\" -- '+s[1],{encoding:'utf8',stdio:['ignore','pipe','pipe']})}catch(e){o=(e.stdout||'')+(e.stderr||'');st=e.status}let lines=o.replace(/\s+$/,'').length>0?o.split(/\r?\n/):[];if(pat.indexOf('render/')===0){lines=lines.filter(l=>l.indexOf('packages-user/client-modules/src/fallback/ui.ts')<0)}if(lines.length>0)bad.push(pat+' => '+lines.slice(0,3).join(' ; '));else if(st!==0&&st!==1)bad.push(pat+' grep status '+st)}}if(bad.length>0){console.error('LAYERING BASELINE NOT ZERO: '+bad.join(' || '));process.exit(1)}console.log('OK layering baseline zero')"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "LAYERING BASELINE NOT ZERO"(被移集合已 import `ui` / `fx` / `weather`,或 `client-base` 已引用 `client-modules`,或 `packages/` / `src/`(排除已登记的 `client-modules/src/fallback/ui.ts`)已命中被移集合目录 —— 说明移植已提前发生或清点范围判断有误)</fails_when>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- 交付文档存在于 `.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.md`,恰好 **11** 个二级标题,且含 `## A ` / `## B ` / `## C ` / `## D ` / `## E ` / `## F ` 与 `## 处置`
|
||||
- 元信息块齐备(日期 / 范围 / 性质 / 移植集合 / 目标布局 / 基准 / 下一步),且明写「只读、未修改生产代码、未引入命名变更」「不新建 `client-base/src/render/`」「本步不移动、不复制、不预建」
|
||||
- `## 方法` 含「只读起始基线」条目,**逐行原样**记录起始 `git status --porcelain -- packages packages-user src` 的输出(规划日单条 ` M packages-user/data-base/src/enemy/types.ts`);门禁断言记录条目与当前状态逐条一致,且用户的 `04-CONTEXT.md` 未提交改动仍在
|
||||
- `## 方法` 写死 A/B/C/D/E/F 六类判定口径与分列规则,并写明每行须含「命中处」与「目标锚点」两个 `file:line`
|
||||
- `## 被移集合清单(39 文件)` 逐条列出 D-52 的 **39** 个文件路径(`components` 13 / `elements` 5 / `map` 20 / `utils/layout.ts` 1),每条含目标路径与职责
|
||||
- A–F 六节各含至少 1 行 `render/utils/layout.ts` 端到端切片行(`#04-10-{A..E}-01` / `#04-10-F-01`),A–E 行各含 ≥2 个 `file:line` 锚点,F 类 ≥2 条
|
||||
- `## 处置` 初稿含「只读 / 零命名变更 / 第二步未规划 / legacy 仅报告 / 命名与解耦由用户裁定 / REND 保持 Pending」
|
||||
- 相对记录在 `## 方法` 的只读起始基线零变化;未修改任何生产源码;未预建 `client-base/src/{components,elements,map,layout}`;未新增计划文件;全文 CRLF;分层基线机器证据为零
|
||||
</acceptance_criteria>
|
||||
<done>交付文档骨架(11 节)+ 元信息块 + `## 背景` / `## 方法`(含只读起始基线)+ `## 被移集合清单(39 文件)` + `render/utils/layout.ts` 贯穿 A–F 的端到端切片 + `## 处置` 初稿全部落位;结构 / 清单 / 切片双锚点 / CRLF / 只读基线 / 分层基线六道门禁转绿;Task 2 只需在同一模板上横向补齐 A / B / C</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2:A / B / C 三类横向补齐 —— 被移集合内部交叉引用(8 个方向)/ 外部导入点(集合之外全部 importer,含其它 monorepo 包)/ barrel 与导出面(7 个节点与断链判定)</name>
|
||||
<files>.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.md</files>
|
||||
<read_first>
|
||||
- .planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.md(Task 1 的产出:在同一骨架上横向补齐,**不改结构、不改元信息块、不改 `## 方法` 的只读基线、不改 `## 被移集合清单` 的 39 条**)
|
||||
- .planning/phases/04-render-adaptation/04-CONTEXT.md(D-51..D-57 原文;D-33 边界;D-07 粒度;D-09 子代理)
|
||||
- .planning/phases/04-render-adaptation/04-10-PLAN.md(本计划:objective 的 A / B / C 分列规则与规划日实测表、禁令、门禁)
|
||||
- packages-user/client-modules/src/render/components/{index.ts,tip.tsx,textbox.tsx,textboxTyper.ts,misc.tsx,choices.tsx,scroll.tsx,input.tsx}(A 类:`../elements` 与留在 `render/` 的 `renderer` / `use.ts` 的引用)
|
||||
- packages-user/client-modules/src/render/elements/{index.ts,props.ts}(A 类:→ `../map`、→ `../renderer`;C 类:`createElements()` 与 3 条 `export *`)
|
||||
- packages-user/client-modules/src/render/map/{index.ts,vertex.ts,element.ts,renderer.ts,types.ts,moving.ts}(A 类:→ `../../shared`、→ `@user/client-base`;C 类:`map/index.ts` 导出集合)
|
||||
- packages-user/client-modules/src/render/map/extension/{door.ts,hero.ts,manager.ts,types.ts,text.ts}(A 类:→ `../types`、→ `../../../shared`)
|
||||
- packages-user/client-modules/src/{client.ts,types.ts}(B 类:`./render/map` 的两处导入)
|
||||
- packages-user/client-modules/src/render/index.tsx(B / C 类:`:5` `./elements`、`:45,46,51` 的 `export *`)
|
||||
- packages-user/client-modules/src/render/ui/{main.tsx,save.tsx,settings.tsx,statistics.tsx,statusBar.tsx,title.tsx,toolbar.tsx,viewmap.tsx}(B 类:8 文件 10 处 `../components` 导入,含 `toolbar.tsx:13` 的 `../components/icons` 与 `:19` 的 `../components/misc` 深层导入)
|
||||
- packages-user/client-modules/src/render/utils/{saves.ts,index.ts}(B 类:`saves.ts:2` `../components`、`index.ts:1` `./layout`)
|
||||
- packages-user/client-modules/src/fallback/ui.ts:2(B 类:深层导入 `../render/components/tip` 的 `TipStore`)
|
||||
- packages-user/client-modules/src/index.ts(C 类:`:3` `import { createGameRenderer, createRender } from './render'`、`:15` `export * from './render'`)
|
||||
- packages-user/client-base/src/index.ts(C 类:现行 4 条 `export *`)
|
||||
- packages-user/entry-client/src/create.ts:10,27 与 packages-user/entry-data/src/mota.ts:11,32 与 packages/legacy-ui/src/preset/ui.ts:86,96,105(B 类:其它 monorepo 包经 `@user/client-modules` 公共面的间接依赖;legacy 侧只登记)
|
||||
- dev.md(「项目结构」单向依赖;barrel / 导出规则)
|
||||
</read_first>
|
||||
<action>
|
||||
(1) **A 类补齐(被移集合内部交叉引用)**:按固定列序表逐条写满,**每行含「导入处 `file:line`」+「被导入符号的声明 / barrel `file:line`」两个锚点;行内不得出现移植方案、import 重写写法或「应改为 X」**:
|
||||
- `#04-10-A-02`:`components → elements`(`../elements`)—— `tip.tsx:7`(`texture`)、`textbox.tsx:33`(`texture`)、`textboxTyper.ts:5`(`RenderableData` / `AutotileRenderable` / `texture`);目标锚点 = `render/elements/index.ts` 的 `export * from './cache' | './misc' | './props'`(规划日 `:45-47`,以当日实测为准)与各符号的声明文件行。
|
||||
- `#04-10-A-03`:`elements → map`(`../map`)—— `elements/index.ts:2`(`MapRenderItem`)、`elements/props.ts:4`(`IMapExtensionManager` / `IMapRenderer`);目标锚点 = `render/map/index.ts` 的 `export *` 行(规划日 `:1-11`)与 `render/map/types.ts` 的声明行。
|
||||
- `#04-10-A-04`:被移集合 → **留在 `render/` 顶层的 `renderer`**(`../renderer`)—— `elements/index.ts:3`(`mainRenderer` / `tagManager`)、`components/textboxTyper.ts:6`(`using`)、`components/misc.tsx:14`(`using`);目标锚点 = `render/renderer.ts` 的对应导出声明行(当日实测)。**须写明:该方向移入后即成为 `client-base` → `client-modules` 反向依赖候选**,并交叉引用 D 类同向条目。
|
||||
- `#04-10-A-05`:被移集合 → **留在 `render/` 的 `use.ts`**(`../use`)—— `components/choices.tsx:8`(`useKey`)、`components/tip.tsx:4`(`transitioned`)、`components/scroll.tsx:31`(`transitioned`)、`components/input.tsx:14`(`transitionedColor` / `useKey`)、`components/misc.tsx:10`(`transitioned`);目标锚点 = `render/use.ts` 的导出声明行(当日实测)。同上为反向依赖候选;`render/use.ts:2` 自身 import `../weather`,须一并登记(交叉引用 D 类)。
|
||||
- `#04-10-A-06`:被移集合 → **`client-modules/src/shared.ts`** —— `map/vertex.ts:25`、`map/element.ts:5`、`map/renderer.ts:53`(均 `../../shared`)、`map/extension/door.ts:9`(`../../../shared`);目标锚点 = `packages-user/client-modules/src/shared.ts` 的导出声明行(当日实测)。**该方向是 D 类反向依赖最硬的一条**(连包内常量都反向)。
|
||||
- `#04-10-A-07`:被移集合 → **`@user/client-base`(自包引用)** —— `map/extension/hero.ts:16`(`IMaterialFramedData`)、`map/moving.ts:3`(`IMaterialFramedData` / `ITextureManager`)、`map/renderer.ts:13`、`map/types.ts:12`、`map/vertex.ts:28`(均 `IMaterialFramedData`);目标锚点 = `packages-user/client-base/src/{material/types.ts,types.ts}` 的对应声明行与 `client-base/src/index.ts` 的 barrel(当日实测)。**移入后成为包内自引**,改写方式属 F 类(不得自拟)。
|
||||
- `#04-10-A-08`:`map/extension/* → map/types`(`../types`)—— `extension/door.ts:7`、`extension/hero.ts:13`、`extension/manager.ts:8`、`extension/types.ts:4`、`extension/text.ts:8`;目标锚点 = `render/map/types.ts` 的对应声明行(当日实测)。**集合内部引用,随集合整体移动、相对路径不变 ⇒ 无断链风险**(须写清这一判定)。
|
||||
- `#04-10-A-09`:**A 类零命中的机器证据(不许凭印象)** —— 被移集合内对 `ui` / `fx` / `weather` 的 import 为 **0** 处:分别执行 `git grep -n -F "../ui"`、`git grep -n -F "../fx"`、`git grep -n -F "../weather"`(限 `packages-user/client-modules/src/render/components`、`render/elements`、`render/map`、`render/utils/layout.ts`),逐条原样抄录输出(规划日三条均无输出 / 退出码 1)。**只登记命令与输出,不判定其含义。**
|
||||
- 每条 A 行只归 A 类;若同事实又属 B / C / D 类,**拆条并互相引用**(如 A-04 ↔ D 类、A-07 ↔ D 类),不得互相冒充。
|
||||
|
||||
(2) **B 类补齐(外部导入点)**:按固定列序表逐条写满,**每行含「importer `file:line`」+「被导入文件 / barrel `file:line` 或导出声明行」两个锚点;行内不得出现移植方案或重写写法**:
|
||||
- `#04-10-B-02`:`client-modules/src/types.ts:2`(`./render/map` 的 `IMapExtensionManager` / `IMapRenderer`)与 `client-modules/src/client.ts:25`(`./render/map`,多符号);目标锚点 = `render/map/index.ts` 的 `export *` 行与 `render/map/types.ts` 的声明行。
|
||||
- `#04-10-B-03`:`client-modules/src/render/index.tsx:5`(`import { createElements } from './elements'`)、`:45`(`export * from './components'`)、`:46`(`export * from './elements'`);目标锚点 = `render/components/index.ts:1-12` 与 `render/elements/index.ts`(`createElements` 声明行 + `:45-47`)。
|
||||
- `#04-10-B-04`:`render/ui/` **8** 文件 **10** 处 `../components` 导入 —— `main.tsx:9`(`Textbox` / `TextboxProps` / `Tip`)、`save.tsx:16`(`getConfirm` / `Page` / `PageExpose` / `Thumbnail`)、`settings.tsx:16`(多符号)与 `:21`(`getInput`)、`statistics.tsx:8`(`waitbox` / `ListPage` / `TextContent`)、`statusBar.tsx:3`(`TextContent`)、`title.tsx:31`(`ExitFullscreen` / `Fullscreen` / `SoundVolume`)、`viewmap.tsx:26`(`FloorSelector`)与 `:29`(`Tip` / `TipExpose`)、`toolbar.tsx:13`(`../components/icons`)与 `:19`(`../components/misc` 的 `Progress`);目标锚点 = 各符号的声明文件行(当日实测)。**深层导入(`components/icons` / `components/misc`)须单列标注**——浅层 barrel 改指覆盖不到深层路径。
|
||||
- `#04-10-B-05`:`render/utils/saves.ts:2`(`getConfirm` / `waitbox`,`../components`);目标锚点 = `render/components` 的导出集合行。**该文件按 D-54 不移植但依赖被移集合 ⇒ 第二步必改点**(须单列标注)。
|
||||
- `#04-10-B-06`:`render/utils/index.ts:1`(`export * from './layout'`);目标锚点 = `render/utils/layout.ts` 的声明行。**与 Task 1 已登记的 `#04-10-B-01` 为同一事实 ⇒ 本条只做交叉引用,不得重复计数 / 另起 ID**(若沿用 B-01 则在本行动写明「见 `#04-10-B-01`」)。
|
||||
- `#04-10-B-07`:`fallback/ui.ts:2`(深层导入 `../render/components/tip` 的 `TipStore`);目标锚点 = `render/components/tip.tsx` 的 `TipStore` 声明行。**该文件按 D-54 不移植(`fallback` 属实现层)⇒ 第二步必改点**(须单列标注)。
|
||||
- `#04-10-B-08`:**其它 monorepo 包经 `@user/client-modules` 公共面的间接依赖** —— `entry-client/src/create.ts:10`(`import * as ClientModules from '@user/client-modules'`)与 `:27`(`Mota.register('@user/client-modules', ClientModules)`)、`entry-data/src/mota.ts:11`(`import type * as ClientModules`)与 `:32`(类型映射)、`packages/legacy-ui/src/preset/ui.ts:86` / `:96`(`Mota.require('@user/client-modules').mainRenderer.setScale(...)`)/ `:105`(`Mota.require('@user/client-modules').client`);目标锚点 = `client-modules/src/index.ts:15`(`export * from './render'`)与被取符号的声明行。**须写明:这些包不直接 import 被移集合,但经 `render` 的再导出链间接暴露被移集合的公共符号;移出后该再导出链必须补位,否则公共面收窄**(是否属破坏、如何补位属 F 类 / 用户裁定)。
|
||||
- `#04-10-B-09`:**对照扫描(机器证据)** —— 分别执行 `git grep -n -F "render/components"`、`-F "render/elements"`、`-F "render/map"`(限 `packages` 与 `src`)并原样抄录输出;规划日仅 `packages-user/client-modules/src/fallback/ui.ts:2` 一条落在 `packages-user` 内,`packages/` 与 `src/` 对**被移集合源文件**零直接命中。**只登记输出与结论,不得为 `packages/` 与 `src/` 提修改建议。**
|
||||
- 深层导入、「不移植但被引用」的第二步必改点须逐条单列标注;**不得把 B 行写成待办或修复项**。
|
||||
|
||||
(3) **C 类补齐(barrel 与导出面)**:按固定列序表逐条写满,**每行含「barrel `file:line`」+「被导出文件的声明行 `file:line`」两个锚点**,并给出「现状导出集合 → 移出后是否断链」的判定(**只判定断链与否,不裁定如何补位,不裁定是否新增 barrel**):
|
||||
- `#04-10-C-02`:`render/components/index.ts:1-12`(12 条 `export *`,逐条抄录);判定 = **随集合整体移动**、集合内相对路径不变 ⇒ 自身不断链;但 `render/index.tsx:45` 与 `render/ui/*` 的 `../components` 路径需改指(属第二步)。
|
||||
- `#04-10-C-03`:`render/elements/index.ts`(`:1` import `@motajs/common`、`:2` import `../map`、`:3` import `../renderer`、`:4` / `:5` 本地 import、`createElements()` 声明行、`:45-47` 三条 `export *`);判定 = 移出后 `:2` 变为集合内引用(不断链)、**`:3` 变为 `client-base` → `client-modules` 反向依赖**(交叉引用 A-04 与 D 类);`createElements()` 的注册点接线属 F 类。
|
||||
- `#04-10-C-04`:`render/map/index.ts:1-11`(`export * from './extension'` + `'./block'` / `'./constant'` / `'./element'` / `'./moving'` / `'./renderer'` / `'./status'` / `'./types'` / `'./vertex'` / `'./viewport'`);判定 = 随集合整体移动、自身不断链;`client.ts:25` 与 `types.ts:2` 的 `./render/map` 需改指。
|
||||
- `#04-10-C-05`:`render/index.tsx:45`(`export * from './components'`)、`:46`(`export * from './elements'`)、`:51`(`export * from './renderer'`);判定 = **移出后 `:45` / `:46` 断链**(`:51` 的 `./renderer` 留原地不断链),必须补位,否则 `@user/client-modules` 公共面收窄(交叉引用 B-08)。
|
||||
- `#04-10-C-06`:`render/utils/index.ts:1-3`(`export * from './layout' | './saves' | './use'`);判定 = **`:1` 移出即断链**(D-54 明示 `utils/index.ts` 不移植);`render/ui/{save,settings,title}.tsx` 经 `../utils` 间接消费该导出(`save.tsx:31` / `settings.tsx:20` / `title.tsx:35`)。
|
||||
- `#04-10-C-07`:`client-modules/src/index.ts:3`(`import { createGameRenderer, createRender } from './render'`)与 `:15`(`export * from './render'`);判定 = 再导出链的顶层出口,公共面收窄的最终承担点。
|
||||
- `#04-10-C-08`:`client-base/src/index.ts:1-5`(现行 `export * from './load' | './material' | './save' | './types'`);判定 = 目标侧 barrel **现状不含** `components` / `elements` / `map` / `layout`。**是否新增导出属 F 类,不得裁定。**
|
||||
- 另写一条 **导出面链条小结**(不新增独立事实,只把上面的链条串起来):`components/index.ts` + `elements/index.ts` + `map/index.ts` → `render/index.tsx:45,46,51` → `client-modules/src/index.ts:3,15` → `@user/client-modules` 消费者(`entry-client` / `entry-data` / `packages/legacy-ui`),供第二步据以补位。
|
||||
|
||||
(4) **重型整文件读取可按 D-09 委派只读子代理**(`render/ui/` 8 文件、`components/` 13 文件、`map/renderer.ts` 与 `map/vertex.ts` 两个较大文件):子代理只回传事实表(每行:文件 + `file:line` + 形态或签名),**不得写文件、不得贴大段源码**;主执行者按 `file:line` 切片复核后落笔。
|
||||
|
||||
(5) **只修改该交付文档**;不得改动任何生产源码(含用户既有的未提交改动);不得新增计划文件;不得预建 `client-base/src/{components,elements,map,layout}`;不得改动 Task 1 已定稿的结构、元信息块、只读基线与 39 条清单。
|
||||
</action>
|
||||
<!-- plan-criteria-allow: R4 - 本任务验证块内的竖线字符全部位于 node 程序的正则分支 / 数组字面量中,不是 shell 管道;所有 git 命令均由 node 的 execSync 调用并在 JS 内捕获 stdout 与 exit status 后自行判定,不经 shell 管道传递状态 -->
|
||||
<verify>
|
||||
<automated>node -e "const fs=require('fs');const t=fs.readFileSync('.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.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 A=seg('## A '),B=seg('## B '),C=seg('## C ');const cnt=(s,re)=>(s.match(re)||[]).length;const rows=(s,c)=>cnt(s,new RegExp('^\\|\\s*#04-10-'+c+'-\\d+\\s*\\|','gm'));const anch=l=>cnt(l,/[A-Za-z0-9_\-.\\/]+\.(tsx?|frag|vert):\d+/g);const p=[];if(!A||!B||!C)p.push('MISSING SECTION');if(rows(A,'A')<8)p.push('A ROWS '+rows(A,'A'));if(rows(B,'B')<8)p.push('B ROWS '+rows(B,'B'));if(rows(C,'C')<7)p.push('C ROWS '+rows(C,'C'));const check=(s,c)=>{const re=new RegExp('^\\|\\s*#04-10-'+c+'-\\d+\\s*\\|');const bad=s.split(/\r?\n/).filter(l=>re.test(l)).filter(l=>anch(l)<2);if(bad.length>0)p.push(c+' ROWS WITHOUT TWO-SIDED ANCHOR '+bad.length)};check(A,'A');check(B,'B');check(C,'C');const needA=['tip.tsx','textbox.tsx','textboxTyper.ts','elements/index.ts','elements/props.ts','renderer','use.ts','shared.ts','@user/client-base','extension'];const mA=needA.filter(k=>A.indexOf(k)<0);if(mA.length>0)p.push('A MISSING '+mA.join('|'));const needB=['client.ts','types.ts','render/index.tsx','main.tsx','save.tsx','settings.tsx','statistics.tsx','statusBar.tsx','title.tsx','toolbar.tsx','viewmap.tsx','saves.ts','fallback/ui.ts','entry-client','entry-data','legacy-ui'];const mB=needB.filter(k=>B.indexOf(k)<0);if(mB.length>0)p.push('B MISSING '+mB.join('|'));const needC=['components/index.ts','elements/index.ts','map/index.ts','render/index.tsx','utils/index.ts','client-modules/src/index.ts','client-base/src/index.ts'];const mC=needC.filter(k=>C.indexOf(k)<0);if(mC.length>0)p.push('C MISSING '+mC.join('|'));if(p.length>0){console.error('ABC GATE FAILED :: '+p.join(' ;; '));process.exit(1)}console.log('OK A'+rows(A,'A')+' B'+rows(B,'B')+' C'+rows(C,'C'))"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "ABC GATE FAILED"(A 少于 8 行 / B 少于 8 行 / C 少于 7 行,或任一行缺「命中处」「目标锚点」两个 `file:line` 锚点,或 A 未覆盖 8 个内部引用方向、B 未覆盖 8 个外部导入点文件族与 3 个间接依赖包、C 未覆盖 7 个 barrel 节点)</fails_when>
|
||||
<automated>node -e "const{execSync}=require('child_process');const sets=[[['../ui','../fx','../weather'],'packages-user/client-modules/src/render/components packages-user/client-modules/src/render/elements packages-user/client-modules/src/render/map packages-user/client-modules/src/render/utils/layout.ts'],[['client-modules'],'packages-user/client-base']];const bad=[];for(const s of sets){for(const pat of s[0]){let o='',st=0;try{o=execSync('git grep -n -F \"'+pat+'\" -- '+s[1],{encoding:'utf8',stdio:['ignore','pipe','pipe']})}catch(e){o=(e.stdout||'')+(e.stderr||'');st=e.status}const lines=o.replace(/\s+$/,'').length>0?o.split(/\r?\n/):[];if(lines.length>0)bad.push(pat+' => '+lines.slice(0,3).join(' ; '));else if(st!==0&&st!==1)bad.push(pat+' grep status '+st)}}if(bad.length>0){console.error('ZERO-HIT CLAIM FALSIFIED: '+bad.join(' || '));process.exit(1)}console.log('OK zero-hit claims verified')"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "ZERO-HIT CLAIM FALSIFIED"(被移集合内仍存在对 `ui` / `fx` / `weather` 的 import,或 `client-base` 已出现对 `client-modules` 的引用 —— 即台账中的「零命中」结论为臆造,或移植已提前发生)
|
||||
</fails_when>
|
||||
<automated>node -e "const fs=require('fs');const s=fs.readFileSync('.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.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>
|
||||
- A 类 **≥ 8 行**,覆盖 8 个方向:`components→elements`、`elements→map`、→`render/renderer`、→`render/use.ts`、→`client-modules/src/shared.ts`、→`@user/client-base`(自包引用)、`map/extension/*→map/types`、A 类零命中机器证据;每行含导入处与目标锚点两个 `file:line`
|
||||
- B 类 **≥ 8 行**,覆盖 `client.ts:25` / `types.ts:2` / `render/index.tsx:5,45,46` / `render/ui` 8 文件 10 处(含 `toolbar.tsx` 的深层导入)/ `render/utils/saves.ts:2` / `render/utils/index.ts:1`(与 B-01 交叉引用而不重复计数)/ `fallback/ui.ts:2` / 其它 monorepo 包(`entry-client` / `entry-data` / `packages/legacy-ui`)的间接依赖 / 对照扫描机器证据;深层导入与「不移植但被引用」的第二步必改点单列标注
|
||||
- C 类 **≥ 7 行**,覆盖 7 个 barrel 节点(`components/index.ts` / `elements/index.ts` / `map/index.ts` / `render/index.tsx` / `render/utils/index.ts` / `client-modules/src/index.ts` / `client-base/src/index.ts`),逐条给出「现状导出集合 → 移出后是否断链」判定,并附导出面链条小结;未裁定「是否新增 barrel / 如何补位」
|
||||
- 所有 A–C 行含 ≥2 个 `file:line` 锚点;行内无移植方案、无 import 重写写法、无「应改为 X」
|
||||
- 相对记录在 `## 方法` 的只读起始基线零变化;未修改任何生产源码;未预建目标目录;全文 CRLF
|
||||
</acceptance_criteria>
|
||||
<done>A / B / C 三类横向补齐:8 个内部交叉引用方向(含零命中机器证据)/ 8 个外部导入点文件族与 3 个间接依赖包 / 7 个 barrel 节点与断链判定 + 导出面链条小结;行数 / 双锚点 / 关键词 / 零命中复验 / CRLF 门禁转绿</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3:D / E / F 三类补齐 + `## 处置` 定稿 + 五道门禁 + 人工复核 + `04-10-SUMMARY.md` 落盘与提交</name>
|
||||
<files>.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.md, .planning/phases/04-render-adaptation/04-10-SUMMARY.md</files>
|
||||
<read_first>
|
||||
- .planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.md(Task 1 / 2 产出,做定稿与横向补齐而非重写)
|
||||
- .planning/phases/04-render-adaptation/04-CONTEXT.md(D-51..D-57;D-33 / D-42 / D-49;Deferred Ideas)
|
||||
- .planning/phases/04-render-adaptation/04-09-SUMMARY.md:1-45(既有 SUMMARY 的元信息块 / actuals / key-decisions 写法,可对齐版式)
|
||||
- .planning/phases/04-render-adaptation/04-TEXTURE-INTERFACE-IMPACT.md:245-268(既有清点文档的 `## F` / `## 处置` 写法:F 类只登记不判定、处置节写明第二步未规划)
|
||||
- .planning/phases/04-render-adaptation/04-10-PLAN.md(本计划:门禁与禁令)
|
||||
- packages-user/client-base/package.json:1-10 与 packages-user/client-modules/package.json:1-19(D 类:依赖现状与缺口)
|
||||
- packages-user/client-modules/src/render/map/renderer.ts:43-46(D 类:`./shader/{map,back}.{vert,frag}?raw`)与 packages-user/client-modules/src/render/map/shader/(4 个 shader 文件)
|
||||
- packages-user/client-modules/src/render/elements/{cache.ts,misc.ts}(E 类:`core.*` / `loading` / `Mota.require('@user/data-base')` 命中)
|
||||
- packages-user/client-modules/src/render/components/{choices.tsx,floorSelect.tsx,misc.tsx,textboxTyper.ts,thumbnail.tsx,tip.tsx}(E 类:`core.*` 命中)
|
||||
- packages-user/client-modules/src/render/use.ts:2(D 类:`use.ts` 自身 import `../weather`)
|
||||
- dev.md(「项目结构」单向依赖 `src → packages-user → packages`;「双端分离」;「其他要求」的 CRLF)
|
||||
</read_first>
|
||||
<action>
|
||||
(1) **D 类补齐(分层与循环依赖风险)**:按固定列序表逐条写满,**每行含「风险源 `file:line`」+「规则 / 依赖基准锚点 `file:line`」两个锚点**,**只登记风险与机器证据,不得自拟解耦方案**(不得写「应下沉 / 应抽类型 / 应保留跨包依赖 / 应改用 X」):
|
||||
- `#04-10-D-02`:移入后 `client-base` → `client-modules` 反向依赖(**常量 / 工具面**)—— `map/vertex.ts:25`、`map/element.ts:5`、`map/renderer.ts:53`、`map/extension/door.ts:9`(交叉引用 A-06,不重复计数);基准锚点 = `packages-user/client-modules/src/shared.ts` 的声明行 + `dev.md` 的单向依赖条目。
|
||||
- `#04-10-D-03`:同向(**渲染器面**)—— `elements/index.ts:3`、`components/textboxTyper.ts:6`、`components/misc.tsx:14`(交叉引用 A-04);基准锚点 = `render/renderer.ts` 的导出声明行 + `dev.md` 单向依赖条目。
|
||||
- `#04-10-D-04`:同向(**hooks 面**)—— `components/{choices.tsx:8,tip.tsx:4,scroll.tsx:31,input.tsx:14,misc.tsx:10}`(交叉引用 A-05);基准锚点 = `render/use.ts` 的导出声明行。**须写明 `render/use.ts:2` 自身 import `../weather`,即该链条可能牵出 `ui` / `fx` / `weather` 与 `client.*`,静态阅读不能判定是否必然成环 ⇒ 交叉引用 F 类。**
|
||||
- `#04-10-D-05`:同向(**barrel 面**)—— `render/utils/index.ts:1`(交叉引用 `#04-10-C-01` / `#04-10-C-06`);基准锚点 = `render/utils/layout.ts` 的声明行。
|
||||
- `#04-10-D-06`:**自包引用** —— `@user/client-base` 的 5 处(`map/extension/hero.ts:16`、`map/moving.ts:3`、`map/renderer.ts:13`、`map/types.ts:12`、`map/vertex.ts:28`;交叉引用 A-07);基准锚点 = `packages-user/client-base/src/index.ts:1-5`(barrel)+ `packages-user/client-base/package.json:3-9`。**改写方式属 F 类。**
|
||||
- `#04-10-D-07`:**`package.json` 依赖缺口** —— `packages-user/client-base/package.json:3-9` 现行只声明 `@motajs/audio` / `@motajs/render` / `@motajs/client-base` / `@user/data-base` / `@user/data-state`;被移集合还用 `@motajs/render-vue`(12 个组件 + `elements/props.ts:1`)、`@motajs/system`(`choices.tsx:7` 等)、`@motajs/common`(`elements/index.ts:1`)、`@user/data-common`(`map/renderer.ts:38` / `map/vertex.ts:2` / `map/extension/{hero.ts:11,manager.ts:1,types.ts:2}`);基准锚点 = `packages-user/client-modules/package.json:4-17`(这些依赖当前都在实现层声明)。**只登记缺口事实,不得提出补声明、安装或改配置的建议。**
|
||||
- `#04-10-D-08`:**反向依赖现状的机器证据** —— 执行 `git grep -n -F "client-modules" -- packages-user/client-base` 并原样抄录输出(规划日无输出 / 退出码 1)⇒ 该风险由本次移植**引入**、非既有;基准锚点 = `packages-user/client-base/package.json:3-9`(deps 内无 `@user/client-modules`)。同条附 `git grep -n -F "from '@user/client-base'" -- packages-user/client-modules/src` 的原样输出(规划日 7 条命中,其中 5 条在被移集合内、另 2 条在 `client.ts:19` / `fallback/load.ts:6`)。
|
||||
- `#04-10-D-09`:**shader `?raw` 构建链** —— `render/map/renderer.ts:43-46`(`./shader/{map,back}.{vert,frag}?raw`)+ `render/map/shader/` 的 4 个文件;基准锚点 = `packages-user/client-modules/` 与 `packages-user/client-base/` 的构建 / 配置现状(只登记事实:`?raw` 由构建链处理,换包后是否仍成立属 F 类)。
|
||||
- `#04-10-D-10`:**规则基准对照** —— `dev.md` 的「依赖方向单向 `src → packages-user → packages`」「不得循环引用」「双端分离(`client-base` 系统层 / `client-modules` 实现层)」;逐条列出与本案的关系(哪些方向被违反、哪些仍合法)。**只对照,不裁定处置。**
|
||||
- **D 类每条不得写成待办 / 修复项 / 解耦方案。**
|
||||
|
||||
(2) **E 类补齐(legacy 命中·仅报告)**:标题下明写 `**本节仅报告:按 D-55 不考虑任何 legacy 内容,legacy 相关报错一律不管、不修、不登记为待办。**` 逐条登记事实与核对命令:
|
||||
- `#04-10-E-02`:`core.*` 命中的逐文件汇总 —— 规划日:`components/choices.tsx` 13 处(`:675,715,717,718,719,728,733,770,772,773,774,783,789`)、`components/floorSelect.tsx` 2 处(`:62,181`)、`components/misc.tsx` 1 处(`:312`)、`components/textboxTyper.ts` 1 处(`:906`)、`components/thumbnail.tsx` 1 处(`:75`)、`components/tip.tsx` 1 处(`:103`)、`render/elements/cache.ts` 9 处(`:11,87,89,131,151,202,206,393,469`)、`render/elements/misc.ts` 2 处(`:221,228`);须执行核对命令并原样抄录输出(`git grep -n -F "core." -- <被移集合四个路径>`,以当日实测为准,命中数不同即按实测写入);基准锚点 = `dev.md` 的 legacy 相关条目 + `04-CONTEXT.md` 的 D-12(`core.*` 属旧引擎适配,归第五阶段)。
|
||||
- `#04-10-E-03`:**全局 `loading` + `Mota.require('@user/data-base')`** —— `render/elements/cache.ts:491-492`(`const { loading } = Mota.require('@user/data-base'); loading.once('loaded', ...)`)与 `render/elements/misc.ts:89-94` / `:219-225`(同形);基准锚点 = `04-CONTEXT.md` 的 D-14(全局 `hook` / `loading` 属 legacy)。**只报告。**
|
||||
- `#04-10-E-04`:**`client.*` 在移出集合内 0 命中** —— 执行 `git grep -n -F "client." -- <被移集合四个路径>` 并原样抄录输出(规划日无输出 / 退出码 1);基准锚点 = `04-CONTEXT.md` 的 D-12 / D-23(`client.*` 属本阶段需处理内容,但本步零代码改动)。**只报告;不得由此提出 `client.*` 的清退方案。**
|
||||
- `#04-10-E-05`:**`packages/` 与 `src/` 的对照扫描** —— 执行 `git grep -n -F "render/components"`、`-F "render/elements"`、`-F "render/map"`(限 `packages` 与 `src`)并原样抄录输出(规划日 `packages/` 与 `src/` 零命中;`packages-user` 内仅 `client-modules/src/fallback/ui.ts:2`);基准锚点 = `04-CONTEXT.md` 的 D-33(范围外一律不改)。**只报告,不提修改建议。**
|
||||
- `#04-10-E-06`:**`render/elements/cache.ts` 的 legacy 贴图路径现状**(对照 04-06 / 04-07 的 big-image 清退面)—— 按当日阅读逐条登记该文件残存的 legacy 贴图访问点(`file:line`)与其形态;基准锚点 = `04-MATERIAL-INTERFACE-IMPACT.md` / `04-07-SUMMARY.md` 中关于 big-image 清退的记录行。**只报告,不登记为待办**(D-55)。
|
||||
- 全节**不得**出现针对被移集合、`packages/` 或 `src/` 的修改性措辞。
|
||||
|
||||
(3) **F 类补齐(未能从阅读确定·未猜测)**:每条以 `- **#04-10-F-NN**:` 开头,写「现象 + 为什么读不出来 + 需要用户裁决的点」,至少覆盖(F-01 / F-02 已在 Task 1 写下,此处续编):① 目标文件名未确定(`client-base/src/layout/layout.ts` 还是 `layout/index.ts`;`client-base/src/{components,elements,map}/index.ts` 是否沿用同名)——**命名须先向用户反馈并获同意后才可使用**;② `render/utils/index.ts` 在 `layout.ts` 移出后的归属(D-54 明示不移植 ⇒ 断链处置未裁定);③ `client-base/src/index.ts` 是否新增 `export * from './{components,elements,map,layout}'`,以及 `render/index.tsx:45,46` 的断链如何补位(导出面是否扩张 / 收窄的裁定权在用户);④ 被移集合对留在 `client-modules` 的 `shared.ts` / `renderer` / `use.ts` / `render/utils` 的依赖如何解耦(交叉引用 D 类各条);⑤ `@user/client-base` 自包引用的改写方式;⑥ `client-base/package.json` 的依赖缺口是否在第二步补齐(D-37 有先例,本步不裁定);⑦ shader `?raw` 在 `client-base` 构建链下是否仍可用;⑧ `packages/legacy-ui` 经 `Mota.require('@user/client-modules')` 运行时取 `mainRenderer` / `client` 的插件面影响(legacy,只登记);⑨ `render/elements/index.ts` 的 `createElements()` 注册点(`mainRenderer.registerElement(...)` / `tagManager.registerTag(...)`)在 `client-base` 无渲染器实例时如何接线。**不得把本节任何一条写成错配、缺失、残留或待办。**
|
||||
|
||||
(4) **`## 处置` 定稿**:明写 —— 本文件是渲染端结构性重构(D-51 / D-57)**第一步(只读清点)**的交付物;本步**未修改任何生产代码、未引入任何命名变更**、`files_modified` 仅本文件;相对 `## 方法` 记录的只读起始基线零变化;**第二步(移植实施)未规划**,待用户审阅本文件后另行规划(D-57);被查范围 = 移植集合 39 文件与其全部 importer(含其它 monorepo 包的间接依赖),`packages/` 与 `src/` 仅报告(D-33);A / B 是事实层、C 是桶与导出面事实与断链判定、**D 是风险登记(解耦方案由用户裁定)**、**E 类按 D-55 只报告、不修、不登记为待办**、F 类须用户裁决;**全部命名问题归用户**(AGENTS.md);第二步的候选工作集 = B 类外部导入点 + C 类的断链点 + D 类的解耦面 + F 类的裁决项(最终纳入范围由用户裁定);`REND-01` / `REND-02` 保持 Pending;若当日实测与规划日数值(39 文件 / A 8 方向 / B 8 文件族 + 3 包 / C 7 节点 / D 9 条 / E 8 文件 / F ≥9)不同,在本节说明差异与原因。
|
||||
|
||||
(5) **运行五道门禁并按实测结果如实记录**:① 只读门禁(`git status --porcelain -- packages packages-user src` 与 `## 方法` 记录逐条一致;并断言 `.planning/phases/04-render-adaptation/04-CONTEXT.md` 的未提交改动仍在、`.planning/REQUIREMENTS.md` 未被改动且 `REND-01` / `REND-02` 仍为 `Pending`);② 类别门禁(A ≥ 8 / B ≥ 8 / C ≥ 7 / D ≥ 9 / E ≥ 6 / F ≥ 9、每行 ≥2 个 `file:line` 锚点、关键词齐备、`## 处置` 存在);③ 机器证据复验(`client-base` 对 `client-modules` 零命中、被移集合对 `ui`/`fx`/`weather` 零命中);④ 既有产物保护 + 计划范围门禁(`04-01`..`04-09` 的 `*-PLAN.md` / `*-SUMMARY.md` porcelain 为空;phase 目录内 `-PLAN.md` 恰为 `04-01`..`04-10` 共 10 个;`04-10-SUMMARY.md` 已落盘);⑤ CRLF 门禁。任一门禁失败即停下修正文档后重跑,**不得**改门禁口径或伪造通过。
|
||||
|
||||
(6) **人工代码复核(不可自动化,如实记录结论)**:抽查 A 类的 `render/components/tip.tsx:7` 与 `render/elements/index.ts:2` 与 `render/elements/index.ts:3` 与 `render/map/renderer.ts:53`、B 类的 `render/ui/toolbar.tsx:13` 与 `render/fallback/ui.ts:2`(深层导入)、C 类的 `render/index.tsx:45,46` 与 `render/utils/index.ts:1`、D 类的 `render/map/renderer.ts:43-46`(`?raw`)与 `packages-user/client-base/package.json` 依赖集合、E 类的 `render/elements/cache.ts:491-492`,逐条打开当日源码确认「命中处锚点指向的确实是该符号 / 成员的引用」「目标锚点指向的确实是该声明 / barrel 行」,并把复核结论(通过 / 发现偏差及修正)写入 SUMMARY。发现偏差即回到文档修正。
|
||||
|
||||
(7) **写 `04-10-SUMMARY.md`**:按执行日实际结果写(元信息块:phase / plan / subsystem / tags / requires / provides / affects / tech-stack / key-files / key-decisions / actuals / metrics / status),并逐条记录:本 run 的实际产出(唯一交付文档 + 本 PLAN + 本 SUMMARY)、被移集合实际文件数(39 与实测差异)、A–F 六类的实际行数与关键结论(反向依赖候选 4 族 13 处、自包引用 5 处、断链点、依赖缺口、legacy 命中数、F 类条数)、`git status --porcelain -- packages packages-user src` 的当日实测值、五道门禁的实际结果、人工复核结论、与规划日数值的差异说明、以及 `REND-01` / `REND-02` 仍为 Pending 与「第二步未规划」。**不得**把未运行的检查写成通过;**不得**把移植方案 / import 重写方案 / 命名写进 SUMMARY(一律由用户裁定)。
|
||||
|
||||
(8) **提交**:以 `docs(04-10): 渲染端结构性重构只读影响清点(D-51/D-57 第一步)` 提交**仅** `.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.md`、`.planning/phases/04-render-adaptation/04-10-PLAN.md` 与 `.planning/phases/04-render-adaptation/04-10-SUMMARY.md` 三个文件(ROADMAP 的登记改动若已由计划阶段提交则不复述;若未提交且属本次登记,可一并纳入并在 SUMMARY 注明);**不得**把任何生产源码改动或用户既有的未提交改动纳入本次提交(尤其不得提交 `.planning/phases/04-render-adaptation/04-CONTEXT.md` 与 `packages-user/data-base/**` 的既有未提交改动),不得改写 / 覆盖 / 改号 `04-01`..`04-09` 的既有产物。
|
||||
</action>
|
||||
<!-- plan-criteria-allow: R4 - 本任务验证块内的竖线字符全部位于 node 程序的正则分支 / 数组字面量中,不是 shell 管道;所有 git 命令均由 node 的 execSync 调用并在 JS 内捕获 stdout 与 exit status 后自行判定,不经 shell 管道传递状态 -->
|
||||
<verify>
|
||||
<automated>node -e "const fs=require('fs'),{execSync}=require('child_process');const t=fs.readFileSync('.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.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 ms=seg('## \u65b9\u6cd5');if(ms.indexOf('\u53ea\u8bfb\u8d77\u59cb\u57fa\u7ebf')<0){console.error('READONLY BASELINE NOT RECORDED');process.exit(1)}const rec=(ms.match(/^[ MARCUD?!]{2} (?:packages|packages-user|src)[^\r\n]*/gm)||[]).map(s=>s.replace(/\s+$/,''));let raw='';try{raw=execSync('git status --porcelain -- packages packages-user src',{encoding:'utf8'})}catch(e){console.error('GIT STATUS FAILED '+(e.message||''));process.exit(1)}const out=raw.replace(/\s+$/,'');const cur=out.length>0?out.split(/\r?\n/).map(s=>s.replace(/\s+$/,'')):[];const extra=cur.filter(l=>rec.indexOf(l)<0);const gone=rec.filter(l=>cur.indexOf(l)<0);if(extra.length+gone.length>0){console.error('READONLY BASELINE CHANGED extra=['+extra.join(' ; ')+'] missing=['+gone.join(' ; ')+']');process.exit(1)}if(execSync('git status --porcelain -- .planning/phases/04-render-adaptation/04-CONTEXT.md',{encoding:'utf8'}).replace(/\s+$/,'').length===0){console.error('USER CONTEXT EDIT DISAPPEARED (D-56)');process.exit(1)}const roReq=execSync('git status --porcelain -- .planning/REQUIREMENTS.md',{encoding:'utf8'}).replace(/\s+$/,'');if(roReq.length>0){console.error('READ-ONLY VIOLATION .planning/REQUIREMENTS.md: '+roReq);process.exit(1)}const req=fs.readFileSync('.planning/REQUIREMENTS.md','utf8').split(/\r?\n/);const notPending=[];for(const id of ['REND-01','REND-02']){const line=req.filter(l=>l.indexOf('| '+id+' |')>=0).join('')||req.filter(l=>l.indexOf(id)>=0).join('');if(!/\|\s*Pending\s*\|/.test(line))notPending.push(id)}if(notPending.length>0){console.error('REND STATUS NOT PENDING: '+notPending.join(','));process.exit(1)}console.log('OK read-only unchanged entries '+cur.length+'; REND-01/REND-02 still Pending')"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "READONLY BASELINE NOT RECORDED" / "READONLY BASELINE CHANGED" / "GIT STATUS FAILED" / "USER CONTEXT EDIT DISAPPEARED" / "READ-ONLY VIOLATION" / "REND STATUS NOT PENDING"(`packages` / `packages-user` / `src` 下出现新增 / 消失 / 状态码变化的条目,或用户的 `04-CONTEXT.md` 未提交改动消失,或 `.planning/REQUIREMENTS.md` 被改动,或 `REND-01` / `REND-02` 不再是 `Pending` —— 违反只读 / D-56 或「REND 保持 Pending」真值不成立)</fails_when>
|
||||
<automated>node -e "const fs=require('fs');const t=fs.readFileSync('.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.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 sec={A:seg('## A '),B:seg('## B '),C:seg('## C '),D:seg('## D '),E:seg('## E '),F:seg('## F '),Z:seg('## \u5904\u7f6e')};const cnt=(s,re)=>(s.match(re)||[]).length;const rows=(s,c)=>cnt(s,new RegExp('^\\|\\s*#04-10-'+c+'-\\d+\\s*\\|','gm'));const anch=l=>cnt(l,/[A-Za-z0-9_\-.\\/]+\.(tsx?|frag|vert):\d+/g);const p=[];if(!sec.Z)p.push('MISSING DISPOSITION');const min={A:8,B:8,C:7,D:9,E:6};for(const c of ['A','B','C','D','E']){const n=rows(sec[c],c);if(n<min[c])p.push(c+' ROWS '+n);const re=new RegExp('^\\|\\s*#04-10-'+c+'-\\d+\\s*\\|');const bad=sec[c].split(/\r?\n/).filter(l=>re.test(l)).filter(l=>anch(l)<2);if(bad.length>0)p.push(c+' ROWS WITHOUT TWO-SIDED ANCHOR '+bad.length)}if(cnt(sec.F,/^- \*\*#04-10-F-\d+/gm)<9)p.push('F ITEMS '+cnt(sec.F,/^- \*\*#04-10-F-\d+/gm));const needD=['shared.ts','renderer','use.ts','@user/client-base','package.json','?raw','dev.md'];const mD=needD.filter(k=>sec.D.indexOf(k)<0);if(mD.length>0)p.push('D MISSING '+mD.join('|'));const needE=['core.','loading','Mota.require','cache.ts','packages/','src/'];const mE=needE.filter(k=>sec.E.indexOf(k)<0);if(mE.length>0)p.push('E MISSING '+mE.join('|'));if(cnt(sec.E,/\u4ec5\u62a5\u544a/g)<1)p.push('E REPORT-ONLY PHRASE');if(p.length>0){console.error('FINAL CATEGORY GATE FAILED :: '+p.join(' ;; '));process.exit(1)}console.log('OK A'+rows(sec.A,'A')+' B'+rows(sec.B,'B')+' C'+rows(sec.C,'C')+' D'+rows(sec.D,'D')+' E'+rows(sec.E,'E')+' F'+cnt(sec.F,/^- \*\*#04-10-F-\d+/gm))"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "FINAL CATEGORY GATE FAILED"(缺 `## 处置`;或 A < 8 / B < 8 / C < 7 / D < 9 / E < 6;或任一行缺两个 `file:line` 锚点;或 F 类少于 9 条;或 D 未覆盖反向依赖 / 自包引用 / `package.json` / `?raw` / `dev.md`;或 E 未覆盖 `core.` / `loading` / `Mota.require` / `cache.ts` / `packages/` / `src/` 或缺「仅报告」措辞)</fails_when>
|
||||
<automated>node -e "const{execSync}=require('child_process');const sets=[[['client-modules'],'packages-user/client-base'],[['../ui','../fx','../weather'],'packages-user/client-modules/src/render/components packages-user/client-modules/src/render/elements packages-user/client-modules/src/render/map packages-user/client-modules/src/render/utils/layout.ts']];const bad=[];for(const s of sets){for(const pat of s[0]){let o='',st=0;try{o=execSync('git grep -n -F \"'+pat+'\" -- '+s[1],{encoding:'utf8',stdio:['ignore','pipe','pipe']})}catch(e){o=(e.stdout||'')+(e.stderr||'');st=e.status}const lines=o.replace(/\s+$/,'').length>0?o.split(/\r?\n/):[];if(lines.length>0)bad.push(pat+' => '+lines.slice(0,3).join(' ; '));else if(st!==0&&st!==1)bad.push(pat+' grep status '+st)}}if(bad.length>0){console.error('ZERO-HIT CLAIM FALSIFIED: '+bad.join(' || '));process.exit(1)}console.log('OK zero-hit claims verified')"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "ZERO-HIT CLAIM FALSIFIED"(`client-base` 已引用 `client-modules`,或被移集合已 import `ui` / `fx` / `weather` —— 台账中的「零命中」结论为臆造,或移植已提前发生)</fails_when>
|
||||
<automated>node -e "const fs=require('fs'),{execSync}=require('child_process');const dir='.planning/phases/04-render-adaptation';const ids=['04-01','04-02','04-03','04-04','04-05','04-06','04-07','04-08','04-09'];const prot=[];for(const n of ids){prot.push(dir+'/'+n+'-PLAN.md');prot.push(dir+'/'+n+'-SUMMARY.md')}const args=prot.filter(f=>fs.existsSync(f)).map(p=>'\"'+p+'\"').join(' ');const o=execSync('git status --porcelain -- '+args,{encoding:'utf8'}).replace(/\s+$/,'');if(o.length>0){console.error('EXISTING 04-01..04-09 ARTIFACTS MODIFIED: '+o);process.exit(1)}const plans=fs.readdirSync(dir).filter(f=>/-PLAN\.md$/.test(f)).sort();const extra=plans.filter(p=>!/^04-(0[1-9]|10)-PLAN\.md$/.test(p));if(extra.length>0){console.error('UNEXPECTED PLAN FILES '+extra.join(','));process.exit(1)}if(plans.length!==10){console.error('PLAN COUNT '+plans.length+' expected 10');process.exit(1)}if(!fs.readdirSync(dir).some(f=>f==='04-10-SUMMARY.md')){console.error('MISSING 04-10 SUMMARY');process.exit(1)}console.log('OK 04-01..04-09 untouched; plans '+plans.join(','))"</automated>
|
||||
<fails_when>non-zero exit, 或 stderr 含 "EXISTING 04-01..04-09 ARTIFACTS MODIFIED" / "UNEXPECTED PLAN FILES" / "PLAN COUNT" / "MISSING 04-10 SUMMARY"(既有前序增量产物被改写;或出现了未授权的 `04-11+` 计划文件——即提前规划了第二步;或 `04-10-SUMMARY.md` 未落盘)</fails_when>
|
||||
<automated>node -e "const fs=require('fs');const s=fs.readFileSync('.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.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>
|
||||
- `## 处置` 定稿,明写:本步只读、生产代码零改动、零命名变更、唯一交付物、相对只读起始基线零变化、**第二步未规划**(D-57)、被查范围含全部 importer 与其它 monorepo 包(`packages/` 与 `src/` 仅报告)、**D 类解耦方案由用户裁定**、**E 类按 D-55 只报告不修不登记待办**、**全部命名归用户**(AGENTS.md)、`REND-01` / `REND-02` 保持 Pending,并(如与规划日不同)说明实测差异
|
||||
- D 类 **≥ 9 行**,覆盖反向依赖候选 4 族(`shared.ts` / `renderer` / `use.ts` / `render/utils`)、自包引用 5 处、`client-base/package.json` 依赖缺口、反向依赖现状机器证据、shader `?raw`、`dev.md` 规则对照;每行含风险源与基准锚点两个 `file:line`;**无任何自拟解耦方案**
|
||||
- E 类 **≥ 6 行**,标题下明写「仅报告」边界,覆盖 `core.*` 逐文件汇总(含 `file:line` 与核对命令输出)、`loading` + `Mota.require`、`client.*` 0 命中机器证据、`packages/` 与 `src/` 对照扫描、`elements/cache.ts` legacy 贴图路径现状;**无任何修复性措辞**
|
||||
- F 类 **≥ 9 条** `#04-10-F-*` 未确定项,覆盖目标命名、`render/utils/index.ts` 归属、barrel 扩张 / 断链补位、反向依赖解耦、自包引用改写、依赖缺口补齐、`?raw` 可行性、legacy 插件面、`createElements()` 注册点接线;**均未写成错配 / 缺失 / 残留 / 待办**
|
||||
- 五道门禁全部转绿:只读门禁(porcelain 逐条一致 + `04-CONTEXT.md` 未提交改动仍在 + `REQUIREMENTS.md` 未改动且 `REND-01` / `REND-02` 仍 `Pending`)、类别门禁(A ≥ 8 / B ≥ 8 / C ≥ 7 / D ≥ 9 / E ≥ 6 / F ≥ 9 且每行双锚点与关键词齐备、`## 处置` 存在)、机器证据复验(两处零命中)、既有产物保护 + 计划范围门禁(`04-01..04-09-*` 未改写、无 `04-11+`、`04-10-SUMMARY.md` 已落盘)、CRLF 门禁
|
||||
- 人工代码复核结论已记录(抽查 A 类 4 处、B 类 2 处深层导入、C 类 2 处断链点、D 类 `?raw` 与 `client-base/package.json`、E 类 `cache.ts:491-492`),偏差均已修正
|
||||
- `04-10-SUMMARY.md` 已产出,如实记录当日实测值、A–F 实际行数与关键结论、五道门禁结果、人工复核结论、与规划日的差异说明、`REND-01` / `REND-02` 仍 Pending 与「第二步未规划」;**未写入任何移植方案 / import 重写方案 / 命名**
|
||||
- 提交仅含 `04-STRUCTURE-MIGRATION-IMPACT.md`、`04-10-PLAN.md`、`04-10-SUMMARY.md`(及属本次 ROADMAP 登记时的 ROADMAP 改动,若适用);未纳入任何生产源码改动与用户既有未提交改动;未改写 `04-01..04-09-*`
|
||||
</acceptance_criteria>
|
||||
<done>渲染端结构性重构只读影响台账定稿并交付:五道门禁全绿、既有前序产物零改写、`04-10-SUMMARY.md` 落盘并提交;用户可据此审阅 A / B / C 三类事实与断链点、D 类分层风险、E 类 legacy 自有面、F 类待裁决项,并裁定第二步的移植方案与 import 重写集</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<threat_model>
|
||||
## Trust Boundaries
|
||||
|
||||
| Boundary | Description |
|
||||
|----------|-------------|
|
||||
| 生产源码 → 清点文档 | 只读引用 `packages-user` / `packages` / `src` 的代码与行号;不得产生任何写回(`packages` / `packages-user` / `src` 的 porcelain 必须零变化) |
|
||||
| 用户并发改动(D-56)→ 本次 run | 用户正在改数据端;本 run 不得回滚 / 暂存 / 提交 / 修改其任何未提交改动(含 `.planning/.../04-CONTEXT.md`) |
|
||||
| 分层规则(dev.md)→ 移植判断 | `client-base` 不得反向依赖 `client-modules`;把反向依赖写成「内部引用」会让用户误判第二步范围 |
|
||||
| 被移集合边界(D-52 / D-54)→ 清点范围 | 移植集合只含三文件夹 + `layout.ts`;把 `ui` / `fx` / `weather` / `render` 顶层文件纳入或漏掉即扩大 / 缩小范围 |
|
||||
| legacy 耦合(D-55)→ AI 工作范围 | legacy 只报告;若把 `core.*` / `loading` 写成待办即越权扩大范围 |
|
||||
| 命名权(AGENTS.md)→ 文档内容 | 文档不得为 `client-base/src/{components,elements,map,layout}` 下的文件 / barrel 命名拍板(含 `layout.ts` 是否改名) |
|
||||
| 公共面收窄 → `@user/client-modules` 消费者 | `render/index.tsx` 的再导出断链会改变其它包可见的公共面;判定必须带 `file:line` 证据,不得猜测 |
|
||||
| 执行者 / 子代理 → 执行前置关卡 | AGENTS.md 要求第一个 block 点先汇报并等待用户回复「可以执行」;`yolo` / `auto_advance` 或子代理派发都不是放行理由(Task 0 为 `blocking-human`、`autonomous: false`) |
|
||||
| 既有 04-01..04-09 产物 → 本次编号 | phase 目录内已有 9 个已执行增量的计划与 SUMMARY;改号 / 覆盖会破坏既有执行记录 |
|
||||
| 清点文档 → 第二步规划 | 第二步计划由用户审阅本文件后另行规划(D-57);文档若夹带移植方案 / import 重写方案即越权替用户设计 |
|
||||
|
||||
## STRIDE Threat Register
|
||||
|
||||
| Threat ID | Category | Component | Severity | Disposition | Mitigation Plan |
|
||||
|-----------|----------|-----------|----------|-------------|-----------------|
|
||||
| T-04-10-01 | Tampering | 生产源码 `packages-user` / `packages` / `src` | high | mitigate | Task 1 步骤 (0a) 记录 `git status --porcelain -- packages packages-user src` 的逐行基线(规划日单条);Task 1 / Task 3 门禁断言其后逐条一致;Task 3 另断言 `.planning/REQUIREMENTS.md` 未改动;`files_modified` 仅含交付文档;prohibitions 明列生产文件零改动、不得预建 / 复制目标目录与文件 |
|
||||
| T-04-10-02 | Elevation of Privilege | 执行前置关卡(AGENTS.md 要求的第一处 block 点) | high | mitigate | Task 0 为 `checkpoint:decision` + `gate="blocking-human"` 且本计划 `autonomous: false`;Task 0 的 action ⑩ / ⑪ 与 acceptance_criteria 明示未收到用户「可以执行」四个字即必须停止、不派发执行子代理;`yolo` / `workflow.auto_advance` 不得自动放行 |
|
||||
| T-04-10-03 | Tampering | 用户并发改动(D-56) | high | mitigate | Task 1 / Task 3 门禁除 porcelain 逐条一致外,另断言 `.planning/phases/04-render-adaptation/04-CONTEXT.md` 的未提交改动仍在(消失即失败);prohibitions 明列不得回滚 / 暂存 / 提交用户改动;Task 3 提交仅列三个(或四个)白名单文件 |
|
||||
| T-04-10-04 | Spoofing | A / B / C / D / E 分类 | high | mitigate | 分列规则写死(A 集合内部交叉引用 / B 集合之外导入点 / C barrel 与断链 / D 分层风险 / E legacy 只报告 / F 未确定);每行强制两个 `file:line` 锚点;门禁机器判定行数下限、关键词与双锚点 |
|
||||
| T-04-10-05 | Spoofing | 「零命中 / 零反向依赖」结论 | high | mitigate | 不以文档自述为准:Task 1 / Task 2 / Task 3 门禁直接运行 `git grep -n -F` 固定串检索(`client-modules` 于 `client-base`、`../ui` / `../fx` / `../weather` 于被移集合),非零输出即失败;`.planning/graphs/*` 的过期标签声明不计入源码命中 |
|
||||
| T-04-10-06 | Tampering | legacy 范围(D-55) | high | mitigate | `## E legacy 命中(仅报告)` 标题下明写「不修、不登记为待办」;Task 3 类别门禁要求 E 节含「仅报告」措辞与 `core.` / `loading` / `Mota.require` / `packages/` / `src/` 关键词;prohibitions 明列不得把 legacy 写成问题 / 待办 |
|
||||
| T-04-10-07 | Elevation of Privilege | 命名权(AGENTS.md) | high | mitigate | 全部命名问题强制归 F 类(Task 3 类别门禁要求 F 类含命名方向条目);prohibitions 明列「不得为目标文件 / 目录命名拍板」;`## 处置` 明写命名归用户 |
|
||||
| T-04-10-08 | Repudiation | A–E 各行条目不可追溯 | medium | mitigate | 固定列序(`ID | 文件/符号 | 命中处(源) | 目标锚点 | 问题描述 | 影响 | 置信`)+ 每行 ≥2 个 `file:line` 锚点 + 行数下限 + 关键词齐备 + 被移集合 39 文件逐条清单,由 Task 1 / Task 2 / Task 3 门禁机器判定 |
|
||||
| T-04-10-09 | Elevation of Privilege | 清点范围(纳入 `ui` / `fx` / `weather`、为 `packages/` 与 `src/` 提修改、提前规划第二步) | medium | mitigate | D-52 / D-54 / D-33 / D-57 为显式边界:清单节只列 39 文件并明写不移动不复制不预建;E 节只报告;prohibitions 禁提移植 / 重写方案;Task 3 门禁禁止出现 `04-11+` 计划文件与前序产物改写 |
|
||||
| T-04-10-10 | Denial of Service | 只读子代理越权写入(D-09) | low | mitigate | Task 2 步骤 (4) 明确子代理仅回传事实表、不得写文件、不得贴大段源码;最终由主执行者以只读门禁 + 类别门禁 + 机器证据复验统一验证 |
|
||||
| T-04-10-11 | Information Disclosure | 清点文档引用的源码行与符号名 | low | accept | 记录只含符号名、文件行号、成员签名与目录结构,不含凭据 / 密钥 / 个人数据 |
|
||||
| T-04-10-SC | Tampering | npm / pip / cargo 安装面 | high | mitigate | 本计划不新增依赖、不安装任何包(prohibitions);若出现安装需求即暂停并告知用户;门禁以 porcelain 基线覆盖 `package.json` / `pnpm-lock.yaml`(本计划零改动),无需包合法性核对 |
|
||||
</threat_model>
|
||||
|
||||
<verification>
|
||||
- **只读门禁**:`git status --porcelain -- packages packages-user src` 的输出与交付文档 `## 方法` 的「只读起始基线」条目逐条一致(不新增、不消失、状态码不变);并断言 `.planning/phases/04-render-adaptation/04-CONTEXT.md` 的未提交改动仍在(D-56)、`.planning/REQUIREMENTS.md` 未被改动且 `REND-01` / `REND-02` 仍为 `Pending`。
|
||||
- **静态内容门禁**:交付文档恰好 11 个二级标题;被移集合 **39** 个文件路径逐条出现(`components` 13 / `elements` 5 / `map` 20 / `utils/layout.ts` 1);A ≥ 8 行 / B ≥ 8 行 / C ≥ 7 行 / D ≥ 9 行 / E ≥ 6 行 / F ≥ 9 条;A–E 每行 ≥2 个 `file:line` 锚点;A / B / C / D / E 覆盖各自关键词集合;E 含「仅报告」措辞;`## 处置` 存在。
|
||||
- **机器证据复验**:`git grep -n -F "client-modules" -- packages-user/client-base`,以及 `git grep -n -F "../ui"` / `-F "../fx"` / `-F "../weather"` 三个**独立**检索(同限被移集合四个路径),逐一无输出(退出码 1);`git grep -n -F "render/components"` / `-F "render/elements"` / `-F "render/map"` 三个**独立**检索(同限 `packages` 与 `src`)在 `packages/` 与 `src/` 零命中。
|
||||
- **既有产物保护 + 计划范围门禁**:`git status --porcelain -- <04-01..04-09 的 PLAN 与 SUMMARY>` 为空;phase 目录内 `-PLAN.md` 恰为 `04-01`..`04-10` 共 10 个;`04-10-SUMMARY.md` 已存在。
|
||||
- **CRLF 门禁**:交付文档的 `\n` 总数等于 `\r\n` 总数(无孤立 LF)。
|
||||
- **人工复核**:抽查 A 类 `components/tip.tsx:7` / `elements/index.ts:2,3` / `map/renderer.ts:53`、B 类 `render/ui/toolbar.tsx:13` / `fallback/ui.ts:2`、C 类 `render/index.tsx:45,46` / `render/utils/index.ts:1`、D 类 `map/renderer.ts:43-46` 与 `client-base/package.json`、E 类 `elements/cache.ts:491-492`,结论与偏差修正记录在 `04-10-SUMMARY.md`。
|
||||
- **不可自动化项的诚实说明**:本步为只读清点,无运行时行为可观察;除上述命令外不存在可运行门禁,不得以任何无法运行的门禁冒充通过。
|
||||
</verification>
|
||||
|
||||
<output>
|
||||
Create `.planning/phases/04-render-adaptation/04-10-SUMMARY.md` when done
|
||||
</output>
|
||||
|
||||
## Artifacts this phase produces
|
||||
|
||||
| Artifact | Kind | Purpose |
|
||||
|----------|------|---------|
|
||||
| `.planning/phases/04-render-adaptation/04-STRUCTURE-MIGRATION-IMPACT.md` | 交付文档(**唯一** `files_modified`) | 渲染端结构性重构(D-51..D-57)第一步只读影响台账:元信息块 + 背景 / 方法 / 被移集合清单(39 文件)/ A 被移集合内部交叉引用 / B 外部导入点 / C barrel 与导出面 / D 分层与循环依赖风险 / E legacy 命中(仅报告)/ F 未能从阅读确定(未猜测)/ 处置 |
|
||||
| `.planning/phases/04-render-adaptation/04-10-PLAN.md` | 计划簿记 | 本计划(编号 04-10;`wave: 9`;`depends_on` 04-01..04-09;`autonomous: false`) |
|
||||
| `.planning/phases/04-render-adaptation/04-10-SUMMARY.md` | 执行簿记 | 当日实测值(porcelain 基线、被移集合实际文件数)、A–F 实际行数与关键结论、五道门禁结果、人工复核结论、与规划日的差异说明、`REND-01` / `REND-02` 仍 Pending 与「第二步未规划」 |
|
||||
| `.planning/ROADMAP.md`(Phase 4 的 Wave 9 登记 + register note) | 计划簿记 | 登记第十个增量 `04-10`(只读影响清点)与执行前置关卡要求 |
|
||||
| 门禁结果(会话内可复跑) | 验证证据 | 只读门禁(porcelain 逐条一致 + 用户改动仍在 + `REQUIREMENTS.md` 未改动且 REND 仍 Pending)、静态内容门禁(11 节 / 39 文件 / A–F 行数与双锚点)、机器证据复验(两处零命中)、既有产物保护 + 计划范围门禁(`04-01..04-09-*` 未改写、无 `04-11+`、SUMMARY 已落盘)、CRLF 门禁 |
|
||||
| 显式**不**产出 | 边界声明 | 任何生产代码改动、任何文件移动 / 复制 / 预建、任何测试文件、任何依赖变更(含 `package.json` 补声明)、任何命名、任何移植方案或 import 重写方案(D-57:第二步待用户审阅本文件后另行规划)、任何针对 legacy 的修复方案(D-55) |
|
||||
Loading…
Reference in New Issue
Block a user