ADR-AIOS-04 · XiForge 架构决议
1. 上下文(Context)
1.1 触发事件
2026-05-25 用户在 ADR-AIOS-03 落地之后,提出 XiForge stage 系统化问题,经过三轮对话与 8 份并行 subagent 真值调研,发现 XiForge 存在 5 个相互关联的架构级问题需要一次性决议:
| 问题 | 用户原话 |
|---|---|
| Q1 控件库策略 | "MC 控件要全面 · 是否构建全部 vs 用户自定义上传(Vue 代码)" |
| Q2 codegen 方向 | "set/get 接口能否从 HMI 自动生成 · preset 结构是否能自动生成" |
| Q3 Module UID | "modulename + 32 位 ModuleID · xistudio 0~0xAAAA0000 · xivst 三方在后" |
| Q4 xml 退役 | "xml 是 C# 调音工具临时桥 · 现在直接 MC 中创建 legacy 界面 · 可以删除" |
| Q5 ModuleMode | "normal 和 legacy 其实就是带链路信息还是不带链路信息直接发 command 进行调音而已" |
1.2 8 份 subagent 真值调研发现的关键事实
第一轮(5 份 · 控件库/类型/命名陷阱):
- ✅ ModuleDef 已统一(XiForge ↔ XiTune 共用) · params.properties.widgets: XmlWidgetDef[]
- ✅ Preset 数据结构已就绪(presetStore 168 行)
- ❌ 全局 0 命中:codegen / customWidget / paramSchema / namespace / vendorPrefix / 0xAAAA
- ⚠️ XmlWidgetRenderer 是硬编码 v-if 链(非动态组件路由)· XmlWidgetType 22 种联合
- ⚠️ ThirdPartyModuleDialog 命名误导:不是导入对话框 · 是运行时模块控制面板(双击模块实例的浮动窗)
第二轮(2 份 · TT 控件 + UID 兼容性):
- ✅ TT 系列全部是 Vue SFC(src/components/TT*.vue · 10 个) · 编译型组件
- ⚠️ TT 与 Xml 是两套并行控件库(5 对功能重叠:Mixer/EQ/Tab/ComboBox/Button)
- ✅ ModuleDef.id 是裸 string · 实际两套混乱:geq_v1 snake_case / AdaptiveGain PascalCase
- ✅ 当前完全无 namespace / vendorId 字段 · UID 设计与现有契约无冲突*(只需新增字段)
第三轮(1 份 · xml 退役可行性):
- 🔥 关键发现:MC 与 xml-tuning 子系统实际耦合极弱(全文件仅 1 行 xmlStore.setAppMode('normal') 在 L2874)
- ⚠️ types 层耦合是真问题:types/module.ts L4 import { XmlWidgetDef } + L78 widgets?: XmlWidgetDef[] — 必须先迁移类型再删除
- ✅ legacy_set_param 后端协议(6+ 文件在用)与 xml 子系统无关 · 必须保留
1.3 用户的关键产品定义
normal 模块 = 带链路信息(参数走 set_params 协议 · 通过 link 路由) legacy 模块 = 不带链路信息(参数走 legacy_set_param + PID 直接寻址) legacy 模块不参与 codegen / simulation · 只为兼容旧调音内容
1.4 9 项决议拍板状态
| # | 决议 | 选择 | 状态 |
|---|---|---|---|
| 1 | Q1 控件库策略 | 方案 C 三层(L1/L2/L3) | ✅ 已确认 |
| 2 | Q2 codegen 方向 | 方向 X 单向驱动 | ✅ 已确认 |
| 3 | L1 控件清单 | 15 候选全部采纳 | ✅ 已确认 |
| 4 | 起 ADR-AIOS-04 | 是 | ✅ 已确认(本文) |
| 5 | code/simulation 范围 | 仅做 layout 增强 · code/simulation 推迟下季度 | ✅ 已确认 |
| 6 | Module UID 子决议 6a-6d | 6a 推荐 · 6b 高 16 位 vendor + 低 16 位模块号 · 6c 三阶段迁移 · 6d freeze 前必须 | ✅ 已确认 |
| 7 | L3 路径 A vs B | 推迟决议 · 等 L1+L2 落地 | ✅ 已确认推迟 |
| 8 | xml-tuning 整体退役 | 整体删除 · 不留兼容 | ✅ 已确认 |
| 9 | ModuleMode 简化 | 方案 B · 2 mode + source 独立 | ✅ 已确认 |
2. 决议(Decision)
2.1 主决议 · 5 个架构级方向
2.1.1 三层控件库架构(L1 编译 + L2 配置 + L3 上传)
L1 · 编译型原子控件(本季度做):
- 形态:Vue 3 SFC(<script setup lang="ts">),编译进 XiStudio 主程序
- 数量:从当前 TT 10 + Xml 5 = 15 个去重后 → 目标 30 个(下季度后补齐)
- 数据下发:控件 emit → WidgetRenderer → store → wsClient.send → 后端 cmd
- 跟随 XiStudio 版本号
L2 · 配置型复合控件(下下季度):
- 形态:JSON 描述 · 多个 L1 + 布局 + 联动
- 不写 Vue 代码 · 不需要沙箱
- 用户在 XiForge 自己"画"复合控件 → 保存为 widget-template.json → 跨模块复用
L3 · 用户扩展控件(明年视生态决定):
- 路径 A(静态合并):用户上传 .vue 源码 → 公司编译发版
- 路径 B(动态加载):预编译 ES module + defineAsyncComponent
- 本 ADR 不做 L3 选择(决议 7 推迟)
2.1.2 Module UID 32 位命名空间
数据结构变更(types/module.ts):
export interface ModuleDef {
// 现有字段保留
id: string // vendor 内的 snake_case 人类可读 id
displayName: string
// ... 其他字段不变
// ⭐ ADR-AIOS-04 新增 4 字段
uid: number // ✅ 必填 · 32-bit unsigned int · 全局唯一
vendor: VendorTag // ✅ 必填 · 枚举
vendorVersion?: string // 可选 · semver
vendorAuthor?: string // 可选 · 显示名
}
export type VendorTag =
| 'xistudio' // 0x00000000 - 0xAAAA_0000
| 'xivst' // 0xAAAA_0001 - 0xFFFF_FFFE
| 'reserved' // 0xFFFF_FFFF
UID 段位规划(高 16 位 = vendor · 低 16 位 = 模块号):
0x0000_0000 ~ 0x0000_FFFF (65536 个) → XiStudio 内置基础库
子段细分:
0x0000_0000~0x00FF: source_*
0x0000_0100~0x01FF: sink_*
0x0000_0200~0x02FF: filter_*
0x0000_0300~0x03FF: dynamic_*
0x0000_0400~0x04FF: spatial_*
0x0000_0500~0x05FF: utility_*
0x0000_0600~0xFFFF: 保留扩展
0x0001_0000 ~ 0xAAA9_FFFF (≈ 28.6 亿) → XiStudio 内部分组扩展
0xAAAA_0000 ~ 0xFFFE_FFFF → XiVST 三方厂商(每家 65536 个 · 共 21845 家)
0xFFFF_0000 ~ 0xFFFF_FFFE → 临时/测试段
0xFFFF_FFFF → 系统保留
全局唯一标识格式:vendor:id@uid(如 xistudio:gain@0x00000200)
3 阶段迁移: - Phase 0(立即):uid 可选 · 默认 vendor='xistudio' · 脚本批量分配 - Phase 1(contract-v1 freeze 时):uid + vendor 必填 · 后端 cmd 改用 module_uid - Phase 2(下半年):提供 vendor 注册机制 · ThirdPartyModuleDialog 真正用于"导入第三方模块"
2.1.3 codegen 单向驱动 + legacy 边界
方向 X(HMI 单向驱动):HMI 是 SSOT · 自动生成 .h(set_xxx/get_xxx) + Preset Schema
legacy 边界(强约束 · 写入 PROMPT):
// legacy 模块跳过 codegen + simulation
function shouldGenerateCode(def: ModuleDef): boolean {
return def.mode === 'normal'
}
// XiForge 3 mode chip 可见性
{
layout: true, // 所有模块
code: def.mode === 'normal', // 仅 normal
simulation: def.mode === 'normal' // 仅 normal
}
Preset 自动派生:Preset Schema 从 ModuleDef.params 自动派生(用户不写 schema) · Preset 实例值用户在 XiTune 调出后保存
注意:本 ADR 决议方向 + 边界 · 但实际 codegen 实施推迟到下季度(决议 5)
2.1.4 xml-tuning 子系统整体退役
退役清单(整体删除 · 无兼容期):
| 文件/目录 | 行数 | 退役理由 |
|---|---|---|
src/stages/xitune/xml-tuning/ 整目录 |
2586 | C# XML 临时桥 |
src/stores/useXmlTuningStore.ts |
- | xml session 状态 |
src/utils/xmlConfigParser.ts |
- | XML 解析器 |
src/types/xmlTuning.ts |
7047 字节 | 类型迁移后删除 |
public/xml-configs/ 数据目录 |
N | legacy 模块改在 MC 重建 |
类型迁移(P-1 阶段先做 · 否则 ModuleDef 类型崩塌):
- 新建 src/types/widget.ts
- XmlWidgetDef → WidgetDef(去 Xml 前缀)
- XmlWidgetType → WidgetType
- types/module.ts L4/L78 改 import 路径
渲染器去 Xml 前缀:
- XmlWidgetGroupLayout → WidgetGroupLayout(放 src/widgets/)
- XmlWidgetRenderer → WidgetRenderer(改造为 widget 注册表 + 动态组件路由)
修改外部引用(9 处):
- MenuBar.vue · xilink/ModuleLibraryPanel.vue · xilink/index.vue · ModuleCreator.vue (3 行) · ThirdPartyModuleDialog.vue · xitune/PresetPanel.vue · useModuleDefStore.ts 注释
必须保留:
- legacy_set_param 后端协议消息(与 xml 子系统无关)
- mode='legacy' 概念(用户产品定义)
- ThirdPartyModuleDialog 的 PID 寻址路径
2.1.5 ModuleMode 4→2 简化(方案 B)
当前 4 mode 矩阵 → v1.2 简化:
// 旧(types/module.ts)
export type ModuleMode = 'builtin_normal' | 'builtin_legacy' | 'dsp_normal' | 'dsp_legacy'
// 新
export type ModuleMode =
| 'normal' // 带链路信息 · set_params 协议
| 'legacy' // 不带链路信息 · legacy_set_param + PID
export type ModuleSource =
| 'builtin' // XiStudio 内置(取代旧 'library')
| 'backend' // 后端推送 JSON(取代旧 'backend_json')
| 'thirdparty' // 三方插件(L3 用)
删除字段:def.kind: 'legacy' | 'native'(ThirdPartyModuleDialog 改用 ModuleDef.mode)
数据迁移脚本(P0 阶段必做):
function migrateMode(oldMode: string): { mode: ModuleMode, source: ModuleSource } {
switch (oldMode) {
case 'builtin_normal': return { mode: 'normal', source: 'builtin' }
case 'builtin_legacy': return { mode: 'legacy', source: 'builtin' }
case 'dsp_normal': return { mode: 'normal', source: 'builtin' }
case 'dsp_legacy': return { mode: 'legacy', source: 'builtin' }
}
}
理由:用户原话 "目前看不区分 dsp 还是 builtin,没有这个需求了"。如未来扩展,再加 source 子类型。
2.2 本季度实施范围(决议 5 限定)
仅做 P-1 + P0 共 4 项任务(layout 增强方向):
| 优先级 | 任务 | 工作量 |
|---|---|---|
| P-1 | xml-tuning 退役 + 类型迁移 + 渲染器去 Xml 前缀 + ThirdPartyModuleDialog 简化 | 2.5d |
| P0 | widget 注册表 + L1 控件评审(15 现状 + 15 候选补齐) | 1d |
| P0 | ModuleMode 简化迁移(4→2 + source 独立 + 数据迁移脚本) | 1d |
| P0 | Module UID 命名空间落地(types + 协议 + 迁移脚本) | 2d |
| 总 | 本季度 P-1 + P0 范围 | 6.5d |
推迟到下季度: - P1 codegen C 头文件模板(2d) - P1 Preset Schema 自动派生(1d) - P2 code mode UI(Monaco editor)(1.5d) - P2 XiForgeSimView 简化版仿真(3d)
2.3 4 agent 边界铁律(继承 ADR-AIOS-03)
| 资源 | 写权限 | 备注 |
|---|---|---|
src/stages/xiforge/ |
ClaudeB-XiForge 独占 | 本 ADR 主战场 |
src/widgets/(新建) |
ClaudeB-XiForge 独占 | 替代 xml-tuning/widgets/ |
src/types/widget.ts(新建) |
ClaudeB-XiForge 独占 | 替代 xmlTuning.ts |
src/types/module.ts |
ClaudeB-XiForge 独占改 mode/uid 字段 | 与 ClaudeC 协调 |
src/stages/xitune/xml-tuning/ |
全部删除(ClaudeC 配合 review) | xml 退役 |
src/stores/useXmlTuningStore.ts |
删除 | xml 退役 |
src/utils/xmlConfigParser.ts |
删除 | xml 退役 |
| 9 处外部引用文件 | 各自 stage agent 配合 | MenuBar/xilink/xitune 等 |
2.4 派发顺序
Day N(本周内):
└── ClaudeB-XiForge:P-1 xml 退役 + 类型迁移 → 2.5d
[依赖]:无 · 可立即派发
Day N+3:
└── ClaudeB-XiForge:P0 widget 注册表(0.5d)+ L1 评审(0.5d) → 1d
[依赖]:P-1 完成
Day N+4:
├── ClaudeB-XiForge:P0 ModuleMode 简化 → 1d
└── ClaudeB-XiForge:P0 Module UID 落地 → 2d
[依赖]:P-1 类型层完成 · 后端 ClaudeB 协议层同步
Day N+7:
└── 本季度任务收尾 · 进入 contract-v1 freeze 准备
3. 备选方案(Alternatives Considered)
3.1 方案 A · 控件库全内置(穷举 50 个 Vue SFC)
否决。 - 控件数量爆炸,每次新需求都要发版 - 无配置复用机制 · L2 ROI 错过 - 与 demo "code mode + simulation mode" 愿景不匹配
3.2 方案 B · 控件库全插件(用户 Vue 上传)
否决(L3 路径 B)。 - 当前客户群小 · 不需要开放生态 - SDK + 沙箱 + 类型契约工程量大(15d+) - 优先级排不上本季度
3.3 方案 C · 三层混合(L1+L2+L3)+ 分期(本 ADR)✅
采纳。 - L1 立即可做(基于 TT* 整合) - L2 中期(下下季度) - L3 推迟(明年视生态)
3.4 ModuleMode 方案 A(完全二维矩阵)
否决。 - 改动大 · 用户原话表明 dsp/builtin 当前无业务区分 - 留大量 dead code
3.5 ModuleMode 方案 C(仅删 def.kind 保留 4 mode)
否决。 - 没解决根本问题(用户希望简化为 2 mode) - 留下技术债
3.6 xml-tuning 渐进迁移(保留兼容期)
否决。 - 用户原话:"由于完全是建立一个新的架构,如果彻底不需要,我们就要彻底删除干净" - 兼容期会拖累代码 + 增加维护成本
4. 后果(Consequences)
4.1 正面后果
- 控件体系统一:从 TT/Xml 两套并行 → 单一 widget 体系 · 接口契约清晰
- 代码减负:删除 ≈ 2586+ 行 xml-tuning 子系统 · 核心代码精简
- 命名空间防重名:Module UID 32 位 + vendor + 段位规划 · 支持 21845 家三方
- 协议简化:后端 cmd 改用
u32 module_uid比 string 更紧凑(网络/嵌入式) - 概念简化:ModuleMode 4→2 · 用户产品直觉对齐(normal=带链路 / legacy=不带链路)
- codegen 边界清晰:legacy 不参与 codegen / simulation · 避免无效复杂度
- 本季度可落地:P-1+P0 共 6.5d · 一个 agent 5-7 天完成
4.2 负面后果
- 重构成本:9 处外部引用文件需要修改 · 容易遗漏(需 review 兜底)
- legacy 模块迁移负担:用户接受 "legacy 模块改在 MC 中重建",但实际工作量取决于
public/xml-configs/真实模块数量(待 P-1 实施时核实) - contract 二次重构风险:Module UID + ModuleMode 改造涉及前后端协议同步 · 必须在 contract-v1 freeze 前完成(否则要二次重构)
- codegen 推迟到下季度:产品愿景(demo 3 mode)的 code/simulation 部分推迟 · 客户能见度延后
4.3 风险缓解
| 风险 | 触发条件 | 预案 |
|---|---|---|
| xml 类型迁移漏掉某个 import | 9 处外部引用未遍历完 | P-1 完成后用 grep XmlWidgetDef\|XmlWidgetType\|xml-tuning 全局兜底 · 确认 0 命中 |
| 真实 legacy 模块数量大 → 重建成本高 | public/xml-configs/ 模块 > 10 |
暂保留 xml-configs 目录 1 周缓冲 · 用户在 MC 中逐个重建后再删 |
| Module UID 段位规划与后端不对齐 | 后端 ClaudeB 提出不同方案 | 本 ADR 拍板 · 后端按本 ADR 实施 · 异议另起 ADR-AIOS-05 |
| contract-v1 freeze 前未完成 UID 落地 | Day 5 EOD 接近 · 任务延期 | AIOS 在 freeze 前 2 天 standup 中升级 → 协调 ClaudeB-FE/BE 双 agent 并行 |
| ModuleMode 迁移脚本错误 → 现有模块加载失败 | builtin_normal 误转为 legacy | 写单元测试 · 4 种旧 mode 全部覆盖 · CI 通过才合并 |
4.4 不影响
- ADR-AIOS-03 的 4 agent 按 stage 分工框架不变 · 本 ADR 只细化 ClaudeB-XiForge 任务范围
legacy_set_param后端协议保留 · XiTune 调音运行时不动mode='legacy'模块的运行时数据流不变(仍走 PID 路径)
5. 命名规范(Naming Convention)
5.1 ModuleDef 字段命名
id(string · vendor 内唯一 · snake_case ·[a-z0-9_]· ≤ 64 字符):人类可读 iddisplayName(string · 任意字符):用户可见 · 允许 vendor 间重复uid(number · u32 · 全局唯一):由 vendor 注册机制分配vendor(VendorTag 枚举):'xistudio' | 'xivst' | 'reserved'mode(ModuleMode 枚举):'normal' | 'legacy'source(ModuleSource 枚举):'builtin' | 'backend' | 'thirdparty'
5.2 Widget 命名
- 类型(WidgetType):去 Xml 前缀 · 全小写 · 如
'slider'/'toggle'/'mixer' - 组件文件:
src/widgets/<TypeName>Widget.vue(如SliderWidget.vue) - 注册:
registerWidget('slider', SliderWidget)在src/widgets/registry.ts
5.3 全局唯一标识显示格式
vendor:id@uid(如 xistudio:gain@0x00000200)
6. 待决议项(本 ADR 已 accepted · 仅留实施期可能浮现的子问题)
- ☐
public/xml-configs/实际 legacy 模块数量 > 10 时是否需要单独迁移 sprint?(P-1 实施时核实) - ☐ 后端 ClaudeB 是否需要为 Module UID 落地新增 contract 章节(
module_uid: u32字段)?(由后端 ClaudeB 在 contract-v1 v0.6 中确认) - ☐ ModuleMode 迁移脚本是否覆盖到
xml-configs/index.json中的 PascalCase 命名?(P-1 实施时核实) - ☐ Phase 2 三方接入期(下半年)的 vendor 注册机制是否需要单独 ADR?(预留 ADR-AIOS-08 占位)
7. 实施清单
7.1 本季度(P-1 + P0)
- 起草
PROMPT-claudeb-xml-tuning-decommission.md(P-1 · 2.5d · xml 退役 + 类型迁移) - 起草
PROMPT-claudeb-widget-registry.md(P0 · 1d · 注册表 + L1 评审) - 起草
PROMPT-claudeb-module-mode-simplify.md(P0 · 1d · 4→2 mode 迁移) - 起草
PROMPT-claudeb-module-uid-namespace.md(P0 · 2d · UID 32 位) - 更新 KANBAN.md v5 · 在 ClaudeB-XiForge 任务表加 P-1/P0 共 4 项
- 派发 P-1 任务给 ClaudeB-XiForge
- P-1 完成后 review · 全局 grep 兜底
- 派发 P0 三项(注册表 / mode 简化 / UID)· 可并行
- 本季度任务全部完成后 · 提案 status: draft → decided
7.2 下季度(P1 推迟项)
- 起草
PROMPT-claudeb-codegen-c-header.md(P1 · 2d · normal-only codegen) - 起草
PROMPT-claudeb-preset-auto-schema.md(P1 · 1d · Preset schema 派生) - 视客户反馈决定是否启动 code mode UI(Monaco)+ simulation 实施
7.3 后续季度(P2/P3/P4)
- L2 复合控件机制(8d · 视客户反馈)
- L3 路径 A vs B 决议(等 L1+L2 落地后)
- vendor 注册机制 + 第三方接入(下半年 · 视生态规模)
8. 关联文档
- 上游决议:
- ADR-AIOS-01(5 角色协作框架)
- ADR-AIOS-03(4 agent 按 stage 分工)
- 触发提案:
XiForge-Architecture-Proposal.md(v1.2 · status: decided) - 实施 PROMPT(本季度 · 待落盘):
PROMPT-claudeb-xml-tuning-decommission.mdPROMPT-claudeb-widget-registry.mdPROMPT-claudeb-module-mode-simplify.mdPROMPT-claudeb-module-uid-namespace.md- 相关代码真值调研:8 份 subagent 报告(2026-05-25 · commit
8e7071b)
ADR-AIOS-04 v1.0 · 2026-05-25 · accepted · 9 项决议拍板完成 · 等待 4 份 PROMPT 落盘后派发