# Validation Suite：400 个可复现模型配置

本套件将批量可靠性验证作为交付证据：使用公开 API 自动建模，由独立 Node.js 检查器验证实际返回坐标、半径和诊断。固定语料标识为 `cad-validation-400-v1`，基础种子为 `20261022`。

## 分组与模型范围

| 组 | 案例数 | 变化因素 |
| --- | ---: | --- |
| 基础解析模型 `analytic` | 60 | 不同尺寸、初始扰动的四类模型 |
| 平移 `translation` | 60 | x 平移 -150000…145000，y 平移 -35000…35000，其余与基础模型对应 |
| 旋转 `rotation` | 60 | 在 -π…π 内取 60 个角度，几何和固定目标一起旋转 |
| 缩放 `scaling` | 60 | 60 个对数等距比例，从 1e-6 到 1e6 |
| 随机初始扰动 `perturbation` | 100 | 固定种子，逐坐标施加 ±0.25r 范围内扰动 |
| 极端尺寸 `extreme` | 60 | 1e-150、1e-100、1e-50、1e-12、1e-9、1e9、1e12、1e50、1e80、1e90，每类模型均覆盖全部十种比例 |
| 合计 | **400** | 四后端重复验证同一语料，不重复计为 1600 个不同模型 |

四类模型各 100 个配置。三角形由固定的基线端点和两条边长确定；矩形包含垂直、平行与长度关系；镜像孔位组合直线镜像、固定圆心、半径与等半径；线圆相切组合半径、切线与圆心到端点的距离。每个模型有 6～10 个标量变量，全部预期局部自由度为零。该批量套件涉及 8 种约束构造器；全部 24 种关系的导数与其他语义继续由原回归测试验证。

尺寸使用 Park–Miller / Schrage 整数生成器，单案例种子为 `20261022 + index * 37`，预热五步后取宽度 w∈(6,24)、高度 h∈(4,14)、半径 r∈(0.7,2)、三角形顶点的水平比例 f∈(0.25,0.75)。普通组逐坐标扰动范围为 ±0.04r；扰动组另用种子 +100000 和 ±0.25r。初始圆半径处于目标半径的 1～1.1 倍。所有点均从扰动后的坐标求解，不将解析答案写回求解结果。

前五个变换组共享对应的基础参数和初始扰动，便于对照；扰动组扩展到 100 组尺寸。这里统计的是 400 个模型配置，包含相同拓扑及基础参数的变换，不是 400 种拓扑或独立随机抽样。生成器不筛选求解成功的种子。

## 独立检查与判定标准

[MoonBit 程序](../cmd/validation/main.mbt) 只负责建模、求解和输出数据；[Node 检查器](../scripts/validation_suite.cjs) 不导入求解器算法，另行验证：

1. 组别、数量、唯一案例 ID、种子、参数、变换、每个初始点及初始半径符合生成规则，防止缺失、重复或将初值替换成精确答案。
2. `Satisfied`、全部几何有限、半径为正、变量数 / 方程数正确、局部自由度为零、迭代次数在预算内。
3. 用返回的世界坐标独立重算固定点、长度、方向、镜像和相切残差；先按比例缩放坐标差，避免极端尺寸导致平方溢出或下溢。每个残差比不超过 1.00001，仅给独立浮点计算保留 1e-5 的比值裕量。
4. 用两圆交点、矩形坐标、镜像公式和切圆解析位置核对坐标、半径及所选构型分支。坐标 / 半径误差不超过 50 倍长度容差；这与约束残差达标是两项不同检查。
5. 每条独立残差比与报告值之差不超过 0.005，报告最大值与逐项值一致。此比较裕量允许平移坐标消去等不同运算顺序的舍入差，不用于放宽独立残差达标标准。
6. 成功时保存的几何与返回候选几何逐项相同。

长度容差为 `1e-7 × scale`，角度 / 方向容差为 `1e-8`。极端组测试统一缩放并同步缩放长度容差，不等同于在同一草图中混合跨 240 个数量级的尺寸，也不表示所有模型可用固定的 1e-7 世界坐标容差。初值接近预期分支，未覆盖任意初值全局收敛、大型模型、任意拓扑或组合变换。

检查器每次还执行 6 项故障注入：错误坐标、负半径、满足关系但位于错误分支的矩形、错误诊断值、错误自由度、没有应用的成功几何，均必须被拒绝。这 6 项不计入 400 个模型配置。已有矛盾、奇异初值、极端输入、启停、删除和失败时保留几何的回归继续保留。

## 复现与结果文件

需要 MoonBit 0.10.15+ 和 Node.js 18+；脚本只用 Node 标准库。

```sh
node scripts/validation_suite.cjs --check --target wasm
node scripts/validation_suite.cjs --check --target wasm-gc
node scripts/validation_suite.cjs --check --target js
node scripts/validation_suite.cjs --check --target native
# 显示指定案例的完整输入、输出及判定。生成整套语料后只显示这一项。
node scripts/validation_suite.cjs --check --target js --case rotation:17
# 仅需原始 MoonBit JSON Lines 时：
moon run cmd/validation --target js
```

