docs(04-15): 渲染端去单例化只读清点(第一步)

This commit is contained in:
unanmed 2026-10-01 15:29:52 +08:00
parent 2d3287804d
commit 015a1993e8
2 changed files with 413 additions and 0 deletions

View File

@ -0,0 +1,212 @@
---
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]
requires:
- phase: 04-render-adaptation
provides: 用户 2026-10-01 去单例化裁定(渲染端不得再有单例、全部挂主类 `ClientCore` / `client`、子系统继承 / 实现 `IClientBaseExtended` / `ICoreStateExtended`、镜像数据端模式、两步走)
- phase: 04-render-adaptation
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 标注)
affects: [04-render-adaptation]
actuals:
tokens: 15145
tasks: 5
commits: 1
plan_head_before: 2d3287804d90bf3cde1d6299ac71815fd677a7eb
tech-stack:
added: []
patterns:
- "只读单例清点台账:元信息块 + 只读起始基线 + 12 小节 + A–F 六类固定列序表 + 单例→目标映射汇总 + 处置"
- "证据纪律:事实行每行 ≥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
- .planning/phases/04-render-adaptation/04-15-SUMMARY.md
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 兼容)"
requirements-completed: []
duration: ~40min
completed: 2026-10-01
status: complete
---
# 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。**
## Performance
- **Duration:** ~40min
- **Started:** 2026-10-01
- **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**
## 只读起始基线(Task 1 步骤 0a)
- **只读起始基线(packages / packages-user / src):**
- ` M packages-user/data-system/src/combat/context.ts`
- **起始 HEAD:** `2d3287804d90bf3cde1d6299ac71815fd677a7eb`(short `2d32878`)
- **起始分支:** `refine/data-client`
- **用户并发改动:** `packages-user/data-system/src/combat/context.ts` 的既有未提交改动仍在(porcelain ` M`,内容哈希 `9982509d3d8ec4c58d5c71f37f1a576a13c3337f`);本 run 未回滚 / 暂存 / 提交 / 修改(D-56 精神)。
- **机读标记:** 台账含 `<!-- baseline-hash-combat-context: 9982509d3d8ec4c58d5c71f37f1a576a13c3337f -->`,Task 1/2/3/4 生产树门禁均正向确认该哈希一致。
## Accomplishments
**唯一交付物:** `.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 | — |
**A–E 分类行:** A 32 / B 9 / C 7 / D 5 / E 7 = **60** 条表行(门禁实测一致);F **7** 条。**两个包内单例对象合计 48 个单例点**(A 30 + B 8 + C 6 + D 4)。
## 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 检查(门禁全绿,无独立提交)
5. **Task 4** — 收口门禁 + 人工复核 + 本 SUMMARY + 白名单提交
**Plan metadata:** 单一白名单提交(见「提交记录」)。Task 1/2/3 的 action 未定义独立提交步骤;Task 4 步骤 (10) 明示单次白名单提交(与 04-10 / 04-13 的单一提交口径一致)。
## 提交记录
- `docs(04-15): 渲染端去单例化只读清点(第一步)` —— 单次白名单提交,仅含 `04-RENDER-SINGLETON-AUDIT.md` + 本 `04-15-SUMMARY.md`(未暂存用户 `combat/context.ts` 或任何其它文件;提交 hash 见 orchestrator 回报 / `git log`)。
## A–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 未能从阅读确定(未猜测)` 一节 |
## 门禁实测结果(全部静态 — D-68 的延续)
门禁按计划 `## Verification Runnability` 的指示,将每条 `<automated>` 的原样语义落到仓库外 `C:\Users\book\AppData\Local\Temp\opencode\04-15-gates-pre.cjs` 执行 `node <file>`(PowerShell 5.1 引号 / `$` / CJK 兼容;判据与 `<fails_when>` 一字不变)。
| # | 门禁 | 结果(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` |
| 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) |
**门禁时刻 porcelain(`packages packages-user src`):** 仅用户既有 ` M packages-user/data-system/src/combat/context.ts` 一条(本计划只读,生产树零改动);该用户改动全程未触碰。
## 人工复核结论(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 判定与事实一致。
## Decisions Made
- **只读收集小切片(用户 2026-10-01 去单例化第一步)**:唯一交付物为台账 + 本 SUMMARY;生产源码改动 0,`files_modified` 仅台账。
- **单一白名单提交**: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` 登记由编排器在计划阶段完成)。
## Deviations from Plan
None - plan executed exactly as written(无 Rule 1–4 偏差)。
说明:Task 1/2/3/4 每条 `<automated>` 均按计划 `## Verification Runnability` 的指示,将原样语义落到仓库外临时 `.cjs` 后 `node <file>` 执行(判据与 `<fails_when>` 一字不变);这是计划明示的既定做法(先例 04-12 / 04-14),**不构成偏差**。
## 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 交用户裁决 |
> 依 orchestrator 指示与计划 Task 4 步骤 (11),未写入 `.planning/WINDOWS.md` / `STATE.md` / `ROADMAP.md`(本步仅允许写台账与 SUMMARY)。
## Issues Encountered
- 无。全部门禁一次通过;无 Rule 1–4 偏差。
## 无运行时验证声明(D-68 的延续)
- 本步**没有「保证能运行」的要求**:**未运行** `pnpm check:type` / `pnpm build`,**未使用** TS 诊断数(全仓或范围内)作为任何门禁或验收项。
- 证明方式全部为**静态**:`git status --porcelain` 正向基线(含用户 `combat/context.ts` 行在场 + 无其它条目 + `git hash-object` 与台账标记一致)/ 台账结构与全量关键锚点 / 分类关键词 / 禁用路径 porcelain / 既有产物保护 / ROADMAP 登记 / CRLF,辅以人工代码复核。
## User Setup Required
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` 并发改动保留且未被提交。
- `REND-01` / `REND-02` 仍为 **Pending**;`.planning/REQUIREMENTS.md` 零改动。
---
*Phase: 04-render-adaptation*
*Completed: 2026-10-01*
## 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-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`)
- `04-01`..`04-14` 既有产物: 零触碰;无 `04-16+`
- commits measured from ledger (`2d32878..HEAD`): 1(白名单提交)

