@helix3/helix-cli 0.1.18-helix3.342 → 0.1.18-helix3.344
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/character/restFrameGuard.d.ts +52 -0
- package/dist/character/restFrameGuard.js +90 -0
- package/dist/character/restFrameGuard.js.map +1 -0
- package/dist/index.js +16 -6
- package/dist/index.js.map +1 -1
- package/dist/lib.js +2 -0
- package/dist/lib.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/visualQa/command.d.ts +8 -0
- package/dist/visualQa/command.js +38 -1
- package/dist/visualQa/command.js.map +1 -1
- package/package.json +2 -2
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_abs.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_expression.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_jbeam.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_materials.cpython-312.pyc +0 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Refuse a `helix-humanoid@1` character GLB whose bones are not in the canonical rest FRAMES.
|
|
3
|
+
*
|
|
4
|
+
* ── THE DEFECT (live, found 2026-10-02 by the whole-catalogue visual-QA sweep) ───────────────────────
|
|
5
|
+
* Cyberpunk Female Base 1.0.4–1.0.7 shipped with every bone frame turned 180 degrees about the vertical axis.
|
|
6
|
+
* The source faced -Z, the importer (`fitSkeletonToWarrior`) embedded the canonical skeleton at the source's joint
|
|
7
|
+
* positions (so left-side bones sat on the -X side of the root frame) and the author turned the whole thing round
|
|
8
|
+
* with a `cyberpunk_forward_frame` wrapper node (q 0,1,0,0) above skeleton AND mesh. A wrapper like that keeps
|
|
9
|
+
* every WORLD POSITION right, so it renders correctly at rest, in every thumbnail and in every T-pose proof — and
|
|
10
|
+
* leaves every bone FRAME 180 degrees off canonical. The clips are absolute canonical local rotations
|
|
11
|
+
* (`retargetLocomotion.ts`: "Canonical rotations are absolute local poses"), so idle folded both hands behind the
|
|
12
|
+
* back and the walk/run swung the arms and legs the wrong way round. Every skinned add-on bound to that base inherits
|
|
13
|
+
* the rig, so none of them could be fitted or posed correctly either.
|
|
14
|
+
*
|
|
15
|
+
* ── WHY EVERY EXISTING GATE PASSED IT ──────────────────────────────────────────────────────────────
|
|
16
|
+
* Same story as `normalMapGuard.ts`: skeleton checks compare joint NAMES, ORDER and rest POSITIONS. None compared
|
|
17
|
+
* a rest ORIENTATION to anything.
|
|
18
|
+
*
|
|
19
|
+
* ── THE TEST ───────────────────────────────────────────────────────────────────────────────────────
|
|
20
|
+
* Every conformed `helix-humanoid@1` body measured on 2026-10-02 (17 live characters, Base Male/Female, Sims 4,
|
|
21
|
+
* Kemonomimi, Unitree G1, Brass Keeper...) has its trunk, neck, head, leg and foot frames within 35 degrees of the
|
|
22
|
+
* canonical rest world frame, and its arm chain (aimed at the source's own arm pose) within 65. The flipped
|
|
23
|
+
* Cyberpunk base is at 171-180 on every one of them. Anything past `REST_FRAME_MAX_DEVIATION_DEG` is a turned or
|
|
24
|
+
* rolled skeleton, never a pose difference. Only a rig that actually carries the canonical joint names is judged;
|
|
25
|
+
* a rig with none of them is somebody else's skeleton and is left alone.
|
|
26
|
+
*
|
|
27
|
+
* Escape hatch: `HELIX_ALLOW_NONCANONICAL_REST_FRAMES=1`.
|
|
28
|
+
*/
|
|
29
|
+
import type { Document } from '@gltf-transform/core';
|
|
30
|
+
export declare const REST_FRAME_MAX_DEVIATION_DEG = 100;
|
|
31
|
+
/** The bones every humanoid body must have in the canonical orientation: trunk, head, legs, feet and the arm chain. */
|
|
32
|
+
export declare const REST_FRAME_CHECKED_JOINTS: readonly string[];
|
|
33
|
+
export interface RestFrameFinding {
|
|
34
|
+
joint: string;
|
|
35
|
+
degrees: number;
|
|
36
|
+
}
|
|
37
|
+
export interface RestFrameReport {
|
|
38
|
+
/** Joints actually compared (those present in both the GLB and the canonical skeleton). */
|
|
39
|
+
checked: number;
|
|
40
|
+
findings: RestFrameFinding[];
|
|
41
|
+
}
|
|
42
|
+
/** Compare the first skin's joint WORLD frames (wrapper nodes included: they are part of what the engine draws) to canonical. */
|
|
43
|
+
export declare function inspectRestFrames(document: Document): RestFrameReport;
|
|
44
|
+
export declare function describeRestFrameFindings(findings: readonly RestFrameFinding[]): string;
|
|
45
|
+
/** Throws with an itemized report when the rig is a canonical humanoid that is turned or rolled away from the canonical frames. */
|
|
46
|
+
export declare function assertRestFramesAreCanonical(document: Document, name?: string): RestFrameReport;
|
|
47
|
+
export declare function assertGlbRestFramesAreCanonical(glb: Uint8Array, name?: string): Promise<RestFrameReport>;
|
|
48
|
+
/** Shared by publish and publish --dry-run, so the gate before the fee is the gate at it. Character BASES only: an add-on carries a part skeleton judged by its host. */
|
|
49
|
+
export declare function assertPublishRestFrames(opts: {
|
|
50
|
+
kind: string;
|
|
51
|
+
mesh?: string;
|
|
52
|
+
}, meshBytes: Uint8Array | null | undefined): Promise<void>;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.REST_FRAME_CHECKED_JOINTS = exports.REST_FRAME_MAX_DEVIATION_DEG = void 0;
|
|
4
|
+
exports.inspectRestFrames = inspectRestFrames;
|
|
5
|
+
exports.describeRestFrameFindings = describeRestFrameFindings;
|
|
6
|
+
exports.assertRestFramesAreCanonical = assertRestFramesAreCanonical;
|
|
7
|
+
exports.assertGlbRestFramesAreCanonical = assertGlbRestFramesAreCanonical;
|
|
8
|
+
exports.assertPublishRestFrames = assertPublishRestFrames;
|
|
9
|
+
const core_1 = require("@gltf-transform/core");
|
|
10
|
+
const extensions_1 = require("@gltf-transform/extensions");
|
|
11
|
+
const canonicalSkeleton_1 = require("./canonicalSkeleton");
|
|
12
|
+
exports.REST_FRAME_MAX_DEVIATION_DEG = 100;
|
|
13
|
+
/** The bones every humanoid body must have in the canonical orientation: trunk, head, legs, feet and the arm chain. */
|
|
14
|
+
exports.REST_FRAME_CHECKED_JOINTS = [
|
|
15
|
+
'pelvis', 'spine_01', 'spine_05', 'neck_01', 'head',
|
|
16
|
+
'clavicle_l', 'clavicle_r',
|
|
17
|
+
'upperarm_l', 'upperarm_r', 'lowerarm_l', 'lowerarm_r',
|
|
18
|
+
'thigh_l', 'thigh_r', 'calf_l', 'calf_r', 'foot_l', 'foot_r',
|
|
19
|
+
];
|
|
20
|
+
/** Rotation angle, in degrees, between two column-major 4x4 world matrices' orthonormalised 3x3 parts. */
|
|
21
|
+
function angleBetween(a, b) {
|
|
22
|
+
const col = (m, c) => {
|
|
23
|
+
const v = [m[4 * c], m[4 * c + 1], m[4 * c + 2]];
|
|
24
|
+
const l = Math.hypot(...v) || 1;
|
|
25
|
+
return [v[0] / l, v[1] / l, v[2] / l];
|
|
26
|
+
};
|
|
27
|
+
// trace(Ra^T * Rb) = sum over columns of dot(a_c, b_c) (scale-free: each column is normalised first)
|
|
28
|
+
let trace = 0;
|
|
29
|
+
for (let c = 0; c < 3; c += 1) {
|
|
30
|
+
const x = col(a, c);
|
|
31
|
+
const y = col(b, c);
|
|
32
|
+
trace += x[0] * y[0] + x[1] * y[1] + x[2] * y[2];
|
|
33
|
+
}
|
|
34
|
+
return (Math.acos(Math.max(-1, Math.min(1, (trace - 1) / 2))) * 180) / Math.PI;
|
|
35
|
+
}
|
|
36
|
+
/** Compare the first skin's joint WORLD frames (wrapper nodes included: they are part of what the engine draws) to canonical. */
|
|
37
|
+
function inspectRestFrames(document) {
|
|
38
|
+
const skin = document.getRoot().listSkins()[0];
|
|
39
|
+
if (!skin)
|
|
40
|
+
return { checked: 0, findings: [] };
|
|
41
|
+
const canonical = (0, canonicalSkeleton_1.vendoredCanonicalSkeleton)().worldByName;
|
|
42
|
+
const findings = [];
|
|
43
|
+
let checked = 0;
|
|
44
|
+
const byName = new Map(skin.listJoints().map((joint) => [joint.getName(), joint]));
|
|
45
|
+
for (const name of exports.REST_FRAME_CHECKED_JOINTS) {
|
|
46
|
+
const joint = byName.get(name);
|
|
47
|
+
const reference = canonical.get(name);
|
|
48
|
+
if (!joint || !reference)
|
|
49
|
+
continue;
|
|
50
|
+
checked += 1;
|
|
51
|
+
const degrees = angleBetween(joint.getWorldMatrix(), reference);
|
|
52
|
+
if (degrees > exports.REST_FRAME_MAX_DEVIATION_DEG)
|
|
53
|
+
findings.push({ joint: name, degrees: Math.round(degrees) });
|
|
54
|
+
}
|
|
55
|
+
return { checked, findings };
|
|
56
|
+
}
|
|
57
|
+
function describeRestFrameFindings(findings) {
|
|
58
|
+
return findings.map((f) => ` - ${f.joint}: ${f.degrees} deg from the canonical rest frame`).join('\n');
|
|
59
|
+
}
|
|
60
|
+
/** Throws with an itemized report when the rig is a canonical humanoid that is turned or rolled away from the canonical frames. */
|
|
61
|
+
function assertRestFramesAreCanonical(document, name = 'this GLB') {
|
|
62
|
+
const report = inspectRestFrames(document);
|
|
63
|
+
// fewer than five canonical joints present: not a conformed helix-humanoid rig, not ours to judge
|
|
64
|
+
if (report.checked < 5 || report.findings.length === 0 || process.env.HELIX_ALLOW_NONCANONICAL_REST_FRAMES === '1')
|
|
65
|
+
return report;
|
|
66
|
+
throw new Error(`Refusing ${name}: ${report.findings.length} of ${report.checked} checked bone frames are more than ${exports.REST_FRAME_MAX_DEVIATION_DEG} degrees from the canonical ` +
|
|
67
|
+
`helix-humanoid@1 rest frames, so every clip will drive this body turned or mirrored (hands folded behind the back in idle, arms and legs swinging the wrong way).\n` +
|
|
68
|
+
`${describeRestFrameFindings(report.findings)}\n` +
|
|
69
|
+
`This is a turned or rolled skeleton, not a pose: a wrapper node (e.g. a 180-degree forward frame) above the skeleton keeps every position right and every frame wrong. ` +
|
|
70
|
+
`Re-conform the source facing +Z, or bake the wrapper into the mesh and give each bone the canonical frame at the same position. ` +
|
|
71
|
+
`To ship anyway set HELIX_ALLOW_NONCANONICAL_REST_FRAMES=1.`);
|
|
72
|
+
}
|
|
73
|
+
async function assertGlbRestFramesAreCanonical(glb, name) {
|
|
74
|
+
let document;
|
|
75
|
+
try {
|
|
76
|
+
document = await new core_1.NodeIO().registerExtensions(extensions_1.ALL_EXTENSIONS).readBinary(glb);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return { checked: 0, findings: [] };
|
|
80
|
+
}
|
|
81
|
+
return assertRestFramesAreCanonical(document, name);
|
|
82
|
+
}
|
|
83
|
+
const REST_FRAME_GUARDED_KINDS = new Set(['avatar']);
|
|
84
|
+
/** Shared by publish and publish --dry-run, so the gate before the fee is the gate at it. Character BASES only: an add-on carries a part skeleton judged by its host. */
|
|
85
|
+
async function assertPublishRestFrames(opts, meshBytes) {
|
|
86
|
+
if (!meshBytes || !REST_FRAME_GUARDED_KINDS.has(opts.kind))
|
|
87
|
+
return;
|
|
88
|
+
await assertGlbRestFramesAreCanonical(meshBytes, opts.mesh ?? 'the mesh');
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=restFrameGuard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restFrameGuard.js","sourceRoot":"","sources":["../../src/character/restFrameGuard.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -38,6 +38,7 @@ const baseColorGuard_1 = require("./character/baseColorGuard");
|
|
|
38
38
|
const normalMapGuard_1 = require("./character/normalMapGuard");
|
|
39
39
|
const itemSetVersion_1 = require("./itemSetVersion");
|
|
40
40
|
const moveUx_1 = require("./visualQa/moveUx");
|
|
41
|
+
const restFrameGuard_1 = require("./character/restFrameGuard");
|
|
41
42
|
const commander_1 = require("commander");
|
|
42
43
|
const commands_1 = require("./sceneHlod/commands");
|
|
43
44
|
const placementRequest_1 = require("./placementRequest");
|
|
@@ -86,7 +87,14 @@ program
|
|
|
86
87
|
.description('HELIX creator CLI — scaffold, validate, and publish Instant Worlds')
|
|
87
88
|
.version((0, lib_1.cliVersion)());
|
|
88
89
|
function fail(message) {
|
|
89
|
-
console.error
|
|
90
|
+
// Synchronous: stderr is an ASYNC pipe on macOS, so console.error + process.exit cut a long refusal at ~512 bytes
|
|
91
|
+
// whenever the output was piped — exactly how an agent or CI reads it — losing the next command it names.
|
|
92
|
+
try {
|
|
93
|
+
(0, node_fs_1.writeSync)(2, `${message}\n`);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
console.error(message);
|
|
97
|
+
}
|
|
90
98
|
process.exit(1);
|
|
91
99
|
}
|
|
92
100
|
function requireAuth() {
|
|
@@ -1631,6 +1639,7 @@ item
|
|
|
1631
1639
|
const plan = (0, lib_1.planItemPublish)(publishOptions);
|
|
1632
1640
|
await (0, baseColorGuard_1.assertPublishBaseColor)(publishOptions, plan.meshBytes);
|
|
1633
1641
|
await (0, normalMapGuard_1.assertPublishNormalMaps)(publishOptions, plan.meshBytes);
|
|
1642
|
+
await (0, restFrameGuard_1.assertPublishRestFrames)(publishOptions, plan.meshBytes);
|
|
1634
1643
|
if (opts.json) {
|
|
1635
1644
|
console.log(JSON.stringify({
|
|
1636
1645
|
dryRun: true,
|
|
@@ -1811,14 +1820,15 @@ item
|
|
|
1811
1820
|
if (opts.json)
|
|
1812
1821
|
console.log(JSON.stringify(st, null, 2));
|
|
1813
1822
|
else {
|
|
1814
|
-
|
|
1823
|
+
// Current version first, with ITS hosted job; pending versions (each with their own job) follow.
|
|
1824
|
+
console.log(`current version: ${st.currentVersion ? (st.currentVersion.passed ? 'PASSED' : 'no passing run') : 'not pinned to a package version'}`);
|
|
1825
|
+
console.log(` hosted job for the current version: ${hosted.describeJob(job)}`);
|
|
1815
1826
|
if (job?.contactSheetUrl)
|
|
1816
|
-
console.log(`
|
|
1827
|
+
console.log(` contact sheet: ${job.contactSheetUrl}`);
|
|
1817
1828
|
for (const r of job?.reasons ?? [])
|
|
1818
|
-
console.log(`
|
|
1829
|
+
console.log(` - ${r}`);
|
|
1819
1830
|
if (job?.error)
|
|
1820
|
-
console.log(`
|
|
1821
|
-
console.log(`current version: ${st.currentVersion ? (st.currentVersion.passed ? 'PASSED' : 'no passing run') : 'not pinned to a package version'}`);
|
|
1831
|
+
console.log(` error: ${job.error}`);
|
|
1822
1832
|
for (const line of (0, moveUx_1.describePendingVersions)(id, st.pendingVersions))
|
|
1823
1833
|
console.log(line);
|
|
1824
1834
|
}
|