One line per module, plus the design rules that keep the codebase coherent. The authoritative research spec is ../pipeline.md; this file maps spec → code.
- No hardware literal outside
configs/hardware.yaml. Every tensor shape, rate, unit scale and threshold derives fromHardwareConfig. Ranks are fixed by the schema; values are expected to change after the bench. Checkpoints snapshot the config and refuse to load if shape-relevant fields changed (value-only changes warn). - Import discipline.
phantom/config,data,drivers,recording,timesync,teleop,evalandtestsnever importcosmos_predict2— they run on any machine. Onlyphantom/backboneandphantom/model(andtrain/inference/deploythrough them) touch cosmos, always viaphantom.backbone.loader.setup_cosmos()(installs shims + sys.path). - One prefix separates ours from theirs. Every new trainable parameter
name contains
phantom_(LoRA params containlora_). Base-checkpoint loading, freezing, checkpoint save/load and teacher→student init are all a single prefix test (backbone/loader.py,train/common.py). - One contact ontology.
phantom/config/model.py::EVENTS(none/onset/hold/slip/release) is shared by derived labels, ACC, ACE and eval.phantom/data/derived.pyis the single implementation of every derived quantity — recording post-pass, dataloaders, ACC labels, HID-S reward and eval metrics all call the same functions. - RF targets are deterministic. Generated groups (contact package,
actions) are packed into latent frames by parameter-free codecs
(
model/ace/packing.py); trainable capacity lives on the input side (HHT) and in the readout heads.
hardware.yaml— the hardware value store;BENCH:marks unverified defaults.paths.yaml(+ optionalpaths.local.yaml) — cosmos repo/weights, data/run roots.eval_campaign.example.yaml— template forrun_eval.
hardware.py— pydantic schema + cross-field validators (CB3⇒FT-300S+125 Hz, divisibility, channel sum = 8, executor==RTDE rate, force-unit sentinel …) and derived quantities (cpk_shape,ur_state_dim,field_bytes_per_s,config_hash,shape_relevant_fields).paths.py— paths schema, local-override merge.backbone.py— transcribed frozen Cosmos net kwargs + latent geometry +tiny()CPU preset +verify_against_state_dict()(transcription-drift guard).model.py— HapticWAM-specific knobs: layout counts, loss weights λ, LoRA r/α, ACC config,rope_time_mode,studentflag; the EVENTS ontology.training.py— dataclass configs for the four training programs.
derived.py— pure numpy: contact mask, CoP (f_z-weighted centroid), slip score (flow ⊕ friction-cone blend), event labels (debounced transitions), gate label, reactive (CASA) statistic, τ_obj auto-calibration, peak force.schema.py— canonical stream names,EpisodeMeta,NormStats.episode_store.py— zarr v2 episodes (data+tsper stream),EpisodeReaderwith nearest/window/interp queries on the master clock.windows.py—WindowSampler: episode → model-tick training window (video, gel, fields, contact state, wrist window, UR state, action chunks, contact-package targets, event/gate labels). Timestamp-driven — degraded rates load identically. Warns on provenance (episode recorded under different shape-relevant config).synthetic.py— schema-conforming episodes from the mock signal model on a virtual clock (--syntheticsmoke data). Regenerated per config hash.contact_play.py— full-res keyframe dataset for the tactile SSL pretrain.
base.py—TactileSensor/Arm/Gripper/CameraABCs, frame dataclasses,Rigaggregate; first-frame shape checks against the config.mock/scenario.py—ContactScenario: the deterministic phase machine (approach→onset→hold→slip→release) ALL mocks share, with the wrist-F/T ramp leading tactile onset (ACC lead-time structure).mock/{dmtac,ur,robotiq,realsense}.py— co-varying synthetic signals; the tactile mock emits SDK-unit forces consistent with the configured unit scale.real/dmtac.py—dmroboticswrapper; hw_order transpose and force-unit scaling happen at this boundary, nowhere else.real/ur.py—ur_rtde; Receive always, Control only onconnect(control=True)(exclusive ownership), protective-stop reconnect.real/robotiq.py— URCap socket (port 63352) ASCII protocol.real/realsense.py— pyrealsense2.factory.py—make_rig(hw): real/mock per configmodesection.
ringbuffer.py— single-writer shared-memory rings (lock-free readers).workers.py— per-tactile-sensor spawn-safe processes (in-child downsample + f16 + keyframe decimation; full-res frames never cross IPC except keyframes); arm/gripper/camera thread pollers;SensorSession.recorder.py— drains rings → zarr episode; t_host→t_master mapping; throughput watchdog vs the config-derived estimate.postprocess.py— offline derived-channel pass (recomputable when τ change).timesync/clock.py— RTDE master clock (lowest-latency-decile calibration, EWMA drift); identity in mock mode.teleop/— keyboard (works everywhere) + SpaceMouse; episode-control button semantics (start/stop, success/fail, failure tagging, F/T zero).
compat.py—sys.modulesshims fortransformer_engine(RMSNorm + RoPE, numerics-matched),megatron,multistorageclient; valid__spec__for peft probing. Shim parity must be verified on Linux before trusting full-checkpoint numbers (scripts/verify_backbone.py).loader.py—setup_cosmos(shims + sys.path +cosmos_cudastub),build_phantom_net,load_base_weights(stripnet./accum_*/_extra_state; assert missing ⊂phantom_*),inject_lora(peft, after base load),set_trainable.vae.py— frozen Wan2.1 VAE wrapper + geometry-exactFakeVAEfor smoke.text_embedding.py— cached empty-string Reason1 embedding (what the action-cond checkpoint was post-trained with).
sequence.py—SequenceLayout: THE single source of truth for the extended frame axis (video | obs | contact | action), cond mask, frame-type ids, RoPE positions, structural attention mask, haptic-group token mask. Student/drop-video variants are layout changes, not new architectures.phantom_dit.py—PhantomDiT(ActionChunkConditionedMinimalV1LVGDiT): re-implemented forward on the same submodules; frame-type embeddings (zero-init), custom per-frame RoPE, intent chunk through the pretrained action-AdaLN path, ACC gate + attention bias, CONTACT hidden taps.attention_bias.py—BiasHolder/BiasedSDPAOpwrap of each block'sself_attn.attn_op(torch-SDPA backend only, hard-asserted). The holder is cleared at the START of the next forward — activation checkpointing re-runs blocks during backward and must see the same bias.acc.py— the anticipatory gate: φ over [wrist TCN ‖ z_vis ‖ intent ‖ prev-ĉ summary]; g/p_evt/α heads; CASA reactive term; α≡0 ⇒ CASA, student ⇒ α→1.hht/— tactile field conv encoder (+ SSL pretrain heads), contact-state MLP, wrist TCN, UR-state MLP, observation-frame assembly.ace/packing.py— deterministic ContactPackage/action ⇄ latent-frame codecs (per-finger Δ-fields, event bands, CoP bumps in per-finger local coords, slip tiles, wrench/wrist block grids; action value strips).ace/heads.py— EventReadout + SigmaHead (heteroscedastic σ → HID confidence + speed governor).ace/losses.py— grouped RF objective (λ_a/λ_v/λ_c/λ_w + ACC auxiliaries).rf.py—PhantomRectifiedFlow: build_x0 (FRAME_REPLACE), training_step,prepare_denoise(shared-(x_t,t) hook for HID/HID-S), few-NFE Eulersample()with drop-video.
builder.py—build_model(): layout → net (+base weights, +LoRA) → HHT → RF wrapper;tiny=TrueCPU preset.common.py— DDP, optimizer/scheduler, EMA, checkpoint format (never re-saves the 2B base; lora + phantom + EMA + config snapshots + norm stats),WindowDataset, synthetic-dataset provisioning, generic train loop.pretrain_tactile.py(1) — masked recon + cross-channel SSL.train_teacher.py(2) — teacher fine-tune, joint objective.distill_hid.py(3) — saliency×confidence trajectory distillation + soft event KL + shared-noise action-velocity behavior matching + GT grounding.dagger_driver.py(3b) — relabel rollouts → manifest → re-distill.finetune_hids.py(4) — AWR with auto-τ_obj + KL leash to frozen reference.
inference/policy.py—PhantomPolicy.replan(obs, prev_plan)→Plan(denormalized chunk on the action grid, σ profile, gate, contact package = next replan's ACC input).deploy/planner.py— ObsSnapshot from rings (system modes select model inputs; tactile always recorded), replan loop, planner trace.deploy/executor.py— executor-rate servo streaming, cumulative-delta pose interp, governed playback time, chunk swap + blend, stale-plan hold.deploy/governor.py— σ → playback speed (path-preserving).deploy/safety.py— wrench/tactile/workspace/protective-stop checks every tick, priority over the governor, t_master-logged events.deploy/runtime.py— wires one episode/trial end to end.
Ground-up operator app for Echo teleop + data collection — see
data_collect_app.md for the why/how; entry point
phantom/scripts/collect.py. Reuses phantom.drivers/recording/
teleop.echo/viz.rerun_logger underneath; replaces only the application
layer that drives them.
config.py—configs/data_collect.yamlschema (ports/serials, external drive, teleop feel, safeguard defaults, mode);load_collect()patches the hardware config's ports section before validation.teleop.py—DirectServoStreamer: pulls the Echo reader's cached target everycontrol_rate_hzcycle (no 10 Hz hop), TRACK is a pure per-cycle slew limit (transparent belowv_max),AccelLimitedTrackerglide kept only for ENGAGE/resume; all phase transitions are compare-and-set so a concurrent safeguardhold()always wins; workspace hold retreats to the last safely-inside pose; protective-stop recovery reconnects the control interface.gripper.py—GripperPilot: continuous 0..1 position on its own thread, pulling the leader's freshest squeeze value (device-rate, not the session loop); pad-force/close clamps stay at the driver boundary.safeguard.py—TactileSafeguard(latched trip on fingertip force / indentation / stream staleness; runtime-editable thresholds; resume only via an explicit call) +ArmGuard(wrench/protective-stop, auto-resume).session.py—CollectApp: the main loop (episode lifecycle, absoluteactions_abslogging, safeguard/arm-guard bookkeeping) andCollectEcho(adds live gripper-tick calibration tophantom.teleop.echo.EchoTeleop).panel.py— stdlib SSE control panel (safeguard card, session wizard with the full/lite mode switch, gripper calibration, offload card).rerun_view.py—CollectRerun(RerunLogger): mode-gated live view (full = everything; lite = scene RGB + arm + gripper + tactile wrench only).offload.py— verified move of staged episodes to the external drive (per-file size/sha256 check before local delete; same-filesystem guard).playback.py— episode playback + recording verification from the panel:verify_episode(per-stream integrity report: presence vs the mode's expected set, rates, monotonic ts, finite values),EpisodePlayer(wall-clock-paced replay of every modality into the embedded rerun viewer on a separatet_episodetimeline; pause/stop/speed), andPlaybackController(drive/staging scan, path confinement, mutual exclusion with sessions/offloads). CLI:phantom/scripts/play_episode.py.
dagger/rollout.py— student rollouts with full-sensor recording.dagger/relabel.py— offline teacher relabeling from recorded streams.dagger/manifest.py— round-k training mixes (DAgger on/off ablation).eval/trial_runner.py— campaign YAML → resumable ledger CSV.eval/tactile_prediction.py— tactile prediction error: the predicted contact package of every replan (deploy/cpk_trace.py→planner_cpk.npz) scored against the pads' later measurements next to a persistence baseline (tpe_*skill scores;docs/tactile_prediction_error.md).eval/metrics.py— peak force, threshold violations, slip recovery, ACC lead time (gate crossing vs derived onset), event F1, latency.eval/aggregate.py— recovery ratio + retention tables, markdown report, lead-time distribution export.
mock_smoke · smoke_test · verify_backbone · bench_day1 ·
record_episodes · postprocess_episodes · dump_norm_stats · run_deploy ·
run_dagger_round · run_eval · collect (phantom.data_collect's entry
point — data_collect_app.md) · play_episode
(verify/replay a recorded episode without the panel) — see
launch_guide.md.