import { type HeldItemPresetLike, type PoseDescriptionLike } from './worldRuntime'; import { type BoneAxisReference } from './axisReference'; export declare const DEFAULT_BONES: string[]; export interface InspectOptions { worldDir: string; /** Clip JSON path, or '-' for stdin. */ clip: string; /** Times in seconds, or '35%' of duration. Empty + no motion/axes ⇒ ['0']. */ times?: string[]; bones?: string[]; motion?: boolean; axes?: boolean; /** Isolate part of the clip for --motion; without it the rest→pose→rest travel dominates every number. */ motionWindow?: [number, number] | null; /** Which bone --axes measures the effect on (default: the last requested bone that exists). */ probe?: string | null; /** Custom character GLB; default is the embedded canonical skeleton. */ rig?: string | null; /** Measure a prop attachment alongside the pose readback (grip-frame bbox, unit verdict, posed placement). */ attach?: InspectAttachSpec | null; } export interface InspectAttachSpec { /** Prop GLB path. */ prop: string; /** Explicit socket; defaults to the preset's, then hand_r.grip. */ socket?: string | null; /** HELD_ITEM_PRESETS key contributing default socket/offsets. */ preset?: string | null; /** Socket-local offsets (m / deg, XYZ). Explicit values override the preset's. */ position?: [number, number, number] | null; rotationEulerDeg?: [number, number, number] | null; } export interface BoneReadback { pos?: number[]; dir?: number[] | null; reads: string; facing?: FacingReadback | null; error?: string; } export interface FacingReadback { palm?: number[]; fingers?: number[]; reads?: string; unavailable?: string; } export interface MotionReadback { lateral?: number; vertical?: number; depth?: number; pathLength?: number; dominant?: string; purity?: number; reversals?: number; reads: string; error?: string; } export interface AxisRow { axis: string; magnitude: number; delta?: number[]; reads: string; } /** A serializable axis-table row. `bones` is the group's pattern SOURCE, not a RegExp — the result of this * module is JSON-emitted (`--json`, the MCP), and a RegExp stringifies to `{}`, losing the group identity. */ export interface AxisRangeRow { bones: string; axes: { x: string; y: string; z: string; }; natural: { x: [number, number]; y: [number, number]; z: [number, number]; }; } export interface AttachmentReadback { prop: string; socket: string; preset: string | null; position: number[]; rotationEulerDeg: number[]; /** True when the preset's offsets were sagitally auto-mirrored for the opposite grip socket (the runtime rule). */ mirrored: boolean; bbox: { min: number[]; max: number[]; }; span: number; unitVerdict: string; gripFrame: { min: number[]; max: number[]; reads: string; }; } export interface AttachmentPlacement { center: number[]; dir: number[]; up: number[]; reads: string; } /** One authored ik goal: target → resolved joint eulers → canonical landing → this-rig landing. */ export interface IkGoalReadback { key: number; t: number; hand: string; goal: { position: number[]; palm: string | null; elbow: string | null; }; resolved: Record; canonical: { position: number[]; palm: number[]; errM: number; reads: string; } | null; rig: { position: number[]; errM: number; } | null; warnings: string[]; reads: string; } export interface InspectResult { clip: string; duration: number; rig: string; system: string; warnings: string[]; frames: { t: number; bones: Record; attachment?: AttachmentPlacement; hands?: PoseDescriptionLike; }[]; motion: Record | null; axes: { probe: string; keys: { t: number; rows: AxisRow[]; }[]; } | null; /** Per-goal ik readback (automatic when the clip has `ik` keys and the system supports them); null otherwise. */ ik: { goals: IkGoalReadback[]; note?: string; } | null; /** Axis-table rows for the bones this clip actually keys — the context a warning needs, not all 15 groups. */ keyedAxisRows: AxisRangeRow[]; /** Prop measurement when `attach` was requested; null otherwise. */ attachment: AttachmentReadback | null; } /** Exported for tests: these two produce the human-facing readback, and are duck-typed on .x/.y/.z so * they need no three. A sign error here silently misleads every measurement an agent takes. */ /** Coarse compass for a unit vector — never a precise angle, because conformed rigs differ by ~20° at the extremities. */ export declare function compass(v: any): string; /** Exported for tests: resolves the attach spec exactly as AttachmentService.attach would. */ export declare function resolveAttachSpec(spec: InspectAttachSpec, presets: Readonly> | null): { socket: string; position: [number, number, number]; rotationEulerDeg: [number, number, number]; mirrored: boolean; }; /** Exported for tests. The runtime rejection wording creators actually hit, plus the too-small suspicion. */ export declare function unitVerdictFor(span: number): string; /** Exported for tests — duck-typed on .x/.y/.z like compass. English for the socket-frame bbox; the grip * frame IS the semantic held-item frame (+z out, +y up). */ export declare function gripFrameReads(sMin: any, sMax: any): string; export interface Refs { head: number | null; shoulder: number; hip: number; centerX: number; centerZ: number; } /** Plain-English readback so an agent with no eyes can still tell a good pose from a broken one. */ export declare function describePose(name: string, pos: any, dir: any, ref: Refs): string; export declare function inspectGesture(opts: InspectOptions): Promise; /** Human-readable report. `--json` returns the InspectResult instead. */ export declare function formatInspect(r: InspectResult, opts?: { motionWindow?: [number, number] | null; }): string; /** Natural-range context for the bones a clip actually keys — the table rows that matter, not all 15. */ export declare function relevantAxisRows(table: readonly BoneAxisReference[] | null, clipJson: any): AxisRangeRow[];