每次完整运行生成 `_build/validation/<target>.jsonl`（原始逐模型数据）、`.json`（含完整输入 / 输出、判定及汇总）、`.csv`（逐案例索引与指标）及 `.stderr.log`。单案例的组名、index、seed、尺寸、初始几何、变换、容差均保留，可直接用 `--case` 重现。执行或解析失败前已保存的原始输出也会保留。

汇总包括各组及各模型族的成功数、成功率、迭代次数、最大独立残差比、解析坐标误差和失败分类。失败分类包含求解错误、未收敛、非法 / 非有限输出、独立残差超标、解析位置 / 分支不符、自由度 / 维度不符、诊断不符及几何应用不符。任何案例失败、检查器故障注入未被拒绝、语料校验不符都会使命令以非零状态退出。

手动完整验证在四后端分别检查 400 个配置，上传 `validation-results` artifact 保存逐案例文件；`python scripts/check_package.py --full` 也在实际解包目录运行 JS 版完整套件。默认 CI 不执行批量实验。

## 实测快照

2026-10-22 本地 Windows x64、MoonBit 0.10.15：wasm、wasm-gc、JS、native 各 **400/400 通过**，每个后端的 6 项检查器故障注入也全部通过。实际迭代次数为 2～4，四后端最大独立残差比约 0.964，最大坐标 / 半径误差除以 scale 约 2.72e-7。这是固定语料的观测，不是任意草图的成功率承诺，也不是性能 Benchmark。

原始汇总快照见 [wasm](validation-results/wasm.json)、[wasm-gc](validation-results/wasm-gc.json)、[JS](validation-results/js.json)、[native](validation-results/native.json)，保留环境、工具链及相关源码 SHA-256。源码指纹按文件名和统一换行的内容计算，涵盖生成器、检查器和核心求解源文件；`--check --require-current-snapshot` 要求快照与当前源码一致，不要求不同系统得到逐位相同的浮点统计。修改这些源文件后，应审查结果并用 `--write` 为四个后端重新生成快照。

400 个自动配置独立于原有测试框架的测试条目数；应分别报告回归测试数和模型配置数。

接近目标构型的扰动测试之外，另有 [1000 项三角形随机初值实验](RANDOM_TRIANGLE.md)，其六个初始坐标直接从 (-10,10) 生成，只添加三条边长关系、保留 3 个自由度。该实验单独统计真实状态，未并入上面的 400 个配置或四后端成功率。

类型化错误升级后，以上数据保留为历史测量，本次未重跑。`--check` 独立验证本次新运行的结果，并在源码指纹不同时明确提示历史快照；不会重写已提交测量。加 `--require-current-snapshot` 可要求快照必须对应当前源码，不符即失败。CSV 完整性及当前结果正确性检查仍保留。需要刷新证据时，审查完整实测结果后显式使用 `--write`。


## 维护者按需验证

日常改动优先选择相关检查，例如公开接口示例：

```sh
moon test README.mbt.md --target js
```

以下是维护者按需执行的完整验证，不是使用 API 的前置步骤：

<details>
<summary>完整验证命令</summary>

```sh
moon fmt --check
moon check --target all --deny-warn
moon build
moon test
moon test --target wasm-gc
moon test --target js
moon test --target native
moon run examples/basic
moon run cmd/edit_demo
moon run examples/mirror_holes
moon run examples/parametric_bracket
node scripts/bracket_showcase.cjs --check
moon run examples/four_bar
node scripts/four_bar_showcase.cjs --check
```

</details>

测试包含不同尺寸与平移下的矩形、解析可验的三角形和夹角、两侧线圆相切、圆内切、中心对称、带符号偏移、长度比例、约束启停、修改尺寸、连续 21 个曲柄位置的四杆机构，以及冗余、矛盾、奇异初值、输出舍入和资源限制。内部数值算法的验证设计见[技术说明](ARCHITECTURE.md#如何验证)。测试通过不代表任意非线性草图均会收敛。

`python scripts/check_package.py` 使用 Python 3.10+ 标准库检查实际发布 ZIP 的文件与许可，再解包到临时 workspace，显式选择独立消费模块执行 5 项 JS 测试。只有传入 `--full` 才执行四后端及批量模型检查，并运行包内安装板、四杆机构及 SVG 检查（完整路径还需要 Node.js 18+）。Python 与 Node 图形脚本仅用于开发验证；核心求解与 wasm 示例不需要它们。

本次审查另覆盖 64 组经过旋转 / 平移 / 缩放的解析三角形、96 组容差临界值输入，以及跨草图同号句柄的拒绝行为。

[验收对照](ACCEPTANCE.md)区分源码证据与未完成发布事项。日常只运行本次改动相关的轻量检查；完整矩阵由维护者显式决定是否运行。


## 注册表 Consumer Test

`python scripts/check_consumer.py` 在仓库外执行 `moon new`、`moon add mik1e80/cad_sketch`，编写小型消费程序并运行三个 JS 测试和一次可执行示例。它针对已发布的包，不使用本地 workspace；标准注册表缓存允许使用并记录。独立项目代码、真实输出及完整复现见 [CONSUMER_TEST](CONSUMER_TEST.md)。这项轻量检查不调用上面的源码包全矩阵检查或 400 / 1000 模型实验。
