From 6cff48741a784f7b7ed8f71c320fcb667cd1e3e9 Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Thu, 1 Oct 2026 16:12:27 +0800 Subject: [PATCH] =?UTF-8?q?docs(04-15):=20=E6=B8=B2=E6=9F=93=E7=AB=AF?= =?UTF-8?q?=E5=8E=BB=E5=8D=95=E4=BE=8B=E5=8C=96=E5=8F=AA=E8=AF=BB=E6=B8=85?= =?UTF-8?q?=E7=82=B9=EF=BC=88=E4=BB=85=E5=8D=95=E4=BE=8B=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../04-render-adaptation/04-15-SUMMARY.md | 220 +++++++------- .../04-RENDER-SINGLETON-AUDIT.md | 268 +++++++----------- 2 files changed, 221 insertions(+), 267 deletions(-) diff --git a/.planning/phases/04-render-adaptation/04-15-SUMMARY.md b/.planning/phases/04-render-adaptation/04-15-SUMMARY.md index ccda98e..ad1a27f 100644 --- a/.planning/phases/04-render-adaptation/04-15-SUMMARY.md +++ b/.planning/phases/04-render-adaptation/04-15-SUMMARY.md @@ -1,29 +1,28 @@ --- phase: 04-render-adaptation plan: 15 -subsystem: render-de-singletonization -tags: [read-only, singleton-audit, de-singletonization, client-modules, client-base, IClientBaseExtended, ICoreStateExtended, d69-barrel] +subsystem: render-singleton-audit +tags: [read-only, singleton-audit, de-singletonization, d68, d56, two-step] requires: - phase: 04-render-adaptation - provides: 用户 2026-10-01 去单例化裁定(渲染端不得再有单例、全部挂主类 `ClientCore` / `client`、子系统继承 / 实现 `IClientBaseExtended` / `ICoreStateExtended`、镜像数据端模式、两步走) + provides: 用户裁定 2026-10-01(渲染端不得再有单例、全部挂 ClientCore / client、子系统继承 / 实现 IClientBaseExtended / ICoreStateExtended、镜像数据端模式、两步走、仅限「模块顶层 export const x = new X()」单例) - phase: 04-render-adaptation - provides: 既有只读台账 04-UI-ADAPTATION-IMPACT.md / 04-STRUCTURE-MIGRATION-IMPACT.md(版式与证据纪律模板) + provides: 既有台账 04-UI-ADAPTATION-IMPACT.md(格式模板)与 04-STRUCTURE-MIGRATION-IMPACT.md(证据纪律模板) provides: - - .planning/phases/04-render-adaptation/04-RENDER-SINGLETON-AUDIT.md(渲染端去单例化·第一步只读清点台账;元信息块 + 12 小节 + A–F 六类 + 单例→目标映射汇总 + 处置) - - 供第二步(04-16:挂载 + 接口继承重构)消费的单例→目标映射汇总(含 undetermined 标注) + - .planning/phases/04-render-adaptation/04-RENDER-SINGLETON-AUDIT.md(渲染端去单例化第一步·只读单例清点台账;A / E / F 三类 + 单例→目标映射汇总) + - 供第二步(04-16 挂载 + 接口继承重构)消费的单例清单与目标映射汇总 affects: [04-render-adaptation] actuals: - tokens: 15145 - tasks: 5 + tokens: 13919 + tasks: 4 commits: 1 - plan_head_before: 2d3287804d90bf3cde1d6299ac71815fd677a7eb + plan_head_before: 015a1993e8e95ab5fd80b5f8002f196beb2913c2 tech-stack: added: [] patterns: - - "只读单例清点台账:元信息块 + 只读起始基线 + 12 小节 + A–F 六类固定列序表 + 单例→目标映射汇总 + 处置" - - "证据纪律:事实行每行 ≥2 个 file:line 锚点;证据行带 [证据行] 标记 + git grep 核对命令与原样结果" + - "只读单例台账:元信息块 + 只读起始基线 + 背景 / 方法 / 枚举口径 + A / E / F 三类 + 单例→目标映射汇总 + 处置" + - "证据纪律:A 事实行每行 ≥2 个 file:line 锚点;零命中 / 对照扫描行带 [证据行] 标记 + 核对命令与原样结果;完整性由 git grep 反查" - "只登记不判定:静态阅读不能定论者一律进 F 类(未猜测),不得写成错配 / 缺失 / 残留 / 待办" - - "目标模式:挂主类 `ClientCore` / `client` + `IClientBaseExtended` / `ICoreStateExtended` 之一 + 先例 file:line" key-files: created: - .planning/phases/04-render-adaptation/04-RENDER-SINGLETON-AUDIT.md @@ -31,160 +30,169 @@ key-files: modified: [] deleted: [] key-decisions: - - "本 run 为纯只读收集(用户 2026-10-01 去单例化第一步):生产源码改动 0,files_modified 仅台账;Task 1/2/3 不独立提交,Task 4 单次白名单提交" - - "A–E 分类行统一覆盖:A 30 个对象(+ 1 条 [证据行] 完整性反查)/ B 8 / C 6 / D 4 / E 7;F 7 条;单例→目标映射汇总 41 行" - - "目标接口一律给候选 `IClientBaseExtended` / `ICoreStateExtended` 或 undetermined,不裁定取舍、不给挂载写法(命名先获批)" - - "renderer 实例簇与 ClientCore 构造器内自建对象重复(client.ts:90,91,108)/外部框架级全局(mainRenderer / using / tagManager / gameKey)/GameUI 实例是否纳入 一律进 F 类,不臆测" - - "Task 1/2/3 的门禁按原样语义落到仓库外 %TEMP%\\opencode\\04-15-gates-pre.cjs 执行,判据不变(PowerShell 5.1 引号 / $ / CJK 兼容)" + - "本 run 为纯只读单例清点(去单例化第一步):生产源码改动 0,files_modified 仅台账;Task 1/2/3 不独立提交,Task 4 单次白名单提交" + - "范围仅限单例:仅登记模块顶层实例化对象 export const x = new X()(30 条:client-modules 24 + client-base 6);可变模块级状态 / 全局注册表 / 全局访问器 / 顶层副作用 / 非 new 导出一律 OUT" + - "A 表 30 条事实行 + 1 条完整性反查 [证据行];F 类 7 条(仅单例相关,只登记不判定);目标接口取舍一律 undetermined(IClientBaseExtended vs ICoreStateExtended 交用户裁决)" + - "Task 0 blocking-human 汇报关卡已由用户回复「可以执行」闭环;本 run 覆盖先前错误范围(6 类)产物,重写为仅单例范围" requirements-completed: [] -duration: ~40min +duration: ~35min completed: 2026-10-01 status: complete --- -# Phase 4 Plan 15: 渲染端去单例化·第一步(只读收集)Summary +# Phase 4 Plan 15: 渲染端去单例化·第一步(只读收集单例)Summary -**对 `packages-user/client-modules` 与 `packages-user/client-base` 两个包内全部单例做只读清点:枚举 30 个模块级实例化对象 + 8 项可变模块级状态与全局注册表 + 6 项全局访问器与框架级全局引用 + 4 项顶层副作用模块,逐一给出定义 / 消费者 `file:line`、与 `ClientCore` / `client` 的关系、目标接口候选(`IClientBaseExtended` / `ICoreStateExtended` + 先例)或 undetermined,产出 `04-RENDER-SINGLETON-AUDIT.md`;生产代码零改动、未引入任何命名变更、无运行时验证(D-68 的延续),REND-01 / REND-02 保持 Pending。** +**对 `packages-user/client-modules` 与 `packages-user/client-base` 两个包内的全部单例(严格定义:模块顶层实例化对象 `export const x = new X()`,共 30 条)做只读清点,产出 `04-RENDER-SINGLETON-AUDIT.md`(A / E / F 三类 + 单例→目标映射汇总);每个单例带 `file:line` 锚点与目标接口候选 / 先例,未定者进 F 类「只登记不判定」;生产代码零改动、未引入任何命名变更、无运行时验证(D-68 的延续)。** ## Performance -- **Duration:** ~40min -- **Started:** 2026-10-01 +- **Duration:** ~35min +- **Started:** 2026-10-01T08:01:42Z - **Completed:** 2026-10-01 -- **Tasks:** 5(Task 0 blocking-human 汇报关卡 — 用户已回复「可以执行」;Task 1 tracer;Task 2;Task 3;Task 4 收口) -- **Files:** 1 新增(`04-RENDER-SINGLETON-AUDIT.md`)+ 本 SUMMARY;生产源码改动 **0** +- **Tasks:** 4(Task 0 blocking-human 汇报关卡 — 用户已回复「可以执行」;Task 1 tracer;Task 2;Task 3;Task 4 收口) +- **Files:** 1 重写(`04-RENDER-SINGLETON-AUDIT.md`)+ 本 SUMMARY;生产源码改动 **0** ## 只读起始基线(Task 1 步骤 0a) - **只读起始基线(packages / packages-user / src):** - - ` M packages-user/data-system/src/combat/context.ts` -- **起始 HEAD:** `2d3287804d90bf3cde1d6299ac71815fd677a7eb`(short `2d32878`) + ` M packages-user/data-system/src/combat/context.ts` +- **起始 HEAD:** `015a1993e8e95ab5fd80b5f8002f196beb2913c2` - **起始分支:** `refine/data-client` -- **用户并发改动:** `packages-user/data-system/src/combat/context.ts` 的既有未提交改动仍在(porcelain ` M`,内容哈希 `9982509d3d8ec4c58d5c71f37f1a576a13c3337f`);本 run 未回滚 / 暂存 / 提交 / 修改(D-56 精神)。 -- **机读标记:** 台账含 ``,Task 1/2/3/4 生产树门禁均正向确认该哈希一致。 +- **用户并发改动:** ` M packages-user/data-system/src/combat/context.ts`(未提交,**原样保留**,本 run 未回滚 / 未暂存 / 未提交 / 未修改;D-56) +- **机读标记:** `` +- **第二个 block 点:** Task 0 的 `blocking-human` 汇报关卡已由用户明确回复「可以执行」闭环。 ## Accomplishments -**唯一交付物:** `.planning/phases/04-render-adaptation/04-RENDER-SINGLETON-AUDIT.md`(只读)。 +**唯一交付物:** `.planning/phases/04-render-adaptation/04-RENDER-SINGLETON-AUDIT.md`(只读;重写先前错误范围产物)。 | 节 | 落点 | 条目数 | |---|---|---| -| 元信息块 + 只读起始基线 + 背景 + 方法 + 枚举口径 | 6 行元信息块;porcelain 原样(含用户 WIP);用户 2026-10-01 裁定要点;六类判定口径表;证据纪律 | — | -| **A 模块级实例化对象** | `texture` / `client` / renderer 实例簇(`rafExcitation` / `excitationDivider` / `mainRenderer` / `using` / `tagManager`)/ `sceneController` / `mainUIController` / `MainBackgroundUI` / 20 个 `GameUI` 实例 / `DEFAULT_FONT` + 1 条 `[证据行]` 完整性反查 | **30 对象 + 1 证据行** | -| **B 可变模块级状态与全局注册表** | `nowOrientation` / `orientationHooks` / `transitionMap` / `mainScope`(`Symbol.for`)/ `static extern` / `static weathers` / `RenderColorTransition.key` / `textboxTyper` 模块级 `Set` + 1 条 `[证据行]` | **8 + 1 证据行** | -| **C 全局访问器与框架级全局引用** | `Mota.require`(`cache.ts:491` / `misc.ts:89,219`;legacy 只报告)/ `window.*`(`use.ts` 与 UI)/ `core.*`(legacy 只报告)/ 外部包全局 `gameKey` / `tagManager` / `mainRenderer` / 数据端单例 `state` 引用 + 1 条 `[证据行]` | **6 + 1 证据行** | -| **D 顶层副作用模块** | `gameKey` 顶层注册链 / `keyStorage` 存储读写与事件 / `window.addEventListener` / `renderer.ts` 顶层 `bindExcitation` / `setDivider` + 1 条 `[证据行]` | **4 + 1 证据行** | -| **E 主类关系与目标挂载面映射** | `client`(目标主类本身)/ `texture` / renderer 实例簇 / UI 控制器与 `GameUI` 簇 / `use.ts` 可变状态 + `hotkey` 符号 / weather 静态注册表 / client-base `GameUI` + `Mota.require` | **7** | -| **F 未能从阅读确定(未猜测)** | F-01 外部框架级全局归属 / F-02 重复单例权威归属 / F-03 `GameUI` 实例是否纳入 / F-04 `window` 副作用与无 DOM 约束 / F-05 目标接口取舍 / F-06 `IClientBaseExtended` 实现情况 / F-07 无消费者的状态栏 UI | **7** | -| **单例→目标映射汇总(供 04-16 消费)** | 41 行固定列表(定义 file:line / 符号 / 类型 / 目标或 undetermined / 先例 / 归属包 / 置信)+ 两个包内单例总数说明 | **41** | -| **处置** | 只读完成;第二步(04-16)未规划、待用户审阅;REND-01 / REND-02 保持 Pending | — | +| 元信息块 + 只读起始基线 + 背景 + 方法 + 枚举口径 | 6 行元信息块;porcelain 原样(含用户 `combat/context.ts`)+ 哈希标记;用户 2026-10-01 裁定要点;枚举面 / 核对手法 / 证据纪律;单例定义 + 显式排除清单 | — | +| **A 模块级实例化对象** | 30 条单例事实行(`#04-15-A-01`..`#04-15-A-30`)+ 1 条完整性反查 `[证据行]`(`#04-15-A-31`):client-modules 24 / client-base 6 | **31**(30 单例 + 1 证据行) | +| **E 主类关系与目标挂载面映射** | 8 条(`#04-15-E-01`..`#04-15-E-08`):逐簇给出当前归属 / 与 `ClientCore` 关系 / 目标接口候选与先例 / undetermined | **8** | +| **F 未能从阅读确定(未猜测)** | 7 条(`#04-15-F-01`..`#04-15-F-07`):texture / (a) 外部包单例 / (b) 重复 renderer 实例 / (c) `GameUI` 实例是否纳入 / (d) 目标接口取舍 / (e) `IClientBaseExtended` 无实现类 / (f) 无消费者 UI | **7** | +| **单例→目标映射汇总(供 04-16 消费)** | 30 行(每单例一行)+ 单例总数声明(24 + 6 = 30) | **30** | +| **处置** | 只读完成 + 仅登记单例 + 第二步待规划 + `REND-01` / `REND-02` Pending + 单例总数 | — | -**A–E 分类行:** A 32 / B 9 / C 7 / D 5 / E 7 = **60** 条表行(门禁实测一致);F **7** 条。**两个包内单例对象合计 48 个单例点**(A 30 + B 8 + C 6 + D 4)。 +**单例总数(当日 `git grep` 实测,与规划日一致):** 客户端(`packages-user/client-modules`)**24** + 系统层(`packages-user/client-base`)**6** = **30**。 + +**单例清单(A 表 `#04-15-A-01`..`#04-15-A-30`):** `texture`;`client`;`rafExcitation` / `excitationDivider` / `mainRenderer` / `using`;`sceneController`;`mainUIController` / `MainBackgroundUI`;`LoadSceneUI` / `MainSceneUI` / `SaveUI` / `MainSettingsUI` / `ReplaySettingsUI` / `GameInfoUI` / `SyncSaveUI` / `SyncSaveSelectUI` / `DownloadSaveSelectUI` / `ClearSaveSelectUI` / `StatisticsUI` / `leftStatusBarUI` / `rightStatusBarUI` / `GameTitleUI` / `ViewMapUI`;`DEFAULT_FONT`;`ConfirmBoxUI` / `ChoicesUI` / `InputBoxUI` / `WaitBoxUI` / `BackgroundUI`。 ## Task Commits 1. **Task 0(blocking-human 汇报关卡)** — 用户已回复「可以执行」,无文件改动、无提交 -2. **Task 1(tracer)** — 台账骨架 + 12 小节 + `texture` 一条线端到端(`#04-15-A-01`;门禁全绿,无独立提交) -3. **Task 2** — client-modules 单例横向铺开(主单例 / renderer 簇 / scene / UI 控制器与 `GameUI` / `use.ts` 可变状态 / weather 静态注册表 / hotkey 符号与顶层副作用;门禁全绿,无独立提交) -4. **Task 3** — client-base 单例横向铺开 + A–E 分类收口 + `## 单例→目标映射汇总` 定稿 + D-69 barrel 检查(门禁全绿,无独立提交) +2. **Task 1(tracer)** — 台账骨架 + 9 小节 + tracer `texture` 行(`#04-15-A-01`)+ 基线哈希标记(门禁全绿,无独立提交) +3. **Task 2** — client-modules 单例铺开(`#04-15-A-02`..`#04-15-A-25`)+ E-02..E-07 + F-02..F-04 + 映射汇总(门禁全绿,无独立提交) +4. **Task 3** — client-base 单例铺开(`#04-15-A-26`..`#04-15-A-30`)+ 完整性反查 `[证据行]`(`#04-15-A-31`)+ E-08 + F-05..F-07 + 映射汇总定稿 + 处置定稿(门禁全绿,无独立提交) 5. **Task 4** — 收口门禁 + 人工复核 + 本 SUMMARY + 白名单提交 -**Plan metadata:** 单一白名单提交(见「提交记录」)。Task 1/2/3 的 action 未定义独立提交步骤;Task 4 步骤 (10) 明示单次白名单提交(与 04-10 / 04-13 的单一提交口径一致)。 +**Plan metadata:** 单一白名单提交(见「提交记录」)。Task 1/2/3 的 action 未定义独立提交步骤;Task 4 步骤 (10) 明示单次白名单提交(与 04-13 的单一提交口径一致)。 ## 提交记录 -- `docs(04-15): 渲染端去单例化只读清点(第一步)` —— 单次白名单提交,仅含 `04-RENDER-SINGLETON-AUDIT.md` + 本 `04-15-SUMMARY.md`(未暂存用户 `combat/context.ts` 或任何其它文件;提交 hash 见 orchestrator 回报 / `git log`)。 +- `docs(04-15): 渲染端去单例化只读清点(仅单例)` —— 单次白名单提交,仅含 `files_modified`(`04-RENDER-SINGLETON-AUDIT.md`)+ 本 `04-15-SUMMARY.md`(提交 hash 见 orchestrator 回报 / `git log`)。 -## A–F 落点表(关键锚点) +## A / E / F 落点表(关键锚点) | 面 | 条目 | 关键 `file:line` 锚点 | |---|---|---| -| **A 模块级实例化对象** | `texture`(tracer) | `packages-user/client-base/src/elements/cache.ts:280` ↔ `packages-user/client-base/src/elements/cache.ts:48` / `packages-user/client-base/src/components/textbox.tsx:399` / `packages-user/client-base/src/elements/misc.ts:87` | -| | renderer 实例簇 | `packages-user/client-modules/src/render/renderer.ts:18,20,35,43,45` ↔ `packages-user/client-modules/src/client.ts:48,90,108` | -| | 主单例 / scene / UI 控制器 | `packages-user/client-modules/src/core.ts:6` / `packages-user/client-modules/src/render/scene.ts:3` / `packages-user/client-modules/src/render/ui/controller.tsx:11,29` | -| | `GameUI` 实例簇 | `packages-user/client-modules/src/render/ui/load.tsx:161` / `main.tsx:312` / `save.tsx:462` / `settings.tsx:663,665,667,669,671,673,678` / `statistics.tsx:302` / `statusBar.tsx:488,489` / `title.tsx:484` / `viewmap.tsx:556`;`packages-user/client-base/src/components/choices.tsx:796,798` / `input.tsx:602` / `misc.tsx:591,592` | -| **B 可变状态 / 注册表** | use.ts + hotkey + weather | `packages-user/client-modules/src/render/use.ts:34,35,287` / `packages-user/client-modules/src/action/hotkey.ts:5` / `packages-user/client-modules/src/render/weather/controller.ts:15,17` | -| **C 全局访问器 / 框架级全局** | Mota / window / core / 外部包 | `packages-user/client-base/src/elements/cache.ts:491` / `packages-user/client-base/src/elements/misc.ts:89,219` / `packages-user/client-modules/src/render/use.ts:40,48,51,60` / `packages-user/client-modules/src/action/hotkey.ts:2` | -| **D 顶层副作用** | hotkey / use / renderer | `packages-user/client-modules/src/action/hotkey.ts:9,470,471,523,526` / `packages-user/client-modules/src/render/use.ts:51` / `packages-user/client-modules/src/render/renderer.ts:22,26,32` | -| **E 目标映射** | 目标接口 / 先例 | `IClientBaseExtended`(`packages-user/client-base/src/types.ts:27`)/ `ICoreStateExtended`(`packages-user/data-state/src/types.ts:45`)/ 先例 `packages-user/client-base/src/material/types.ts:94,218,406,439` / `packages-user/data-state/src/ins.ts:11` | -| **F undetermined** | F-01..F-07 | 见台账 `## F 未能从阅读确定(未猜测)` 一节 | +| **A 单例(client-base)** | A-01 `texture` | `packages-user/client-base/src/elements/cache.ts:280`(类 `:48`)↔ `textbox.tsx:33` / `textboxTyper.ts:5` / `tip.tsx:8` / `elements/misc.ts:9` | +| **A 单例(client-base 组件)** | A-26..A-30 | `choices.tsx:796,798` / `input.tsx:602` / `misc.tsx:591,592` ↔ `choices.tsx:606,659,722,777` / `input.tsx:555` / `misc.tsx:578` | +| **A 单例(client-modules)** | A-02 `client` | `packages-user/client-modules/src/core.ts:6`(类 `client.ts:41`)↔ 7 处消费者(`load.tsx:27` 等) | +| | A-03..A-06 renderer 簇 | `render/renderer.ts:18,20,35,43` ↔ `render/index.tsx:5,22,23,26` / `client-base/components/misc.tsx:16` | +| | A-07 `sceneController` | `render/scene.ts:3` ↔ `render/index.tsx:8,17,25` | +| | A-08/A-09 控制器 | `render/ui/controller.tsx:11,29` ↔ `render/ui/main.tsx:29,284` / `controller.tsx:32` | +| | A-10..A-22/A-24/A-25 GameUI 簇 | `render/ui/{load,main,save,settings,statistics,statusBar,title,viewmap}.tsx` 各定义行 | +| | A-23 `DEFAULT_FONT` | `shared.ts:105` ↔ `render/index.tsx:3,35` | +| | A-31 完整性反查 `[证据行]` | `git grep -n -E "export const [A-Za-z0-9_]+ = new "` → 30 条,与 A-01..A-30 对齐 | +| **E 目标映射** | E-01..E-08 | `IClientBaseExtended`(`client-base/src/types.ts:27`)/ `ICoreStateExtended`(`data-state/src/types.ts:45`);先例 `client-base/src/material/types.ts:94,218,406,439`、`data-state/src/ins.ts:11` | +| **F undetermined** | F-01..F-07 | 见台账 `## F` 一节 | ## 门禁实测结果(全部静态 — D-68 的延续) -门禁按计划 `## Verification Runnability` 的指示,将每条 `` 的原样语义落到仓库外 `C:\Users\book\AppData\Local\Temp\opencode\04-15-gates-pre.cjs` 执行 `node `(PowerShell 5.1 引号 / `$` / CJK 兼容;判据与 `` 一字不变)。 - | # | 门禁 | 结果(OK 行) | |---|---|---| -| T1-1 | 台账骨架 + 12 小节 + tracer 行 `#04-15-A-01` | ✅ `OK structure + keys present` | -| T1-2 | A–E 事实行 ≥2 锚点(≥1 行) | ✅ `OK anchor discipline: 60 table rows, 7 F entries` | -| T1-3 | 生产树正向基线(` M` 行在场 + 无其它条目 + `git hash-object` 与台账标记一致) | ✅ `OK read-only baseline confirmed (user edit present, hash matches, no other changes)` | -| T1-4 | CRLF | ✅ `OK CRLF .planning/phases/04-render-adaptation/04-RENDER-SINGLETON-AUDIT.md` | -| T2-1 | client-modules 铺开(主单例 / renderer / scene / UI 控制器 / use.ts / weather / hotkey / F / 映射汇总) | ✅ `OK structure + keys present` | -| T2-2 | 锚点纪律(行 ≥12)+ F ≥4 | ✅ `OK anchor discipline: 60 table rows, 7 F entries` | -| T2-3 | 生产树正向基线 | ✅ `OK read-only baseline confirmed (user edit present, hash matches, no other changes)` | -| T2-4 | CRLF | ✅ `OK CRLF ...` | -| T3-1 | client-base 单例 + 两个目标接口 + 数据端先例 + 映射汇总 + 处置 | ✅ `OK structure + keys present` | -| T3-2 | 最终纪律(行 ≥18 + F ≥5 + 映射汇总表头) | ✅ `OK anchor discipline: 60 table rows, 7 F entries` | -| T3-3 | 范围门禁(`REQUIREMENTS.md` 零改动 + 用户 `combat/context.ts` 正向基线) | ✅ `OK scope: read-only, REQUIREMENTS untouched, user edit present + hash matches` | -| T3-4 | CRLF | ✅ `OK CRLF ...` | -| T4-1 | 台账结构 / 内容 / 全量关键锚点 | ✅ `OK structure + keys present` | -| T4-2 | 最终纪律(F ≥5) | ✅ `OK anchor discipline: 60 table rows, 7 F entries` | -| T4-3 | 范围门禁(`material/` / `packages/` / `src/` 空;`REQUIREMENTS.md` 零改动;用户改动保留 + 哈希一致) | ✅ `OK scope: material/packages/src clean; REQUIREMENTS untouched; user edit present + hash matches` | +| T1-1 | 台账骨架(9 小节 A/E/F)+ tracer 行 `#04-15-A-01` + 哈希标记 | ✅ `OK ledger skeleton (A/E/F) + tracer row + hash marker` | +| T1-2 | A 事实行 ≥2 锚点 | ✅ `OK anchor discipline: 1 A rows` | +| T1-3 | 只读基线(用户 `combat/context.ts` 在场 + 哈希一致 + 无其它条目) | ✅ `OK read-only baseline confirmed (user edit present, hash matches, no other changes)` | +| T1-4 | CRLF 台账 | ✅ `OK CRLF ledger` | +| T2-1 | client-modules A 铺开 + F + 映射汇总在场 | ✅ `OK client-modules A expansion` | +| T2-2 | 锚点纪律(A ≥10、F ≥3) | ✅ `OK anchor discipline: 25 A rows, 4 F entries` | +| T2-3 | 只读基线 | ✅ `OK read-only baseline confirmed (user edit present, hash matches, no other changes)` | +| T2-4 | CRLF | ✅ `OK CRLF ledger` | +| T3-1 | client-base 单例 + 两目标接口 + 先例 + 映射汇总 + 处置 | ✅ `OK client-base + mapping coverage` | +| T3-2 | 最终纪律(A ≥15、F ≥5、映射汇总表头) | ✅ `OK final: 31 A rows, 7 F entries, summary present` | +| T3-3 | 范围门禁(`REQUIREMENTS.md` 零改动 + 用户改动正向基线) | ✅ `OK scope: read-only, REQUIREMENTS untouched, user edit present + hash matches` | +| T3-4 | `git grep` 完整性反查(A 行 ≥ grep 条数) | ✅ `OK reverse-check: A rows=31 >= grep new-exports=30` | +| T3-5 | CRLF | ✅ `OK CRLF ledger` | +| T4-1 | 台账结构 / 内容 / 单例锚点(无 B/C/D) | ✅ `OK ledger structure + all singleton anchors` | +| T4-2 | 最终纪律(A ≥15、F ≥5) | ✅ `OK final discipline: 31 A rows, 7 F entries` | +| T4-3 | 范围门禁(`material/` / `packages/` / `src/` 空;`REQUIREMENTS.md` 零改动;用户改动正向基线) | ✅ `OK scope: material/packages/src clean; REQUIREMENTS untouched; user edit present + hash matches` | | T4-4 | 既有产物保护(`04-01`..`04-14` porcelain 空;无 `04-16+`) | ✅ `OK existing 04-01..04-14 artifacts untouched; no 04-16+ plan` | -| T4-5 | ROADMAP 登记(Phase 4 段含 `04-15` / `Wave 14`) | ✅ `OK ROADMAP Phase 4 has 04-15 / Wave 14 registration` | -| T4-6 | 台账 + SUMMARY CRLF 且 SUMMARY 在场 | ✅(见 Self-Check) | -| T4-7 | `04-15-SUMMARY.md` 落盘且含 `04-15` / `去单例化` / `只读` / `Pending` / `04-16` | ✅(见 Self-Check) | +| T4-5 | ROADMAP 登记(`04-15` / `Wave 14`) | ✅ `OK ROADMAP has 04-15 / Wave 14 registration` | +| T4-6 | 台账 + SUMMARY CRLF 且在场 | ✅ `OK CRLF ledger + SUMMARY present` | +| T4-7 | `04-15-SUMMARY.md` 落盘且含 `04-15` / `去单例化` / `只读` / `Pending` / `04-16` | ✅ `OK 04-15-SUMMARY.md present and keyed` | -**门禁时刻 porcelain(`packages packages-user src`):** 仅用户既有 ` M packages-user/data-system/src/combat/context.ts` 一条(本计划只读,生产树零改动);该用户改动全程未触碰。 +**门禁时刻生产树 porcelain(`packages packages-user src`):** **1** 条 —— ` M packages-user/data-system/src/combat/context.ts`(用户并发改动,原样保留);台账 / SUMMARY 位于 `.planning/`,不属生产树。 ## 人工复核结论(Task 4 步骤 8) 逐条打开当日源码核对,**全部通过,无偏差**: -- A 类锚点均指向真实声明:`texture`(`packages-user/client-base/src/elements/cache.ts:280` / 类 `:48`)、renderer 簇(`packages-user/client-modules/src/render/renderer.ts:18,20,35,43,45`)、`sceneController`(`packages-user/client-modules/src/render/scene.ts:3`)、UI 控制器(`packages-user/client-modules/src/render/ui/controller.tsx:11,29`)、全部 `GameUI` 实例定义行与组件定义行实读确认。 -- A-32 `[证据行]` 完整性反查命令 `git grep -n -E "export const [A-Za-z0-9_]+ = new "` 原样输出与 A-01..A-31 逐条对齐,**无遗漏**。 -- B 类锚点指向真实可变状态:`packages-user/client-modules/src/render/use.ts:34,35,287`、`packages-user/client-modules/src/action/hotkey.ts:5`、`packages-user/client-modules/src/render/weather/controller.ts:15,17`;B-09 `[证据行]` 复验 `client-base/src/elements` 面模块级 `let` 零命中。 -- C 类锚点指向真实全局访问 / 引用:`Mota.require`(`packages-user/client-base/src/elements/cache.ts:491` / `misc.ts:89,219`)、`window.*`、`core.*`(计数与 `git grep -c` 一致);C 类全节明写「legacy 只报告,不修、不登记为待办」;C-07 `[证据行]` 复验 `client-base` 运行时 `window.*` 仅注释命中。 -- D 类锚点指向真实顶层语句:`packages-user/client-modules/src/action/hotkey.ts:9,470,471,523,526`、`packages-user/client-modules/src/render/use.ts:51`、`packages-user/client-modules/src/render/renderer.ts:22,26,32`;D-05 `[证据行]` 复验 `client-base/src/elements` 面顶层监听 / 定时器零命中。 -- E 类目标接口证据锚点指向真实声明:`packages-user/client-base/src/types.ts:27`(`IClientBaseExtended`)、`packages-user/data-state/src/types.ts:45`(`ICoreStateExtended`)、`packages-user/client-base/src/material/types.ts:94,218,406,439`(四处 `extends ICoreStateExtended`)、`packages-user/data-state/src/ins.ts:11`(数据端单例)实读确认。 -- F 类 7 条均未越过「只登记不判定」边界,逐条为「现象 + 为什么读不出来 + 需要用户裁决的点」,无「错配 / 缺失 / 残留 / 待办」措辞。 -- `packages-user/client-base/src/index.ts:1-9` / `packages-user/client-modules/src/index.ts:9-16` 及各子 barrel(`elements/index.ts:46-48` / `components/index.ts:1-12` / `render/index.tsx:38-44` / `render/ui/index.ts:7-14`)导出面实读确认,D-69 判定与事实一致。 +- A 类每条锚点指向真实存在的 `export const x = new X()` 及其消费者:`cache.ts:280`(类 `:48`)、`core.ts:6`(类 `client.ts:41`)、`render/renderer.ts:18,20,35,43`、`render/scene.ts:3`、`render/ui/controller.tsx:11,29`、各 `render/ui/*.tsx` 定义行、`shared.ts:105`、`client-base/components/{choices,input,misc}.tsx` 各定义行 —— 均实读 / `git grep` 确认。 +- A-31 `[证据行]` 的 `git grep -n -E "export const [A-Za-z0-9_]+ = new "` 原样结果 **30** 条,与 A-01..A-30 逐条对齐、**无遗漏、无多登**;`render/renderer.ts:45` 的解构导出 `createApp` / `render` / `tagManager` **未登记**(非 `new`)。 +- `[证据行]` 标记仅出现在 A-24 / A-25 / A-30(零消费者)与 A-31(完整性反查)四条;其余 A 事实行均 ≥2 个 `file:line` 锚点,无标记误用。 +- E 类目标接口证据的 `file:line` 指向真实声明:`IClientBaseExtended`(`client-base/src/types.ts:27`)、`ICoreStateExtended`(`data-state/src/types.ts:45`)、先例 `material/types.ts:94,218,406,439`、数据端 `ins.ts:11` 均实读确认。 +- F 类 7 条均未越过「只登记不判定」边界,**无**「错配 / 缺失 / 残留 / 待办」措辞;**无一条**涉及非单例(`window` / `core` / `Mota.require` / 静态注册表 / 顶层副作用)。 +- 台账**无** `## B` / `## C` / `## D` 小节;`## A` / `## E` 为固定列序表。 ## Decisions Made -- **只读收集小切片(用户 2026-10-01 去单例化第一步)**:唯一交付物为台账 + 本 SUMMARY;生产源码改动 0,`files_modified` 仅台账。 +- **只读单例清点小切片(用户 2026-10-01 裁定第一步)**:唯一交付物为台账 + 本 SUMMARY;生产源码改动 0,`files_modified` 仅台账。 +- **范围仅限单例**:只登记模块顶层实例化对象 `export const x = new X()`(30 条);可变模块级状态 / 全局注册表 / 全局访问器 / 顶层副作用 / 非 `new` 导出一律 OUT(不设门禁、不写入台账)。 - **单一白名单提交**:Task 1/2/3 不独立提交;Task 4 步骤 (10) 单次提交,仅暂存台账 + SUMMARY。 -- **undetermined 纪律**:目标接口取舍 / 外部框架级全局归属 / renderer 重复单例权威 / `GameUI` 实例是否纳入 一律进 F 类,不臆测、不裁定、不给挂载写法(新增命名须先获批)。 -- **未写其它 `.planning/` 文件**:按 orchestrator 指示与计划 prohibitions,除本 SUMMARY 外未写 `STATE.md` / `ROADMAP.md` / `WINDOWS.md` / `REQUIREMENTS.md`(`REND-01` / `REND-02` 保持 Pending;ROADMAP 的 `04-15` / `Wave 14` 登记由编排器在计划阶段完成)。 +- **undetermined 纪律**:所有单例的目标接口取舍一律 `undetermined`(`IClientBaseExtended` vs `ICoreStateExtended` 交用户裁决,F-05);外部包单例 / 重复 renderer 实例 / `GameUI` 实例是否纳入 / 无消费者 UI 一律进 F 类,不臆测。 +- **覆盖先前错误范围产物**:先前 6 类范围(含 B/C/D)的台账与 SUMMARY 被本 run 重写为「仅单例」范围;同一白名单文件路径,单次提交覆盖。 +- **未写其它 `.planning/` 文件**:除本 SUMMARY 外未写 `STATE.md` / `ROADMAP.md` / `WINDOWS.md` / `REQUIREMENTS.md`(`REND-01` / `REND-02` 保持 Pending)。 ## Deviations from Plan -None - plan executed exactly as written(无 Rule 1–4 偏差)。 +### Auto-fixed Issues -说明:Task 1/2/3/4 每条 `` 均按计划 `## Verification Runnability` 的指示,将原样语义落到仓库外临时 `.cjs` 后 `node ` 执行(判据与 `` 一字不变);这是计划明示的既定做法(先例 04-12 / 04-14),**不构成偏差**。 +**1. [Rule 3 - Tooling] Task 1/2/3/4 内联 `node -e` 门禁在 PowerShell 5.1 下不可直跑** + +- **Found during:** Task 1 起(每条 `` 门禁) +- **Issue:** 计划门禁为内联 `node -e "..."`,Windows PowerShell 5.1 会破坏其中的内嵌引号 / `$`(正则尾锚)/ CJK / `→`,使命令被 mangle 而非按语义失败。 +- **Fix:** 按计划 `` 的强制要求,把每条门禁的**原样语义**落到仓库外临时 `.cjs` 文件(`%TEMP%\opencode\04-15-*.cjs`)后执行 `node `;判据与 `` 一字不变,全部 18 条门禁实测通过。 +- **Files modified:** 无生产文件(临时工装,位于仓库外) +- **Commit:** 不适用 + +--- + +**Total deviations:** 1(门禁执行方式,非判据放宽)——**均不涉及生产代码,所有实质判据全部通过**。 ## Known Stubs (只报告不处置) | # | 余留 | 位置 | 说明 | |---|---|---|---| -| 1 | 目标接口取舍未定 | `texture` / client-base `GameUI` / 模块级状态 | F-05 交用户裁决(`IClientBaseExtended` vs `ICoreStateExtended`) | -| 2 | 外部框架级全局能否挂主类未定 | `mainRenderer` / `using` / `tagManager` / `gameKey` / `sceneController` / `mainUIController` | F-01 交用户裁决 | -| 3 | renderer 重复单例权威归属未定 | `packages-user/client-modules/src/render/renderer.ts:18,20,35` ↔ `packages-user/client-modules/src/client.ts:90,91,108` | F-02 交用户裁决 | -| 4 | `GameUI` / `UIController` 实例是否纳入未定 | 20 个 `GameUI` 实例 | F-03 交用户裁决 | -| 5 | `window` 顶层副作用与无 DOM 约束关系未定 | `packages-user/client-modules/src/render/use.ts:51` | F-04 交用户裁决 | -| 6 | `IClientBaseExtended` 现行实现情况未知 | `packages-user/client-base/src/types.ts:27` | F-06 交用户裁决 | -| 7 | 状态栏 UI 无消费者 | `packages-user/client-modules/src/render/ui/statusBar.tsx:488,489` | F-07 交用户裁决 | +| 1 | 目标接口取舍未定(全部 30 单例) | 台账 A / E / 映射汇总 | `IClientBaseExtended` vs `ICoreStateExtended` 交用户裁决(F-05) | +| 2 | 外部包 A 单例能否挂主类未定 | `render/renderer.ts:35,43`、`render/scene.ts:3`、`render/ui/controller.tsx:11` | `@motajs/render` / `@motajs/render-vue` / `@motajs/system`(F-02) | +| 3 | 重复 renderer 实例权威归属未定 | `render/renderer.ts:18,20,35` ↔ `client.ts:90,91,108` | F-03 | +| 4 | `GameUI` / `UIController` 实例是否纳入未定 | `render/ui/*.tsx`、`client-base/components/*.tsx` | F-04 | +| 5 | `IClientBaseExtended` 无实现类 | `client-base/src/types.ts:27` | F-06 | +| 6 | 无消费者 UI 单例 | `statusBar.tsx:488,489`、`misc.tsx:592` | F-07 | -> 依 orchestrator 指示与计划 Task 4 步骤 (11),未写入 `.planning/WINDOWS.md` / `STATE.md` / `ROADMAP.md`(本步仅允许写台账与 SUMMARY)。 +> 依计划 prohibitions 与 Task 4 步骤 (11),未写入 `.planning/WINDOWS.md` / `STATE.md` / `ROADMAP.md`(本步仅允许写台账与 SUMMARY)。 ## Issues Encountered -- 无。全部门禁一次通过;无 Rule 1–4 偏差。 +- 见「Deviations from Plan」的 1 处(门禁脚本 shell 兼容性),已按计划 `` 的强制做法处置,无生产代码影响。 ## 无运行时验证声明(D-68 的延续) - 本步**没有「保证能运行」的要求**:**未运行** `pnpm check:type` / `pnpm build`,**未使用** TS 诊断数(全仓或范围内)作为任何门禁或验收项。 -- 证明方式全部为**静态**:`git status --porcelain` 正向基线(含用户 `combat/context.ts` 行在场 + 无其它条目 + `git hash-object` 与台账标记一致)/ 台账结构与全量关键锚点 / 分类关键词 / 禁用路径 porcelain / 既有产物保护 / ROADMAP 登记 / CRLF,辅以人工代码复核。 +- 证明方式全部为**静态**:`git status --porcelain` 正向基线(用户 `combat/context.ts` 在场 + `git hash-object` 与台账标记一致 + 无其它条目)/ 台账结构与 `[证据行]` 纪律 / `git grep` 完整性反查 / 禁用路径 porcelain / CRLF / 既有产物保护 / ROADMAP 登记,辅以人工代码复核。 ## User Setup Required @@ -192,10 +200,10 @@ None - no external service configuration required. ## Next Phase Readiness -- **第一步(只读收集)完成**:A 30 对象 / B 8 / C 6 / D 4 / E 7 条 + F 7 条 + 单例→目标映射汇总 41 行;可确定目标(如 `client` 即主类本身)与 undetermined 项(外部框架级全局 / 重复单例 / 接口取舍 / `GameUI` 实例)分离清晰。 -- **第二步(04-16:挂载 + 接口继承重构)未规划**,待用户审阅 `04-RENDER-SINGLETON-AUDIT.md` 后另行规划;本步不产出任何新 `*-PLAN.md`,第二步如确需新增命名(挂载字段 / 接口名)须先获用户批准(AGENTS.md)。 -- **D-69 与 legacy 边界遵守**:D 类 barrel 涉及只登记;C 类 `core.*` / `Mota.require` / `window.*` 一律只报告、不修、不登记为待办。 -- **范围零外溢**:`packages-user/client-base/src/material/**`(D-42 / D-48)、`packages/**`、`src/**`、测试文件全部零触碰;用户 `packages-user/data-system/src/combat/context.ts` 并发改动保留且未被提交。 +- **第一步(只读收集)完成**:A 30 单例(+1 完整性反查证据行)/ E 8 / F 7 / 映射汇总 30 行;`client` 主单例与其余单例、重复 renderer 实例、外部包单例、`GameUI` 实例簇均已定位,目标接口候选与先例齐备,undetermined 项分离清晰。 +- **第二步(04-16 挂载 + 接口继承重构)未规划**,待用户审阅 `04-RENDER-SINGLETON-AUDIT.md` 后另行规划;本步不产出任何新 `*-PLAN.md`。 +- **命名零变更**:未新增 / 改名 / 删除任何公共、受保护、私有成员、方法、字段、文件或目录。 +- **范围零外溢**:数据端(含用户未提交 `combat/context.ts`)/ `packages/` / `src/` / 其它 `package.json` / 测试文件全部零触碰;用户改动被保留且未被提交。 - `REND-01` / `REND-02` 仍为 **Pending**;`.planning/REQUIREMENTS.md` 零改动。 --- @@ -204,9 +212,9 @@ None - no external service configuration required. ## Self-Check: PASSED -- `.planning/phases/04-render-adaptation/04-RENDER-SINGLETON-AUDIT.md`: FOUND(12 小节 + A–E 60 行 + F 7 条 + 单例→目标映射汇总 41 行 + 处置) +- `.planning/phases/04-render-adaptation/04-RENDER-SINGLETON-AUDIT.md`: FOUND(A 30 单例 + 1 证据行 / E 8 / F 7 / 映射汇总 30 行;无 B/C/D) - `.planning/phases/04-render-adaptation/04-15-SUMMARY.md`: FOUND -- 生产源码改动: 0(`git status --porcelain -- packages packages-user src` 仅用户既有 ` M packages-user/data-system/src/combat/context.ts`);`material/` / `packages/` / `src/` 零触碰 -- 用户并发改动 `packages-user/data-system/src/combat/context.ts`: PRESERVED(未提交、未触碰,哈希 `9982509d3d8ec4c58d5c71f37f1a576a13c3337f`) +- 生产源码改动: 0(`git status --porcelain -- packages packages-user src` 仅用户既有 ` M .../combat/context.ts`);`material/` / `packages/` / `src/` 零触碰 +- 用户并发改动 `combat/context.ts`: PRESERVED(未提交、未触碰、哈希一致) - `04-01`..`04-14` 既有产物: 零触碰;无 `04-16+` -- commits measured from ledger (`2d32878..HEAD`): 1(白名单提交) +- commits measured from ledger (`015a1993..HEAD`): 1 diff --git a/.planning/phases/04-render-adaptation/04-RENDER-SINGLETON-AUDIT.md b/.planning/phases/04-render-adaptation/04-RENDER-SINGLETON-AUDIT.md index bdae001..71bd05c 100644 --- a/.planning/phases/04-render-adaptation/04-RENDER-SINGLETON-AUDIT.md +++ b/.planning/phases/04-render-adaptation/04-RENDER-SINGLETON-AUDIT.md @@ -1,201 +1,147 @@ # 渲染端去单例化·只读清点(第一步) **日期:** 2026-10-01 -**范围:** 被查 = `packages-user/client-modules/src/**` + `packages-user/client-base/src/**` 内全部单例及其消费者;只读基准 = `packages-user/data-*`;`packages/` 与 `src/` 仅报告(D-33) +**范围:** 被查 = `packages-user/client-modules/src/**` + `packages-user/client-base/src/**` 内全部**单例**(模块顶层实例化对象 `export const x = new X()`)及其消费者;只读基准 = `packages-user/data-*`;`packages/` 与 `src/` 仅报告(D-33) **性质:** 只读清点(去单例化第一步),未修改任何生产代码,未引入任何命名变更 -**基准:** HEAD `2d3287804d90bf3cde1d6299ac71815fd677a7eb`(short `2d32878`),分支 `refine/data-client` -**目标模式:** 挂主类 `ClientCore` / `client` + 子系统继承 / 实现 `IClientBaseExtended` 或 `ICoreStateExtended`,镜像数据端模式 -**下一步:** 第二步 04-16 未规划,待用户审阅本文件后另行规划 +**基准:** HEAD `015a1993e8e95ab5fd80b5f8002f196beb2913c2`;分支 `refine/data-client`;只读起始基线见下节 +**目标模式:** 挂主类 `ClientCore` / `client` + 单例对应子系统继承 / 实现 `IClientBaseExtended`(`packages-user/client-base/src/types.ts:27`)或 `ICoreStateExtended`(`packages-user/data-state/src/types.ts:45`),镜像数据端既有模式(`packages-user/data-state/src/ins.ts:11`) +**下一步:** 第二步(04-16:挂载 + 接口继承重构)未规划,待用户审阅本文件后另行规划 ## 只读起始基线 - **只读起始基线(packages / packages-user / src)**: -- ` M packages-user/data-system/src/combat/context.ts` -- **起始 HEAD:** `2d3287804d90bf3cde1d6299ac71815fd677a7eb` + M packages-user/data-system/src/combat/context.ts +- **起始 HEAD:** `015a1993e8e95ab5fd80b5f8002f196beb2913c2` - **起始分支:** `refine/data-client` -- **用户未提交改动断言:** ` M packages-user/data-system/src/combat/context.ts` 行在场(用户 WIP,本 run 全程零触碰)。 -- **机读标记:** -- 说明:上述 porcelain 于 Task 1 步骤 (0a) 当日实测原样记录;`git hash-object -- packages-user/data-system/src/combat/context.ts` 当日实测为 `9982509d3d8ec4c58d5c71f37f1a576a13c3337f`(40 位,记入机读标记行)。 +- **用户并发改动:** ` M packages-user/data-system/src/combat/context.ts`(未提交,**原样保留**,本 run 不回滚 / 不暂存 / 不提交 / 不修改) +- **机读标记:** `` ## 背景 -- **用户裁定(2026-10-01):** 渲染端(`packages-user/client-modules` 与 `packages-user/client-base`)**不得再保留单例**;现行一切以单例形式存在的对象须改为**挂载在主类上**(`ClientCore` / `client`),且各子系统须**继承 / 实现 `IClientBaseExtended`(`packages-user/client-base/src/types.ts:27`)或 `ICoreStateExtended`(`packages-user/data-state/src/types.ts:45`)**(子系统接口携带指向主对象的 `readonly state`),**镜像数据端既有模式**(数据端单例 `packages-user/data-state/src/ins.ts:11`;渲染 / 系统层既有先例 `packages-user/client-base/src/material/types.ts:94,218,406,439` 四处 `extends ICoreStateExtended`)。裁定原文见 `.planning/ROADMAP.md:191`(Plan register note 2026-10-01)与 `.planning/phases/04-render-adaptation/04-15-PLAN.md` 的 objective / Task 0。 -- **两步走(用户 2026-10-01 裁定):** 第一步(本文件,04-15)= **只读清点全部单例**(枚举 / 分类 / 定位消费者 / 映射目标模式;生产代码零改动、不引入任何命名变更);第二步(后续 04-16)= 挂载 + 接口继承重构。**本文件只清点、不修改、不规划第二步。** -- **本步边界:** 只读注册事实与 `file:line` 锚点;静态阅读不能定论者一律进 F 类「只登记,不判定」,**不得写成错配 / 缺失 / 残留 / 待办**;第二步(04-16)不含任何代码改动方案 / import 改写 / 新命名。 -- **沿用约束:** D-33(范围外不改、不追平全部类型错误)、D-42 / D-48(`client-base/src/material/**` 归用户、AI 不得改)、D-49 / D-55 / D-65(不考虑任何 legacy)、D-56 精神(不触碰用户并发改动)、D-68(不要求可运行、不得以 `check:type` / `build` / TS 诊断数作为门禁)、D-69(桶导出边界)。 +用户 2026-10-01 裁定要点: + +- **去单例化**:渲染端(`packages-user/client-modules` 与 `packages-user/client-base`)不得再有单例;现行一切单例,第二步须**挂到主类上**(`ClientCore` / `client`,主类允许多例)。 +- **接口继承 / 实现**:单例对应子系统须**继承 / 实现 `IClientBaseExtended`(`packages-user/client-base/src/types.ts:27`)或 `ICoreStateExtended`(`packages-user/data-state/src/types.ts:45`)**,即子系统接口携带 `readonly state` 指向主对象,**镜像数据端既有模式**(数据端单例 `packages-user/data-state/src/ins.ts:11`;渲染端先例 `packages-user/client-base/src/material/types.ts:94,218,406,439`)。 +- **两步走**:第一步(本计划 04-15)= **只读清点全部单例**(枚举 / 消费者 / 目标映射;生产代码零改动、不引入任何命名变更);第二步(后续 04-16)= 实际挂载 + 接口继承重构。**本计划不规划 04-16。** +- **本步只清点、不修改、不规划第二步**:本文件只登记单例,不给出挂载写法 / import 改写方案 / 新 `*-PLAN.md`。 +- **沿用约束**:D-33(范围外不改)、D-42 / D-48(`client-base/src/material/**` 归用户、AI 不得改)、D-49 / D-55 / D-65(不考虑 legacy)、D-56 精神(不触碰用户并发改动)、D-68(不要求可运行、不得以 `check:type` / `build` / TS 诊断数作为门禁)、D-69(桶导出边界,本步不触发)。 ## 方法 -- **枚举面:** `packages-user/client-modules/src/**` 与 `packages-user/client-base/src/**`(两个包的全部 `.ts` / `.tsx`)。 -- **核对手法:** 静态阅读 + `git grep -n`(符号名 / 文本检索);当日行号为实测值,若与规划日不同以当日实测为准。 -- **六类判定口径:** 见下一节「枚举口径」。 -- **分类纪律:** A 记模块级实例化对象;B 记可变模块级状态与全局注册表;C 记全局访问器与框架级全局引用;D 记顶层副作用模块;E 记主类关系与目标挂载面映射。同一事实若跨类,拆条并互相引用,不得互相冒充。 -- **证据纪律:** A–E 的**事实行**每行至少 **2** 个完整 `文件:行` 锚点(识别正则接受 `.(tsx?|md|json):\d+`);**证据行**仅在 ID 单元格带 `[证据行]` 标记,改为必须携带核对命令(`git grep` / `git status --porcelain`)与原样结果,**豁免 ≥2 计数**;**非证据行不得带 `[证据行]` 标记**。 -- **只登记不判定:** 静态阅读不能定论者一律进 F 类,**不得写成错配 / 缺失 / 残留 / 待办**。 -- **目标映射:** 每个单例给出「挂主类 `ClientCore` / `client` + `IClientBaseExtended`(`packages-user/client-base/src/types.ts:27`)或 `ICoreStateExtended`(`packages-user/data-state/src/types.ts:45`)之一 + 先例」;无法确定者写 `undetermined` 并交叉引用 F 类,不得臆测、不得裁定目标接口、不得给出挂载写法。 -- **无运行时要求(D-68 的延续):** 本步为只读收集,不产生运行时行为,承载体为静态门禁 + 人工复核;**不得**执行 `pnpm check:type` / `pnpm build`,**不得**以 TS 诊断数作为门禁或验收项。 +- **枚举面**:`packages-user/client-modules/src/**` 与 `packages-user/client-base/src/**` 两个包内的全部模块顶层实例化对象。 +- **核对手法**:`git grep -n -E "export const [A-Za-z0-9_]+ = new " -- packages-user/client-modules packages-user/client-base`(规划日实测 30 条:client-modules 24 / client-base 6;执行日以当日实测为准)+ 逐文件阅读定位消费者。 +- **证据纪律**:A / E 事实行每行至少 2 个完整 `文件:行` 锚点;**证据行**(零命中 / 对照扫描,仅在 ID 单元格带 `[证据行]` 标记)必须携带核对命令(`git grep`)与原样结果、有真实锚点时至少 1 个,**豁免 ≥2 计数**;非证据行不得带 `[证据行]` 标记。 +- **只登记不判定**:静态阅读不能定论者一律进 F 类;**不得**写成错配 / 缺失 / 残留 / 待办。 ## 枚举口径 -| 类别 | 定义 | 当日实测代表 | -|---|---|---| -| 模块级实例化对象 | 模块顶层 `new X()` 后以 `export const`(或顶层 `const`)暴露 / 持有的对象 | `texture` / `client` / `mainRenderer` / `using` / 各 `GameUI` 实例 | -| 可变模块级状态 | 模块顶层 `let` / `Set` / `Map` 等可被跨调用修改的状态容器 | `nowOrientation` / `orientationHooks` / `transitionMap` | -| 全局注册表 | 以 `Symbol.for` / `static Map` 等注册、供全局按 key 查询的注册表 | `mainScope` / `WeatherController.extern` / `.weathers` | -| 全局访问器 | 通过全局对象(`Mota.require` / `window.*` / `core.*`)读取外部状态 | `Mota.require('@user/data-base')` / `window.addEventListener` / `core.*` | -| 框架级全局引用 | 直接引用外部包(`@motajs/render` / `@motajs/render-vue` / `@motajs/system`)提供的全局对象 | `mainRenderer` / `using` / `tagManager` / `gameKey` | -| 顶层副作用模块 | 模块顶层直接执行的语句(注册 / 监听 / 存储读写 / 初始化副作用) | `action/hotkey.ts` 的 `gameKey` 注册链 / `render/use.ts:51` 的 `window.addEventListener` | +**单例定义唯一且严格**:模块顶层实例化对象,即 `export const x = new X()`(或模块顶层 `new X()` 存于模块级 `const` 并导出)。 + +**显式排除清单(一律 OUT,不写入本台账任何小节、不设门禁)**: + +- 可变模块级状态(如 `render/use.ts` 的 `nowOrientation` / `orientationHooks` / `transitionMap`)。 +- 全局注册表 / 类静态 `Map` / 计数器(如 `WeatherController.extern` / `.weathers`、`RenderColorTransition.key`)。 +- 全局符号(如 `Symbol.for('@key_main')`)。 +- 全局访问器(`Mota.require` / `window.*` / `core.*`)。 +- 顶层副作用(`gameKey` 注册链 / `window.addEventListener` / 模块级 `bindExcitation`)。 +- 非 `new` 导出(如 `render/renderer.ts:45` 的解构导出 `createApp` / `render` / `tagManager`,及任何裸 / 解构函数)。 ## A 模块级实例化对象 | ID | 符号 / 项目 | 定义 file:line | 类型 / 导出机制 | 全部消费者 file:line | 当前归属 / 挂载 | 与 ClientCore / client 的关系 | 目标挂载 / 接口(证据或 undetermined) | 置信 | |---|---|---|---|---|---|---|---|---| -| #04-15-A-01 | `texture` | packages-user/client-base/src/elements/cache.ts:280 | ESM `export const`(模块级 `new TextureCache()`;类定义 packages-user/client-base/src/elements/cache.ts:48;经 packages-user/client-base/src/elements/index.ts:46 barrel + packages-user/client-base/src/index.ts:8 再导出) | packages-user/client-base/src/components/textbox.tsx:399 / packages-user/client-base/src/components/textboxTyper.ts:837 / packages-user/client-base/src/components/tip.tsx:54 / packages-user/client-base/src/elements/misc.ts:87 / packages-user/client-base/src/elements/cache.ts:502 | client-base 系统层 elements 模块级;`ClientCore` 未持有 `texture` 字段(packages-user/client-modules/src/client.ts:43-56 无对应成员) | 不在主类字段中;无构造器注入 | 挂 `ClientCore`;接口候选 `IClientBaseExtended`(packages-user/client-base/src/types.ts:27)或 `ICoreStateExtended`(packages-user/data-state/src/types.ts:45),先例 packages-user/client-base/src/material/types.ts:94 / packages-user/data-state/src/ins.ts:11;取舍 undetermined(见 F-05) | 中 | -| #04-15-A-02 | `client`(主挂载类实例本身) | packages-user/client-modules/src/core.ts:6 | ESM `export const`(`new ClientCore({...})`;类定义 packages-user/client-modules/src/client.ts:41) | packages-user/client-modules/src/fallback/audio.ts:5 / packages-user/client-modules/src/render/ui/load.tsx:27 / packages-user/client-modules/src/render/ui/main.tsx:32 / packages-user/client-modules/src/render/ui/settings.tsx:28 / packages-user/client-modules/src/render/ui/statusBar.tsx:15 / packages-user/client-modules/src/render/ui/title.tsx:38 / packages-user/client-modules/src/render/ui/toolbar.tsx:28;packages-user/client-modules/src/index.ts:14 再导出 | client-modules 实现层入口单例 | 即主类实例本身(`ClientCore`) | 即目标主类;另见 packages-user/client-modules/src/core.ts:3 的 TODO「逐渐弱化 ClientCore 的单例概念」 | 高 | -| #04-15-A-03 | `rafExcitation` | packages-user/client-modules/src/render/renderer.ts:18 | ESM `export const`(模块级 `new RafExcitation()`) | packages-user/client-modules/src/render/renderer.ts:24 / packages-user/client-modules/src/render/renderer.ts:28 / packages-user/client-modules/src/client.ts:90(`ClientCore` 构造器内自建)/ packages-user/client-modules/src/client.ts:106 | client-modules render 模块级;与 `ClientCore` 字段重复 | 与主类字段 `rafExcitation`(packages-user/client-modules/src/client.ts:48)为两个不同实例 → 重复单例,归属未定 | undetermined(重复单例,交叉引用 F-02) | 中 | -| #04-15-A-04 | `excitationDivider` | packages-user/client-modules/src/render/renderer.ts:20 | ESM `export const`(模块级 `new ExcitationDivider()`) | packages-user/client-modules/src/render/renderer.ts:26 / packages-user/client-modules/src/render/renderer.ts:32 / packages-user/client-modules/src/client.ts:91(构造器内自建)/ packages-user/client-modules/src/client.ts:107 | client-modules render 模块级;与 `ClientCore` 字段重复 | 与主类字段 `excitationDivider`(packages-user/client-modules/src/client.ts:49)为两个不同实例 → 重复单例,归属未定 | undetermined(重复单例,交叉引用 F-02) | 中 | -| #04-15-A-05 | `mainRenderer` | packages-user/client-modules/src/render/renderer.ts:35 | ESM `export const`(模块级 `new MotaRenderer({...})`) | packages-user/client-modules/src/render/index.tsx:5 / packages-user/client-modules/src/render/index.tsx:23 / packages-user/client-base/src/elements/index.ts:4 / packages-user/client-base/src/elements/index.ts:12 | client-modules render 模块级;framework-level global(`@motajs/render`) | 与主类字段 `renderer`(packages-user/client-modules/src/client.ts:50,构造器 packages-user/client-modules/src/client.ts:108 内 `new MotaRenderer`)为两个不同实例 → 重复单例,归属未定;`ClientCore` 未直接持有 `mainRenderer` | undetermined(外部框架级全局 + 重复单例,见 F-01 / F-02) | 中 | -| #04-15-A-06 | `using` | packages-user/client-modules/src/render/renderer.ts:43 | ESM `export const`(模块级 `new RendererUsing(mainRenderer)`) | packages-user/client-base/src/components/misc.tsx:227 / packages-user/client-base/src/components/textboxTyper.ts:313 / packages-user/client-modules/src/render/ui/main.tsx:155 | client-modules render 模块级(`@motajs/render-vue`) | 不在任何主类字段;由 `mainRenderer` 派生 | undetermined(外部框架级全局,见 F-01) | 中 | -| #04-15-A-07 | `createApp` / `render` / `tagManager`(解构导出组) | packages-user/client-modules/src/render/renderer.ts:45 | ESM 解构 `export const { createApp, render, tagManager } = createRendererFor(mainRenderer)` | packages-user/client-modules/src/render/index.tsx:10 / packages-user/client-modules/src/render/index.tsx:23 / packages-user/client-base/src/elements/index.ts:4 / packages-user/client-base/src/elements/index.ts:16 / packages-user/client-base/src/elements/index.ts:24 | client-modules render 模块级(`@motajs/render-vue`);`tagManager` 被系统层 elements 反向引用 | 不在任何主类字段 | undetermined(外部框架级全局,见 F-01) | 低 | -| #04-15-A-08 | `sceneController` | packages-user/client-modules/src/render/scene.ts:3 | ESM `export const`(模块级 `new UIController('main-scene')`;`UIController` 来自 `@motajs/system`) | packages-user/client-modules/src/render/index.tsx:8 / packages-user/client-modules/src/render/index.tsx:17 / packages-user/client-modules/src/render/index.tsx:25 | client-modules render 模块级(`@motajs/system`) | 不在 `ClientCore` 字段 | undetermined(外部框架级全局;是否挂主类见 F-01) | 中 | -| #04-15-A-09 | `mainUIController` | packages-user/client-modules/src/render/ui/controller.tsx:11 | ESM `export const`(模块级 `new UIController('main-ui')`) | packages-user/client-modules/src/render/action.ts:17 / packages-user/client-modules/src/render/ui/main.tsx:281 / packages-user/client-modules/src/render/ui/statusBar.tsx:380 / packages-user/client-modules/src/render/ui/toolbar.tsx:94 | client-modules UI 模块级(`@motajs/system`) | 不在 `ClientCore` 字段 | undetermined(见 F-01 / F-03) | 中 | -| #04-15-A-10 | `MainBackgroundUI` | packages-user/client-modules/src/render/ui/controller.tsx:29 | ESM `export const`(模块级 `new GameUI('main-background', MainBackground)`;组件定义 packages-user/client-modules/src/render/ui/controller.tsx:19) | packages-user/client-modules/src/render/ui/controller.tsx:32(`setBackground`) | client-modules UI 模块级(`@motajs/system`) | 不在 `ClientCore` 字段 | undetermined(`GameUI` 实例是否属须挂主类对象,见 F-03) | 中 | -| #04-15-A-11 | `LoadSceneUI` | packages-user/client-modules/src/render/ui/load.tsx:161 | ESM `export const`(`new GameUI('load-scene', LoadScene)`;组件定义 packages-user/client-modules/src/render/ui/load.tsx:35) | packages-user/client-modules/src/render/index.tsx:11 / packages-user/client-modules/src/render/index.tsx:25 | client-modules UI 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03) | 中 | -| #04-15-A-12 | `MainSceneUI` | packages-user/client-modules/src/render/ui/main.tsx:312 | ESM `export const`(`new GameUI('main-scene', MainScene)`;组件定义 packages-user/client-modules/src/render/ui/main.tsx:34) | packages-user/client-modules/src/render/ui/title.tsx:34 / packages-user/client-modules/src/render/ui/title.tsx:206 | client-modules UI 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03) | 中 | -| #04-15-A-13 | `SaveUI` | packages-user/client-modules/src/render/ui/save.tsx:462 | ESM `export const`(`new GameUI('save', Save)`;组件定义 packages-user/client-modules/src/render/ui/save.tsx:165) | packages-user/client-modules/src/render/ui/save.tsx:510 | client-modules UI 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03) | 中 | -| #04-15-A-14 | `MainSettingsUI` | packages-user/client-modules/src/render/ui/settings.tsx:663 | ESM `export const`(`new GameUI('main-settings', MainSettings)`;组件定义 packages-user/client-modules/src/render/ui/settings.tsx:53) | packages-user/client-modules/src/render/ui/settings.tsx:688 | client-modules UI 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03) | 中 | -| #04-15-A-15 | `ReplaySettingsUI` | packages-user/client-modules/src/render/ui/settings.tsx:665 | ESM `export const`(`new GameUI('replay-settings', ReplaySettings)`;组件定义 packages-user/client-modules/src/render/ui/settings.tsx:146) | packages-user/client-modules/src/render/ui/settings.tsx:92 / packages-user/client-modules/src/render/ui/settings.tsx:699 | client-modules UI 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03) | 中 | -| #04-15-A-16 | `GameInfoUI` | packages-user/client-modules/src/render/ui/settings.tsx:667 | ESM `export const`(`new GameUI('game-info', GameInfo)`;组件定义 packages-user/client-modules/src/render/ui/settings.tsx:264) | packages-user/client-modules/src/render/ui/settings.tsx:100 | client-modules UI 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03) | 中 | -| #04-15-A-17 | `SyncSaveUI` | packages-user/client-modules/src/render/ui/settings.tsx:669 | ESM `export const`(`new GameUI('sync-save', SyncSave)`;组件定义 packages-user/client-modules/src/render/ui/settings.tsx:359) | packages-user/client-modules/src/render/ui/settings.tsx:96 | client-modules UI 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03) | 中 | -| #04-15-A-18 | `SyncSaveSelectUI` | packages-user/client-modules/src/render/ui/settings.tsx:671 | ESM `export const`(`new GameUI('sync-save-select', SyncSaveSelect)`;组件定义 packages-user/client-modules/src/render/ui/settings.tsx:419) | packages-user/client-modules/src/render/ui/settings.tsx:375 | client-modules UI 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03) | 中 | -| #04-15-A-19 | `DownloadSaveSelectUI` | packages-user/client-modules/src/render/ui/settings.tsx:673 | ESM `export const`(`new GameUI(...)`;组件定义 packages-user/client-modules/src/render/ui/settings.tsx:476) | packages-user/client-modules/src/render/ui/settings.tsx:389 | client-modules UI 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03) | 中 | -| #04-15-A-20 | `ClearSaveSelectUI` | packages-user/client-modules/src/render/ui/settings.tsx:678 | ESM `export const`(`new GameUI(...)`;组件定义 packages-user/client-modules/src/render/ui/settings.tsx:549) | packages-user/client-modules/src/render/ui/settings.tsx:397 | client-modules UI 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03) | 中 | -| #04-15-A-21 | `StatisticsUI` | packages-user/client-modules/src/render/ui/statistics.tsx:302 | ESM `export const`(`new GameUI('statistics', Statistics)`;组件定义 packages-user/client-modules/src/render/ui/statistics.tsx:49) | packages-user/client-modules/src/render/ui/statistics.tsx:299 | client-modules UI 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03) | 中 | -| #04-15-A-22 | `leftStatusBarUI` | packages-user/client-modules/src/render/ui/statusBar.tsx:488 | ESM `export const`(`new GameUI('left-status-bar', LeftStatusBar)`;组件定义 packages-user/client-modules/src/render/ui/statusBar.tsx:106) | 当日 `git grep -n -w leftStatusBarUI` 仅命中定义行 packages-user/client-modules/src/render/ui/statusBar.tsx:488(无其它消费者,登记事实,见 F-07) | client-modules UI 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03 / F-07) | 低 | -| #04-15-A-23 | `rightStatusBarUI` | packages-user/client-modules/src/render/ui/statusBar.tsx:489 | ESM `export const`(`new GameUI('right-status-bar', RightStatusBar)`;组件定义 packages-user/client-modules/src/render/ui/statusBar.tsx:460) | 当日 `git grep -n -w rightStatusBarUI` 仅命中定义行 packages-user/client-modules/src/render/ui/statusBar.tsx:489(无其它消费者,登记事实,见 F-07) | client-modules UI 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03 / F-07) | 低 | -| #04-15-A-24 | `GameTitleUI` | packages-user/client-modules/src/render/ui/title.tsx:484 | ESM `export const`(`new GameUI('game-title', GameTitle)`;组件定义 packages-user/client-modules/src/render/ui/title.tsx:66) | packages-user/client-modules/src/render/ui/load.tsx:26 / packages-user/client-modules/src/render/ui/load.tsx:67 | client-modules UI 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03) | 中 | -| #04-15-A-25 | `ViewMapUI` | packages-user/client-modules/src/render/ui/viewmap.tsx:556 | ESM `export const`(`new GameUI('view-map', ViewMap)`;组件定义 packages-user/client-modules/src/render/ui/viewmap.tsx:53) | packages-user/client-modules/src/render/ui/viewmap.tsx:563 / packages-user/client-modules/src/render/ui/settings.tsx:86 | client-modules UI 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03) | 中 | -| #04-15-A-26 | `ConfirmBoxUI` | packages-user/client-base/src/components/choices.tsx:796 | ESM `export const`(`new GameUI('confirm-box', ConfirmBox)`;组件定义 packages-user/client-base/src/components/choices.tsx:98) | packages-user/client-base/src/components/choices.tsx:606 / packages-user/client-base/src/components/choices.tsx:722 | client-base 系统层 components 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03 / F-05) | 中 | -| #04-15-A-27 | `ChoicesUI` | packages-user/client-base/src/components/choices.tsx:798 | ESM `export const`(`new GameUI('choices', Choices)`;组件定义 packages-user/client-base/src/components/choices.tsx:319) | packages-user/client-base/src/components/choices.tsx:659 / packages-user/client-base/src/components/choices.tsx:777 | client-base 系统层 components 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03 / F-05) | 中 | -| #04-15-A-28 | `InputBoxUI` | packages-user/client-base/src/components/input.tsx:602 | ESM `export const`(`new GameUI('input-box', InputBox)`;组件定义 packages-user/client-base/src/components/input.tsx:382) | packages-user/client-base/src/components/input.tsx:555 | client-base 系统层 components 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03 / F-05) | 中 | -| #04-15-A-29 | `WaitBoxUI` | packages-user/client-base/src/components/misc.tsx:591 | ESM `export const`(`new GameUI('wait-box', WaitBox)`;组件定义 packages-user/client-base/src/components/misc.tsx:468) | packages-user/client-base/src/components/misc.tsx:578 | client-base 系统层 components 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03 / F-05) | 中 | -| #04-15-A-30 | `BackgroundUI` | packages-user/client-base/src/components/misc.tsx:592 | ESM `export const`(`new GameUI('background', Background)`;组件定义 packages-user/client-base/src/components/misc.tsx:391) | packages-user/client-base/src/components/misc.tsx:592(当日 `git grep -n -w BackgroundUI` 仅命中定义行;无其它消费者,登记事实) | client-base 系统层 components 模块级 | 不在 `ClientCore` 字段 | undetermined(见 F-03 / F-05) | 低 | -| #04-15-A-31 | `DEFAULT_FONT` | packages-user/client-modules/src/shared.ts:105 | ESM `export const`(模块级 `new Font('Verdana', 16)`) | packages-user/client-modules/src/render/index.tsx:3 / packages-user/client-modules/src/render/index.tsx:35(`Font.setDefaults`) | client-modules shared 模块级 | 不在 `ClientCore` 字段 | undetermined(字体常量,是否纳入去单例化见 F-03) | 低 | -| #04-15-A-32 | `[证据行]` 完整性反查:两个包内全部 `export const ... = new ...` | — | 核对命令:`git grep -n -E "export const [A-Za-z0-9_]+ = new " -- packages-user/client-modules packages-user/client-base` | 原样输出(当日实测):`packages-user/client-base/src/components/choices.tsx:796` ConfirmBoxUI、`packages-user/client-base/src/components/choices.tsx:798` ChoicesUI、`packages-user/client-base/src/components/input.tsx:602` InputBoxUI、`packages-user/client-base/src/components/misc.tsx:591` WaitBoxUI、`packages-user/client-base/src/components/misc.tsx:592` BackgroundUI、`packages-user/client-base/src/elements/cache.ts:280` texture、`packages-user/client-modules/src/core.ts:6` client、`packages-user/client-modules/src/render/renderer.ts:18` rafExcitation、`:20` excitationDivider、`:35` mainRenderer、`:43` using、`packages-user/client-modules/src/render/scene.ts:3` sceneController、`packages-user/client-modules/src/render/ui/controller.tsx:11` mainUIController、`:29` MainBackgroundUI、`packages-user/client-modules/src/render/ui/load.tsx:161` LoadSceneUI、`main.tsx:312` MainSceneUI、`save.tsx:462` SaveUI、`settings.tsx:663/665/667/669/671/673/678` 七个 settings UI、`statistics.tsx:302` StatisticsUI、`statusBar.tsx:488/489` 两个状态栏 UI、`title.tsx:484` GameTitleUI、`viewmap.tsx:556` ViewMapUI、`packages-user/client-modules/src/shared.ts:105` DEFAULT_FONT | A-01..A-31 与上述输出逐条对齐,无遗漏 | 高 | - -## B 可变模块级状态与全局注册表 - -| ID | 符号 / 项目 | 定义 file:line | 类型 / 导出机制 | 全部消费者 file:line | 当前归属 / 挂载 | 与 ClientCore / client 的关系 | 目标挂载 / 接口(证据或 undetermined) | 置信 | -|---|---|---|---|---|---|---|---|---| -| #04-15-B-01 | `nowOrientation` | packages-user/client-modules/src/render/use.ts:34 | 模块级 `let`(可变模块级状态,非导出) | packages-user/client-modules/src/render/use.ts:38 / packages-user/client-modules/src/render/use.ts:41 / packages-user/client-modules/src/render/use.ts:48 | client-modules render 模块级 | 不在 `ClientCore` 字段 | 挂 `ClientCore`(朝向状态);接口候选 undetermined(见 F-04) | 中 | -| #04-15-B-02 | `orientationHooks` | packages-user/client-modules/src/render/use.ts:35 | 模块级 `const Set`(可变模块级状态容器,非导出) | packages-user/client-modules/src/render/use.ts:47 / packages-user/client-modules/src/render/use.ts:59 / packages-user/client-modules/src/render/use.ts:63 | client-modules render 模块级 | 不在 `ClientCore` 字段 | 挂 `ClientCore`(监听器集合);接口候选 undetermined(见 F-04) | 中 | -| #04-15-B-03 | `transitionMap` | packages-user/client-modules/src/render/use.ts:287 | 模块级 `const Map`(可变模块级状态容器,非导出) | packages-user/client-modules/src/render/use.ts:298 / packages-user/client-modules/src/render/use.ts:306 / packages-user/client-modules/src/render/use.ts:312 | client-modules render 模块级 | 不在 `ClientCore` 字段 | 挂 `ClientCore`(渐变实例表);接口候选 undetermined(见 F-04) | 中 | -| #04-15-B-04 | `mainScope` | packages-user/client-modules/src/action/hotkey.ts:5 | ESM `export const`(`Symbol.for('@key_main')`,全局符号注册表) | packages-user/client-modules/src/action/hotkey.ts:471 / packages-user/client-modules/src/action/move.ts:6 / packages-user/client-modules/src/action/move.ts:31 | client-modules action 模块级 | 不在 `ClientCore` 字段 | undetermined(全局符号;是否挂主类见 F-01) | 中 | -| #04-15-B-05 | `WeatherController.extern`(`static extern`) | packages-user/client-modules/src/render/weather/controller.ts:15 | 类静态 `Map`(全局注册表) | packages-user/client-modules/src/render/weather/controller.ts:110 / packages-user/client-modules/src/render/weather/controller.ts:117 / packages-user/client-modules/src/render/weather/controller.ts:126 | client-modules weather 类静态 | 不在 `ClientCore` 字段 | undetermined(全局注册表;见 F-01 / F-06) | 中 | -| #04-15-B-06 | `WeatherController.weathers`(`static weathers`) | packages-user/client-modules/src/render/weather/controller.ts:17 | 类静态 `Map`(全局注册表) | packages-user/client-modules/src/render/weather/controller.ts:61 / packages-user/client-modules/src/render/weather/controller.ts:135 / packages-user/client-modules/src/render/weather/index.ts:11 | client-modules weather 类静态 | 不在 `ClientCore` 字段 | undetermined(全局注册表;见 F-01) | 中 | -| #04-15-B-07 | `RenderColorTransition.key` | packages-user/client-modules/src/render/use.ts:150 | 类静态可变计数器(`private static key: number = 0`) | packages-user/client-modules/src/render/use.ts:152 / packages-user/client-modules/src/render/use.ts:155 | client-modules render 类静态 | 不在 `ClientCore` 字段 | undetermined(类内静态计数器,是否纳入去单例化见 F-04) | 低 | -| #04-15-B-08 | `breakSet` / `ignoreStart` / `ignoreEnd` | packages-user/client-base/src/components/textboxTyper.ts:567 | 模块级 `const Set(...)`(可变模块级状态容器,非导出) | packages-user/client-base/src/components/textboxTyper.ts:568 / packages-user/client-base/src/components/textboxTyper.ts:569 | client-base 系统层 components 模块级 | 不在 `ClientCore` 字段 | undetermined(模块级常量集合,见 F-05) | 低 | -| #04-15-B-09 | `[证据行]` `client-base/src/elements` 面 B 类候选(模块级 `let`) | — | 核对命令:`git grep -n -E "^(export )?let " -- packages-user/client-base/src/elements` | 原样结果:无输出(零命中) | 说明 `client-base/src/elements` 面当前无模块级 `let`;B 类可变状态集中在 client-modules 侧 | — | 高 | - -## C 全局访问器与框架级全局引用 - -| ID | 符号 / 项目 | 定义 file:line | 类型 / 导出机制 | 全部消费者 file:line | 当前归属 / 挂载 | 与 ClientCore / client 的关系 | 目标挂载 / 接口(证据或 undetermined) | 置信 | -|---|---|---|---|---|---|---|---|---| -| #04-15-C-01 | `Mota.require('@user/data-base')` 全局访问器 | packages-user/client-base/src/elements/cache.ts:491 | 全局对象 `Mota` 访问器(legacy,仅报告,不修、不登记为待办) | packages-user/client-base/src/elements/misc.ts:89 / packages-user/client-base/src/elements/misc.ts:219 | client-base 系统层 elements | 不在 `ClientCore` 字段 | undetermined(legacy 命中,仅报告;见 F-01) | 中 | -| #04-15-C-02 | `window.*`(朝向检测的运行时代码) | packages-user/client-modules/src/render/use.ts:51 | 框架级全局 `window`(`addEventListener` / `innerWidth` / `innerHeight`) | packages-user/client-modules/src/render/use.ts:40 / packages-user/client-modules/src/render/use.ts:48 / packages-user/client-modules/src/render/use.ts:60 | client-modules render 模块级 | 不在 `ClientCore` 字段 | undetermined(浏览器全局;与「数据端无 DOM」约束关系见 F-04) | 中 | -| #04-15-C-03 | `window.open` / `window.location` / `window.hero` / `window.flags` | packages-user/client-modules/src/render/ui/settings.tsx:284 | 框架级全局 `window`(UI 面使用) | packages-user/client-modules/src/render/ui/settings.tsx:293 / packages-user/client-modules/src/render/ui/settings.tsx:302 / packages-user/client-modules/src/render/ui/statistics.tsx:216 / packages-user/client-modules/src/render/ui/statistics.tsx:249 | client-modules UI 模块级 | 不在 `ClientCore` 字段 | undetermined(浏览器全局,仅报告;见 F-04) | 低 | -| #04-15-C-04 | `core.*` 全局引用(legacy,仅报告) | packages-user/client-modules/src/action/hotkey.ts:478 | 旧引擎全局 `core`(legacy;D-49 / D-55 / D-65 不考虑,仅报告,不修、不登记为待办) | packages-user/client-modules/src/render/ui/main.tsx:97 / packages-user/client-modules/src/render/ui/settings.tsx:284 / packages-user/client-base/src/components/choices.tsx:676 / packages-user/client-base/src/elements/cache.ts:87;当日 `git grep -c -E "\bcore\."` 计数:client-modules `action/hotkey.ts:13` / `action/move.ts:5` / `render/ui/main.tsx:20` / `render/ui/settings.tsx:54` / `render/ui/statusBar.tsx:13` / `render/ui/statistics.tsx:15` / `render/ui/toolbar.tsx:17` / `render/ui/viewmap.tsx:14`;client-base `components/choices.tsx:13` / `elements/cache.ts:9` / `components/floorSelect.tsx:2` | client-modules 与 client-base 均有 | 不在 `ClientCore` 字段 | undetermined(legacy,仅报告) | 高 | -| #04-15-C-05 | 外部包框架级全局 `gameKey` / `tagManager` / `mainRenderer` | packages-user/client-modules/src/action/hotkey.ts:2 | 外部包(`@motajs/system` / `@motajs/render-vue` / `@motajs/render`)提供的全局对象 | packages-user/client-modules/src/render/action.ts:1 / packages-user/client-modules/src/render/use.ts:11 / packages-user/client-modules/src/render/renderer.ts:45(`tagManager`)/ packages-user/client-modules/src/render/renderer.ts:35(`mainRenderer`) | client-modules 框架级全局 | `ClientCore` 未持有 `gameKey` / `tagManager`;`mainRenderer` 与 `ClientCore.renderer` 重复(见 A-05) | undetermined(外部包所有,能否挂主类见 F-01) | 中 | -| #04-15-C-06 | 数据端单例 `state` 引用 | packages-user/client-modules/src/render/ui/main.tsx:28 | 直接 `import { state } from '@user/data-state'`(数据端单例 `state`,定义 packages-user/data-state/src/ins.ts:11) | packages-user/client-modules/src/render/ui/main.tsx:28(导入面) | client-modules UI 模块级引用 | 非渲染端主类;数据端单例 | undetermined(数据端单例,仅报告;D-23 / D-28 存量单例由用户自行整改) | 低 | -| #04-15-C-07 | `[证据行]` `client-base` 面 `window.*` 运行时代码 | — | 核对命令:`git grep -n -E "\bwindow\." -- packages-user/client-base/src` | 原样结果:仅 packages-user/client-base/src/components/misc.tsx:450 / packages-user/client-base/src/components/misc.tsx:549(均为 jsDoc 注释示例,非运行时代码) | 说明 `client-base` 面当前无运行时 `window.*` 访问 | — | 高 | - -## D 顶层副作用模块 - -| ID | 符号 / 项目 | 定义 file:line | 类型 / 导出机制 | 全部消费者 file:line | 当前归属 / 挂载 | 与 ClientCore / client 的关系 | 目标挂载 / 接口(证据或 undetermined) | 置信 | -|---|---|---|---|---|---|---|---|---| -| #04-15-D-01 | `gameKey` 顶层注册链(`.group(...).register(...)`) | packages-user/client-modules/src/action/hotkey.ts:9 | 模块顶层执行语句(按键注册副作用) | packages-user/client-modules/src/action/hotkey.ts:467(注册链结束)/ packages-user/client-modules/src/action/hotkey.ts:470(`gameKey.enable()`)/ packages-user/client-modules/src/action/hotkey.ts:471(`gameKey.use(mainScope)`) | client-modules action 模块顶层 | 不在 `ClientCore` 字段 | undetermined(外部框架级全局注册,见 F-01) | 中 | -| #04-15-D-02 | `keyStorage` 顶层存储读写与事件接线 | packages-user/client-modules/src/action/hotkey.ts:518 | 模块顶层执行语句(`new GameStorage` / `read` / `on` / `fromJSON`) | packages-user/client-modules/src/action/hotkey.ts:521(`keyStorage.read()`)/ packages-user/client-modules/src/action/hotkey.ts:523(`gameKey.on('set', ...)`)/ packages-user/client-modules/src/action/hotkey.ts:526(`gameKey.fromJSON(...)`) | client-modules action 模块顶层 | 不在 `ClientCore` 字段 | undetermined(存储副作用,见 F-01) | 中 | -| #04-15-D-03 | `window.addEventListener('resize', checkOrientation)` | packages-user/client-modules/src/render/use.ts:51 | 模块顶层执行语句(窗口监听副作用) | packages-user/client-modules/src/render/use.ts:37(`checkOrientation` 定义)/ packages-user/client-modules/src/render/use.ts:48(回调内 `window.innerWidth`) | client-modules render 模块顶层 | 不在 `ClientCore` 字段 | undetermined(顶层副作用与无 DOM 约束关系见 F-04) | 中 | -| #04-15-D-04 | 模块级 `bindExcitation` / `setDivider` 顶层分支 | packages-user/client-modules/src/render/renderer.ts:22 | 模块顶层执行语句(`if (DEBUG_VARIATOR)` / `if (DEBUG_DIVIDER)` 分支内的绑定副作用) | packages-user/client-modules/src/render/renderer.ts:26 / packages-user/client-modules/src/render/renderer.ts:32 | client-modules render 模块顶层 | 不在 `ClientCore` 字段 | undetermined(重复单例的顶层副作用,见 F-02) | 中 | -| #04-15-D-05 | `[证据行]` `client-base/src/elements` 面 D 类候选(顶层监听 / 定时器) | — | 核对命令:`git grep -n -E "addEventListener|setInterval" -- packages-user/client-base/src/elements` | 原样结果:无输出(零命中) | 说明 `client-base/src/elements` 面当前无顶层监听 / 定时器副作用 | — | 高 | +| #04-15-A-01 | `texture` | `packages-user/client-base/src/elements/cache.ts:280`(`export const texture = new TextureCache()`;`class TextureCache` 定义 `packages-user/client-base/src/elements/cache.ts:48`) | 模块顶层实例化对象(`new TextureCache()`),`export const` 直接导出;经 barrel `packages-user/client-base/src/elements/index.ts`(`export * from './cache'`)与 `packages-user/client-base/src/index.ts`(`export * from './elements'`)透出 | `packages-user/client-base/src/components/textbox.tsx:33,399,400`;`packages-user/client-base/src/components/textboxTyper.ts:5,837,1079`;`packages-user/client-base/src/components/tip.tsx:8,54,98`;`packages-user/client-base/src/elements/misc.ts:9,87,125`;`packages-user/client-base/src/elements/cache.ts:502`(`createCache()` 内 `texture.init()`) | 模块级导出,未挂主类;经 `@user/client-base` 公共面暴露 | `ClientCore`(`packages-user/client-modules/src/client.ts:41`)未持有 `texture` 字段(字段清单 `packages-user/client-modules/src/client.ts:43-56` 无 `texture`);`ClientCore.materials`(`packages-user/client-modules/src/client.ts:79`)为另一素材管理对象 | undetermined(候选:挂 `ClientCore` / `client` + 接口 `IClientBaseExtended`(`packages-user/client-base/src/types.ts:27`)或 `ICoreStateExtended`(`packages-user/data-state/src/types.ts:45`);先例 `packages-user/client-base/src/material/types.ts:94,218,406,439`、`packages-user/data-state/src/ins.ts:11`;取舍见 `#04-15-F-01` / `#04-15-F-05`) | 低 | +| #04-15-A-02 | `client` | `packages-user/client-modules/src/core.ts:6`(`export const client = new ClientCore({...})`;构造类 `class ClientCore` 定义 `packages-user/client-modules/src/client.ts:41`) | 模块顶层实例化对象(`new ClientCore({...})`),`export const`;经 `packages-user/client-modules/src/index.ts:13`(`export * from './core'`)透出 | `packages-user/client-modules/src/fallback/audio.ts:5,11`;`packages-user/client-modules/src/render/ui/load.tsx:27,36`;`packages-user/client-modules/src/render/ui/main.tsx:32`;`packages-user/client-modules/src/render/ui/settings.tsx:28`;`packages-user/client-modules/src/render/ui/statusBar.tsx:15`;`packages-user/client-modules/src/render/ui/title.tsx:38`;`packages-user/client-modules/src/render/ui/toolbar.tsx:28` | `client-modules` 入口 `core.ts` 模块级导出;即主挂载类实例本身 | **主挂载类实例本身**(用户 2026-10-01 裁定的挂载目标);`packages-user/client-modules/src/client.ts:43-56` 为其现有字段清单 | 无需上挂(本身即 `ClientCore` / `client`);第二步其余单例挂于此实例 | 中 | +| #04-15-A-03 | `rafExcitation` | `packages-user/client-modules/src/render/renderer.ts:18`(`export const rafExcitation = new RafExcitation()`) | 模块顶层实例化对象(`new RafExcitation()`),`export const`;经 `packages-user/client-modules/src/render/index.tsx`(`export * from './renderer'`)透出 | `packages-user/client-modules/src/render/renderer.ts:24,28`(`bindExcitation` 链) | `render/renderer.ts` 模块级导出,未挂主类 | `ClientCore` 有同名字段 `rafExcitation`(`packages-user/client-modules/src/client.ts:48,90,106`),为构造器内自建的另一 `RafExcitation` 实例 → **重复单例,权威归属未定**(见 `#04-15-F-03`) | undetermined(候选:挂 `ClientCore` / `client` + `IClientBaseExtended` / `ICoreStateExtended`;先例 `packages-user/client-base/src/material/types.ts:94,218,406,439`、`packages-user/data-state/src/ins.ts:11`;重复归属见 `#04-15-F-03`) | 低 | +| #04-15-A-04 | `excitationDivider` | `packages-user/client-modules/src/render/renderer.ts:20`(`export const excitationDivider = new ExcitationDivider()`) | 模块顶层实例化对象(`new ExcitationDivider()`),`export const`;经 `packages-user/client-modules/src/render/index.tsx` 透出 | `packages-user/client-modules/src/render/renderer.ts:26,28,32,40`(`bindExcitation` / `setDivider` / 传入 `MotaRenderer`) | `render/renderer.ts` 模块级导出,未挂主类 | `ClientCore` 有同名字段 `excitationDivider`(`packages-user/client-modules/src/client.ts:49,91,107`),为构造器内自建的另一实例 → **重复单例,权威归属未定**(见 `#04-15-F-03`) | undetermined(候选同上;重复归属见 `#04-15-F-03`) | 低 | +| #04-15-A-05 | `mainRenderer` | `packages-user/client-modules/src/render/renderer.ts:35`(`export const mainRenderer = new MotaRenderer({...})`) | 模块顶层实例化对象(`new MotaRenderer({...})`,来源 `@motajs/render`),`export const`;经 `packages-user/client-modules/src/render/index.tsx` 透出 | `packages-user/client-modules/src/render/renderer.ts:43,46`(传给 `RendererUsing` / `createRendererFor`);`packages-user/client-modules/src/render/index.tsx:5,22,23,26`(`hide` / `mount` / `show`);`packages-user/client-base/src/elements/index.ts:4,12,13,14`(`registerElement`) | `render/renderer.ts` 模块级导出,未挂主类 | `ClientCore.renderer`(`packages-user/client-modules/src/client.ts:50,108`)为构造器内自建的另一 `MotaRenderer` 实例 → **重复单例,权威归属未定**(见 `#04-15-F-03`) | undetermined(外部包 `@motajs/render` 产出,能否挂主类见 `#04-15-F-02`;重复归属见 `#04-15-F-03`) | 低 | +| #04-15-A-06 | `using` | `packages-user/client-modules/src/render/renderer.ts:43`(`export const using = new RendererUsing(mainRenderer)`) | 模块顶层实例化对象(`new RendererUsing(mainRenderer)`,来源 `@motajs/render-vue`),`export const`;经 `packages-user/client-modules/src/render/index.tsx` 透出 | `packages-user/client-base/src/components/misc.tsx:16,227,340`(`onExcitedFunc`);`packages-user/client-base/src/components/textboxTyper.ts:7,313`(`onExcitedFunc`);`packages-user/client-modules/src/render/ui/main.tsx:31,155`(`onExcitedFunc`) | `render/renderer.ts` 模块级导出,未挂主类 | `ClientCore` 无 `using` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员);是否挂主类未定 | undetermined(外部包 `@motajs/render-vue` 产出,能否挂主类见 `#04-15-F-02`) | 低 | +| #04-15-A-07 | `sceneController` | `packages-user/client-modules/src/render/scene.ts:3`(`export const sceneController = new UIController('main-scene')`) | 模块顶层实例化对象(`new UIController('main-scene')`,来源 `@motajs/system`),`export const`;经 `packages-user/client-modules/src/render/index.tsx`(`export * from './scene'`)透出 | `packages-user/client-modules/src/render/index.tsx:8,17,25`(`render` / `open(LoadSceneUI)`) | `render/scene.ts` 模块级导出,未挂主类 | `ClientCore` 无 `sceneController` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(外部包 `@motajs/system` 产出,能否挂主类见 `#04-15-F-02`) | 低 | +| #04-15-A-08 | `mainUIController` | `packages-user/client-modules/src/render/ui/controller.tsx:11`(`export const mainUIController = new UIController('main-ui')`) | 模块顶层实例化对象(`new UIController('main-ui')`,来源 `@motajs/system`),`export const`;经 `packages-user/client-modules/src/render/ui/index.ts`(`export * from './controller'`)透出 | `packages-user/client-modules/src/render/action.ts:5,17,20,23,28,33,36`;`packages-user/client-modules/src/render/ui/main.tsx:29,281,284`;`packages-user/client-modules/src/render/ui/statusBar.tsx:7,380`;`packages-user/client-modules/src/render/ui/toolbar.tsx:23,94,97,115,120,126,195`;`packages-user/client-modules/src/render/ui/controller.tsx:32` | `render/ui/controller.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `mainUIController` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(外部包 `@motajs/system` 产出,能否挂主类见 `#04-15-F-02`;是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-A-09 | `MainBackgroundUI` | `packages-user/client-modules/src/render/ui/controller.tsx:29`(`export const MainBackgroundUI = new GameUI('main-background', MainBackground)`) | 模块顶层实例化对象(`new GameUI(...)`,来源 `@motajs/system`),`export const`;经 `packages-user/client-modules/src/render/ui/index.ts` 透出 | `packages-user/client-modules/src/render/ui/controller.tsx:32`(`mainUIController.setBackground(MainBackgroundUI, {})`) | `render/ui/controller.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `MainBackgroundUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-A-10 | `LoadSceneUI` | `packages-user/client-modules/src/render/ui/load.tsx:161`(`export const LoadSceneUI = new GameUI('load-scene', LoadScene)`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-modules/src/render/ui/index.ts` 透出 | `packages-user/client-modules/src/render/index.tsx:11,25`(`sceneController.open(LoadSceneUI, {})`) | `render/ui/load.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `LoadSceneUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-A-11 | `MainSceneUI` | `packages-user/client-modules/src/render/ui/main.tsx:312`(`export const MainSceneUI = new GameUI('main-scene', MainScene)`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-modules/src/render/ui/index.ts` 透出 | `packages-user/client-modules/src/render/ui/title.tsx:34,206,225`(`controller.open(MainSceneUI, {})`) | `render/ui/main.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `MainSceneUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-A-12 | `SaveUI` | `packages-user/client-modules/src/render/ui/save.tsx:462`(`export const SaveUI = new GameUI('save', Save)`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-modules/src/render/ui/index.ts` 透出 | `packages-user/client-modules/src/render/ui/save.tsx:510`(`controller.open(SaveUI, {...})`) | `render/ui/save.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `SaveUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-A-13 | `MainSettingsUI` | `packages-user/client-modules/src/render/ui/settings.tsx:663`(`export const MainSettingsUI = new GameUI('main-settings', MainSettings)`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-modules/src/render/ui/index.ts` 透出 | `packages-user/client-modules/src/render/ui/settings.tsx:688`(`controller.open(MainSettingsUI, {...})`) | `render/ui/settings.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `MainSettingsUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-A-14 | `ReplaySettingsUI` | `packages-user/client-modules/src/render/ui/settings.tsx:665`(`export const ReplaySettingsUI = new GameUI('replay-settings', ReplaySettings)`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-modules/src/render/ui/index.ts` 透出 | `packages-user/client-modules/src/render/ui/settings.tsx:92,699`(`controller.open(ReplaySettingsUI, {...})`) | `render/ui/settings.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `ReplaySettingsUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-A-15 | `GameInfoUI` | `packages-user/client-modules/src/render/ui/settings.tsx:667`(`export const GameInfoUI = new GameUI('game-info', GameInfo)`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-modules/src/render/ui/index.ts` 透出 | `packages-user/client-modules/src/render/ui/settings.tsx:100`(`controller.open(GameInfoUI, {...})`) | `render/ui/settings.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `GameInfoUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-A-16 | `SyncSaveUI` | `packages-user/client-modules/src/render/ui/settings.tsx:669`(`export const SyncSaveUI = new GameUI('sync-save', SyncSave)`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-modules/src/render/ui/index.ts` 透出 | `packages-user/client-modules/src/render/ui/settings.tsx:96`(`controller.open(SyncSaveUI, {...})`) | `render/ui/settings.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `SyncSaveUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-A-17 | `SyncSaveSelectUI` | `packages-user/client-modules/src/render/ui/settings.tsx:671`(`export const SyncSaveSelectUI = new GameUI('sync-save-select', SyncSaveSelect)`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-modules/src/render/ui/index.ts` 透出 | `packages-user/client-modules/src/render/ui/settings.tsx:375`(`controller.open(SyncSaveSelectUI, {...})`) | `render/ui/settings.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `SyncSaveSelectUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-A-18 | `DownloadSaveSelectUI` | `packages-user/client-modules/src/render/ui/settings.tsx:673`(`export const DownloadSaveSelectUI = new GameUI(...)`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-modules/src/render/ui/index.ts` 透出 | `packages-user/client-modules/src/render/ui/settings.tsx:389`(`controller.open(DownloadSaveSelectUI, {...})`) | `render/ui/settings.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `DownloadSaveSelectUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-A-19 | `ClearSaveSelectUI` | `packages-user/client-modules/src/render/ui/settings.tsx:678`(`export const ClearSaveSelectUI = new GameUI(...)`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-modules/src/render/ui/index.ts` 透出 | `packages-user/client-modules/src/render/ui/settings.tsx:397`(`controller.open(ClearSaveSelectUI, {...})`) | `render/ui/settings.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `ClearSaveSelectUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-A-20 | `StatisticsUI` | `packages-user/client-modules/src/render/ui/statistics.tsx:302`(`export const StatisticsUI = new GameUI('statistics', Statistics)`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-modules/src/render/ui/index.ts` 透出 | `packages-user/client-modules/src/render/ui/statistics.tsx:299`(`controller.open(StatisticsUI, { data })`) | `render/ui/statistics.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `StatisticsUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-A-21 | `GameTitleUI` | `packages-user/client-modules/src/render/ui/title.tsx:484`(`export const GameTitleUI = new GameUI('game-title', GameTitle)`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-modules/src/render/ui/index.ts` 透出 | `packages-user/client-modules/src/render/ui/load.tsx:26,67`(`controller.open(GameTitleUI, {})`) | `render/ui/title.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `GameTitleUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-A-22 | `ViewMapUI` | `packages-user/client-modules/src/render/ui/viewmap.tsx:556`(`export const ViewMapUI = new GameUI('view-map', ViewMap)`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-modules/src/render/ui/index.ts` 透出 | `packages-user/client-modules/src/render/ui/settings.tsx:25,86`;`packages-user/client-modules/src/render/ui/viewmap.tsx:563`(`controller.open(ViewMapUI, {...})`) | `render/ui/viewmap.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `ViewMapUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-A-23 | `DEFAULT_FONT` | `packages-user/client-modules/src/shared.ts:105`(`export const DEFAULT_FONT = new Font('Verdana', 16)`) | 模块顶层实例化对象(`new Font('Verdana', 16)`,来源 `@motajs/render`),`export const`;经 `packages-user/client-modules/src/index.ts:16`(`export * from './shared'`)透出 | `packages-user/client-modules/src/render/index.tsx:3,35`(`Font.setDefaults(DEFAULT_FONT)`) | `shared.ts` 模块级导出,未挂主类 | `ClientCore` 无 `DEFAULT_FONT` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(`Font` 默认值对象,是否属挂载面未定) | 低 | +| #04-15-A-24 [证据行] | `leftStatusBarUI` | `packages-user/client-modules/src/render/ui/statusBar.tsx:488`(`export const leftStatusBarUI = new GameUI('left-status-bar', LeftStatusBar)`;组件 `LeftStatusBar` 定义 `packages-user/client-modules/src/render/ui/statusBar.tsx:106`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-modules/src/render/ui/index.ts` 透出 | 核对命令 `git grep -n -w leftStatusBarUI -- packages-user/client-modules/src packages-user/client-base/src src packages` → 原样结果仅定义行 `packages-user/client-modules/src/render/ui/statusBar.tsx:488`(消费者零命中) | `render/ui/statusBar.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `leftStatusBarUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(无消费者,见 `#04-15-F-07`) | 低 | +| #04-15-A-25 [证据行] | `rightStatusBarUI` | `packages-user/client-modules/src/render/ui/statusBar.tsx:489`(`export const rightStatusBarUI = new GameUI('right-status-bar', RightStatusBar)`;组件 `RightStatusBar` 定义 `packages-user/client-modules/src/render/ui/statusBar.tsx:460`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-modules/src/render/ui/index.ts` 透出 | 核对命令 `git grep -n -w rightStatusBarUI -- packages-user/client-modules/src packages-user/client-base/src src packages` → 原样结果仅定义行 `packages-user/client-modules/src/render/ui/statusBar.tsx:489`(消费者零命中) | `render/ui/statusBar.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `rightStatusBarUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(无消费者,见 `#04-15-F-07`) | 低 | +| #04-15-A-26 | `ConfirmBoxUI` | `packages-user/client-base/src/components/choices.tsx:796`(`export const ConfirmBoxUI = new GameUI('confirm-box', ConfirmBox)`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-base/src/components/index.ts`(`export * from './choices'`)与 `packages-user/client-base/src/index.ts`(`export * from './components'`)透出 | `packages-user/client-base/src/components/choices.tsx:606,722`(`controller.open(ConfirmBoxUI, {...})`) | `client-base/src/components/choices.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `ConfirmBoxUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-A-27 | `ChoicesUI` | `packages-user/client-base/src/components/choices.tsx:798`(`export const ChoicesUI = new GameUI('choices', Choices)`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-base/src/components/index.ts` 与 `packages-user/client-base/src/index.ts` 透出 | `packages-user/client-base/src/components/choices.tsx:659,777`(`controller.open(ChoicesUI, {...})`) | `client-base/src/components/choices.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `ChoicesUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-A-28 | `InputBoxUI` | `packages-user/client-base/src/components/input.tsx:602`(`export const InputBoxUI = new GameUI('input-box', InputBox)`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-base/src/components/index.ts`(`export * from './input'`)与 `packages-user/client-base/src/index.ts` 透出 | `packages-user/client-base/src/components/input.tsx:555`(`controller.open(InputBoxUI, {...})`) | `client-base/src/components/input.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `InputBoxUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-A-29 | `WaitBoxUI` | `packages-user/client-base/src/components/misc.tsx:591`(`export const WaitBoxUI = new GameUI('wait-box', WaitBox)`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-base/src/components/index.ts`(`export * from './misc'`)与 `packages-user/client-base/src/index.ts` 透出 | `packages-user/client-base/src/components/misc.tsx:578`(`controller.open(WaitBoxUI, {...})`) | `client-base/src/components/misc.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `WaitBoxUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-A-30 [证据行] | `BackgroundUI` | `packages-user/client-base/src/components/misc.tsx:592`(`export const BackgroundUI = new GameUI('background', Background)`;组件 `Background` 定义 `packages-user/client-base/src/components/misc.tsx:391`) | 模块顶层实例化对象(`new GameUI(...)`),`export const`;经 `packages-user/client-base/src/components/index.ts` 与 `packages-user/client-base/src/index.ts` 透出 | 核对命令 `git grep -n -w BackgroundUI -- packages-user/client-modules/src packages-user/client-base/src src packages` → 原样结果仅 `packages-user/client-base/src/components/misc.tsx:592` 与上述定义行(消费者零命中) | `client-base/src/components/misc.tsx` 模块级导出,未挂主类 | `ClientCore` 无 `BackgroundUI` 字段(`packages-user/client-modules/src/client.ts:43-56` 无对应成员) | undetermined(无消费者,见 `#04-15-F-07`) | 低 | +| #04-15-A-31 [证据行] | 完整性反查(`git grep`) | 核对命令 `git grep -n -E "export const [A-Za-z0-9_]+ = new " -- packages-user/client-modules packages-user/client-base` | 对照扫描(非单例条目;证明无遗漏 / 无多登) | 原样结果 30 条 —— client-modules 24:`packages-user/client-modules/src/core.ts:6`、`packages-user/client-modules/src/render/renderer.ts:18,20,35,43`、`packages-user/client-modules/src/render/scene.ts:3`、`packages-user/client-modules/src/render/ui/controller.tsx:11,29`、`packages-user/client-modules/src/render/ui/load.tsx:161`、`packages-user/client-modules/src/render/ui/main.tsx:312`、`packages-user/client-modules/src/render/ui/save.tsx:462`、`packages-user/client-modules/src/render/ui/settings.tsx:663,665,667,669,671,673,678`、`packages-user/client-modules/src/render/ui/statistics.tsx:302`、`packages-user/client-modules/src/render/ui/statusBar.tsx:488,489`、`packages-user/client-modules/src/render/ui/title.tsx:484`、`packages-user/client-modules/src/render/ui/viewmap.tsx:556`、`packages-user/client-modules/src/shared.ts:105`;client-base 6:`packages-user/client-base/src/components/choices.tsx:796,798`、`packages-user/client-base/src/components/input.tsx:602`、`packages-user/client-base/src/components/misc.tsx:591,592`、`packages-user/client-base/src/elements/cache.ts:280` | `packages-user/client-modules/src` + `packages-user/client-base/src` | 与台账 A-01..A-30 逐条对齐,无遗漏、无多登 | 高 | ## E 主类关系与目标挂载面映射 | ID | 符号 / 项目 | 定义 file:line | 类型 / 导出机制 | 全部消费者 file:line | 当前归属 / 挂载 | 与 ClientCore / client 的关系 | 目标挂载 / 接口(证据或 undetermined) | 置信 | |---|---|---|---|---|---|---|---|---| -| #04-15-E-01 | `client` 主类实例本身 | packages-user/client-modules/src/core.ts:6 | 主挂载类实例(`ClientCore`) | packages-user/client-modules/src/client.ts:41(类声明)/ packages-user/client-modules/src/render/ui/main.tsx:32 / packages-user/client-modules/src/render/ui/load.tsx:27 | client-modules 入口单例 | 即 `ClientCore` / `client` 目标主类 | 目标 = 主类本身(无需再挂);字段对照 packages-user/client-modules/src/client.ts:43-56 | 高 | -| #04-15-E-02 | `texture` → 目标接口映射 | packages-user/client-base/src/elements/cache.ts:280 | 模块级实例化对象(A-01) | packages-user/client-base/src/components/textbox.tsx:399 / packages-user/client-base/src/elements/misc.ts:87 | client-base 系统层 | 不在主类字段 | 挂 `ClientCore`;接口候选 `IClientBaseExtended`(packages-user/client-base/src/types.ts:27,携带 `readonly state: IClientBase`;`IClientBase extends ICoreState` 同文件 :8)或 `ICoreStateExtended`(packages-user/data-state/src/types.ts:45);先例 packages-user/client-base/src/material/types.ts:94 / packages-user/data-state/src/ins.ts:11;取舍 undetermined(见 F-05) | 中 | -| #04-15-E-03 | renderer 实例簇(`rafExcitation` / `excitationDivider` / `mainRenderer` / `using` / `tagManager`) | packages-user/client-modules/src/render/renderer.ts:18 | 模块级实例化对象 + 外部框架级全局(A-03..A-07) | packages-user/client-modules/src/render/renderer.ts:35 / packages-user/client-modules/src/render/renderer.ts:43 / packages-user/client-modules/src/render/renderer.ts:45 / packages-user/client-modules/src/client.ts:48 / packages-user/client-modules/src/client.ts:108 | client-modules render 模块级 | 与 `ClientCore` 构造器内自建的同名激励源 / 渲染器重复(packages-user/client-modules/src/client.ts:90 / packages-user/client-modules/src/client.ts:91 / packages-user/client-modules/src/client.ts:108) | undetermined(重复单例权威归属未定,见 F-02;外部框架级全局见 F-01) | 中 | -| #04-15-E-04 | UI 控制器与 `GameUI` 实例簇(`sceneController` / `mainUIController` / `MainBackgroundUI` / A-11..A-30) | packages-user/client-modules/src/render/ui/controller.tsx:11 | 模块级实例化对象(A-08..A-30) | packages-user/client-modules/src/render/scene.ts:3 / packages-user/client-modules/src/render/ui/controller.tsx:29 / packages-user/client-modules/src/render/ui/viewmap.tsx:556 / packages-user/client-base/src/components/choices.tsx:796 | client-modules UI / client-base 系统层 | 均不在 `ClientCore` 字段 | undetermined(`GameUI` / `UIController` 实例是否属须挂主类对象见 F-03;目标接口候选 `IClientBaseExtended`(packages-user/client-base/src/types.ts:27)) | 低 | -| #04-15-E-05 | `render/use.ts` 可变状态 + `hotkey.ts` 全局符号 | packages-user/client-modules/src/render/use.ts:34 | 可变模块级状态 + 全局符号(B-01..B-04) | packages-user/client-modules/src/render/use.ts:35 / packages-user/client-modules/src/render/use.ts:51 / packages-user/client-modules/src/render/use.ts:287 / packages-user/client-modules/src/action/hotkey.ts:5 | client-modules render / action 模块级 | 均不在 `ClientCore` 字段 | undetermined(是否挂主类 / 选何接口见 F-01 / F-04) | 低 | -| #04-15-E-06 | weather 静态注册表(`WeatherController.extern` / `.weathers`) | packages-user/client-modules/src/render/weather/controller.ts:15 | 全局注册表(B-05 / B-06) | packages-user/client-modules/src/render/weather/controller.ts:17 / packages-user/client-modules/src/render/weather/controller.ts:125 / packages-user/client-modules/src/render/weather/controller.ts:134 | client-modules weather 类静态 | 不在 `ClientCore` 字段 | undetermined(全局注册表;能否改挂主类见 F-01) | 低 | -| #04-15-E-07 | client-base `GameUI` 实例 + `Mota.require` | packages-user/client-base/src/components/misc.tsx:592 | 模块级实例化对象 + 全局访问器(A-26..A-30 / C-01) | packages-user/client-base/src/components/choices.tsx:796 / packages-user/client-base/src/elements/cache.ts:491 | client-base 系统层 | 不在 `ClientCore` 字段 | 挂 `ClientCore`;接口候选 `IClientBaseExtended`(packages-user/client-base/src/types.ts:27);先例 packages-user/client-base/src/material/types.ts:218;取舍 undetermined(见 F-05) | 低 | +| #04-15-E-01 | `texture` | `packages-user/client-base/src/elements/cache.ts:280` | A-01 单一例 | 同 A-01(见 `packages-user/client-base/src/components/textbox.tsx:33` / `packages-user/client-base/src/elements/misc.ts:9`) | `client-base/src/elements/cache.ts` 模块级导出,经 `@user/client-base` 公共面暴露 | `ClientCore` 未持有 `texture` 字段(`packages-user/client-modules/src/client.ts:43-56`) | undetermined;目标接口候选与先例 —— `IClientBaseExtended`(`packages-user/client-base/src/types.ts:27`,携带 `readonly state: IClientBase`,`IClientBase extends ICoreState` 见 `packages-user/client-base/src/types.ts:8`)或 `ICoreStateExtended`(`packages-user/data-state/src/types.ts:45`);渲染 / 系统层先例 `packages-user/client-base/src/material/types.ts:94,218,406,439`;数据端先例 `packages-user/data-state/src/ins.ts:11` | 低 | +| #04-15-E-02 | `rafExcitation` / `excitationDivider` / `mainRenderer` / `using`(renderer 实例簇) | `packages-user/client-modules/src/render/renderer.ts:18,20,35,43` | A-03..A-06 | `packages-user/client-modules/src/render/index.tsx:5,22,23,26`;`packages-user/client-base/src/components/misc.tsx:16`;`packages-user/client-modules/src/render/ui/main.tsx:31` | `render/renderer.ts` 模块级导出,未挂主类 | `ClientCore` 构造器内自建同名 `rafExcitation` / `excitationDivider` / `renderer`(`packages-user/client-modules/src/client.ts:90,91,108`)→ **重复单例,权威归属未定**(`#04-15-F-03`);`using` 无对应主类字段 | undetermined(外部包 `@motajs/render` / `@motajs/render-vue` 产出,能否挂主类见 `#04-15-F-02`;接口候选 `IClientBaseExtended`(`packages-user/client-base/src/types.ts:27`)/ `ICoreStateExtended`(`packages-user/data-state/src/types.ts:45`),先例 `packages-user/client-base/src/material/types.ts:94,218,406,439`、`packages-user/data-state/src/ins.ts:11`;取舍见 `#04-15-F-05`) | 低 | +| #04-15-E-03 | `client` | `packages-user/client-modules/src/core.ts:6` | A-02(主挂载类实例本身) | `packages-user/client-modules/src/render/ui/load.tsx:27`;`packages-user/client-modules/src/render/ui/main.tsx:32`;`packages-user/client-modules/src/fallback/audio.ts:5` | `client-modules` 入口模块级导出,即主挂载类实例本身 | 自身即 `ClientCore` / `client`;`packages-user/client-modules/src/client.ts:43-56` 为其现有字段,第二步其余单例挂于此 | 目标 = 主挂载类本身(无需上挂) | 中 | +| #04-15-E-04 | `sceneController` | `packages-user/client-modules/src/render/scene.ts:3` | A-07 | `packages-user/client-modules/src/render/index.tsx:8,17,25` | `render/scene.ts` 模块级导出,未挂主类 | `ClientCore` 无对应字段(`packages-user/client-modules/src/client.ts:43-56`) | undetermined(外部包 `@motajs/system`,见 `#04-15-F-02`;是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-E-05 | `mainUIController` / `MainBackgroundUI`(UI 控制器簇) | `packages-user/client-modules/src/render/ui/controller.tsx:11,29` | A-08 / A-09 | `packages-user/client-modules/src/render/ui/main.tsx:29,284`;`packages-user/client-modules/src/render/ui/toolbar.tsx:23,115`;`packages-user/client-modules/src/render/ui/controller.tsx:32` | `render/ui/controller.tsx` 模块级导出,未挂主类 | `ClientCore` 无对应字段(`packages-user/client-modules/src/client.ts:43-56`) | undetermined(外部包 `@motajs/system`,见 `#04-15-F-02`;`GameUI` / `UIController` 是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-E-06 | `LoadSceneUI` / `MainSceneUI` / `SaveUI` / `MainSettingsUI` / `ReplaySettingsUI` / `GameInfoUI` / `SyncSaveUI` / `SyncSaveSelectUI` / `DownloadSaveSelectUI` / `ClearSaveSelectUI` / `StatisticsUI` / `leftStatusBarUI` / `rightStatusBarUI` / `GameTitleUI` / `ViewMapUI`(GameUI 实例簇) | `packages-user/client-modules/src/render/ui/load.tsx:161`;`packages-user/client-modules/src/render/ui/main.tsx:312`;`packages-user/client-modules/src/render/ui/save.tsx:462`;`packages-user/client-modules/src/render/ui/settings.tsx:663,665,667,669,671,673,678`;`packages-user/client-modules/src/render/ui/statistics.tsx:302`;`packages-user/client-modules/src/render/ui/statusBar.tsx:488,489`;`packages-user/client-modules/src/render/ui/title.tsx:484`;`packages-user/client-modules/src/render/ui/viewmap.tsx:556` | A-10..A-22 / A-24 / A-25 | `packages-user/client-modules/src/render/index.tsx:11,25`;`packages-user/client-modules/src/render/ui/title.tsx:34,206`;`packages-user/client-modules/src/render/ui/settings.tsx:86,92,96,100,375,389,397,688,699`;`packages-user/client-modules/src/render/ui/statistics.tsx:299`;`packages-user/client-modules/src/render/ui/viewmap.tsx:563` | 模块级导出,未挂主类;`leftStatusBarUI` / `rightStatusBarUI` 无消费者(`#04-15-F-07`) | `ClientCore` 无对应字段(`packages-user/client-modules/src/client.ts:43-56`) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`) | 低 | +| #04-15-E-07 | `DEFAULT_FONT` | `packages-user/client-modules/src/shared.ts:105` | A-23 | `packages-user/client-modules/src/render/index.tsx:3,35` | `shared.ts` 模块级导出,未挂主类 | `ClientCore` 无对应字段(`packages-user/client-modules/src/client.ts:43-56`) | undetermined(是否属挂载面未定) | 低 | +| #04-15-E-08 | `ConfirmBoxUI` / `ChoicesUI` / `InputBoxUI` / `WaitBoxUI` / `BackgroundUI`(client-base GameUI 实例簇) | `packages-user/client-base/src/components/choices.tsx:796,798`;`packages-user/client-base/src/components/input.tsx:602`;`packages-user/client-base/src/components/misc.tsx:591,592` | A-26..A-30 | `packages-user/client-base/src/components/choices.tsx:606,659,722,777`;`packages-user/client-base/src/components/input.tsx:555`;`packages-user/client-base/src/components/misc.tsx:578` | 模块级导出,未挂主类;`BackgroundUI` 无消费者(`#04-15-F-07`) | `ClientCore` 无对应字段(`packages-user/client-modules/src/client.ts:43-56`) | undetermined(`GameUI` 实例是否纳入见 `#04-15-F-04`;接口候选 `IClientBaseExtended`(`packages-user/client-base/src/types.ts:27`)/ `ICoreStateExtended`(`packages-user/data-state/src/types.ts:45`),取舍见 `#04-15-F-05`) | 低 | ## F 未能从阅读确定(未猜测) -- **#04-15-F-01**:外部包框架级全局(`mainRenderer` / `using` / `tagManager` / `gameKey` / `sceneController` / `mainUIController`)分别来自 `@motajs/render` / `@motajs/render-vue` / `@motajs/system`;这些对象由外部包单例式提供,能否(以及如何)改挂到本仓 `ClientCore` / `client` 上,无法仅从本仓两个包的静态阅读确定。需要用户裁决:外部框架级全局是否属「渲染端单例」的处置范围。**只登记,不判定。** -- **#04-15-F-02**:`packages-user/client-modules/src/render/renderer.ts` 模块级的 `rafExcitation`(`:18` / `:20`)与 `mainRenderer`(`:35`)同 `ClientCore` 构造器内自建的同名对象(packages-user/client-modules/src/client.ts:90 / :91 / :108)并存 —— 两套实例同时存在时哪一份是权威(运行时被使用)、另一份是否废弃,无法仅从阅读确定。需要用户裁决。**只登记,不判定。** -- **#04-15-F-03**:`GameUI` / `UIController` 实例单例(`LoadSceneUI` / `MainSceneUI` / `ViewMapUI` 等,含 `leftStatusBarUI` / `rightStatusBarUI` 当日无消费者者)是否属用户裁定中「须挂主类」的对象;UI 实例生命周期与主类的关系无法仅从阅读确定。需要用户裁决。**只登记,不判定。** -- **#04-15-F-04**:`packages-user/client-modules/src/render/use.ts:51` 的 `window.addEventListener('resize', ...)` 顶层副作用与 `window.*` 使用,同 `dev.md`「数据端无 DOM」约束之间的关系(渲染端运行时依赖浏览器全局是否属可接受边界)无法仅从阅读确定。需要用户裁决。**只登记,不判定。** -- **#04-15-F-05**:数据端先例未覆盖的渲染端子系统(`texture` / client-base `GameUI` / 模块级状态)应选择 `IClientBaseExtended`(packages-user/client-base/src/types.ts:27)还是 `ICoreStateExtended`(packages-user/data-state/src/types.ts:45)作为目标接口;两接口携带的 `readonly state` 类型(`IClientBase` vs `ICoreState`)取舍无法仅从阅读确定。需要用户裁决。**只登记,不判定。** -- **#04-15-F-06**:`IClientBaseExtended`(packages-user/client-base/src/types.ts:27)现行是否已有实现类 / 消费者;规划日 `git grep` 仅见其定义、未见实现类,而 `ICoreStateExtended` 在 `packages-user/client-base/src/material/types.ts` 有四处实现先例。该差异是否影响目标接口取舍无法仅从阅读确定。需要用户裁决。**只登记,不判定。** -- **#04-15-F-07**:`leftStatusBarUI`(packages-user/client-modules/src/render/ui/statusBar.tsx:488)与 `rightStatusBarUI`(packages-user/client-modules/src/render/ui/statusBar.tsx:489)当日无 `git grep -w` 消费者(仅定义行);其是否存在未接线的装配点(如动态注册 / 反射)无法仅从阅读确定。**只登记,不判定。** +- **#04-15-F-01(`texture` 是否须挂主类 / 目标接口取舍)**:现象 —— `texture` 为 `packages-user/client-base/src/elements/cache.ts:280` 的模块级实例化导出,被 `packages-user/client-base/src/components/textbox.tsx:33` / `packages-user/client-base/src/components/textboxTyper.ts:5` / `packages-user/client-base/src/components/tip.tsx:8` / `packages-user/client-base/src/elements/misc.ts:9` 直接 import。为什么读不出来 —— 用户裁定给出了「单例须挂主类 + 镜像数据端模式」的方向,但未给出「哪些单例纳入挂载面」与「取 `IClientBaseExtended` 还是 `ICoreStateExtended`」的判据。需要用户裁决的点 —— ① `texture` 是否纳入挂载面;② 其对应子系统接口取哪一个扩展接口。**只登记,不判定。** +- **#04-15-F-02((a) 外部包 A 单例能否挂主类)**:现象 —— `mainRenderer`(`packages-user/client-modules/src/render/renderer.ts:35`)/ `using`(`packages-user/client-modules/src/render/renderer.ts:43`)/ `sceneController`(`packages-user/client-modules/src/render/scene.ts:3`)/ `mainUIController`(`packages-user/client-modules/src/render/ui/controller.tsx:11`)分别由外部包 `@motajs/render` / `@motajs/render-vue` / `@motajs/system` 的类实例化。为什么读不出来 —— 这些类的构造与挂载面在 `packages/`(D-33 只报告)内,本步不改、不追平;能否挂到主类取决于外部包是否允许以主对象构造。需要用户裁决的点 —— 这四个外部包单例是否纳入挂载面、以何种方式挂。**只登记,不判定。** +- **#04-15-F-03((b) 重复 renderer 实例的权威归属)**:现象 —— `packages-user/client-modules/src/render/renderer.ts:18,20,35` 的 `rafExcitation` / `excitationDivider` / `mainRenderer` 与 `ClientCore` 构造器内自建的同名实例(`packages-user/client-modules/src/client.ts:90,91,108`)重复。为什么读不出来 —— 两套实例均在案,但用户未裁定以哪一套为权威、另一套是否废弃。需要用户裁决的点 —— 重复单例的权威归属(保留模块级 / 保留构造器内 / 合并)。**只登记,不判定。** +- **#04-15-F-04((c) `GameUI` / `UIController` 实例是否属「须挂主类」对象)**:现象 —— 各 `*UI`(如 `packages-user/client-modules/src/render/ui/load.tsx:161`、`packages-user/client-modules/src/render/ui/main.tsx:312`、`packages-user/client-base/src/components/choices.tsx:796`)均为模块顶层 `new GameUI(...)` / `new UIController(...)`。为什么读不出来 —— 用户裁定「单例须挂主类」,但未给出 `GameUI` / `UIController` 实例这一类是否属挂载对象(它们语义上是 UI 定义而非子系统)。需要用户裁决的点 —— 这类 UI 实例单例是否纳入挂载面。**只登记,不判定。** +- **#04-15-F-05((d) 目标接口取舍)**:现象 —— 用户裁定单例对应子系统接口取 `IClientBaseExtended`(`packages-user/client-base/src/types.ts:27`,`readonly state: IClientBase`,`IClientBase extends ICoreState` 见 `packages-user/client-base/src/types.ts:8`)**或** `ICoreStateExtended`(`packages-user/data-state/src/types.ts:45`,`readonly state: ICoreState`)。为什么读不出来 —— 两个接口都携带 `readonly state`,但指向不同的主对象层级(渲染端基本层 `IClientBase` vs 数据端 `ICoreState`);用户未给出「渲染端单例子系统应指向哪一个」的判据。需要用户裁决的点 —— 每个单例子系统接口取哪一个扩展接口。**只登记,不判定。** +- **#04-15-F-06((e) `IClientBaseExtended` 现行无实现类)**:现象 —— 规划日 `git grep -n ICoreStateExtended -- packages-user/client-base/src` 显示渲染 / 系统层先例 `packages-user/client-base/src/material/types.ts:94,218,406,439` 四处 `extends ICoreStateExtended`;而 `IClientBaseExtended` 仅在 `packages-user/client-base/src/types.ts:27` 定义、无实现类。为什么读不出来 —— 无实现先例使「取 `IClientBaseExtended`」缺少渲染端既成模式支撑,但这是否构成取舍判据须由用户裁定。需要用户裁决的点 —— `IClientBaseExtended` 无实现类是否影响目标接口取舍。**只登记,不判定。** +- **#04-15-F-07((f) 无消费者的 UI 单例)**:现象 —— `leftStatusBarUI`(`packages-user/client-modules/src/render/ui/statusBar.tsx:488`)/ `rightStatusBarUI`(`packages-user/client-modules/src/render/ui/statusBar.tsx:489`)与 `BackgroundUI`(`packages-user/client-base/src/components/misc.tsx:592`)在 `packages-user/client-modules/src` / `packages-user/client-base/src` / `src` / `packages` 内消费者零命中(见台账 A-24 / A-25 / A-30 证据行)。为什么读不出来 —— 无消费者的单例是否仍须纳入挂载面,用户未给出判据。需要用户裁决的点 —— 无消费者 UI 单例是否纳入挂载面 / 是否保留。**只登记,不判定。** ## 单例→目标映射汇总(供 04-16 消费) -> 只汇总本台账已登记条目;目标接口写候选或 undetermined,**不给出挂载写法 / import 改写 / 新命名**。 - | 定义 file:line | 符号 | 类型 | 目标(挂主类 + 目标接口,或 undetermined) | 先例 file:line | 归属包 | 置信 | |---|---|---|---|---|---|---| -| packages-user/client-modules/src/core.ts:6 | `client` | 主类实例本身 | 目标主类本身(挂载面) | packages-user/client-modules/src/client.ts:41 | client-modules | 高 | -| packages-user/client-base/src/elements/cache.ts:280 | `texture` | A 模块级实例化对象 | 挂 `ClientCore`;接口候选 `IClientBaseExtended` / `ICoreStateExtended`(undetermined,见 F-05) | packages-user/client-base/src/material/types.ts:94 / packages-user/data-state/src/ins.ts:11 | client-base | 中 | -| packages-user/client-modules/src/render/renderer.ts:18 | `rafExcitation` | A 模块级实例化对象 | undetermined(与 ClientCore 字段重复,见 F-02) | packages-user/client-modules/src/client.ts:48 | client-modules | 中 | -| packages-user/client-modules/src/render/renderer.ts:20 | `excitationDivider` | A 模块级实例化对象 | undetermined(与 ClientCore 字段重复,见 F-02) | packages-user/client-modules/src/client.ts:49 | client-modules | 中 | -| packages-user/client-modules/src/render/renderer.ts:35 | `mainRenderer` | A 模块级实例化对象 / 框架级全局 | undetermined(外部框架级全局 + 重复单例,见 F-01 / F-02) | packages-user/client-modules/src/client.ts:108 | client-modules | 中 | -| packages-user/client-modules/src/render/renderer.ts:43 | `using` | A 模块级实例化对象 / 框架级全局 | undetermined(外部框架级全局,见 F-01) | packages-user/client-base/src/components/misc.tsx:227 | client-modules | 中 | -| packages-user/client-modules/src/render/renderer.ts:45 | `createApp` / `render` / `tagManager` | A 模块级解构导出 / 框架级全局 | undetermined(外部框架级全局,见 F-01) | packages-user/client-base/src/elements/index.ts:16 | client-modules | 低 | -| packages-user/client-modules/src/render/scene.ts:3 | `sceneController` | A 模块级实例化对象 | undetermined(外部框架级全局,见 F-01) | packages-user/client-modules/src/render/index.tsx:25 | client-modules | 中 | -| packages-user/client-modules/src/render/ui/controller.tsx:11 | `mainUIController` | A 模块级实例化对象 | undetermined(见 F-01 / F-03) | packages-user/client-modules/src/render/action.ts:17 | client-modules | 中 | -| packages-user/client-modules/src/render/ui/controller.tsx:29 | `MainBackgroundUI` | A 模块级实例化对象 | undetermined(见 F-03) | packages-user/client-modules/src/render/ui/controller.tsx:19 | client-modules | 中 | -| packages-user/client-modules/src/render/ui/load.tsx:161 | `LoadSceneUI` | A 模块级实例化对象 | undetermined(见 F-03) | packages-user/client-modules/src/render/ui/load.tsx:35 | client-modules | 中 | -| packages-user/client-modules/src/render/ui/main.tsx:312 | `MainSceneUI` | A 模块级实例化对象 | undetermined(见 F-03) | packages-user/client-modules/src/render/ui/main.tsx:34 | client-modules | 中 | -| packages-user/client-modules/src/render/ui/save.tsx:462 | `SaveUI` | A 模块级实例化对象 | undetermined(见 F-03) | packages-user/client-modules/src/render/ui/save.tsx:165 | client-modules | 中 | -| packages-user/client-modules/src/render/ui/settings.tsx:663 | `MainSettingsUI` | A 模块级实例化对象 | undetermined(见 F-03) | packages-user/client-modules/src/render/ui/settings.tsx:53 | client-modules | 中 | -| packages-user/client-modules/src/render/ui/settings.tsx:665 | `ReplaySettingsUI` | A 模块级实例化对象 | undetermined(见 F-03) | packages-user/client-modules/src/render/ui/settings.tsx:146 | client-modules | 中 | -| packages-user/client-modules/src/render/ui/settings.tsx:667 | `GameInfoUI` | A 模块级实例化对象 | undetermined(见 F-03) | packages-user/client-modules/src/render/ui/settings.tsx:264 | client-modules | 中 | -| packages-user/client-modules/src/render/ui/settings.tsx:669 | `SyncSaveUI` | A 模块级实例化对象 | undetermined(见 F-03) | packages-user/client-modules/src/render/ui/settings.tsx:359 | client-modules | 中 | -| packages-user/client-modules/src/render/ui/settings.tsx:671 | `SyncSaveSelectUI` | A 模块级实例化对象 | undetermined(见 F-03) | packages-user/client-modules/src/render/ui/settings.tsx:419 | client-modules | 中 | -| packages-user/client-modules/src/render/ui/settings.tsx:673 | `DownloadSaveSelectUI` | A 模块级实例化对象 | undetermined(见 F-03) | packages-user/client-modules/src/render/ui/settings.tsx:476 | client-modules | 中 | -| packages-user/client-modules/src/render/ui/settings.tsx:678 | `ClearSaveSelectUI` | A 模块级实例化对象 | undetermined(见 F-03) | packages-user/client-modules/src/render/ui/settings.tsx:549 | client-modules | 中 | -| packages-user/client-modules/src/render/ui/statistics.tsx:302 | `StatisticsUI` | A 模块级实例化对象 | undetermined(见 F-03) | packages-user/client-modules/src/render/ui/statistics.tsx:49 | client-modules | 中 | -| packages-user/client-modules/src/render/ui/statusBar.tsx:488 | `leftStatusBarUI` | A 模块级实例化对象 | undetermined(见 F-03 / F-07) | packages-user/client-modules/src/render/ui/statusBar.tsx:106 | client-modules | 低 | -| packages-user/client-modules/src/render/ui/statusBar.tsx:489 | `rightStatusBarUI` | A 模块级实例化对象 | undetermined(见 F-03 / F-07) | packages-user/client-modules/src/render/ui/statusBar.tsx:460 | client-modules | 低 | -| packages-user/client-modules/src/render/ui/title.tsx:484 | `GameTitleUI` | A 模块级实例化对象 | undetermined(见 F-03) | packages-user/client-modules/src/render/ui/title.tsx:66 | client-modules | 中 | -| packages-user/client-modules/src/render/ui/viewmap.tsx:556 | `ViewMapUI` | A 模块级实例化对象 | undetermined(见 F-03) | packages-user/client-modules/src/render/ui/viewmap.tsx:53 | client-modules | 中 | -| packages-user/client-base/src/components/choices.tsx:796 | `ConfirmBoxUI` | A 模块级实例化对象 | 挂 `ClientCore`(候选);接口候选 `IClientBaseExtended`(undetermined,见 F-03 / F-05) | packages-user/client-base/src/components/choices.tsx:98 | client-base | 低 | -| packages-user/client-base/src/components/choices.tsx:798 | `ChoicesUI` | A 模块级实例化对象 | 挂 `ClientCore`(候选);接口候选 `IClientBaseExtended`(undetermined,见 F-03 / F-05) | packages-user/client-base/src/components/choices.tsx:319 | client-base | 低 | -| packages-user/client-base/src/components/input.tsx:602 | `InputBoxUI` | A 模块级实例化对象 | 挂 `ClientCore`(候选);接口候选 `IClientBaseExtended`(undetermined,见 F-03 / F-05) | packages-user/client-base/src/components/input.tsx:382 | client-base | 低 | -| packages-user/client-base/src/components/misc.tsx:591 | `WaitBoxUI` | A 模块级实例化对象 | 挂 `ClientCore`(候选);接口候选 `IClientBaseExtended`(undetermined,见 F-03 / F-05) | packages-user/client-base/src/components/misc.tsx:468 | client-base | 低 | -| packages-user/client-base/src/components/misc.tsx:592 | `BackgroundUI` | A 模块级实例化对象 | 挂 `ClientCore`(候选);接口候选 `IClientBaseExtended`(undetermined,见 F-03 / F-05) | packages-user/client-base/src/components/misc.tsx:391 | client-base | 低 | -| packages-user/client-modules/src/shared.ts:105 | `DEFAULT_FONT` | A 模块级实例化对象 | undetermined(字体常量,见 F-03) | packages-user/client-modules/src/render/index.tsx:35 | client-modules | 低 | -| packages-user/client-modules/src/render/use.ts:34 | `nowOrientation` | B 可变模块级状态 | 挂 `ClientCore`(候选);接口 undetermined(见 F-04) | packages-user/client-modules/src/render/use.ts:38 | client-modules | 中 | -| packages-user/client-modules/src/render/use.ts:35 | `orientationHooks` | B 可变模块级状态 | 挂 `ClientCore`(候选);接口 undetermined(见 F-04) | packages-user/client-modules/src/render/use.ts:47 | client-modules | 中 | -| packages-user/client-modules/src/render/use.ts:287 | `transitionMap` | B 可变模块级状态 | 挂 `ClientCore`(候选);接口 undetermined(见 F-04) | packages-user/client-modules/src/render/use.ts:298 | client-modules | 中 | -| packages-user/client-modules/src/action/hotkey.ts:5 | `mainScope` | B 全局符号注册表 | undetermined(见 F-01) | packages-user/client-modules/src/action/move.ts:31 | client-modules | 中 | -| packages-user/client-modules/src/render/weather/controller.ts:15 | `WeatherController.extern` | B 全局注册表 | undetermined(见 F-01 / F-06) | packages-user/client-modules/src/render/weather/controller.ts:125 | client-modules | 中 | -| packages-user/client-modules/src/render/weather/controller.ts:17 | `WeatherController.weathers` | B 全局注册表 | undetermined(见 F-01) | packages-user/client-modules/src/render/weather/controller.ts:134 | client-modules | 中 | -| packages-user/client-modules/src/render/use.ts:150 | `RenderColorTransition.key` | B 类静态可变状态 | undetermined(见 F-04) | packages-user/client-modules/src/render/use.ts:152 | client-modules | 低 | -| packages-user/client-base/src/components/textboxTyper.ts:567 | `breakSet` / `ignoreStart` / `ignoreEnd` | B 可变模块级状态 | undetermined(见 F-05) | packages-user/client-base/src/components/textboxTyper.ts:568 | client-base | 低 | -| packages-user/client-base/src/elements/cache.ts:491 | `Mota.require` | C 全局访问器(legacy) | undetermined(仅报告,见 F-01) | packages-user/client-base/src/elements/misc.ts:89 | client-base | 中 | -| packages-user/client-modules/src/render/use.ts:51 | `window.addEventListener` | C 框架级全局 / D 顶层副作用 | undetermined(见 F-04) | packages-user/client-modules/src/render/use.ts:37 | client-modules | 中 | -| packages-user/client-modules/src/action/hotkey.ts:9 | `gameKey` 顶层注册链 | D 顶层副作用 | undetermined(外部框架级全局,见 F-01) | packages-user/client-modules/src/action/hotkey.ts:470 | client-modules | 中 | +| `packages-user/client-base/src/elements/cache.ts:280` | `texture` | `TextureCache` 实例 | undetermined(候选:挂 `ClientCore` / `client` + `IClientBaseExtended` / `ICoreStateExtended`;见 `#04-15-F-01` / `#04-15-F-05`) | `packages-user/client-base/src/material/types.ts:94,218,406,439`;`packages-user/data-state/src/ins.ts:11` | `packages-user/client-base` | 低 | +| `packages-user/client-modules/src/core.ts:6` | `client` | `ClientCore` 实例 | 主挂载类本身(无需上挂) | `packages-user/client-modules/src/client.ts:41` | `packages-user/client-modules` | 中 | +| `packages-user/client-modules/src/render/renderer.ts:18` | `rafExcitation` | `RafExcitation` 实例 | undetermined(重复单例 `#04-15-F-03`;候选挂 `ClientCore` + `IClientBaseExtended` / `ICoreStateExtended`,见 `#04-15-F-05`) | `packages-user/client-base/src/material/types.ts:94,218,406,439`;`packages-user/data-state/src/ins.ts:11` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/renderer.ts:20` | `excitationDivider` | `ExcitationDivider` 实例 | undetermined(重复单例 `#04-15-F-03`;候选同上) | `packages-user/client-base/src/material/types.ts:94,218,406,439`;`packages-user/data-state/src/ins.ts:11` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/renderer.ts:35` | `mainRenderer` | `MotaRenderer` 实例 | undetermined(外部包 `@motajs/render`,见 `#04-15-F-02`;重复归属见 `#04-15-F-03`) | `packages-user/client-base/src/material/types.ts:94,218,406,439`;`packages-user/data-state/src/ins.ts:11` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/renderer.ts:43` | `using` | `RendererUsing` 实例 | undetermined(外部包 `@motajs/render-vue`,见 `#04-15-F-02`) | `packages-user/client-base/src/material/types.ts:94,218,406,439`;`packages-user/data-state/src/ins.ts:11` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/scene.ts:3` | `sceneController` | `UIController` 实例 | undetermined(外部包 `@motajs/system`,见 `#04-15-F-02` / `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439`;`packages-user/data-state/src/ins.ts:11` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/ui/controller.tsx:11` | `mainUIController` | `UIController` 实例 | undetermined(外部包 `@motajs/system`,见 `#04-15-F-02` / `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439`;`packages-user/data-state/src/ins.ts:11` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/ui/controller.tsx:29` | `MainBackgroundUI` | `GameUI` 实例 | undetermined(见 `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/ui/load.tsx:161` | `LoadSceneUI` | `GameUI` 实例 | undetermined(见 `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/ui/main.tsx:312` | `MainSceneUI` | `GameUI` 实例 | undetermined(见 `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/ui/save.tsx:462` | `SaveUI` | `GameUI` 实例 | undetermined(见 `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/ui/settings.tsx:663` | `MainSettingsUI` | `GameUI` 实例 | undetermined(见 `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/ui/settings.tsx:665` | `ReplaySettingsUI` | `GameUI` 实例 | undetermined(见 `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/ui/settings.tsx:667` | `GameInfoUI` | `GameUI` 实例 | undetermined(见 `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/ui/settings.tsx:669` | `SyncSaveUI` | `GameUI` 实例 | undetermined(见 `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/ui/settings.tsx:671` | `SyncSaveSelectUI` | `GameUI` 实例 | undetermined(见 `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/ui/settings.tsx:673` | `DownloadSaveSelectUI` | `GameUI` 实例 | undetermined(见 `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/ui/settings.tsx:678` | `ClearSaveSelectUI` | `GameUI` 实例 | undetermined(见 `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/ui/statistics.tsx:302` | `StatisticsUI` | `GameUI` 实例 | undetermined(见 `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/ui/statusBar.tsx:488` | `leftStatusBarUI` | `GameUI` 实例 | undetermined(无消费者,见 `#04-15-F-07`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/ui/statusBar.tsx:489` | `rightStatusBarUI` | `GameUI` 实例 | undetermined(无消费者,见 `#04-15-F-07`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/ui/title.tsx:484` | `GameTitleUI` | `GameUI` 实例 | undetermined(见 `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/render/ui/viewmap.tsx:556` | `ViewMapUI` | `GameUI` 实例 | undetermined(见 `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-modules` | 低 | +| `packages-user/client-modules/src/shared.ts:105` | `DEFAULT_FONT` | `Font` 实例 | undetermined(是否属挂载面未定) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-modules` | 低 | +| `packages-user/client-base/src/components/choices.tsx:796` | `ConfirmBoxUI` | `GameUI` 实例 | undetermined(见 `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-base` | 低 | +| `packages-user/client-base/src/components/choices.tsx:798` | `ChoicesUI` | `GameUI` 实例 | undetermined(见 `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-base` | 低 | +| `packages-user/client-base/src/components/input.tsx:602` | `InputBoxUI` | `GameUI` 实例 | undetermined(见 `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-base` | 低 | +| `packages-user/client-base/src/components/misc.tsx:591` | `WaitBoxUI` | `GameUI` 实例 | undetermined(见 `#04-15-F-04`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-base` | 低 | +| `packages-user/client-base/src/components/misc.tsx:592` | `BackgroundUI` | `GameUI` 实例 | undetermined(无消费者,见 `#04-15-F-07`) | `packages-user/client-base/src/material/types.ts:94,218,406,439` | `packages-user/client-base` | 低 | -**两个包内单例总数(当日实测):** 模块级实例化对象(A)共 30 个对象(A-01..A-31,含 `#04-15-A-32` 的一条 `[证据行]` 完整性反查不计入对象数):`client` 1 + client-base `texture` 1 + client-modules `renderer` 簇 6 + UI 控制器 3(`sceneController` / `mainUIController` / `MainBackgroundUI`)+ `GameUI` 实例 20(client-modules 15 + client-base 5)+ `DEFAULT_FONT` 1。可变模块级状态与全局注册表(B)8 项;全局访问器与框架级全局引用(C)6 项;顶层副作用模块(D)4 项。合计 **48 个单例点**。client / 系统层分列见 A/B/C/D 各行「当前归属 / 挂载」列:client-modules 侧为主(含 `client` 主单例、renderer 簇、UI 控制器与 GameUI、B/D 全部),client-base 侧为 `texture` + 5 个 components `GameUI` + 3 个模块级 `Set`(B-08)+ `Mota.require`(C-01)。 +- **单例总数(当日 `git grep` 实测,与规划日一致):** 客户端(`packages-user/client-modules`)**24** + 系统层(`packages-user/client-base`)**6** = **30**(与 A 表事实行 `#04-15-A-01`..`#04-15-A-30` 一一对应;`#04-15-A-31` 为完整性反查 `[证据行]`,非单例条目)。 ## 处置 -- 本文件是渲染端去单例化(用户 2026-10-01 裁定)**第一步(只读收集)**的交付物;本步未修改任何生产代码、未引入任何命名变更。 -- 相对 `## 只读起始基线` 零变化(用户既有 `packages-user/data-system/src/combat/context.ts` 改动未被触碰、未被暂存、未被提交)。 -- **第二步(04-16:挂载 + 接口继承重构)未规划**,待用户审阅本文件后另行规划;本文件不含挂载方案 / import 改写方案 / 新 `*-PLAN.md`;第二步如确需新增命名(挂载字段 / 接口名),须待用户批准,不在本步引入。 -- `REND-01` / `REND-02` 保持 **Pending**;`.planning/REQUIREMENTS.md` 零改动。 -- `core.*` / `Mota.require` / `window.*` 一律只报告,不修、不登记为待办(D-49 / D-55 / D-65);D-69 桶导出边界与 legacy 边界遵守。 +本文件是渲染端去单例化(用户 2026-10-01 裁定)第一步(只读收集单例)的交付物。本步未修改任何生产代码、未引入任何命名变更;相对 `## 只读起始基线` 零变化(用户既有 `packages-user/data-system/src/combat/context.ts` 改动未被触碰);第二步(04-16:挂载 + 接口继承重构)未规划,待用户审阅本文件后另行规划。本文件**仅登记单例**,不含可变模块级状态 / 全局访问器 / 顶层副作用等非单例,也不含挂载方案 / import 改写方案 / 新 `*-PLAN.md`。`REND-01` / `REND-02` 保持 Pending。两个包内单例合计 30(`packages-user/client-modules` 24 + `packages-user/client-base` 6,当日 `git grep` 实测),与 `## A` 表事实行 `#04-15-A-01`..`#04-15-A-30` 一一对应。