@helix3/helix-cli 0.1.10-helix3.49 → 0.1.11-helix3.50

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.
@@ -1,5 +1,6 @@
1
1
  import { type BrowserKey } from '../screenshot/captureScreenshots';
2
2
  import { type HarnessConfig } from './harnessPage';
3
+ import { type InspectAttachSpec } from './inspect';
3
4
  export declare const VIEW_NAMES: readonly ["front", "back", "right", "left", "three-quarter"];
4
5
  export type ViewName = typeof VIEW_NAMES[number];
5
6
  export declare const MAX_VIEWS = 2;
@@ -20,6 +21,8 @@ export type CaptureGestureOptions = {
20
21
  /** One moment instead of a sequence: seconds, or a percentage of duration like '60%'. Views go side by
21
22
  * side at roughly 1.8x the cell size, for inspecting a specific detail rather than comparing over time. */
22
23
  at?: number | string;
24
+ /** Render a prop attached while the clip plays — same spec as inspect's, resolved against the world's presets. */
25
+ attach?: InspectAttachSpec;
23
26
  cellHeight?: number;
24
27
  timeoutMs?: number;
25
28
  browser?: BrowserKey;
@@ -36,6 +39,12 @@ export type CaptureGestureResult = {
36
39
  /** True when both views look down the same axis, so neither reveals depth — worth telling the caller. */
37
40
  sharedAxis: boolean;
38
41
  warnings: string[];
42
+ /** What was attached, when a prop was requested. */
43
+ attachment: {
44
+ prop: string;
45
+ socket: string;
46
+ preset: string | null;
47
+ } | null;
39
48
  };
40
49
  export declare function captureGesture(opts: CaptureGestureOptions): Promise<CaptureGestureResult>;
41
50
  type ClipShape = {
@@ -55,6 +55,7 @@ const node_path_1 = require("node:path");
55
55
  const captureScreenshots_1 = require("../screenshot/captureScreenshots");
56
56
  const staticServe_1 = require("../screenshot/staticServe");
57
57
  const harnessPage_1 = require("./harnessPage");
58
+ const inspect_1 = require("./inspect");
58
59
  const worldRuntime_1 = require("./worldRuntime");
59
60
  const paths_1 = require("../paths");
60
61
  /** 0/25/50/75/100 % of the clip — enough to read a gesture's arc without a sheet per frame. */
@@ -113,6 +114,19 @@ async function captureGesture(opts) {
113
114
  (0, node_fs_1.copyFileSync)((0, node_path_1.join)(vendorDir(), 'capture-body.glb'), (0, node_path_1.join)(stage, 'capture-body.glb'));
114
115
  (0, node_fs_1.copyFileSync)((0, node_path_1.join)(vendorDir(), 'capture-face.glb'), (0, node_path_1.join)(stage, 'capture-face.glb'));
115
116
  (0, node_fs_1.copyFileSync)(opts.clip, (0, node_path_1.join)(stage, 'clip.json'));
117
+ // Prop attaches resolve presets NODE-side (the world's own runtime), so a stale system fails here with
118
+ // install guidance instead of as a bare page error. The prop is COPIED into the stage — the static
119
+ // server's traversal guard is string-compare, so serving from an arbitrary path is off the table.
120
+ let attach = null;
121
+ if (opts.attach !== undefined) {
122
+ const runtime = await (0, worldRuntime_1.loadGestureRuntime)(opts.worldDir);
123
+ if (runtime.SocketService === null || runtime.defaultSockets === null) {
124
+ throw new Error('the installed humanoid-character does not export SocketService/DEFAULT_SOCKETS — it predates attachment tooling.\n'
125
+ + ' Rerun the install and rebuild: MCP: install_world_packages · CLI: helix install.');
126
+ }
127
+ attach = (0, inspect_1.resolveAttachSpec)(opts.attach, runtime.heldItemPresets);
128
+ (0, node_fs_1.copyFileSync)(opts.attach.prop, (0, node_path_1.join)(stage, 'prop.glb'));
129
+ }
116
130
  // The page needs concrete seconds, not fractions, so the clip is parsed here rather than in-page.
117
131
  const source = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(stage, 'clip.json'), 'utf8'));
118
132
  const duration = readDuration(source, opts.clip);
@@ -121,7 +135,7 @@ async function captureGesture(opts) {
121
135
  const times = moment
122
136
  ? [parseMoment(opts.at, duration)]
123
137
  : Array.from({ length: frames }, (_, i) => Math.round((i / (frames - 1)) * duration * 1000) / 1000);
124
- const config = { ...arrangeGrid(times, chosen, moment, side), cellW, cellH };
138
+ const config = { ...arrangeGrid(times, chosen, moment, side), cellW, cellH, ...(attach !== null && { attach }) };
125
139
  (0, node_fs_1.writeFileSync)((0, node_path_1.join)(stage, 'index.html'), (0, harnessPage_1.harnessPage)(config));
126
140
  const playwright = await Promise.resolve().then(() => __importStar(require('playwright')));
127
141
  server = await (0, staticServe_1.startStaticServer)(stage);
@@ -167,6 +181,9 @@ async function captureGesture(opts) {
167
181
  moment,
168
182
  sharedAxis: sharesAxis(chosen),
169
183
  warnings: state.warnings ?? [],
184
+ attachment: attach !== null && opts.attach !== undefined
185
+ ? { prop: opts.attach.prop, socket: attach.socket, preset: opts.attach.preset ?? null }
186
+ : null,
170
187
  };
171
188
  }
172
189
  finally {
@@ -1 +1 @@
1
- {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/gesture/capture.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/gesture/capture.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,12 @@ export interface HarnessConfig {
12
12
  rowLabels: string[];
13
13
  cellW: number;
14
14
  cellH: number;
15
+ /** Attach /prop.glb to this socket with RESOLVED offsets (capture resolves presets node-side). */
16
+ attach?: {
17
+ socket: string;
18
+ position: [number, number, number];
19
+ rotationEulerDeg: [number, number, number];
20
+ };
15
21
  }
16
22
  export declare const READY_FLAG = "__helixGestureCapture";
17
23
  export declare function harnessPage(config: HarnessConfig): string;
@@ -35,7 +35,7 @@ function harnessPage(config) {
35
35
  <script type="module">
36
36
  import * as THREE from 'three';
37
37
  import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
38
- import { compileGesture, GesturePlayer } from '/helix_modules/humanoid-character/index.js';
38
+ import { compileGesture, GesturePlayer${config.attach !== undefined ? ', SocketService, DEFAULT_SOCKETS' : ''} } from '/helix_modules/humanoid-character/index.js';
39
39
 
40
40
  const CONFIG = ${JSON.stringify(config)};
41
41
  const FLAG = ${JSON.stringify(exports.READY_FLAG)};
@@ -56,7 +56,13 @@ try {
56
56
  root.traverse((n) => { if (n.isBone === true) bind.set(n, n.quaternion.clone()); });
57
57
  parts.push({ root, bind, player: new GesturePlayer(root) });
58
58
  }
59
-
59
+ ${config.attach !== undefined ? `
60
+ // Body carries the full skeleton; sockets build in bind pose — before anything poses the rig. The prop
61
+ // rides its bone from here on, so the union-bbox framing below covers it at every sampled time for free.
62
+ const sockets = new SocketService(parts[0].root, DEFAULT_SOCKETS);
63
+ const prop = (await loader.loadAsync('/prop.glb')).scene;
64
+ sockets.attach(CONFIG.attach.socket, prop, 'capture', { position: CONFIG.attach.position, rotationEulerDeg: CONFIG.attach.rotationEulerDeg });
65
+ ` : ''}
60
66
  const scene = new THREE.Scene();
61
67
  scene.background = new THREE.Color(0xf4f4f6);
62
68
  for (const p of parts) scene.add(p.root);
@@ -1 +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"}
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;;;AAuBxG,kCAwIC;AA1IY,QAAA,UAAU,GAAG,uBAAuB,CAAC;AAElD,SAAgB,WAAW,CAAC,MAAqB;IAC/C,OAAO;;;;;;;;;;;;;;;;;;;;;wCAqB+B,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAAC,EAAE;;iBAE5F,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;eACxB,IAAI,CAAC,SAAS,CAAC,kBAAU,CAAC;;;;;;;;;;;;;;;;;;EAkBvC,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC;;;;;;CAM/B,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsFL,CAAC;AACF,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { type HeldItemPresetLike, type PoseDescriptionLike } from './worldRuntime';
1
2
  import { type BoneAxisReference } from './axisReference';
2
3
  export declare const DEFAULT_BONES: string[];
3
4
  export interface InspectOptions {
@@ -15,6 +16,19 @@ export interface InspectOptions {
15
16
  probe?: string | null;
16
17
  /** Custom character GLB; default is the embedded canonical skeleton. */
17
18
  rig?: string | null;
19
+ /** Measure a prop attachment alongside the pose readback (grip-frame bbox, unit verdict, posed placement). */
20
+ attach?: InspectAttachSpec | null;
21
+ }
22
+ export interface InspectAttachSpec {
23
+ /** Prop GLB path. */
24
+ prop: string;
25
+ /** Explicit socket; defaults to the preset's, then hand_r.grip. */
26
+ socket?: string | null;
27
+ /** HELD_ITEM_PRESETS key contributing default socket/offsets. */
28
+ preset?: string | null;
29
+ /** Socket-local offsets (m / deg, XYZ). Explicit values override the preset's. */
30
+ position?: [number, number, number] | null;
31
+ rotationEulerDeg?: [number, number, number] | null;
18
32
  }
19
33
  export interface BoneReadback {
20
34
  pos?: number[];
@@ -61,6 +75,53 @@ export interface AxisRangeRow {
61
75
  z: [number, number];
62
76
  };
63
77
  }
78
+ export interface AttachmentReadback {
79
+ prop: string;
80
+ socket: string;
81
+ preset: string | null;
82
+ position: number[];
83
+ rotationEulerDeg: number[];
84
+ bbox: {
85
+ min: number[];
86
+ max: number[];
87
+ };
88
+ span: number;
89
+ unitVerdict: string;
90
+ gripFrame: {
91
+ min: number[];
92
+ max: number[];
93
+ reads: string;
94
+ };
95
+ }
96
+ export interface AttachmentPlacement {
97
+ center: number[];
98
+ dir: number[];
99
+ reads: string;
100
+ }
101
+ /** One authored ik goal: target → resolved joint eulers → canonical landing → this-rig landing. */
102
+ export interface IkGoalReadback {
103
+ key: number;
104
+ t: number;
105
+ hand: string;
106
+ goal: {
107
+ position: number[];
108
+ palm: string | null;
109
+ elbow: string | null;
110
+ };
111
+ resolved: Record<string, number[]>;
112
+ canonical: {
113
+ position: number[];
114
+ palm: number[];
115
+ errM: number;
116
+ reads: string;
117
+ } | null;
118
+ rig: {
119
+ position: number[];
120
+ errM: number;
121
+ } | null;
122
+ warnings: string[];
123
+ reads: string;
124
+ }
64
125
  export interface InspectResult {
65
126
  clip: string;
66
127
  duration: number;
@@ -70,6 +131,8 @@ export interface InspectResult {
70
131
  frames: {
71
132
  t: number;
72
133
  bones: Record<string, BoneReadback>;
134
+ attachment?: AttachmentPlacement;
135
+ hands?: PoseDescriptionLike;
73
136
  }[];
74
137
  motion: Record<string, MotionReadback> | null;
75
138
  axes: {
@@ -79,13 +142,31 @@ export interface InspectResult {
79
142
  rows: AxisRow[];
80
143
  }[];
81
144
  } | null;
145
+ /** Per-goal ik readback (automatic when the clip has `ik` keys and the system supports them); null otherwise. */
146
+ ik: {
147
+ goals: IkGoalReadback[];
148
+ note?: string;
149
+ } | null;
82
150
  /** Axis-table rows for the bones this clip actually keys — the context a warning needs, not all 15 groups. */
83
151
  keyedAxisRows: AxisRangeRow[];
152
+ /** Prop measurement when `attach` was requested; null otherwise. */
153
+ attachment: AttachmentReadback | null;
84
154
  }
85
155
  /** Exported for tests: these two produce the human-facing readback, and are duck-typed on .x/.y/.z so
86
156
  * they need no three. A sign error here silently misleads every measurement an agent takes. */
87
157
  /** Coarse compass for a unit vector — never a precise angle, because conformed rigs differ by ~20° at the extremities. */
88
158
  export declare function compass(v: any): string;
159
+ /** Exported for tests: resolves the attach spec exactly as AttachmentService.attach would. */
160
+ export declare function resolveAttachSpec(spec: InspectAttachSpec, presets: Readonly<Record<string, HeldItemPresetLike>> | null): {
161
+ socket: string;
162
+ position: [number, number, number];
163
+ rotationEulerDeg: [number, number, number];
164
+ };
165
+ /** Exported for tests. The runtime rejection wording creators actually hit, plus the too-small suspicion. */
166
+ export declare function unitVerdictFor(span: number): string;
167
+ /** Exported for tests — duck-typed on .x/.y/.z like compass. English for the socket-frame bbox; the grip
168
+ * frame IS the semantic held-item frame (+z out, +y up). */
169
+ export declare function gripFrameReads(sMin: any, sMax: any): string;
89
170
  export interface Refs {
90
171
  head: number | null;
91
172
  shoulder: number;
@@ -1,7 +1,43 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.DEFAULT_BONES = void 0;
4
37
  exports.compass = compass;
38
+ exports.resolveAttachSpec = resolveAttachSpec;
39
+ exports.unitVerdictFor = unitVerdictFor;
40
+ exports.gripFrameReads = gripFrameReads;
5
41
  exports.describePose = describePose;
6
42
  exports.inspectGesture = inspectGesture;
7
43
  exports.formatInspect = formatInspect;
@@ -94,6 +130,150 @@ function facingNow(ctx, frame) {
94
130
  const fingers = frame.fingersLocal.clone().applyQuaternion(q);
95
131
  return { palm: vec(palm), fingers: vec(fingers), reads: `palm faces ${compass(palm)}, fingers point ${compass(fingers)}` };
96
132
  }
133
+ // ---- Attachment measurement --------------------------------------------------------------------------
134
+ // Mirrors AttachmentService.attach: explicit offsets override the preset's, the socket falls back to the
135
+ // preset's own, and the span gate is the runtime's DEFAULT_MAX_PROP_SPAN_M rejection — keep them equal.
136
+ const MAX_PROP_SPAN_M = 2;
137
+ /** Exported for tests: resolves the attach spec exactly as AttachmentService.attach would. */
138
+ function resolveAttachSpec(spec, presets) {
139
+ let preset = null;
140
+ if (spec.preset != null) {
141
+ if (presets === null) {
142
+ throw new Error('the installed humanoid-character does not export HELD_ITEM_PRESETS — it predates attachments (added in 0.2.14).\n'
143
+ + ' Any existing ^0.2 pin already allows it — no helix.json edit needed, just rerun the install and rebuild:\n'
144
+ + ' MCP: install_world_packages · CLI: helix install (via npx: `npx @hypersoniclabs/helix-cli install` — bare `helix` is an unrelated npm package).');
145
+ }
146
+ preset = presets[spec.preset] ?? null;
147
+ if (preset === null)
148
+ throw new Error(`--preset: unknown preset '${spec.preset}' (known: ${Object.keys(presets).join(', ')})`);
149
+ }
150
+ return {
151
+ socket: spec.socket ?? preset?.socket ?? 'hand_r.grip',
152
+ position: spec.position ?? preset?.position ?? [0, 0, 0],
153
+ rotationEulerDeg: spec.rotationEulerDeg ?? preset?.rotationEulerDeg ?? [0, 0, 0],
154
+ };
155
+ }
156
+ /** Exported for tests. The runtime rejection wording creators actually hit, plus the too-small suspicion. */
157
+ function unitVerdictFor(span) {
158
+ if (span > MAX_PROP_SPAN_M) {
159
+ return `runtime REJECTS this prop: spans ${round(span, 2)} m (limit ${MAX_PROP_SPAN_M} m) — almost always a cm/mm unit slip; author props in meters`;
160
+ }
161
+ return span < 0.01 ? `suspiciously small: ${round(span, 3)} m max span — double unit conversion?` : `meters OK (${round(span, 2)} m max span)`;
162
+ }
163
+ /** Exported for tests — duck-typed on .x/.y/.z like compass. English for the socket-frame bbox; the grip
164
+ * frame IS the semantic held-item frame (+z out, +y up). */
165
+ function gripFrameReads(sMin, sMax) {
166
+ const parts = [];
167
+ if (sMax.z > 0.005)
168
+ parts.push(`extends ${round(sMax.z, 2)}m out along +z`);
169
+ if (sMin.z < -0.005)
170
+ parts.push(`${round(-sMin.z, 2)}m behind the grip point`);
171
+ if (sMax.y > 0.005)
172
+ parts.push(`${round(sMax.y, 2)}m above it`);
173
+ if (sMin.y < -0.005)
174
+ parts.push(`${round(-sMin.y, 2)}m below`);
175
+ const inside = sMin.x <= 0 && sMax.x >= 0 && sMin.y <= 0 && sMax.y >= 0 && sMin.z <= 0 && sMax.z >= 0;
176
+ if (inside)
177
+ parts.push('grip origin is inside the prop volume');
178
+ else {
179
+ const clamp = (v, lo, hi) => Math.min(Math.max(v, lo), hi);
180
+ const dist = Math.hypot(clamp(0, sMin.x, sMax.x), clamp(0, sMin.y, sMax.y), clamp(0, sMin.z, sMax.z));
181
+ parts.push(`grip origin is OUTSIDE the prop volume (nearest point ${round(dist, 3)}m away — is the grip modeled at the origin?)`);
182
+ }
183
+ return parts.join(', ');
184
+ }
185
+ /** Node-side GLB reads carry no geometry objects, so the bbox comes from POSITION accessor min/max per
186
+ * primitive — the same conservative corner-transform bound Box3.setFromObject computes in the browser. */
187
+ async function propCorners(three, glbPath) {
188
+ const { NodeIO } = await Promise.resolve().then(() => __importStar(require('@gltf-transform/core')));
189
+ const { ALL_EXTENSIONS } = await Promise.resolve().then(() => __importStar(require('@gltf-transform/extensions')));
190
+ let doc;
191
+ try {
192
+ doc = await new NodeIO().registerExtensions(ALL_EXTENSIONS).read(glbPath);
193
+ }
194
+ catch (err) {
195
+ throw new Error(`--attach: ${glbPath} is not a readable .glb/.gltf — ${err instanceof Error ? err.message : String(err)}`);
196
+ }
197
+ const scene = doc.getRoot().listScenes()[0];
198
+ if (scene === undefined)
199
+ throw new Error(`--attach: prop GLB has no scenes: ${glbPath}`);
200
+ const corners = [];
201
+ const visit = (node, parent) => {
202
+ const local = new three.Matrix4().compose(new three.Vector3().fromArray(node.getTranslation()), new three.Quaternion().fromArray(node.getRotation()), new three.Vector3().fromArray(node.getScale()));
203
+ const world = new three.Matrix4().multiplyMatrices(parent, local);
204
+ const mesh = node.getMesh();
205
+ if (mesh !== null) {
206
+ for (const prim of mesh.listPrimitives()) {
207
+ const pos = prim.getAttribute('POSITION');
208
+ const pMin = pos?.getMin([]);
209
+ const pMax = pos?.getMax([]);
210
+ if (pMin == null || pMax == null)
211
+ continue;
212
+ for (let i = 0; i < 8; i++) {
213
+ corners.push(new three.Vector3((i & 1) === 0 ? pMin[0] : pMax[0], (i & 2) === 0 ? pMin[1] : pMax[1], (i & 4) === 0 ? pMin[2] : pMax[2]).applyMatrix4(world));
214
+ }
215
+ }
216
+ }
217
+ for (const child of node.listChildren())
218
+ visit(child, world);
219
+ };
220
+ for (const node of scene.listChildren())
221
+ visit(node, new three.Matrix4());
222
+ if (corners.length === 0)
223
+ throw new Error(`--attach: prop GLB has no mesh geometry: ${glbPath}`);
224
+ return corners;
225
+ }
226
+ function boxOf(three, points) {
227
+ const min = new three.Vector3(Infinity, Infinity, Infinity);
228
+ const max = new three.Vector3(-Infinity, -Infinity, -Infinity);
229
+ for (const p of points) {
230
+ min.min(p);
231
+ max.max(p);
232
+ }
233
+ return { min, max };
234
+ }
235
+ async function measureAttachment(runtime, ctx, spec) {
236
+ if (runtime.SocketService === null || runtime.defaultSockets === null) {
237
+ throw new Error('the installed humanoid-character does not export SocketService/DEFAULT_SOCKETS — it predates attachment tooling.\n'
238
+ + ' Rerun the install and rebuild: MCP: install_world_packages · CLI: helix install.');
239
+ }
240
+ const resolved = resolveAttachSpec(spec, runtime.heldItemPresets);
241
+ const { three } = ctx;
242
+ let sockets;
243
+ try {
244
+ sockets = new runtime.SocketService(ctx.rig.root, runtime.defaultSockets); // bind pose — the same construction-time constraint as Character
245
+ }
246
+ catch (err) {
247
+ throw new Error(`--attach: socket construction failed on this rig: ${err instanceof Error ? err.message : String(err)}`);
248
+ }
249
+ if (sockets.has(resolved.socket) !== true) {
250
+ throw new Error(`--socket: '${resolved.socket}' is not defined (defined: ${sockets.list().join(', ')})`);
251
+ }
252
+ const corners = await propCorners(three, spec.prop);
253
+ const local = boxOf(three, corners);
254
+ const size = local.max.clone().sub(local.min);
255
+ const span = Math.max(size.x, size.y, size.z);
256
+ const offsetQ = new three.Quaternion().setFromEuler(new three.Euler(...resolved.rotationEulerDeg.map((d) => (d * Math.PI) / 180), 'XYZ'));
257
+ const offsetP = new three.Vector3().fromArray(resolved.position);
258
+ const inSocket = boxOf(three, corners.map((c) => c.clone().applyQuaternion(offsetQ).add(offsetP)));
259
+ return {
260
+ report: {
261
+ prop: spec.prop, socket: resolved.socket, preset: spec.preset ?? null,
262
+ position: resolved.position, rotationEulerDeg: resolved.rotationEulerDeg,
263
+ bbox: { min: vec(local.min), max: vec(local.max) }, span: round(span, 3), unitVerdict: unitVerdictFor(span),
264
+ gripFrame: { min: vec(inSocket.min), max: vec(inSocket.max), reads: gripFrameReads(inSocket.min, inSocket.max) },
265
+ },
266
+ socket: resolved.socket, sockets, offsetQ, center: inSocket.min.clone().add(inSocket.max).multiplyScalar(0.5),
267
+ };
268
+ }
269
+ /** Posed placement of the prop: where its volume center lands and where its +z points, right now. */
270
+ function attachmentPlacement(three, attach, ref) {
271
+ const pose = { position: new three.Vector3(), quaternion: new three.Quaternion() };
272
+ attach.sockets.getWorldTransform(attach.socket, pose);
273
+ const center = attach.center.clone().applyQuaternion(pose.quaternion).add(pose.position);
274
+ const dir = new three.Vector3(0, 0, 1).applyQuaternion(pose.quaternion.clone().multiply(attach.offsetQ));
275
+ return { center: vec(center), dir: vec(dir), reads: describePose(`prop@${attach.socket}`, center, dir, ref) };
276
+ }
97
277
  /** Plain-English readback so an agent with no eyes can still tell a good pose from a broken one. */
98
278
  function describePose(name, pos, dir, ref) {
99
279
  const parts = [];
@@ -149,17 +329,87 @@ async function inspectGesture(opts) {
149
329
  throw new Error(`${opts.clip} is not valid JSON: ${err.message}`);
150
330
  }
151
331
  const runtime = await (0, worldRuntime_1.loadGestureRuntime)(opts.worldDir);
332
+ // The gate MUST fire before compiling: a pre-0.2.15 system silently ignores an `ik` field (or fails
333
+ // blaming keys[].bones), so the clip would inspect WRONG rather than error.
334
+ if ((0, worldRuntime_1.clipUsesIk)(source) && runtime.describePose === null)
335
+ throw new Error(worldRuntime_1.IK_UNSUPPORTED_MESSAGE);
152
336
  const { three } = runtime;
153
337
  const compiled = runtime.compileGesture(source);
154
338
  const rig = opts.rig ? await (0, rig_1.glbRig)(three, opts.rig) : (0, rig_1.canonicalRig)(three);
155
339
  // The player captures the bind pose at construction — must happen before anything poses the rig.
156
340
  const ctx = { three, rig, player: new runtime.GesturePlayer(rig.root) };
341
+ // Sockets are built in bind pose too, so the attachment must be measured before anything poses the rig.
342
+ const attach = opts.attach != null ? await measureAttachment(runtime, ctx, opts.attach) : null;
157
343
  const bones = opts.bones ?? exports.DEFAULT_BONES;
158
344
  const times = (opts.times ?? []).length > 0 || opts.motion === true || opts.axes === true ? (opts.times ?? []) : ['0'];
159
345
  const handFrames = new Map();
160
346
  for (const name of bones)
161
347
  if (/^hand_(l|r)$/.test(name))
162
348
  handFrames.set(name, handFrame(ctx, name));
349
+ // ---- ik report: goal → resolved eulers → canonical landing → this-rig landing ----------------------
350
+ // Two skeletons can be in play: describePose runs on the system's EMBEDDED canonical snapshot; poseAt runs
351
+ // the requested rig. With --rig their disagreement is conform drift, not a solver bug — show both.
352
+ const eulerDegAt = (bone, t) => {
353
+ const track = compiled.gesture.tracks.find((tr) => tr.bone === bone);
354
+ if (track === undefined)
355
+ return null;
356
+ const i = track.times.findIndex((time) => Math.abs(time - t) < 1e-6);
357
+ if (i === -1)
358
+ return null;
359
+ const e = new three.Euler().setFromQuaternion(track.quats[i], 'ZYX');
360
+ return [e.x, e.y, e.z].map((r) => round((r * 180) / Math.PI, 1));
361
+ };
362
+ let ik = null;
363
+ if (runtime.describePose !== null) {
364
+ const keys = Array.isArray(source.keys) ? source.keys : [];
365
+ const goals = [];
366
+ const clipWarnings = compiled.warnings ?? [];
367
+ for (let ki = 0; ki < keys.length; ki++) {
368
+ const ikGoals = keys[ki]?.ik;
369
+ if (typeof ikGoals !== 'object' || ikGoals === null)
370
+ continue;
371
+ const t = keys[ki].t ?? 0;
372
+ const described = runtime.describePose(compiled.gesture, t);
373
+ poseAt(ctx, compiled.gesture, t);
374
+ for (const side of ['l', 'r']) {
375
+ const goal = ikGoals[`hand_${side}`];
376
+ if (goal === undefined || !Array.isArray(goal.position))
377
+ continue;
378
+ const hand = side === 'l' ? described.leftHand : described.rightHand;
379
+ const bone = rig.find(`hand_${side}`);
380
+ const rigPos = bone !== null ? worldOf(three, bone) : null;
381
+ const dist = (p) => round(Math.hypot(p[0] - goal.position[0], p[1] - goal.position[1], p[2] - goal.position[2]), 3);
382
+ const canonicalErr = hand !== null ? dist(hand.position) : null;
383
+ const rigErr = rigPos !== null ? dist([rigPos.x, rigPos.y, rigPos.z]) : null;
384
+ const resolved = {};
385
+ for (const emitted of [`upperarm_${side}`, `lowerarm_${side}`, ...(goal.palm !== undefined ? [`hand_${side}`] : [])]) {
386
+ const e = eulerDegAt(emitted, t);
387
+ if (e !== null)
388
+ resolved[emitted] = e;
389
+ }
390
+ const bucket = clipWarnings.filter((w) => w.startsWith(`keys[${ki}].ik`));
391
+ goals.push({
392
+ key: ki, t, hand: `hand_${side}`,
393
+ goal: { position: goal.position, palm: goal.palm ?? null, elbow: goal.elbow ?? null },
394
+ resolved,
395
+ canonical: hand !== null && canonicalErr !== null ? { position: hand.position, palm: hand.palm, errM: canonicalErr, reads: hand.text } : null,
396
+ rig: rigPos !== null && rigErr !== null ? { position: vec(rigPos), errM: rigErr } : null,
397
+ warnings: bucket,
398
+ reads: `keys[${ki}] ${side === 'l' ? 'left' : 'right'} hand → [${goal.position.join(', ')}]`
399
+ + `${goal.palm !== undefined ? ` palm ${goal.palm}` : ''}${goal.elbow !== undefined ? ` elbow ${goal.elbow}` : ''}`
400
+ + `${canonicalErr !== null ? ` — canonical lands ${round(canonicalErr * 100, 1)} cm off` : ''}`
401
+ + `${rigErr !== null && canonicalErr !== null ? `, this rig ${round(rigErr * 100, 1)} cm off (Δ = conform drift)` : ''}`
402
+ + `${bucket.length > 0 ? ` — ${bucket.length} warning(s)` : ''}`,
403
+ });
404
+ }
405
+ }
406
+ if (goals.length > 0) {
407
+ ik = { goals };
408
+ // describePose measures against REST — an additive clip layers over live locomotion instead.
409
+ if (source.compose === 'additive')
410
+ ik.note = 'additive clip: landings are measured against rest, not the locomotion it will layer onto';
411
+ }
412
+ }
163
413
  // ---- static frames --------------------------------------------------------------------------------
164
414
  const frames = [];
165
415
  for (const spec of times) {
@@ -183,7 +433,16 @@ async function inspectGesture(opts) {
183
433
  entry.facing = facingNow(ctx, handFrames.get(name));
184
434
  out[name] = entry;
185
435
  }
186
- frames.push({ t: seconds, bones: out });
436
+ const frame = { t: seconds, bones: out };
437
+ if (attach !== null)
438
+ frame.attachment = attachmentPlacement(three, attach, ref);
439
+ // Canonical-skeleton landmark inverse (0.2.15+) — null per hand when the clip never keys that arm.
440
+ if (runtime.describePose !== null) {
441
+ const described = runtime.describePose(compiled.gesture, seconds);
442
+ if (described.rightHand !== null || described.leftHand !== null)
443
+ frame.hands = described;
444
+ }
445
+ frames.push(frame);
187
446
  }
188
447
  // ---- --motion: what the clip DOES over time -------------------------------------------------------
189
448
  // A static frame cannot show this. Tracks each bone's TIP, so wrist/finger rotation is visible.
@@ -294,14 +553,39 @@ async function inspectGesture(opts) {
294
553
  frames,
295
554
  motion,
296
555
  axes,
556
+ ik,
297
557
  keyedAxisRows: relevantAxisRows(runtime.axisTable, source),
558
+ attachment: attach !== null ? attach.report : null,
298
559
  };
299
560
  }
300
561
  /** Human-readable report. `--json` returns the InspectResult instead. */
301
562
  function formatInspect(r, opts = {}) {
302
563
  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 ')}`);
564
+ // ik-attributed warnings print bucketed under their goal below — keep the top block for the rest.
565
+ const topWarnings = r.ik !== null ? r.warnings.filter((w) => !/^keys\[\d+\]\.ik/.test(w)) : r.warnings;
566
+ if (topWarnings.length > 0)
567
+ out.push(`warnings:\n ${topWarnings.join('\n ')}`);
568
+ if (r.ik !== null) {
569
+ out.push(`\nik goals${r.ik.note !== undefined ? ` (${r.ik.note})` : ''}:`);
570
+ for (const g of r.ik.goals) {
571
+ out.push(` ${g.reads}`);
572
+ if (g.canonical !== null)
573
+ out.push(` canonical: ${g.canonical.reads}`);
574
+ for (const [bone, e] of Object.entries(g.resolved))
575
+ out.push(` resolved ${bone}: [${e.join(', ')}]°`);
576
+ for (const w of g.warnings)
577
+ out.push(` ! ${w}`);
578
+ }
579
+ }
580
+ if (r.attachment != null) {
581
+ const a = r.attachment;
582
+ const range = (min, max) => AXIS_NAMES.map((k, i) => `${k} ${min[i]}…${max[i]}`).join(' · ');
583
+ out.push(`\nattachment: ${a.prop.split(/[\\/]/).pop()} → ${a.socket}${a.preset !== null ? ` (preset ${a.preset})` : ''}`);
584
+ out.push(` offsets: position ${JSON.stringify(a.position)} m · rotation ${JSON.stringify(a.rotationEulerDeg)} deg`);
585
+ out.push(` prop bbox (m): ${range(a.bbox.min, a.bbox.max)} — ${a.unitVerdict}`);
586
+ out.push(` grip frame (m): ${range(a.gripFrame.min, a.gripFrame.max)}`);
587
+ out.push(` ${a.gripFrame.reads}`);
588
+ }
305
589
  for (const f of r.frames) {
306
590
  out.push(`\nt=${f.t}s`);
307
591
  for (const [name, b] of Object.entries(f.bones)) {
@@ -311,6 +595,15 @@ function formatInspect(r, opts = {}) {
311
595
  if (b.facing != null)
312
596
  out.push(` ${b.facing.unavailable !== undefined ? `facing unavailable — ${b.facing.unavailable}` : b.facing.reads}`);
313
597
  }
598
+ if (f.hands !== undefined) {
599
+ for (const h of [f.hands.rightHand, f.hands.leftHand])
600
+ if (h !== null && h !== undefined)
601
+ out.push(` hands: ${h.text}`);
602
+ }
603
+ if (f.attachment !== undefined) {
604
+ out.push(` ${f.attachment.reads}`);
605
+ out.push(` center=${JSON.stringify(f.attachment.center)} dir=${JSON.stringify(f.attachment.dir)}`);
606
+ }
314
607
  }
315
608
  if (r.motion !== null) {
316
609
  out.push(`\nmotion over ${opts.motionWindow ? `t=${opts.motionWindow[0]}..${opts.motionWindow[1]}` : 'the whole clip'}`);