View File

@ -0,0 +1,201 @@
# 渲染端去单例化·只读清点(第一步)
**日期:** 2026-10-01
**范围:** 被查 = `packages-user/client-modules/src/**` + `packages-user/client-base/src/**` 内全部单例及其消费者;只读基准 = `packages-user/data-*`;`packages/` 与 `src/` 仅报告(D-33)
**性质:** 只读清点(去单例化第一步),未修改任何生产代码,未引入任何命名变更
**基准:** HEAD `2d3287804d90bf3cde1d6299ac71815fd677a7eb`(short `2d32878`),分支 `refine/data-client`
**目标模式:** 挂主类 `ClientCore` / `client` + 子系统继承 / 实现 `IClientBaseExtended` 或 `ICoreStateExtended`,镜像数据端模式
**下一步:** 第二步 04-16 未规划,待用户审阅本文件后另行规划
## 只读起始基线
- **只读起始基线(packages / packages-user / src)**:
- ` M packages-user/data-system/src/combat/context.ts`
- **起始 HEAD:** `2d3287804d90bf3cde1d6299ac71815fd677a7eb`
- **起始分支:** `refine/data-client`
- **用户未提交改动断言:** ` M packages-user/data-system/src/combat/context.ts` 行在场(用户 WIP,本 run 全程零触碰)。
- **机读标记:** <!-- baseline-hash-combat-context: 9982509d3d8ec4c58d5c71f37f1a576a13c3337f -->
- 说明:上述 porcelain 于 Task 1 步骤 (0a) 当日实测原样记录;`git hash-object -- packages-user/data-system/src/combat/context.ts` 当日实测为 `9982509d3d8ec4c58d5c71f37f1a576a13c3337f`(40 位,记入机读标记行)。
## 背景
- **用户裁定(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(桶导出边界)。
## 方法
- **枚举面:** `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 诊断数作为门禁或验收项。
## 枚举口径
| 类别 | 定义 | 当日实测代表 |
|---|---|---|
| 模块级实例化对象 | 模块顶层 `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` |
## 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<number>()`) | 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<OrientationHook>`(可变模块级状态容器,非导出) | 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<ComponentInternalInstance, ITransition>`(可变模块级状态容器,非导出) | 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<string, IWeatherController>`(全局注册表) | 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<string, WeatherConstructor>`(全局注册表) | 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` 面当前无顶层监听 / 定时器副作用 | — | 高 |
## 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) | 低 |
## 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-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 | 中 |
**两个包内单例总数(当日实测):** 模块级实例化对象(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)。
## 处置
- 本文件是渲染端去单例化(用户 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 边界遵守。