@helix3/helix-cli 0.1.7-helix3.44 → 0.1.7-helix3.45

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.
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ // The capture harness page. Assembled as a string because `tsc` does not copy assets into dist, and the
3
+ // page is written into a temp dir at run time anyway (alongside links to the world's three + system).
4
+ //
5
+ // The page renders a grid it is TOLD about — a flat cell list plus row/column labels — rather than deciding
6
+ // the arrangement itself. That is what lets one code path serve both the contact sheet (times across, views
7
+ // down) and the single-moment comparison (views across, one row, much larger cells).
8
+ //
9
+ // Why it poses TWO skeletons: the default character ships as body + face, each carrying its own skeleton
10
+ // with a different skin joint count (77-node full tree vs a 16-node root->spine->neck->head chain), so they
11
+ // cannot share one skin. Posing each by bone name is what keeps the head following spine and neck keys.
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.READY_FLAG = void 0;
14
+ exports.harnessPage = harnessPage;
15
+ exports.READY_FLAG = '__helixGestureCapture';
16
+ function harnessPage(config) {
17
+ return `<!doctype html>
18
+ <meta charset="utf-8">
19
+ <title>gesture capture</title>
20
+ <style>
21
+ :root { color-scheme: light }
22
+ body { margin: 0; background: #f4f4f6; font: 12px/1.3 ui-sans-serif, system-ui, sans-serif; color: #222 }
23
+ #sheet { position: relative; display: inline-block }
24
+ #sheet canvas { display: block }
25
+ .lbl { position: absolute; font-variant-numeric: tabular-nums; color: #444; pointer-events: none; font-weight: 600 }
26
+ .col { top: 5px; transform: translateX(-50%) }
27
+ .row { left: 5px; transform: translateY(-50%) rotate(-90deg); transform-origin: left center }
28
+ #err { padding: 12px; color: #a00; font-family: ui-monospace, monospace; white-space: pre-wrap }
29
+ </style>
30
+ <div id="sheet"></div>
31
+ <div id="err"></div>
32
+ <script type="importmap">
33
+ { "imports": { "three": "/three/build/three.module.js", "three/": "/three/" } }
34
+ </script>
35
+ <script type="module">
36
+ import * as THREE from 'three';
37
+ import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
38
+ import { compileGesture, GesturePlayer } from '/helix_modules/humanoid-character/index.js';
39
+
40
+ const CONFIG = ${JSON.stringify(config)};
41
+ const FLAG = ${JSON.stringify(exports.READY_FLAG)};
42
+ const fail = (message) => { document.getElementById('err').textContent = message; window[FLAG] = { ready: false, error: message }; };
43
+
44
+ try {
45
+ const clip = await (await fetch('/clip.json')).json();
46
+ const compiled = compileGesture(clip);
47
+
48
+ const loader = new GLTFLoader();
49
+ const parts = [];
50
+ for (const file of ['/capture-body.glb', '/capture-face.glb']) {
51
+ const gltf = await loader.loadAsync(file);
52
+ const root = gltf.scene;
53
+ root.traverse((o) => { if (o.isSkinnedMesh) { o.frustumCulled = false; o.castShadow = true; } });
54
+ // The bind pose must be restored before every pose, or deltas accumulate across grid cells.
55
+ const bind = new Map();
56
+ root.traverse((n) => { if (n.isBone === true) bind.set(n, n.quaternion.clone()); });
57
+ parts.push({ root, bind, player: new GesturePlayer(root) });
58
+ }
59
+
60
+ const scene = new THREE.Scene();
61
+ scene.background = new THREE.Color(0xf4f4f6);
62
+ for (const p of parts) scene.add(p.root);
63
+
64
+ // Three-point rig: a key light high and camera-left, a softer fill opposite, a rim from behind to keep
65
+ // the silhouette off the background. Ambient alone flattens exactly the depth cues a pose is judged by.
66
+ scene.add(new THREE.HemisphereLight(0xffffff, 0x555560, 0.55));
67
+ const key = new THREE.DirectionalLight(0xffffff, 2.0); key.position.set(-2.2, 3.2, 3.0); scene.add(key);
68
+ const fill = new THREE.DirectionalLight(0xffffff, 0.7); fill.position.set(2.6, 1.0, 1.8); scene.add(fill);
69
+ const rim = new THREE.DirectionalLight(0xffffff, 0.9); rim.position.set(0.4, 2.0, -3.2); scene.add(rim);
70
+
71
+ const poseAll = (t) => {
72
+ for (const p of parts) {
73
+ for (const [bone, q] of p.bind) bone.quaternion.copy(q);
74
+ p.player.pose(compiled.gesture, t);
75
+ }
76
+ for (const p of parts) p.root.updateMatrixWorld(true);
77
+ };
78
+
79
+ const cellW = CONFIG.cellW, cellH = CONFIG.cellH;
80
+
81
+ // Frame from the UNION of every pose in the grid, not the bind pose: one camera for the whole image keeps
82
+ // the cells comparable (a per-cell refit would make the body appear to zoom), while the union guarantees an
83
+ // overhead reach cannot be clipped out of frame.
84
+ const box = new THREE.Box3();
85
+ for (const t of [...new Set(CONFIG.cells.map((c) => c.t))]) { poseAll(t); box.expandByObject(scene); }
86
+ const centre = box.getCenter(new THREE.Vector3());
87
+ // Horizontal extent is per-VIEW: a camera at azimuth t sees |dx*cos t| + |dz*sin t| across, so an off-axis
88
+ // 3/4 is wider than the front view and would clip if only world X were budgeted. One camera is shared, so
89
+ // take the widest view in the grid.
90
+ const dx = box.max.x - box.min.x, dz = box.max.z - box.min.z;
91
+ const widest = Math.max(...CONFIG.cells.map((c) => {
92
+ const a = (c.azimuth * Math.PI) / 180;
93
+ return Math.abs(dx * Math.cos(a)) + Math.abs(dz * Math.sin(a));
94
+ }), 0.1);
95
+ const span = Math.max(box.max.y - box.min.y, widest / (cellW / cellH), 0.1);
96
+ const fov = 32;
97
+ const radius = (span * 0.60) / Math.tan((fov / 2) * Math.PI / 180);
98
+
99
+ const width = CONFIG.colLabels.length * cellW, totalHeight = CONFIG.rowLabels.length * cellH;
100
+ const renderer = new THREE.WebGLRenderer({ antialias: true, preserveDrawingBuffer: true });
101
+ renderer.setPixelRatio(1);
102
+ renderer.setSize(width, totalHeight);
103
+ renderer.setScissorTest(true);
104
+ const sheet = document.getElementById('sheet');
105
+ sheet.appendChild(renderer.domElement);
106
+
107
+ const camera = new THREE.PerspectiveCamera(fov, cellW / cellH, 0.05, 100);
108
+
109
+ // Everything renders in ONE frame: with scissor per cell the drawing buffer ends up holding the whole
110
+ // image, so the screenshot needs no per-cell readback. Sorted by time so each pose is applied once per
111
+ // distinct time rather than once per cell.
112
+ for (const cell of [...CONFIG.cells].sort((a, b) => a.t - b.t)) {
113
+ poseAll(cell.t);
114
+ const angle = (cell.azimuth * Math.PI) / 180;
115
+ camera.position.set(centre.x + Math.sin(angle) * radius, centre.y, centre.z + Math.cos(angle) * radius);
116
+ camera.lookAt(centre);
117
+ camera.updateProjectionMatrix();
118
+ // WebGL's origin is bottom-left; row 0 must be the TOP of the image.
119
+ const y = totalHeight - (cell.row + 1) * cellH;
120
+ renderer.setViewport(cell.col * cellW, y, cellW, cellH);
121
+ renderer.setScissor(cell.col * cellW, y, cellW, cellH);
122
+ renderer.render(scene, camera);
123
+ }
124
+
125
+ CONFIG.colLabels.forEach((text, c) => {
126
+ const el = document.createElement('div');
127
+ el.className = 'lbl col';
128
+ el.style.left = (c * cellW + cellW / 2) + 'px';
129
+ el.textContent = text;
130
+ sheet.appendChild(el);
131
+ });
132
+ CONFIG.rowLabels.forEach((text, r) => {
133
+ const el = document.createElement('div');
134
+ el.className = 'lbl row';
135
+ el.style.top = (r * cellH + cellH / 2) + 'px';
136
+ el.textContent = text;
137
+ sheet.appendChild(el);
138
+ });
139
+
140
+ window[FLAG] = { ready: true, clip: compiled.gesture.name, duration: compiled.gesture.duration, warnings: compiled.warnings ?? [] };
141
+ } catch (err) {
142
+ fail(err && err.stack ? err.stack : String(err));
143
+ }
144
+ </script>
145
+ `;
146
+ }
147
+ //# sourceMappingURL=harnessPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harnessPage.js","sourceRoot":"","sources":["../../src/gesture/harnessPage.ts"],"names":[],"mappings":";AAAA,wGAAwG;AACxG,sGAAsG;AACtG,EAAE;AACF,4GAA4G;AAC5G,4GAA4G;AAC5G,qFAAqF;AACrF,EAAE;AACF,yGAAyG;AACzG,4GAA4G;AAC5G,wGAAwG;;;AAqBxG,kCAkIC;AApIY,QAAA,UAAU,GAAG,uBAAuB,CAAC;AAElD,SAAgB,WAAW,CAAC,MAAqB;IAC/C,OAAO;;;;;;;;;;;;;;;;;;;;;;;iBAuBQ,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;eACxB,IAAI,CAAC,SAAS,CAAC,kBAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwGxC,CAAC;AACF,CAAC"}
@@ -0,0 +1,104 @@
1
+ import { type BoneAxisReference } from './axisReference';
2
+ export declare const DEFAULT_BONES: string[];
3
+ export interface InspectOptions {
4
+ worldDir: string;
5
+ /** Clip JSON path, or '-' for stdin. */
6
+ clip: string;
7
+ /** Times in seconds, or '35%' of duration. Empty + no motion/axes ⇒ ['0']. */
8
+ times?: string[];
9
+ bones?: string[];
10
+ motion?: boolean;
11
+ axes?: boolean;
12
+ /** Isolate part of the clip for --motion; without it the rest→pose→rest travel dominates every number. */
13
+ motionWindow?: [number, number] | null;
14
+ /** Which bone --axes measures the effect on (default: the last requested bone that exists). */
15
+ probe?: string | null;
16
+ /** Custom character GLB; default is the embedded canonical skeleton. */
17
+ rig?: string | null;
18
+ }
19
+ export interface BoneReadback {
20
+ pos?: number[];
21
+ dir?: number[] | null;
22
+ reads: string;
23
+ facing?: FacingReadback | null;
24
+ error?: string;
25
+ }
26
+ export interface FacingReadback {
27
+ palm?: number[];
28
+ fingers?: number[];
29
+ reads?: string;
30
+ unavailable?: string;
31
+ }
32
+ export interface MotionReadback {
33
+ lateral?: number;
34
+ vertical?: number;
35
+ depth?: number;
36
+ pathLength?: number;
37
+ dominant?: string;
38
+ purity?: number;
39
+ reversals?: number;
40
+ reads: string;
41
+ error?: string;
42
+ }
43
+ export interface AxisRow {
44
+ axis: string;
45
+ magnitude: number;
46
+ delta?: number[];
47
+ reads: string;
48
+ }
49
+ /** A serializable axis-table row. `bones` is the group's pattern SOURCE, not a RegExp — the result of this
50
+ * module is JSON-emitted (`--json`, the MCP), and a RegExp stringifies to `{}`, losing the group identity. */
51
+ export interface AxisRangeRow {
52
+ bones: string;
53
+ axes: {
54
+ x: string;
55
+ y: string;
56
+ z: string;
57
+ };
58
+ natural: {
59
+ x: [number, number];
60
+ y: [number, number];
61
+ z: [number, number];
62
+ };
63
+ }
64
+ export interface InspectResult {
65
+ clip: string;
66
+ duration: number;
67
+ rig: string;
68
+ system: string;
69
+ warnings: string[];
70
+ frames: {
71
+ t: number;
72
+ bones: Record<string, BoneReadback>;
73
+ }[];
74
+ motion: Record<string, MotionReadback> | null;
75
+ axes: {
76
+ probe: string;
77
+ keys: {
78
+ t: number;
79
+ rows: AxisRow[];
80
+ }[];
81
+ } | null;
82
+ /** Axis-table rows for the bones this clip actually keys — the context a warning needs, not all 15 groups. */
83
+ keyedAxisRows: AxisRangeRow[];
84
+ }
85
+ /** Exported for tests: these two produce the human-facing readback, and are duck-typed on .x/.y/.z so
86
+ * they need no three. A sign error here silently misleads every measurement an agent takes. */
87
+ /** Coarse compass for a unit vector — never a precise angle, because conformed rigs differ by ~20° at the extremities. */
88
+ export declare function compass(v: any): string;
89
+ export interface Refs {
90
+ head: number | null;
91
+ shoulder: number;
92
+ hip: number;
93
+ centerX: number;
94
+ centerZ: number;
95
+ }
96
+ /** Plain-English readback so an agent with no eyes can still tell a good pose from a broken one. */
97
+ export declare function describePose(name: string, pos: any, dir: any, ref: Refs): string;
98
+ export declare function inspectGesture(opts: InspectOptions): Promise<InspectResult>;
99
+ /** Human-readable report. `--json` returns the InspectResult instead. */
100
+ export declare function formatInspect(r: InspectResult, opts?: {
101
+ motionWindow?: [number, number] | null;
102
+ }): string;
103
+ /** Natural-range context for the bones a clip actually keys — the table rows that matter, not all 15. */
104
+ export declare function relevantAxisRows(table: readonly BoneAxisReference[] | null, clipJson: any): AxisRangeRow[];
@@ -0,0 +1,357 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_BONES = void 0;
4
+ exports.compass = compass;
5
+ exports.describePose = describePose;
6
+ exports.inspectGesture = inspectGesture;
7
+ exports.formatInspect = formatInspect;
8
+ exports.relevantAxisRows = relevantAxisRows;
9
+ // PORTED from helix-web-engine-new/systems/humanoid-character/scripts/pose.mjs — the source of truth for
10
+ // pose observability. SYNC OBLIGATION: fix bugs there first, then mirror the change here; do not diverge.
11
+ /**
12
+ * Headless pose observability — answers "where does this clip actually put the body, and what is it
13
+ * actually doing" without a browser.
14
+ *
15
+ * WHY THIS EXISTS
16
+ * ---------------
17
+ * The bone axis table describes what each axis does FROM REST. Those meanings stop being true the moment
18
+ * a parent rotates: rotations chain, so a child's "raises the arm" axis is carried wherever the parent
19
+ * twist put it. Authoring a large multi-joint pose therefore cannot be reasoned out from the table alone
20
+ * — the only ground truth is where the bones land once the whole chain is posed.
21
+ *
22
+ * Runs the world's OWN compileGesture + GesturePlayer, so it cannot drift from what the world renders.
23
+ */
24
+ const node_fs_1 = require("node:fs");
25
+ const rig_1 = require("./rig");
26
+ const worldRuntime_1 = require("./worldRuntime");
27
+ const axisReference_1 = require("./axisReference");
28
+ exports.DEFAULT_BONES = ['clavicle_r', 'upperarm_r', 'lowerarm_r', 'hand_r', 'head', 'spine_03'];
29
+ const MOTION_SAMPLES = 64;
30
+ const AXIS_PROBE_DEG = 10;
31
+ const round = (v, n = 3) => Math.round(v * 10 ** n) / 10 ** n;
32
+ const vec = (v) => [round(v.x), round(v.y), round(v.z)];
33
+ const AXIS_NAMES = ['x', 'y', 'z'];
34
+ /** Exported for tests: these two produce the human-facing readback, and are duck-typed on .x/.y/.z so
35
+ * they need no three. A sign error here silently misleads every measurement an agent takes. */
36
+ /** Coarse compass for a unit vector — never a precise angle, because conformed rigs differ by ~20° at the extremities. */
37
+ function compass(v) {
38
+ const opts = [
39
+ ['up', v.y], ['down', -v.y], ['forward', v.z], ['backward', -v.z],
40
+ ['character-left', v.x], ['character-right', -v.x],
41
+ ].sort((a, b) => b[1] - a[1]);
42
+ return opts[0][1] < 0.8 ? `${opts[0][0]} and ${opts[1][0]}` : opts[0][0];
43
+ }
44
+ const worldOf = (three, bone) => { const p = new three.Vector3(); bone.getWorldPosition(p); return p; };
45
+ const childBone = (bone) => bone.children.find((c) => c.isBone === true);
46
+ /** The bone's TIP (its child joint). Rotating a bone does not move its own origin — only the tip moves,
47
+ * which is why wrist rotation is invisible to a hand_r position probe. */
48
+ const tipOf = (three, bone) => { const c = childBone(bone); return c !== undefined ? worldOf(three, c) : worldOf(three, bone); };
49
+ function poseAt(ctx, gesture, seconds) {
50
+ for (const [bone, q] of ctx.rig.bind)
51
+ bone.quaternion.copy(q);
52
+ ctx.player.pose(gesture, seconds);
53
+ ctx.rig.root.updateMatrixWorld(true);
54
+ }
55
+ // ---- Self-calibrating hand frame ---------------------------------------------------------------------
56
+ // Conform rebinds every character to the canonical skeleton but AIMS each mapped bone at that character's
57
+ // own child joint (shortestArc4) — so hand frames differ by up to ~20° between rigs. Deriving the palm
58
+ // from THIS rig's own bind pose absorbs that arc by construction; a canonical constant would not.
59
+ function handFrame(ctx, handName) {
60
+ const { three, rig } = ctx;
61
+ const hand = rig.find(handName);
62
+ if (hand === null)
63
+ return null;
64
+ const side = handName.endsWith('_l') ? '_l' : '_r';
65
+ const fingerBone = rig.find(`middle_01${side}`) ?? rig.find(`index_01${side}`);
66
+ const thumbBone = rig.find(`thumb_01${side}`);
67
+ if (fingerBone === null || thumbBone === null)
68
+ return { unavailable: 'rig lacks finger bones' };
69
+ for (const [bone, q] of rig.bind)
70
+ bone.quaternion.copy(q);
71
+ rig.root.updateMatrixWorld(true);
72
+ const origin = worldOf(three, hand);
73
+ const fingers = worldOf(three, fingerBone).sub(origin).normalize();
74
+ const thumb = worldOf(three, thumbBone).sub(origin).normalize();
75
+ const palm = new three.Vector3().crossVectors(fingers, thumb).normalize();
76
+ // Cross-product handedness is a convention, not a measurement — fix it per side rather than sniffing a
77
+ // component. Verified on body-m / body-f / web-viking: right-hand cross(fingers,thumb) points INTO the
78
+ // palm on all three, and the left hand mirrors it exactly (Y/Z negated, X equal).
79
+ if (side === '_r')
80
+ palm.negate();
81
+ const bindQ = new three.Quaternion();
82
+ hand.getWorldQuaternion(bindQ);
83
+ const inv = bindQ.clone().invert();
84
+ return { hand, fingersLocal: fingers.applyQuaternion(inv), palmLocal: palm.applyQuaternion(inv) };
85
+ }
86
+ function facingNow(ctx, frame) {
87
+ if (frame === null)
88
+ return null;
89
+ if ('unavailable' in frame)
90
+ return { unavailable: frame.unavailable };
91
+ const q = new ctx.three.Quaternion();
92
+ frame.hand.getWorldQuaternion(q);
93
+ const palm = frame.palmLocal.clone().applyQuaternion(q);
94
+ const fingers = frame.fingersLocal.clone().applyQuaternion(q);
95
+ return { palm: vec(palm), fingers: vec(fingers), reads: `palm faces ${compass(palm)}, fingers point ${compass(fingers)}` };
96
+ }
97
+ /** Plain-English readback so an agent with no eyes can still tell a good pose from a broken one. */
98
+ function describePose(name, pos, dir, ref) {
99
+ const parts = [];
100
+ if (ref.head !== null) {
101
+ const d = pos.y - ref.head;
102
+ if (d > 0.08)
103
+ parts.push(`${round(d, 2)}m above head`);
104
+ else if (d > -0.08)
105
+ parts.push('at head height');
106
+ else if (pos.y > ref.shoulder - 0.08)
107
+ parts.push('between shoulder and head');
108
+ else if (pos.y > ref.hip)
109
+ parts.push('between hip and shoulder');
110
+ else
111
+ parts.push('below hip');
112
+ }
113
+ const side = pos.x - ref.centerX;
114
+ if (Math.abs(side) > 0.12)
115
+ parts.push(`${round(Math.abs(side), 2)}m to the ${side > 0 ? 'character-left' : 'character-right'}`);
116
+ else
117
+ parts.push('near the midline');
118
+ const fwd = pos.z - ref.centerZ;
119
+ if (Math.abs(fwd) > 0.12)
120
+ parts.push(fwd > 0 ? `${round(fwd, 2)}m in front` : `${round(-fwd, 2)}m behind`);
121
+ if (dir !== null)
122
+ parts.push(`points ${compass(dir)}`);
123
+ return `${name}: ${parts.join(', ')}`;
124
+ }
125
+ function refsNow(ctx) {
126
+ const at = (n) => { const b = ctx.rig.find(n); return b !== null ? worldOf(ctx.three, b) : null; };
127
+ const head = at('head'), clav = at('clavicle_r'), pelvis = at('pelvis'), spine = at('spine_03');
128
+ return {
129
+ head: head !== null ? head.y : null,
130
+ shoulder: clav !== null ? clav.y : 0,
131
+ hip: pelvis !== null ? pelvis.y : 0,
132
+ centerX: spine !== null ? spine.x : 0,
133
+ centerZ: spine !== null ? spine.z : 0,
134
+ };
135
+ }
136
+ async function inspectGesture(opts) {
137
+ let raw;
138
+ try {
139
+ raw = opts.clip === '-' ? (0, node_fs_1.readFileSync)(0, 'utf8') : (0, node_fs_1.readFileSync)(opts.clip, 'utf8');
140
+ }
141
+ catch (err) {
142
+ throw new Error(`cannot read the gesture clip ${opts.clip}: ${err instanceof Error ? err.message : String(err)}`);
143
+ }
144
+ let source;
145
+ try {
146
+ source = JSON.parse(raw);
147
+ }
148
+ catch (err) {
149
+ throw new Error(`${opts.clip} is not valid JSON: ${err.message}`);
150
+ }
151
+ const runtime = await (0, worldRuntime_1.loadGestureRuntime)(opts.worldDir);
152
+ const { three } = runtime;
153
+ const compiled = runtime.compileGesture(source);
154
+ const rig = opts.rig ? await (0, rig_1.glbRig)(three, opts.rig) : (0, rig_1.canonicalRig)(three);
155
+ // The player captures the bind pose at construction — must happen before anything poses the rig.
156
+ const ctx = { three, rig, player: new runtime.GesturePlayer(rig.root) };
157
+ const bones = opts.bones ?? exports.DEFAULT_BONES;
158
+ const times = (opts.times ?? []).length > 0 || opts.motion === true || opts.axes === true ? (opts.times ?? []) : ['0'];
159
+ const handFrames = new Map();
160
+ for (const name of bones)
161
+ if (/^hand_(l|r)$/.test(name))
162
+ handFrames.set(name, handFrame(ctx, name));
163
+ // ---- static frames --------------------------------------------------------------------------------
164
+ const frames = [];
165
+ for (const spec of times) {
166
+ const seconds = spec.endsWith('%') ? (parseFloat(spec) / 100) * compiled.gesture.duration : parseFloat(spec);
167
+ if (Number.isNaN(seconds))
168
+ throw new Error(`--t: '${spec}' is not a number of seconds or a percentage`);
169
+ poseAt(ctx, compiled.gesture, seconds);
170
+ const ref = refsNow(ctx);
171
+ const out = {};
172
+ for (const name of bones) {
173
+ const bone = rig.find(name);
174
+ if (bone === null) {
175
+ out[name] = { reads: `${name}: no such bone`, error: 'no such bone' };
176
+ continue;
177
+ }
178
+ const pos = worldOf(three, bone);
179
+ const child = childBone(bone);
180
+ const dir = child !== undefined ? worldOf(three, child).sub(pos).normalize() : null;
181
+ const entry = { pos: vec(pos), dir: dir !== null ? vec(dir) : null, reads: describePose(name, pos, dir, ref) };
182
+ if (handFrames.has(name))
183
+ entry.facing = facingNow(ctx, handFrames.get(name));
184
+ out[name] = entry;
185
+ }
186
+ frames.push({ t: seconds, bones: out });
187
+ }
188
+ // ---- --motion: what the clip DOES over time -------------------------------------------------------
189
+ // A static frame cannot show this. Tracks each bone's TIP, so wrist/finger rotation is visible.
190
+ let motion = null;
191
+ if (opts.motion === true) {
192
+ motion = {};
193
+ const paths = new Map(bones.map((n) => [n, []]));
194
+ const [w0, w1] = opts.motionWindow ?? [0, compiled.gesture.duration];
195
+ for (let i = 0; i < MOTION_SAMPLES; i++) {
196
+ poseAt(ctx, compiled.gesture, w0 + (i / (MOTION_SAMPLES - 1)) * (w1 - w0));
197
+ for (const name of bones) {
198
+ const bone = rig.find(name);
199
+ if (bone !== null)
200
+ paths.get(name).push(tipOf(three, bone));
201
+ }
202
+ }
203
+ for (const [name, path] of paths) {
204
+ if (path.length === 0) {
205
+ motion[name] = { reads: `${name}: no such bone`, error: 'no such bone' };
206
+ continue;
207
+ }
208
+ const ext = ['x', 'y', 'z'].map((k) => {
209
+ const vals = path.map((p) => p[k]);
210
+ return Math.max(...vals) - Math.min(...vals);
211
+ });
212
+ const [lateral, vertical, depth] = ext;
213
+ let length = 0;
214
+ for (let i = 1; i < path.length; i++)
215
+ length += path[i].distanceTo(path[i - 1]);
216
+ const dominant = ext.indexOf(Math.max(...ext));
217
+ const total = Math.hypot(lateral, vertical, depth) || 1;
218
+ // Reversals along the dominant axis: a wave has several, a one-way reach has none.
219
+ const key = ['x', 'y', 'z'][dominant];
220
+ let reversals = 0, sign = 0;
221
+ for (let i = 1; i < path.length; i++) {
222
+ const d = path[i][key] - path[i - 1][key];
223
+ if (Math.abs(d) < 1e-4)
224
+ continue;
225
+ const s = Math.sign(d);
226
+ if (sign !== 0 && s !== sign)
227
+ reversals++;
228
+ sign = s;
229
+ }
230
+ const label = ['side-to-side', 'up-and-down', 'front-to-back'][dominant];
231
+ const purity = round(ext[dominant] / total, 2);
232
+ motion[name] = {
233
+ lateral: round(lateral), vertical: round(vertical), depth: round(depth),
234
+ pathLength: round(length), dominant: label, purity, reversals,
235
+ reads: `${name}: moves ${round(ext[dominant], 2)}m ${label} (purity ${purity}), `
236
+ + `lateral ${round(lateral, 2)} / vertical ${round(vertical, 2)} / depth ${round(depth, 2)}, ${reversals} reversal(s)`,
237
+ };
238
+ }
239
+ }
240
+ // ---- --axes: what each keyed axis actually does AT the posed chain ---------------------------------
241
+ // The rest-frame table cannot answer this once parents have rotated. Perturbs the SOURCE key value (what
242
+ // an author would edit) and recompiles, so the reported effect is exactly what changing that number does.
243
+ let axes = null;
244
+ if (opts.axes === true) {
245
+ const keys = Array.isArray(source.keys) ? source.keys : [];
246
+ const probeName = opts.probe ?? [...bones].reverse().find((n) => rig.find(n) !== null) ?? 'hand_r';
247
+ axes = { probe: probeName, keys: [] };
248
+ for (let ki = 0; ki < keys.length; ki++) {
249
+ const key = keys[ki];
250
+ const bonesAtKey = key.bones ?? {};
251
+ const t = key.t ?? 0;
252
+ poseAt(ctx, compiled.gesture, t);
253
+ const probeBone = rig.find(probeName);
254
+ if (probeBone === null)
255
+ break;
256
+ const base = tipOf(three, probeBone);
257
+ const rows = [];
258
+ for (const boneName of Object.keys(bonesAtKey)) {
259
+ for (let ai = 0; ai < 3; ai++) {
260
+ const probeSource = JSON.parse(JSON.stringify(source));
261
+ probeSource.keys[ki].bones[boneName][ai] += AXIS_PROBE_DEG;
262
+ let probeGesture;
263
+ try {
264
+ probeGesture = runtime.compileGesture(probeSource).gesture;
265
+ }
266
+ catch {
267
+ continue;
268
+ }
269
+ poseAt(ctx, probeGesture, t);
270
+ const moved = tipOf(three, rig.find(probeName)).sub(base);
271
+ const mag = moved.length();
272
+ if (mag < 1e-4) {
273
+ rows.push({ axis: `${boneName}.${AXIS_NAMES[ai]}`, magnitude: 0, reads: `${boneName}.${AXIS_NAMES[ai]}: no effect on ${probeName}` });
274
+ continue;
275
+ }
276
+ const unit = moved.clone().normalize();
277
+ rows.push({
278
+ axis: `${boneName}.${AXIS_NAMES[ai]}`, magnitude: round(mag), delta: vec(moved),
279
+ reads: `${boneName}.${AXIS_NAMES[ai]}: +${AXIS_PROBE_DEG}° moves ${probeName} ${round(mag, 3)}m ${compass(unit)}`,
280
+ });
281
+ poseAt(ctx, compiled.gesture, t);
282
+ }
283
+ }
284
+ rows.sort((a, b) => b.magnitude - a.magnitude);
285
+ axes.keys.push({ t, rows });
286
+ }
287
+ }
288
+ return {
289
+ clip: compiled.gesture.name,
290
+ duration: compiled.gesture.duration,
291
+ rig: rig.source,
292
+ system: runtime.systemPath,
293
+ warnings: compiled.warnings ?? [],
294
+ frames,
295
+ motion,
296
+ axes,
297
+ keyedAxisRows: relevantAxisRows(runtime.axisTable, source),
298
+ };
299
+ }
300
+ /** Human-readable report. `--json` returns the InspectResult instead. */
301
+ function formatInspect(r, opts = {}) {
302
+ const out = [`${r.clip} (${r.duration}s) — rig ${r.rig}`];
303
+ if (r.warnings.length > 0)
304
+ out.push(`warnings:\n ${r.warnings.join('\n ')}`);
305
+ for (const f of r.frames) {
306
+ out.push(`\nt=${f.t}s`);
307
+ for (const [name, b] of Object.entries(f.bones)) {
308
+ out.push(` ${b.reads}`);
309
+ if (b.pos !== undefined)
310
+ out.push(` pos=${JSON.stringify(b.pos)} dir=${JSON.stringify(b.dir)}`);
311
+ if (b.facing != null)
312
+ out.push(` ${b.facing.unavailable !== undefined ? `facing unavailable — ${b.facing.unavailable}` : b.facing.reads}`);
313
+ }
314
+ }
315
+ if (r.motion !== null) {
316
+ out.push(`\nmotion over ${opts.motionWindow ? `t=${opts.motionWindow[0]}..${opts.motionWindow[1]}` : 'the whole clip'}`);
317
+ for (const m of Object.values(r.motion))
318
+ out.push(` ${m.reads}`);
319
+ }
320
+ if (r.axes !== null) {
321
+ out.push(`\naxis effects at the posed chain (probe: ${r.axes.probe}, +${AXIS_PROBE_DEG}° each)`);
322
+ for (const k of r.axes.keys) {
323
+ if (k.rows.length === 0)
324
+ continue;
325
+ out.push(` t=${k.t}s`);
326
+ for (const row of k.rows.slice(0, 8))
327
+ out.push(` ${row.reads}`);
328
+ }
329
+ }
330
+ if (r.warnings.length > 0 && r.keyedAxisRows.length > 0) {
331
+ out.push('\nnatural ranges for the bones this clip keys (outside them warns, it does not fail)');
332
+ for (const row of r.keyedAxisRows) {
333
+ out.push(` ${row.bones} x ${row.natural.x.join('…')} y ${row.natural.y.join('…')} z ${row.natural.z.join('…')}`);
334
+ }
335
+ }
336
+ return out.join('\n');
337
+ }
338
+ /** Natural-range context for the bones a clip actually keys — the table rows that matter, not all 15. */
339
+ function relevantAxisRows(table, clipJson) {
340
+ if (table === null)
341
+ return [];
342
+ const keyed = new Set();
343
+ for (const key of Array.isArray(clipJson?.keys) ? clipJson.keys : [])
344
+ for (const b of Object.keys(key.bones ?? {}))
345
+ keyed.add(b);
346
+ const seen = new Set();
347
+ const hits = [];
348
+ for (const bone of keyed) {
349
+ const ref = (0, axisReference_1.axisReferenceFor)(table, bone);
350
+ if (ref === undefined || seen.has(ref))
351
+ continue;
352
+ seen.add(ref);
353
+ hits.push({ bones: ref.bones.source, axes: ref.axes, natural: ref.natural });
354
+ }
355
+ return hits;
356
+ }
357
+ //# sourceMappingURL=inspect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.js","sourceRoot":"","sources":["../../src/gesture/inspect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export interface Rig {
2
+ root: any;
3
+ /** Bind-pose quaternion per bone, captured before any posing — the pose reset restores from this. */
4
+ bind: Map<any, any>;
5
+ find: (name: string) => any | null;
6
+ source: string;
7
+ }
8
+ /** The embedded canonical skeleton: local rest transforms are column-major mat4s, decomposed to TRS. */
9
+ export declare function canonicalRig(three: any): Rig;
10
+ /** A custom character's own rig. Only names + TRS are read, so KTX2 textures never need transcoding.
11
+ * Mirrors `buildRig` in the engine's scripts/pose.mjs — same SYNC OBLIGATION as ./inspect.ts. */
12
+ export declare function glbRig(three: any, glbPath: string): Promise<Rig>;