契约 §2 的参考实现是 opendance-web 的 keypoint-codec.ts(其 decodeBinaryFrame
注释就是「Windows 端参考实现」)。Android 已用金标准向量与它对齐;而本端的解码器
此前**只跟自己比过**(自己编码、自己解码),两个方向共用同一份错误假设也能一直绿。
新增:
* build/integration/frame-vectors.json —— 由参考实现生成并锁定的向量
(12 用例:i16 最小值 -32768、i16 最大值、±1 全量程、置信度 0/128/255、
flags 低 3 位组合、frame_id 0xFFFFFFFF 与 0x80000000、取整边界)。
* build/integration/probe-frame-vectors.gd —— 用**包内** KeypointFrame 解码同一批字节,
与参考解码结果**逐值精确比对**(坐标/置信度先收敛到 float32 再比精确相等,
因为本端点存 PackedVector3Array、置信度存 PackedFloat32Array)。
* build/accept-frame-vectors.sh —— 编排:用参考实现重新生成向量并与锁定文件比对
(参考实现变了却不同步向量即失败)→ 解包 → 包内解码比对 → 报告核对。
实测(**已发布**的 v0.2.3 资产重新下载后跑):
✓ 锁定的向量与参考实现重新生成的结果逐字节一致
✓ 解码用例 12/12,逐点比对 396 个,解码差异 0 项
✓ 编码器差异 1 项,且全部属于「量化前恰好 .5」的取整边界
关键点帧跨实现一致性验收全部通过
已测量并归类的一处差异(非缺陷):JS Math.round 与 Kotlin(生产发送方)Math.round
对 -2.5 取 -2(半数朝 +∞),本端 roundi 取 -3(半数远离零)。Windows 是接收方,
encode() 只在自测/协议回归里用,故对产品无影响;脚本硬性要求这类差异只能出现在
取整边界用例上,否则视为新问题。若将来本端要当发送方,把 roundi 换成 floor(x+0.5) 即可。
踩坑(两处「看着通过其实没测到」,都写进任务文档):
1. 生成器第一版把「喂进编码器的输入」当成 points 写进向量 → 比对变成「比编码量化」,
靠抽查数值才发现;现在向量同时含 inputPoints / f32InputPoints / f32Hex / points。
2. 编码器比对一开始用 float64 输入编出的 hex 当基准(正数恰好 .5 那例整例 99 字节不同),
实际只是输入从 float64 收敛到 float32 的量化差;改用同输入的 f32Hex 基准后,
差异收敛到唯一一个真正的取整边界用例。教训:跨实现比对必须先统一输入。
package-release.sh 结尾把四条发布前验收一次列全;verify.sh 全绿(774 通过 / 0 失败)。
127 lines
4.2 KiB
YAML
127 lines
4.2 KiB
YAML
project: opendance-windows-client
|
||
version: 0.2.3
|
||
repository: opendance-windows
|
||
default_branch: main
|
||
engine: Godot 4.7.2
|
||
contracts_version:
|
||
rest-api: 0.5.0
|
||
websocket-keypoints: 0.2.0
|
||
data-models: 0.7.0
|
||
skeleton-topology: 0.2.0
|
||
model-formats: 0.5.0
|
||
database: 0.4.0
|
||
|
||
# 契约变更流程(文档 7.2):
|
||
# 任何跨端契约变更必须先在 opendance-web 修改 contracts/ 并提升版本,
|
||
# 再在本项目创建适配任务。本项目内的 contracts/ 只是只读快照。
|
||
|
||
dependencies:
|
||
- name: opendance-web
|
||
kind: rest-api
|
||
contract: contracts/rest-api.yaml
|
||
usage: 曲目/动作/模型目录与关键点序列
|
||
- name: opendance-android
|
||
kind: websocket-consumer
|
||
contract: contracts/websocket-keypoints.md
|
||
usage: 本端为服务端,Android 主动连入推流
|
||
|
||
tasks:
|
||
- id: T-WIN-001
|
||
file: tasks/001-scaffold.md
|
||
scope: Godot 项目骨架
|
||
status: done
|
||
- id: T-WIN-002
|
||
file: tasks/002-rest-client.md
|
||
scope: 调用 Web 服务端 API
|
||
status: done
|
||
- id: T-WIN-003
|
||
file: tasks/003-websocket-receiver.md
|
||
scope: 接收 Android 关键点帧
|
||
status: done
|
||
- id: T-WIN-004
|
||
file: tasks/004-keypoint-deserialize.md
|
||
scope: 239 字节帧反序列化
|
||
status: done
|
||
- id: T-WIN-005
|
||
file: tasks/005-vrm-loader.md
|
||
scope: VRM 模型加载
|
||
status: done
|
||
- id: T-WIN-006
|
||
file: tasks/006-skeleton-retarget.md
|
||
scope: 关键点 -> VRM 骨骼重定向
|
||
status: done
|
||
- id: T-WIN-007
|
||
file: tasks/007-scoring-dtw.md
|
||
scope: DTW 评分引擎
|
||
status: done
|
||
- id: T-WIN-008
|
||
file: tasks/008-game-ui.md
|
||
scope: 主界面 + 游戏界面 + 结算
|
||
status: done
|
||
- id: T-WIN-009
|
||
file: tasks/009-source-display.md
|
||
scope: 模型/动作来源信息展示
|
||
status: done
|
||
- id: T-WIN-010
|
||
file: tasks/010-about-page.md
|
||
scope: 关于页面 + 开源声明
|
||
status: done
|
||
- id: T-WIN-011
|
||
file: tasks/011-build-script.md
|
||
scope: Windows 打包脚本
|
||
status: done
|
||
- id: T-WIN-012
|
||
file: tasks/012-about-version.md
|
||
scope: 「关于」清单展示当前版本号
|
||
status: done
|
||
- id: T-WIN-013
|
||
file: tasks/013-scene-selection.md
|
||
scope: API 升级 rest-api 0.5.0 + 场景选择 + 物理落地
|
||
status: done
|
||
- id: T-WIN-014
|
||
file: tasks/014-full-package.md
|
||
scope: 发布整包(单个 zip + SHA256SUMS,不拆分卷)
|
||
status: done
|
||
- id: T-WIN-016
|
||
file: tasks/016-aabb-transforms.md
|
||
scope: 场景包围盒沿树累乘变换(修复入树前用 global_transform 导致的 ERROR 与范围偏位)
|
||
status: done
|
||
- id: T-WIN-015
|
||
file: tasks/015-keepalive-dedup.md
|
||
scope: 连接保活 / 设备去重 / 状态机(契约 websocket-keypoints 0.2.0,与 T-AND-011 对齐)
|
||
status: done
|
||
- id: T-WIN-017
|
||
file: tasks/017-pe-version.md
|
||
scope: 发布包 exe 的 PE 版本资源(Windows 属性页显示的文件/产品版本)必须等于发布版本
|
||
status: done
|
||
- id: T-WIN-018
|
||
file: tasks/018-release-acceptance.md
|
||
scope: 发布包级端到端验收(读包内 pck:版本号 / 界面显示值 / 契约表 / 资源可加载)
|
||
status: done
|
||
- id: T-WIN-019
|
||
file: tasks/019-cross-end-integration.md
|
||
scope: 跨端集成验收(包内客户端 × 真实 Web 服务端)+ 补 Motion.thumbnailUrl 契约字段
|
||
status: done
|
||
- id: T-WIN-020
|
||
file: tasks/020-ws-contract-conformance.md
|
||
scope: WebSocket 契约一致性验收(Node 独立客户端 × 发布包内 PoseServer)+ 故意不合规的负例服务端
|
||
status: done
|
||
- id: T-WIN-021
|
||
file: tasks/021-frame-vector-conformance.md
|
||
scope: 关键点帧跨实现一致性(Web 参考实现 × 包内 GDScript 解码器,12 用例 / 396 点逐值比对)
|
||
status: done
|
||
|
||
deliverable:
|
||
artifact: opendance-windows-v0.2.3.zip
|
||
packaging: Godot 导出脚本(Linux 直接导出 / Windows 兜底)
|
||
release_rules: # 文档 §5.7 硬性要求
|
||
- 单个完整包,禁止 .partN 分卷
|
||
- 同时上传 SHA256SUMS(裸文件名,可直接 sha256sum -c)
|
||
includes:
|
||
- OpenDance.exe
|
||
- OpenDance.pck
|
||
- THIRD_PARTY.md
|
||
- README.txt
|
||
- README.md
|
||
- contracts/ # 当前版本契约快照
|