背景
mcpp 的机器可读输出目前是分散演化的:xpkg parse --json、cache list --json 各自决定输出结构,pack --format 是产物形态不是输出格式,self env 只有人类文本,#372 又引入了第三套(ide snapshot --format json / ide configure --format ndjson + 独立的 envelope 和 ID 体系)。
同时已经有两个真实客户端在等接口:
本 RFC 提议先把契约层 统一下来,再谈新增命令。
一、现状盘点(均为实测/源码核对)
1.1 输出格式选项已经分裂,且 --format 有语义冲突
命令
选项
语义
状态
mcpp pack --format tar|dir
--format
产物形态
已发布
mcpp xpkg parse --json
--json
输出格式
已发布,mcpp-community/mcpp-vscode#8 在用
mcpp cache list --json
--json
输出格式
已发布
mcpp ide snapshot --format json
--format
输出格式
仅在 #372
mcpp ide configure --format ndjson
--format
输出格式
仅在 #372
已发布的 mcpp 里,"输出格式"的事实拼写是 --json;--format 被 pack 占用为另一个语义。
1.2 未知格式的响应,#372 内部就不一致
同一个 PR、同一天写的两个命令:
输出通道
输出格式
退出码
ide snapshot --format yaml
stdout
JSON 文档 + MCPP_IDE_UNSUPPORTED_FORMAT 诊断
3
ide configure --format json
stderr
人类文本
2
三个维度全不同。在把 --format 推广到更多命令之前,必须先定死这一条,否则是把已知缺陷标准化。
1.3 客户端拿不到的东西,mcpp 其实已经在算
mcpp self env 已经打印 MCPP_HOME / xlings home / index repos / default toolchain,但没有 --format json。结果 mcpp-community/mcpp-vscode#8 §2.4 被迫自己重实现整条定位逻辑:
mcpp home 定位按 src/home.cppm 的顺序:$MCPP_HOME > 二进制自包含布局 > ~/.mcpp……判定:二进制位于 <dir>/bin/mcpp,且祖先路径 不含 target/ 或 data/xpkgs/……扩展侧补充一条检查:PATH 上的 mcpp 可能是 xlings shim (符号链接追到调度器而非真实二进制),因此自包含分支额外要求 <dir>/registry 实际存在
这段逻辑 100% 依赖 mcpp 内部实现、跨平台、易碎,而且是 mcpp-community/mcpp-vscode#8 全篇里唯一没有契约测试兜底的部分。给 self env 加 JSON 输出约 15 行,可以直接删掉它。
1.4 xpkg parse --json 确实没有 schema 版本字段
实测确认,mcpp-community/mcpp-vscode#8 §7.1 的请求成立且未被满足。成本是一个字段。
1.5 我们自己就是"汇合式协议"的消费者,而且绕开了它
xlings interface 是完整的汇合式设计:interface <capability> --args '<JSON>' + --list(20 个 capability,含 destructive 标记和 inputSchema)+ --version。
而 mcpp 对它的实际用法(src/xlings.cppm:1064-1076,main 分支):
// All platforms: try direct `xlings install ... -y` first.
// The direct command is more reliable for large packages (e.g. LLVM ~800MB) because:
// - it doesn't pipe through NDJSON interface (simpler subprocess chain)
// - xlings manages its own stdin/stdout/stderr
// - extraction subprocess coordination works normally
// The NDJSON interface path is kept as a fallback for progress reporting.
主路径走裸 xlings install -y,把输出全部重定向到 null,然后 mcpp 自己在 stderr 画一个只有秒数的 spinner 。也就是说:我们宁愿丢掉 xlings 的全部结构化进度事件,也不走那条 NDJSON 管道。
事件流的唯一独占价值就是进度事件,它在真实压力下不可靠 → 消费者放弃它。这是"汇合传输层"最直接的反证。
另一个观察:xlings interface --list 里 20 个 capability 的 outputSchema 全部是 {"properties":{"exitCode":{"type":"integer"}}}。声明了 schema 但没填 —— 这比不声明更危险,因为客户端会以为有契约。(我们踩过:#238 的 multi-repo 失败模式发出 {"exitCode":1} 且没有 error 事件,所以 InstallProgressHandler 才要用 capturedDiagnostics_ 手工兜住 error/warn 文本。)
1.6 CDB 的 bootstrap 问题比想象中小
实测(mcpp 2026.8.6.3):
src/main.cpp: int main( { return missing_symbol; }
$ mcpp build → rc=1, "3 errors generated"
$ ls compile_commands.json → 1624 bytes,entry 完整
-std=c++23 -fprebuilt-module-path=... --no-default-config -nostdinc++ -isystem .../c++/v1
源码上的原因:src/build/ninja_backend.cppm:1546,write_compile_commands() 在 spawn ninja 之前 执行。真正的门槛不是"编译成功",而是 prepare_build() 成功。
因此 IDE 侧真正缺的不是"能在编不过时拿到 CDB"(已经有了),而是:
不为拿 CDB 付一次完整编译 + 链接 (这才是核心)
CDB 覆盖 tests/** 及其 dev-dependency 上下文
退出码能区分"CDB 没写"和"CDB 写了但编译失败"
哪些输入变化会让这份 CDB 失效 —— 目前只有文档散文,没有机器可读输出
二、判据
沿用三档划分:
只有 mcpp 能做、且适合 mcpp 做的 → mcpp 做
mcpp 可以很简单实现、且可复用的 → 可以 mcpp 做
外部插件实现与 mcpp 实现复杂度相当的 → mcpp 不做
第 3 档要注意一个反直觉的事实:有些能力 mcpp 做反而更贵 ,因为 mcpp 是多进程、公开契约、要向后兼容的,必须额外承担只读性保证、路径 containment、选择器语义、诊断降级 —— 而插件在自己进程里读文件,这些负担都不存在。
三、提案
阶段 0 — 先定死"未知 format 怎么办"(前置条件)
客户端在拿到输出之前 无法知道 mcpp 支不支持它请求的格式,所以拒绝也必须用客户端能解析的形式说出来。
统一契约:
- 走 stdout(不是 stderr)
- 输出标准 envelope + diagnostics[0].code = MCPP_UNSUPPORTED_FORMAT
- 退出码 2(用法错误,符合 CLI 惯例)
- 不执行任何有副作用的工作
这一条不定,后面所有 --format 推广都是在复制缺陷。
阶段 1 — 通用输出信封(新模块 mcpp.wire)
destructive 字段的价值 :mcpp-community/mcpp-vscode#8 §7.2 花了一整段请求"请确认 xpkg parse --json 无写副作用并可作为契约依赖",本机实测过还要请上游固定。有了这个字段,请求当场变成机器可判定的契约。它同时替代 #372 文档里那段"configure 不是 read-only,IDE 必须先拿 workspace trust"的散文 —— VSCode 的 untrusted workspace 门可以直接读字段决定跑不跑。
代码来源 :Diagnostic/Position/Range/Severity 模型和 envelope 构造 + 内容寻址 ID 在 #372 里已经写好且质量很高(src/ide/model.cppm、src/ide/snapshot.cppm,约 150 行)。提议把它们从 mcpp.ide.* 提升为 mcpp.wire,服务所有命令而不只是 IDE。
新增协商入口 (唯一"汇合"的地方):
mcpp --protocol-version → {"protocol":{"min":1,"max":1}}
一次调用、不需要项目、不触网。客户端启动时判断该走哪条路,不用先 spawn 一个可能失败的命令再解析错误消息(mcpp-community/mcpp-vscode#5 验收标准第 2 条)。
阶段 2 — --format 归一 + 老命令永久兼容
规范拼写 :--format json(ndjson 保留给未来真正需要流式的场景)。
选 --format 而非 --json 的理由不是"跟 #372 一致",而是:布尔开关无法表达第二种格式,也无法承载"未知值"这个错误分支——而阶段 0 恰恰需要它。
兼容策略 —— 直接套用本仓库已有的范式 (src/toolchain/compat.cppm):
THE ONLY FILE that knows pre-0.0.93 spellings. Core code sees canonical forms exclusively; the public parse entry points call normalize_ first. * Deleting this module would break exactly one thing: old inputs — never a canonical path.
cmdline 入口一处归一化: --json → --format json
核心代码只见 --format
三条硬约束:
--json 永久保留 ,不删
不打 deprecation 警告 —— design: mcpp.toml 补全重做方案 —— 语义模块 + index 动态数据(#4 重做) mcpp-vscode#8 已经在用它,用户装的 mcpp 版本参差;警告只会污染扩展捕获的输出
归一化只在入口做一次 ,核心代码不得再感知旧拼写
pack --format tar|dir 的语义冲突 :它是产物形态不是 stdout 格式。两条路,倾向前者:
(a) 文档声明 pack 为例外(它没有机器可读输出,不参与本协议)
(b) 加 --layout tar|dir 为规范拼写,--format 降为别名,走同一套兼容机制
阶段 3 — 补齐机器接口(按判据筛过)
两个设计约束:
mcpp metadata 默认必须不触网、不解析依赖 (对标 cargo metadata --no-deps)。否则 design: mcpp.toml 补全重做方案 —— 语义模块 + index 动态数据(#4 重做) mcpp-vscode#8 的场景(编辑 mcpp.toml 时补全)每次敲键都可能触发网络。需要依赖图和失效清单的,显式加 --resolved。
CDB 失效输入清单是当前最大的缺口 ,它是插件绝对拿不到的信息(哪些输入进了指纹),而且数据已经全在 BuildContext::fp 和 BuildPlan 里:
有了它,客户端的 watcher 就有了机器可读依据,而不是照着文档里一段会漂移的散文硬编码。
阶段 4 — 明确不做
不做
理由
mcpp interface <cap> --args / --list / capability 自描述
mcpp 已有 subcommand 树 + --help 作为发现机制;xlings 的 interface 面向 AI agent 编排,mcpp 的消费者是 IDE 插件和 CI 脚本,形态不同
NDJSON 事件流(seq / operationId / progress 事件)
one-shot 进程用「spawn + 退出码 + 读结果文件」就够(插件侧约 10 行)。事件协议是为 daemon 准备的,daemon 不在计划内。而且我们自己已经绕开了 xlings 的同款设计(§1.5)
workspace 成员发现的独立命令(ide snapshot)
插件读 [workspace].members 约 60 行;mcpp 做要 400+ 行(额外承担只读保证、路径 containment、选择器语义、诊断降级)。成员发现并入 mcpp metadata 即可
artifact 状态枚举 / phase 状态机 / 快照 ID 体系
stat() + 客户端自己的状态机
CDB 的版本化发布体系(reply 内容寻址 / current.json / 发布锁 / 回滚)
插件要「保留上一份可用 CDB」只需 copy + 失败 copy 回来(约 20 行);mcpp 做要 330+ 行且引入 current.json 单例 vs 多 configurationId 的结构性问题。mcpp 侧只需保证「自己写 CDB 时不写坏」(原子 replace,约 30 行)
四、必须守住的纪律
xlings interface 的 outputSchema 全空(§1.5)教了一课:envelope 的价值全在 data 被真正版本化和文档化上 。只做外层信封、内层随手改,客户端会因为"看到 schemaVersion 就以为有契约"而被坑得更惨。
具体到 mcpp:
同一条纪律也适用于错误码:MCPP_IDE_CONFIGURE_FAILED 这种「一个码覆盖全部失败 + 文档明令不许解析人类消息」的形状,是名义结构化、实际空洞。新增的每个失败分支要么有自己的 code,要么显式声明为「不可细分」。
#372 里有三类内容,建议分开处理:
A. 直接可用、建议尽快单独合入
src/build/test_targets.cppm(81 行)—— 把 tests/** 发现从 run_tests 提取出来,消除了 IDE CDB 与 mcpp test 在 member 选择 / 命名 / per-glob flags 上漂移的可能。是真正的收敛。
write_fresh_compile_commands + platform::fs::replace_file + FileLock(ec) —— 顺带修掉一个既有缺陷:write_compile_commands() 目前是 ofstream 截断写,非原子、不检查失败,clangd 可能读到半截 JSON。
prepare.cppm 的 stdout 纪律修复。
对应单测(test_compile_commands / test_platform_fs / test_test_options)。
B. 建议捞进本 RFC 复用
src/ide/model.cppm 的 Diagnostic/Position/Range/Severity + wire_name(~90 行)
src/ide/snapshot.cppm 的 envelope 构造 + 内容寻址 ID(~60 行)
这两块设计质量高,只是被绑死在一个命令上。提升为 mcpp.wire 后可服务全部 JSON 出口。
C. 建议不合入
inspect.cppm(433) / publish.cppm(333) / events.cppm(106) / cmd_ide.cppm(119) / ide snapshot / ide configure / IdePhase·SnapshotState·ArtifactState(生产代码零使用者)/ describe_std_module(仅单测调用)/ .xlings.json pin bump(与本 PR 无关)/ docs/superpowers/ 目录树(本仓库设计文档惯例是 .agents/docs/)。
另外,若 #372 按现状推进,两个问题需要先修:
NDJSON stdout 仍有未堵住的污染源。 src/pm/package_fetcher.cppm:1036 硬编码 /*quiet=*/false 调用 ensure_official_package_index_fresh,其内部 xlings::print_status(xlings.cppm:1583)和 update_index_unguarded 的 run_streaming 回调直接 std::println 到 stdout,不看 mcpp::ui::is_quiet() 。任一 xim: 包(含工具链)在本地索引缺失且未 debounce 时触发,xlings update 的全量输出会进 NDJSON 流。tests/e2e/198 用 _inherit_toolchain.sh 预置本机工具链,索引永远命中,结构性覆盖不到。
根因是 stdout 归属分散在多个 bool 参数里;建议收敛为单一开关(让 xlings::print_status 走 mcpp::ui::status,或加 ui::stdout_is_protocol() 一票否决)。
文档指定的客户端流程在 rooted workspace 的根成员上必然失败。 inspect.cppm 对 rooted workspace 产出 workspacePath == "."(单测 RootedWorkspaceSelectsRoot 明确断言),而文档 §7.2 要求客户端 configure --package <workspacePath> per member;-p . 经 resolve_member_dir 在 [workspace].members 里找不到 . → 报错退出 3。
根因是 member selector 语法在三处独立推导:project.cppm::resolve_member_dir、prepare.cppm:951、ide/inspect.cppm::matches_selector,前两处一致、第三处多了 . 别名。现有测试恰好绕开(e2e 用 virtual workspace;单测里 name/dir/workspacePath 三者相同)。
六、实施顺序
1. 阶段 0:未知 format 的统一契约(前置,不做后面全是复制缺陷)
2. 阶段 1:mcpp.wire envelope + destructive + --protocol-version (~150 行,从 #372 捞)
3. 阶段 2:--format 归一 + --json 入口别名(compat 模式,无警告) (~50 行)
4. 阶段 3a:self env / xpkg parse / cache list 接入 envelope (~35 行)
5. 阶段 3b:mcpp build --configure-only + CDB 失效输入清单 (~170 行)
6. 阶段 3c:mcpp metadata [--resolved] (~250 行)
前 5 步合计约 400 行,即可满足 mcpp-community/mcpp-vscode#5 的全部验收标准和 mcpp-community/mcpp-vscode#8 §7 的两条请求。
七、待确认
@Sunrisepeak
--format 作为规范拼写、--json 永久别名且不打 deprecation 警告 —— 是否接受?
pack --format tar|dir 走「声明为例外」还是「加 --layout 别名迁移」?
mcpp --protocol-version 作为唯一的汇合式协商入口 —— 是否接受?(明确不做 mcpp interface)
destructive 字段是否接受作为公开契约(等于把 design: mcpp.toml 补全重做方案 —— 语义模块 + index 动态数据(#4 重做) mcpp-vscode#8 §7.2 的人工承诺固化)?
@wellwei
feat(ide): add versioned project snapshots and pre-build CDB #372 按 §5 的 A/B/C 拆分是否可行?A 部分单独 PR 可以很快合入并发版,不阻塞 feat: integrate the mcpp IDE configure protocol into clangd workflow mcpp-vscode#5 。
feat: integrate the mcpp IDE configure protocol into clangd workflow mcpp-vscode#5 若改为消费 mcpp build --configure-only(spawn + 退出码 + 读 CDB)而非 NDJSON 事件流,扩展侧代码会更少 —— 但已有实现分支需返工,是否值得?
§5 末尾两个问题(NDJSON 污染、-p .)若 feat(ide): add versioned project snapshots and pre-build CDB #372 继续推进,需要先处理。
@Ximiaw
mcpp self env --format json 是否能覆盖 design: mcpp.toml 补全重做方案 —— 语义模块 + index 动态数据(#4 重做) mcpp-vscode#8 §2.4 的全部需求(home / registry / index 路径 + shim 情形)?还缺什么字段请列出。
mcpp metadata --format json(不触网,含 manifest 诊断 code/path/line/column)是否满足 design: mcpp.toml 补全重做方案 —— 语义模块 + index 动态数据(#4 重做) mcpp-vscode#8 §1「不做」栏里那条"等上游版本化 schema"的一部分?还是说静态字段键/枚举值仍需要独立的 schema 出口?
背景
mcpp 的机器可读输出目前是分散演化的:
xpkg parse --json、cache list --json各自决定输出结构,pack --format是产物形态不是输出格式,self env只有人类文本,#372 又引入了第三套(ide snapshot --format json/ide configure --format ndjson+ 独立的 envelope 和 ID 体系)。同时已经有两个真实客户端在等接口:
xpkg parse --json加 schema 版本字段、请求把"无写副作用"固定为契约本 RFC 提议先把契约层统一下来,再谈新增命令。
一、现状盘点(均为实测/源码核对)
1.1 输出格式选项已经分裂,且
--format有语义冲突mcpp pack --format tar|dir--formatmcpp xpkg parse --json--jsonmcpp cache list --json--jsonmcpp ide snapshot --format json--formatmcpp ide configure --format ndjson--format已发布的 mcpp 里,"输出格式"的事实拼写是
--json;--format被pack占用为另一个语义。1.2 未知格式的响应,#372 内部就不一致
同一个 PR、同一天写的两个命令:
ide snapshot --format yamlMCPP_IDE_UNSUPPORTED_FORMAT诊断ide configure --format json三个维度全不同。在把
--format推广到更多命令之前,必须先定死这一条,否则是把已知缺陷标准化。1.3 客户端拿不到的东西,mcpp 其实已经在算
mcpp self env已经打印MCPP_HOME/xlings home/ index repos / default toolchain,但没有--format json。结果 mcpp-community/mcpp-vscode#8 §2.4 被迫自己重实现整条定位逻辑:这段逻辑 100% 依赖 mcpp 内部实现、跨平台、易碎,而且是 mcpp-community/mcpp-vscode#8 全篇里唯一没有契约测试兜底的部分。给
self env加 JSON 输出约 15 行,可以直接删掉它。1.4
xpkg parse --json确实没有 schema 版本字段实测确认,mcpp-community/mcpp-vscode#8 §7.1 的请求成立且未被满足。成本是一个字段。
1.5 我们自己就是"汇合式协议"的消费者,而且绕开了它
xlings interface是完整的汇合式设计:interface <capability> --args '<JSON>'+--list(20 个 capability,含destructive标记和inputSchema)+--version。而 mcpp 对它的实际用法(
src/xlings.cppm:1064-1076,main 分支):主路径走裸
xlings install -y,把输出全部重定向到 null,然后 mcpp 自己在 stderr 画一个只有秒数的 spinner。也就是说:我们宁愿丢掉 xlings 的全部结构化进度事件,也不走那条 NDJSON 管道。事件流的唯一独占价值就是进度事件,它在真实压力下不可靠 → 消费者放弃它。这是"汇合传输层"最直接的反证。
另一个观察:
xlings interface --list里 20 个 capability 的outputSchema全部是{"properties":{"exitCode":{"type":"integer"}}}。声明了 schema 但没填 —— 这比不声明更危险,因为客户端会以为有契约。(我们踩过:#238 的 multi-repo 失败模式发出{"exitCode":1}且没有 error 事件,所以InstallProgressHandler才要用capturedDiagnostics_手工兜住 error/warn 文本。)1.6 CDB 的 bootstrap 问题比想象中小
实测(mcpp 2026.8.6.3):
源码上的原因:
src/build/ninja_backend.cppm:1546,write_compile_commands()在 spawn ninja 之前执行。真正的门槛不是"编译成功",而是prepare_build()成功。因此 IDE 侧真正缺的不是"能在编不过时拿到 CDB"(已经有了),而是:
tests/**及其 dev-dependency 上下文二、判据
沿用三档划分:
第 3 档要注意一个反直觉的事实:有些能力 mcpp 做反而更贵,因为 mcpp 是多进程、公开契约、要向后兼容的,必须额外承担只读性保证、路径 containment、选择器语义、诊断降级 —— 而插件在自己进程里读文件,这些负担都不存在。
三、提案
阶段 0 — 先定死"未知 format 怎么办"(前置条件)
客户端在拿到输出之前无法知道 mcpp 支不支持它请求的格式,所以拒绝也必须用客户端能解析的形式说出来。
这一条不定,后面所有
--format推广都是在复制缺陷。阶段 1 — 通用输出信封(新模块
mcpp.wire){ "schemaVersion": 1, "kind": "mcpp.metadata", // mcpp.env / mcpp.xpkg / mcpp.cdb / ... "destructive": false, // ← 借鉴 xlings interface 的设计 "mcpp": { "version": "2026.8.8.1", "protocol": { "min": 1, "max": 1 } }, "data": { /* 命令特有 */ }, "diagnostics": [ { "code": "...", "severity": "error|warning", "source": "mcpp", "message": "...", "path": "...", "range": {"start":{"line":1,"column":1},"end":{...}} } ] }destructive字段的价值:mcpp-community/mcpp-vscode#8 §7.2 花了一整段请求"请确认xpkg parse --json无写副作用并可作为契约依赖",本机实测过还要请上游固定。有了这个字段,请求当场变成机器可判定的契约。它同时替代 #372 文档里那段"configure 不是 read-only,IDE 必须先拿 workspace trust"的散文 —— VSCode 的 untrusted workspace 门可以直接读字段决定跑不跑。代码来源:
Diagnostic/Position/Range/Severity模型和 envelope 构造 + 内容寻址 ID 在 #372 里已经写好且质量很高(src/ide/model.cppm、src/ide/snapshot.cppm,约 150 行)。提议把它们从mcpp.ide.*提升为mcpp.wire,服务所有命令而不只是 IDE。新增协商入口(唯一"汇合"的地方):
一次调用、不需要项目、不触网。客户端启动时判断该走哪条路,不用先 spawn 一个可能失败的命令再解析错误消息(mcpp-community/mcpp-vscode#5 验收标准第 2 条)。
阶段 2 —
--format归一 + 老命令永久兼容规范拼写:
--format json(ndjson保留给未来真正需要流式的场景)。选
--format而非--json的理由不是"跟 #372 一致",而是:布尔开关无法表达第二种格式,也无法承载"未知值"这个错误分支——而阶段 0 恰恰需要它。兼容策略 —— 直接套用本仓库已有的范式(
src/toolchain/compat.cppm):三条硬约束:
--json永久保留,不删pack --format tar|dir的语义冲突:它是产物形态不是 stdout 格式。两条路,倾向前者:pack为例外(它没有机器可读输出,不参与本协议)--layout tar|dir为规范拼写,--format降为别名,走同一套兼容机制阶段 3 — 补齐机器接口(按判据筛过)
destructivemcpp self env --format jsonmcpp xpkg parse --format jsonmcpp cache list --format jsonmcpp metadata --format jsonmcpp metadata --resolved --format jsonmcpp build --configure-only --format json两个设计约束:
mcpp metadata默认必须不触网、不解析依赖(对标cargo metadata --no-deps)。否则 design: mcpp.toml 补全重做方案 —— 语义模块 + index 动态数据(#4 重做) mcpp-vscode#8 的场景(编辑 mcpp.toml 时补全)每次敲键都可能触发网络。需要依赖图和失效清单的,显式加--resolved。BuildContext::fp和BuildPlan里:有了它,客户端的 watcher 就有了机器可读依据,而不是照着文档里一段会漂移的散文硬编码。
阶段 4 — 明确不做
mcpp interface <cap> --args/--list/ capability 自描述--help作为发现机制;xlings 的 interface 面向 AI agent 编排,mcpp 的消费者是 IDE 插件和 CI 脚本,形态不同ide snapshot)[workspace].members约 60 行;mcpp 做要 400+ 行(额外承担只读保证、路径 containment、选择器语义、诊断降级)。成员发现并入mcpp metadata即可stat()+ 客户端自己的状态机四、必须守住的纪律
xlings interface的outputSchema全空(§1.5)教了一课:envelope 的价值全在data被真正版本化和文档化上。只做外层信封、内层随手改,客户端会因为"看到 schemaVersion 就以为有契约"而被坑得更惨。具体到 mcpp:
kind的data形状进docs/spec/schemaVersion且protocol.min/max同时给出重叠窗口kind至少一个 golden fixture 测试(feat(ide): add versioned project snapshots and pre-build CDB #372 的tests/fixtures/ide/snapshot-v1.json是好范式,值得保留并推广)同一条纪律也适用于错误码:
MCPP_IDE_CONFIGURE_FAILED这种「一个码覆盖全部失败 + 文档明令不许解析人类消息」的形状,是名义结构化、实际空洞。新增的每个失败分支要么有自己的 code,要么显式声明为「不可细分」。五、与 #372 的关系
#372 里有三类内容,建议分开处理:
A. 直接可用、建议尽快单独合入
src/build/test_targets.cppm(81 行)—— 把tests/**发现从run_tests提取出来,消除了 IDE CDB 与mcpp test在 member 选择 / 命名 / per-glob flags 上漂移的可能。是真正的收敛。write_fresh_compile_commands+platform::fs::replace_file+FileLock(ec)—— 顺带修掉一个既有缺陷:write_compile_commands()目前是ofstream截断写,非原子、不检查失败,clangd 可能读到半截 JSON。prepare.cppm的 stdout 纪律修复。test_compile_commands/test_platform_fs/test_test_options)。B. 建议捞进本 RFC 复用
src/ide/model.cppm的Diagnostic/Position/Range/Severity+wire_name(~90 行)src/ide/snapshot.cppm的 envelope 构造 + 内容寻址 ID(~60 行)这两块设计质量高,只是被绑死在一个命令上。提升为
mcpp.wire后可服务全部 JSON 出口。C. 建议不合入
inspect.cppm(433) /publish.cppm(333) /events.cppm(106) /cmd_ide.cppm(119) /ide snapshot/ide configure/IdePhase·SnapshotState·ArtifactState(生产代码零使用者)/describe_std_module(仅单测调用)/.xlings.jsonpin bump(与本 PR 无关)/docs/superpowers/目录树(本仓库设计文档惯例是.agents/docs/)。另外,若 #372 按现状推进,两个问题需要先修:
src/pm/package_fetcher.cppm:1036硬编码/*quiet=*/false调用ensure_official_package_index_fresh,其内部xlings::print_status(xlings.cppm:1583)和update_index_unguarded的run_streaming回调直接std::println到 stdout,不看mcpp::ui::is_quiet()。任一xim:包(含工具链)在本地索引缺失且未 debounce 时触发,xlings update的全量输出会进 NDJSON 流。tests/e2e/198用_inherit_toolchain.sh预置本机工具链,索引永远命中,结构性覆盖不到。根因是 stdout 归属分散在多个 bool 参数里;建议收敛为单一开关(让
xlings::print_status走mcpp::ui::status,或加ui::stdout_is_protocol()一票否决)。inspect.cppm对 rooted workspace 产出workspacePath == "."(单测RootedWorkspaceSelectsRoot明确断言),而文档 §7.2 要求客户端configure --package <workspacePath>per member;-p .经resolve_member_dir在[workspace].members里找不到.→ 报错退出 3。根因是 member selector 语法在三处独立推导:
project.cppm::resolve_member_dir、prepare.cppm:951、ide/inspect.cppm::matches_selector,前两处一致、第三处多了.别名。现有测试恰好绕开(e2e 用 virtual workspace;单测里 name/dir/workspacePath 三者相同)。六、实施顺序
前 5 步合计约 400 行,即可满足 mcpp-community/mcpp-vscode#5 的全部验收标准和 mcpp-community/mcpp-vscode#8 §7 的两条请求。
七、待确认
@Sunrisepeak
--format作为规范拼写、--json永久别名且不打 deprecation 警告 —— 是否接受?pack --format tar|dir走「声明为例外」还是「加--layout别名迁移」?mcpp --protocol-version作为唯一的汇合式协商入口 —— 是否接受?(明确不做mcpp interface)destructive字段是否接受作为公开契约(等于把 design: mcpp.toml 补全重做方案 —— 语义模块 + index 动态数据(#4 重做) mcpp-vscode#8 §7.2 的人工承诺固化)?@wellwei
mcpp build --configure-only(spawn + 退出码 + 读 CDB)而非 NDJSON 事件流,扩展侧代码会更少 —— 但已有实现分支需返工,是否值得?-p .)若 feat(ide): add versioned project snapshots and pre-build CDB #372 继续推进,需要先处理。@Ximiaw
mcpp self env --format json是否能覆盖 design: mcpp.toml 补全重做方案 —— 语义模块 + index 动态数据(#4 重做) mcpp-vscode#8 §2.4 的全部需求(home / registry / index 路径 + shim 情形)?还缺什么字段请列出。mcpp metadata --format json(不触网,含 manifest 诊断 code/path/line/column)是否满足 design: mcpp.toml 补全重做方案 —— 语义模块 + index 动态数据(#4 重做) mcpp-vscode#8 §1「不做」栏里那条"等上游版本化 schema"的一部分?还是说静态字段键/枚举值仍需要独立的 schema 出口?