适用范围
本文对应 LiTwin 工业级轻量化无代码数字孪生引擎的任务 004:契约校验与代码质量流水线。
项目定位来自 README.md:LiTwin 面向工艺工程师,覆盖浏览器端拖拽搭建、Web 轻量化渲染、工业协议双向通信、插件式降阶仿真接入和私有化容器部署,不是纯可视化大屏工具。
当前研发依据为:
text
docs/12-优化后需求与架构基线.md 唯一需求与架构基线
docs/13-详细架构设计补充.md 模块边界、数据链路、控制状态、运维与测试
docs/14-MVP开发顺序与协作计划.md 12 个月开发顺序、阶段门和协作机制
contracts/openapi.yaml REST API v1 契约
contracts/*.schema.json 场景、遥测、插件、控制契约
任务 004 只建立契约和质量门禁,不新增业务 API,不修改数据库业务语义,不扩大三维编辑器、生产 PLC 控制和发布运行时范围。
1. 问题背景
LiTwin 的 contracts/ 是单一契约来源:
text
scene.schema.json
telemetry.schema.json
plugin-manifest.schema.json
command.schema.json
openapi.yaml
在任务 004 之前,项目已有契约约定,但前端 TypeScript 类型、Java DTO、OpenAPI、后端运行时 schema 副本之间仍主要依赖人工同步。
风险点包括:
| 风险 | 后果 |
|---|---|
| JSON Schema 修改后运行时副本未同步 | 后端使用旧规则校验场景 |
| OpenAPI 字段改动后 DTO 未跟进 | 接口文档与真实 JSON 不一致 |
| TypeScript interface 漏字段 | 编辑器能编译,但提交内容与契约漂移 |
| Java enum 同名污染 | 校验了错误枚举来源 |
| required 字段没有不可空表达 | 运行时可能出现 null 数据 |
| P3C 只做增量或扫描 0 文件 | CI 误报质量通过 |
因此 004 的核心目标是建立统一入口,让这些漂移在本地和 CI 中都能失败。
2. 命令入口
统一入口位于:
bash
scripts/quality.sh
细粒度命令:
| 命令 | 作用 |
|---|---|
./scripts/quality.sh validate-contracts |
校验 JSON Schema、OpenAPI、本地 $ref、关键约束,并触发类型对齐 |
./scripts/quality.sh check-schema-sync |
校验运行时 scene.schema.json 副本与 contracts/scene.schema.json 一致 |
./scripts/quality.sh frontend-typecheck |
调用前端 TypeScript typecheck |
./scripts/quality.sh backend-compile |
Java 17 后端编译 |
./scripts/quality.sh backend-unit-test |
纯 JUnit 单元测试,不依赖 Docker |
./scripts/quality.sh p3c-check |
全量 Java 质量基线扫描 |
./scripts/quality.sh diff-check |
git diff --check 加未跟踪文本尾随空白检查 |
./scripts/quality.sh backend-it |
可选 Testcontainers 集成测试,Docker 不可用时明确报告 |
组合命令:
bash
./scripts/quality.sh contracts
./scripts/quality.sh frontend
./scripts/quality.sh backend
./scripts/quality.sh all
未知命令和无参数会返回非零,避免 CI 误把帮助输出当成通过。
3. 契约校验
契约校验脚本:
text
scripts/validate-contracts.js
覆盖内容:
| 检查项 | 说明 |
|---|---|
| JSON 语法 | 校验 4 个 JSON Schema 可解析 |
| Schema 根结构 | 检查 2020-12 根类型、必填字段、枚举、版本字段 |
$ref |
检查 JSON Schema 与 OpenAPI 本地引用可解析,禁止断裂引用 |
| OpenAPI 3.1 | 校验 YAML 可解析、基础结构存在 |
| 场景内容引用 | SceneResource.content、SceneSaveRequest.content 必须直接引用 scene.schema.json |
| 运行时副本 | backend/api-service/src/main/resources/schemas/scene.schema.json 与 contracts/scene.schema.json 逐字节一致 |
边界:当前是结构级门禁,不是完整 OpenAPI 3.1 / JSON Schema 语义验证器。后续如接入 Spectral、openapi-tools 或完整 codegen,需要单独升级。
4. TypeScript 与 Java 对齐
对齐脚本:
text
scripts/check-alignment.js
TypeScript 侧重点:
| 类型 | 覆盖 |
|---|---|
| interface | 字段集合、required/optional、基础类型、数组、对象、tuple、$ref |
| enum/type alias | 字面量集合与契约枚举一致 |
| oneOf | Mapping、Trigger、EventAction 按 type 判别分支递归校验 |
| 根结构 | SceneProject 根字段、schemaVersion、project、scene 完整检查 |
Java 侧重点:
| 类型 | 覆盖 |
|---|---|
| DTO 字段 | 按 JSON 序列化名比较字段集合 |
| 类型映射 | string -> String、integer -> Integer/Long、number -> Double/BigDecimal、date-time -> Instant、object -> JsonNode |
| required 策略 | primitive 表达数值/布尔不可空;非 primitive required 必须带 @NotNull |
| optional 策略 | optional 字段保持可空引用,不允许误加 @NotNull |
@JsonProperty |
真实解析注解,例如 defaultValue 必须映射为 JSON 字段 default |
| enum 来源 | 使用全限定名校验 Java enum,避免同名枚举覆盖 |
任务过程中曾发现过真实漂移:前端 AssetRef 缺少契约里的 stats 字段,后续已补齐并纳入门禁。
5. P3C / Java 质量基线
Java 质量脚本:
text
scripts/check-p3c.js
当前策略是全量扫描:
text
backend/api-service/src/main/java/**/*.java
任务记录中当前基线为 29 个 Java 文件通过。扫描不到任何 Java 文件时返回非零,避免 CI 干净 checkout 中空跑。
已覆盖的最低规则集:
| 类别 | 覆盖 |
|---|---|
| 命名 | 类型、方法、字段、常量命名 |
| 异常 | 空 catch、printStackTrace |
| 日志 | 字符串拼接、敏感信息 |
| 线程 | 裸线程池 |
| 资源 | 文件流、JDBC connection、statement 需要可靠关闭 |
| 代码风格 | 魔法值、通配符 import、控制台输出 |
边界:参数、局部变量、包名等完整命名规则建议后续统一接入 Checkstyle 或 Alibaba P3C 插件;当前脚本覆盖任务 004 的最低阻断规则。
6. 脚本级自测
自测入口:
bash
node scripts/tests/quality-self-test.mjs
自测不是只跑正向样例,而是固化负例矩阵。典型负例包括:
| 负例 | 预期 |
|---|---|
| TS 字段类型改错 | check-alignment 返回非零 |
| oneOf 分支字段改错 | check-alignment 返回非零 |
| Java DTO 删除字段 | check-alignment 返回非零 |
删除 @JsonProperty("default") |
check-alignment 返回非零 |
删除 required 字段的 @NotNull |
check-alignment 返回非零 |
| 运行时 schema 副本篡改 | check-schema-sync 返回非零 |
| P3C 加入非法命名、资源泄漏 | p3c-check 返回非零 |
任务最终记录为:
text
node scripts/tests/quality-self-test.mjs PASS(42/42)
7. 验收记录
任务 004 文件记录的最终验收结果:
text
node scripts/tests/quality-self-test.mjs PASS(42/42)
./scripts/quality.sh validate-contracts PASS
./scripts/quality.sh check-schema-sync PASS
./scripts/quality.sh p3c-check PASS(29 个 Java 文件)
./scripts/quality.sh diff-check PASS
tsc -p frontend/packages/scene-schema/tsconfig.json --noEmit PASS
Java 17 + Maven 3.6.3 package/unit test PASS
说明:本文按任务交接与架构验收记录整理,未在写稿过程中重新执行全部命令;因此不使用"实测证明"表述。
8. 使用 AI 大模型开发时的约束
LiTwin 仍然使用 AI 大模型辅助实现,但 004 明确把开发方式压回工程约束:
- 先读
README.md确认项目定位; - 以
docs/12为唯一需求与架构基线; - 用
docs/13、docs/14约束模块边界、数据链路和开发顺序; - 以
contracts/openapi.yaml和 JSON Schema 作为接口与数据源头; - 让脚本、自测、负例和架构审核决定是否通过。
模型可以写实现,但不能替代契约、测试和审核。
9. 后续方向
任务 004 完成后,后续资产、实时数据、控制、仿真和发布任务都可以复用同一质量入口。
后续可以继续增强:
- 接入完整 OpenAPI / JSON Schema 语义校验器;
- 评审完整 codegen,减少手写 TS/Java 类型;
- 接入 Checkstyle / Alibaba P3C 插件;
- 将质量门禁作为 CI 必跑阶段;
- 为每个业务任务补充对应的负例矩阵。
这次的重点不是"又完成一个功能",而是让项目后面继续新增功能时,字段、类型和代码质量不再靠人工记忆兜底。