AgentCanvas / Pages / Developer Guide / Core / Glossary
Reach for the section that matches the code/ADR you're reading, not an alphabetical lookup. Only terms that are currently live in the codebase are listed; removed/superseded names live in the changelog of the v1 source + the ADR that retired them. v2 addition: live filter β€” type in the box and only matching terms remain.
Press / to focus Β· Esc to clear.

Β§1Canvas & Editor

The visual editor β€” canvas surface, node catalog sidebar, toolbar, graph-save/load surface. One editor, one registry, one catalog at every graph level (ADR-canvas-002).

Flat WorkspaceComfyUI-style canvas where all node types coexist on one surface β€” no outer/inner layer split (see ADR-canvas-001)
Canvas StackNavigation stack for entering/exiting composite node subgraphs; replaces the binary layer toggle (see ADR-dataflow-001)
Root CanvasThe top-level graph (replaces "outer graph" in the recursive model)
SubgraphThe graph inside any composite node (replaces "inner graph" as the general term)
UnifiedGraphEditorDual-mode React Flow editor: root mode reads from Zustand store, subgraph mode uses local state with save-back (see ADR-canvas-002)
Unified Node RegistrySingle map (unifiedNodeTypes.ts) with 2 custom components (compositeNode, stateContainer) + _generic Proxy fallback to GenericBlockRenderer. All other node types (14 built-in + NodeSet tools) are rendered via the Proxy β€” no explicit entry needed
NodeSet ManagerDedicated UI page for managing NodeSets, server-mode nodesets, and environments β€” separate from the canvas (see ADR-canvas-001)
ExecutionToolbarStandalone Play/Pause/Stop/Step/Reset toolbar at page level (see ADR-canvas-002)
SaveGraphDialogModal dialog for saving the current canvas graph with a user-defined name to workspace/graphs/
Source tabBottom-panel tab (between Logs and Report) that edits the selected node's slice of its NodeSet source β€” module-level globals, the functions its class transitively references, and the class itself β€” spliced back by line range via PUT /api/components/nodesets/{name}/source/scoped; local NodeSets hot-reload via the nodeset watcher, server-mode ones are flagged stale until restarted
getGraphForExecution()Zustand store method that serializes the root canvas as a GraphDefinition, filtering out the frontend-only stateContainer node type (FRONTEND_ONLY_TYPES; containers travel as graph.containers + access_grants, not nodes). Output viewers are real backend nodes and are sent along

Β§2Graph Data Model

The pure-data JSON schema that travels over the wire and sits in workspace/graphs/. Framework doesn't read domain data here β€” only topology + configuration.

GraphDefinitionUniversal graph type (replaces AgentLoopDefinition) β€” recursive: contains NodeDef[] which may themselves contain subgraphs (see ADR-dataflow-001)
NodeDefUniversal node type used at every nesting depth (replaces InnerNode) β€” may contain optional subgraph for composites
EdgeDefUniversal edge type used at every nesting depth (replaces InnerEdge)
Composite NodeA node that contains a subgraph (GraphDefinition). Any group of nodes can become a composite with defined I/O via graphIn/graphOut
graphInBoundary node inside a composite that defines an input on the parent composite node β€” the composite's parameter slot (class GraphInNode; formerly PortIn)
graphOut (boundary)Boundary node inside a composite that defines an output on the parent composite node β€” the composite's return slot (class GraphOutNode; formerly PortOut). The same node type doubles as the WebSocket sink (Β§9)
FlattenRecursive expansion of composite nodes into a flat graph before execution β€” backend never sees nesting
FlattenMapMapping from flattened node IDs to their original composite path, used for error tracing
kind (GraphDefinition)Field distinguishing graph types: "graph" (editable template, opens in tab) vs "node" (frozen composite, draggable). Default "graph", backward compatible (see ADR-canvas-003)
Graph NodeA saved graph archived as a frozen reusable composite (kind="node"). Stored in workspace/graph_nodes/, draggable onto any canvas. Uses snapshot semantics β€” copies by value, no reference to source

Β§3Component System

The extension surface β€” base classes authors subclass in workspace/, auto-discovered by WorkspaceComponentRegistry at startup and hot-reload.

BaseCanvasNodeUniversal base class for all canvas nodes with forward() method, ui_config (NodeUIConfig) for Python-driven rendering, typed port declarations, and voluntary logging via _self_log() / log()
BaseNodeSetBase class for atomic tool groups that load/unload together β€” managed on the NodeSet Manager page
Component RegistryRuntime system that auto-discovers Python classes in workspace/ and bridges them into the platform
NodeUIConfigClassVar on BaseCanvasNode declaring visual properties (color, layout, width, min_height, rounding), config_fields (user-editable inline widgets), and display_fields (read-only runtime data widgets). Layout values: block, strip, viewer, note, imageGrid. Enables Python-driven node UI β€” one Python class = one canvas node, no .tsx needed
ConfigFieldDataclass declaring an inline user-editable config control on a canvas node. 7 widget types: label, slider, text, select, toggle, textarea, port_list
DisplayFieldDataclass declaring a read-only runtime data display widget on a canvas node. 4 display types: image_viewer (base64 β†’ img), log_list (scrollable entry list), metric_table (key-value metrics), text_viewer (scrollable text block)
GenericBlockRendererUniversal frontend React component that renders any BaseCanvasNode from its ui_config. Thin dispatcher delegating to layout components: BlockLayout, StripLayout, ViewerLayout
ports_modeClass-level field on BaseCanvasNode controlling how config.ports is mapped onto input/output schemas: "sink" (input-only), "source" (output-only), "input" (inputs from config), "mirror" (both sides mirror config)
batched / batch_dimClassVars on BaseCanvasNode opting a node into the batched-inference tier. batched: bool = False (default). When True, batch_dim: str must name an actual input port β€” that port carries the per-sample slot the server stacks across K callers (see ADR-eval-002)
parallelismClassVar on BaseNodeSet declaring deployment topology under eval worker_count>1 (see ADR-server-003). Values: "shared" (default β€” 1 instance; K callers coalesce through the already-hosted BatchedInferenceServer) or "replicated" (stateful env nodesets opt in β€” N independent tagged copies, one per worker). worker_count=1 is bit-identical in both modes

Β§4Wire & Dataflow

Typed edges between ports β€” how data moves between nodes, per-firing. Separate from state containers (Β§5).

Wire TypeTyped data carried by data wires. Current set (9): IMAGE, DEPTH, POSE, DISCRETE_ACTION, CONTROL, TEXT, BOOL, METRICS, ANY (standard/wire_types.py). Any inner type T may be wrapped as LIST[T]; each current type has one canonical on-wire format in WIRE_FORMAT_SPEC. POSE was renamed from STATE in ADR-dataflow-004 so that "state" can refer exclusively to stored memory slots
DISCRETE_ACTIONint | str β€” index or id into the env's declared valid action set. Replaces the retired VLN-only ACTION type (fixed 0–3): no fixed range, the env nodeset declares the space. The VLN 0–3 space (Β§10) is one instance
CONTROLContinuous control command for VLA / manipulation: dict{pos:[3], rot:[3] axis-angle rad, gripper: float∈[-1,1] (+1=open), joint_position?:[N]}. Split from the old single ACTION type together with DISCRETE_ACTION so the catalog spans VLN / VLA / manipulation
Deprecated wire typesACTION (alias of DISCRETE_ACTION), OBSERVATION, STEP_RESULT β€” kept registered only so legacy graphs/nodesets load until the migration sweep; do not use in new graphs. OBSERVATION lost to flat rgb/depth ports; STEP_RESULT lost to the gym-style tuple
LIST[T]Wire-type modifier (ADR-dataflow-005). Any wire type T may be wrapped as LIST[T] to make a port carry list[T]. Producers emit scalar T; consumer ports declared LIST[T] always see a list β€” the executor wraps single values to [value] and concatenates fan-in in edge declaration order at one port-binding seam. Enables multi-image LLM calls, multi-LLM debate, search-operator population fan-in. Nested LIST[LIST[T]] is not supported in v1
Data EdgeDirectional wire carrying typed data between node ports β€” the primary data transport. Solid animated line, colored by wire type

Β§5State Containers

Visible shared state β€” distinct from wires because they carry no data and do not trigger firing. Multi-writer, cross-iteration, checkpointable.

StateContainerA dict of named BaseState entries, rendered as a visible canvas element. Holds agent memory β€” multi-writer, cross-iteration, checkpointable, read does not trigger firing
BaseStateAbstract base for a single named state entry. Parameterized by reducer type (accumulator, lastWrite, counter), a value type (TEXT, POSE, POINTCLOUD, …), and a reset_on list expanded from lifetime. Default on_signal clears to initial_value when a subscribed signal fires
AccumulatorStateBaseState reducer that appends each write to a list. Config: max_size trims oldest
LastWriteStateBaseState reducer that keeps only the most recent value
CounterStateBaseState reducer that sums numeric writes
LifetimeState-clearing axis orthogonal to the reducer. Values: forever (default), step, episode, run, custom. At build time, each lifetime expands into a reset_on signal list the state subscribes to via on_signal
SignalNamed framework event delivered to states via broadcast_signal(name, payload). The executor emits run_start, step_start, step_end (at each IterOut boundary), and run_end; episode_reset is emitted by env panels (an action returning side_effect="signal"), not the executor. A state's lifetime expands to a reset_on signal list; the default on_signal clears the state to initial_value when a subscribed signal fires
Access GrantAuthorisation for a node to read() / write() a StateContainer. Not a wire: carries no data, does not trigger firing. Rendered as a dashed violet line. Renamed from "State Edge" in ADR-dataflow-004
State Value TypeNarrow registry for memory slot shapes (ADR-dataflow-004): TEXT, BOOL, METRICS, POSE, POINTCLOUD, OCCUPANCY_MAP, EMBEDDING, EPISODE_CONTEXT, ANY. Raw wire payloads rejected by build_container
StateDefGraph definition entry for a single named state: reducer type + value type + lifetime + config
ContainerDefGraph definition entry for a state container: id, label, position, dict of StateDefs
AccessGrantDefGraph definition entry authorising a node to read/write a container: {id, node_id, container_id}. Lives in graph.access_grants. Renamed from StateEdgeDef in ADR-dataflow-004
__state__ portHidden bottom-center handle on every node for attaching access grants. Visible only when the access-grant toggle is on (CSS-controlled)
graph_stateWell-known container id "graph_state" β€” a regular ContainerDef in graph.containers that plays the role of the graph-level blackboard. Every node that wants access must hold an explicit AccessGrantDef to it. Nodes with the grant get a convenience binding ctx._graph_state
Nodeset-owned containerA container owned by a BaseNodeSet via get_containers() rather than declared in graph JSON β€” may hold opaque (non-JSON-safe) values via allow_opaque and supports per-key eviction so worker-parallel eval can isolate per-episode entries. Lives in the nodeset's home process; a shared server nodeset owning mutable containers draws a load-time warning (roadmap #68)

Β§6Execution Engine

The runtime that turns a GraphDefinition into a live agent run β€” node scheduling, iteration gates, termination.

Graph ExecutorData-driven executor β€” nodes fire when inputs arrive. Handles both DAG workflows (single forward pass) and cyclic agent loops (via IterIn/IterOut). No separate DAG executor exists
Entry nodeA node the executor queues at run-start, discovered automatically (no author marking) by three structural conditions: not an iterIn, no incoming edges, no required input ports. Entry nodes fire first and feed the rest of the graph; a loop starts when an entry node’s output reaches the iterIn’s init_* handles. Formerly called β€œseed node” (renamed 2026-06-11 β€” β€œseed” collided with RNG seeds and AAS seed data)
Loop RunnerSingleton that wraps the executor and manages pause/stop/resume lifecycle
InitializeRemoved (2026-06-10, follow-through of ADR-dataflow-008): its run-start collection role lives on iterIn's left/input side (declared via iterIn.config.initPorts). The node type is no longer registered; validate_graph_connectivity rejects graphs that still carry one, with a migration hint. Historic (ADR-dataflow-006): a run-start pivot (node_type="initialize", ports_mode="sink") that collected step-0 state and handed it to the paired iterIn via executor-internal pairedWith transfer
initPortsConfig list on a two-sided iterIn (ADR-dataflow-008) declaring its run-start left/input ports β€” [{name, wire_type, persist}]. _synthesize_iterin_ports reads these as init_-origin slots (the former initialize node's role, removed 2026-06-10). Named to avoid the rejected legacy init_ports key
IterIn / IterOutIteration boundary pivots. Since ADR-dataflow-008 iterIn is two-sided: its left input ports (declared in initPorts) receive run-start values captured once into init_ slots, and its right output ports expose the loop-carry bundle. Loop-carry values arrive via executor transfer from iterOut (per-iteration); init values arrive as ordinary incoming edges routed into port_slots.
port_slotsField on NodeInstance (iterIn only). One slot per synthesised port, keyed by the prefixed handle (init_<X> / iterout_<X>); written by run-start init edges and the iterOut transfer, read on every iterIn fire. Replaces the former init_port_cache + pending_inputs split
pairedWithConfig field on iterOut storing the id of the paired iterIn. Drives the executor-internal transfer that delivers values into iterIn's port_slots without a canvas edge
validate_graph_connectivityLoad-time validator in graph_def.py. Rejects any graph that contains a node with a required input port lacking an incoming edge, raising ValueError translated to HTTP 400 at the run/eval API boundaries
Termination NodeRemoved (2026-06-11): its halt role lives on the loop iterOut's stop input port, checked once per iteration by the engine's Decide phase; validate_graph_connectivity rejects graphs that still carry one, with a migration hint. Historic: a node that ended the agent loop when done=true, bound to its innermost containing scope (ADR-dataflow-007)
stop portClass-level BOOL input on iterOut β€” the loop's halt signal. Wired from the done/is_stop producer; read by the iterOut-boundary Decide check exactly once per iteration. Unwired = budget-only loop. A bare stop with no loop-carry value does not fire the boundary. Excluded from the loop-carry transfer and the final mirror
Final sideiterOut's right/output side: one final_<name> handle per loop-carry port plus the constant final_stop (True once at termination β€” the canonical after-loop trigger). Emits exactly once when the scope terminates (stop, budget exhaust, or best-effort on the error path), carrying the terminal iteration's values. Edges from iterOut may use only these handles
After-loop bandThe downstream closure of the root iterOut's final-side edges β€” the verdict stage (evaluate β†’ graphOut chains), fed exactly once at termination and drained by _after_loop_pass. Purity rule: band nodes take inputs only from the final side or from other band nodes ("verdict inputs ride the pivot"). Replaces the removed config.post_loop flag β€” membership is derivable from topology
execution_idUUID generated per run, tags all WebSocket events to route them to the correct output nodes
ScopeOne (iterIn, iterOut) pair plus its body, IO interface (graphIn/graphOut), and per-scope config β€” the unit of iteration cadence in a graph (ADR-dataflow-007). The scope's canonical id is its iter_in node id
Scope ForestComputed by analyze_scopes() in agent_loop/scope_analysis.py. The set of all scopes in a graph plus their parent/child topology
Inner Scope / Outer ScopeRelative terms in a nested scope tree. An inner scope's iter_in and iter_out both lie in an outer scope's BFS-reachable interior. Inner scopes are bounded by mandatory graphIn (parameter slots) and graphOut (return slots)
Outermost ScopeThe root of the scope forest (no parent). Its iterOut's stop (or budget exhaust) ends the entire run
graphOut latchWhen a graphOut node lives inside a non-graph scope, it BUFFERS its incoming value into state["latched_value"] instead of propagating immediately. On the owning scope's termination, the buffered value is flushed to outer-scope downstream (formerly "portOut latch")
Scope re-entryWhen an outer scope's iter brings the inner scope's iter_in back into the ready queue, the executor resets the inner _ScopeState (terminated=False, step_counter=0). Makes inner scopes function-call-shaped
FireSpecOne captured child firing inside a FireList (ADR-executor-004). Carries node_type + inputs + per-call config + optional label + optional capture_outputs whitelist. The engine resolves node_type through NODE_HANDLERS and fires the corresponding class as an ephemeral child
FireListSentinel return type from a DynamicFireListNode's forward(). Holds specs: list[FireSpec] + spawner_outputs: dict (direct spawner outputs that flow alongside the children) + aggregator: dict (declarative collapse recipe). The engine recognises isinstance(result, FireList) and dispatches each spec sequentially (ADR-executor-004)
DynamicFireListNodeBaseCanvasNode subclass whose forward() returns a FireList instead of an output dict. aggregate(child_results) β†’ dict collapses children's outputs back into the spawner's declared ports β€” required for local spawners; server-mode proxies use the declarative FireList.aggregator recipe instead
Dynamic Fire-List dispatchEngine path inside _fire_node: when a spawner returns FireList, _fire_dynamic_children fires each spec sequentially as an ephemeral NodeInstance (id {spawner.id}::dyn{i}) that is NOT in self.nodes/adjacency/scope_forest. Children's outputs collected explicitly, then collapsed via aggregator and merged with spawner_outputs for downstream propagation (ADR-executor-004)
Declarative aggregatorJSON-safe recipe on FireList.aggregator telling the engine how to collapse children into the spawner's outputs without calling aggregate(). Supported kinds: passthrough_last, passthrough_index, merge_all, rename. Required when the spawner is a server-mode proxy class (which doesn't inherit the spawner's Python aggregate() method)
Ephemeral childA NodeInstance created at run-time by the dynamic fire-list dispatcher for one FireSpec. NOT registered in self.nodes/adjacency/scope_forest/ready_queue; cannot be a loop pivot, a final-side member, or any structural / boundary type. Identified by id {spawner.id}::dyn{i}; logged with parent_node_id + dynamic_index provenance
parent_node_id / dynamic_indexOptional fields on NodeLogEntry (default None, backward-compatible) carrying provenance from a dynamic-firelist spawner to its child firings. Lets downstream consumers (eval analysis, replay) group children by spawner without re-running it (ADR-executor-004)

Β§7Server Mode

Running a BaseNodeSet in its own interpreter via HTTP subprocess β€” the mechanism that lets Habitat-Sim (Python 3.8) coexist with the modern agentcanvas env.

AutoServerAppA ServerApp subclass that auto-generates server functions from any BaseNodeSet by introspecting tool ports β€” no manual PortSchema declaration needed (see ADR-server-001)
auto_hostCLI entry point (python -m app.server.auto_host) that launches any BaseNodeSet as a server-mode subprocess
server_pythonOptional ClassVar on BaseNodeSet specifying the Python interpreter for server mode; defaults to sys.executable
BatchedInferenceServerIn-process rendezvous tier hosted by an AutoServerApp subprocess. Holds one _BatchQueue per (function_name, config_hash); collects K parallel callers' submissions, calls the underlying handler once with stacked inputs, scatters outputs to K awaiting futures
BatchedClientThe submitter side of the batched-inference rendezvous: per-call await server.submit(function_name, inputs, config) returns the slice for this caller

Β§8Evaluation

Batch evaluation harness β€” each run is its own Python subprocess spawned by JobScheduler, with EnvWorkerPool fan-out inside each subprocess for parallel env workers.

ExecutionGuard / ExecutionModeThread-safe mutex in app/state.py making canvas Play and batch eval mutually exclusive β€” ExecutionMode is idle / canvas / eval; acquire() succeeds only from idle. Subprocess eval jobs don't hold the guard β€” the JobScheduler's admission gate simply refuses to admit while the canvas lock is held (the eval mode is acquired only by the legacy in-process path). Env-panel POSTs are guarded by it too
JobSchedulerBackend service managing admission control + a FIFO queue of eval jobs across all Claude sessions hitting one backend. Lives at app/services/job_scheduler.py; tick loop runs every 1s admitting queued jobs through a per-resource measured gate β€” calibrated estimate vs measured free (VRAM + RAM) minus standing reservations (see ADR-eval-003 and the JobScheduler design doc)
run subprocessIndependent Python process (python -m app.eval_subprocess_main --run-dir ...) that runs one eval. Reads spec.json + shared_urls.json from the run dir, registers parent backend's shared singletons via WorkspaceComponentRegistry.register_remote_nodeset, runs BatchEvalRunner.execute() unmodified. PR_SET_PDEATHSIG-tied to backend
marginal_vram_mbPer-job VRAM declaration in spec.scheduling β€” since 2026-07 the fallback admission rung: the measured gate charges calibrated per-resource estimates when coverage exists, the declaration when not (RAM rides ungated on that rung). Submit rejects declarations beyond the machine ceiling
register_remote_nodesetWorkspaceComponentRegistry method letting a run subprocess attach to a parent-owned shared singleton without spawning a duplicate. Fetches the auto_host manifest, generates proxy nodes, registers a RemoteEnvPanelProxy
_DONE markerEmpty file at outputs/eval_runs/{run_id}/_DONE written by the run subprocess on clean exit. Presence ⇔ run finalized; absence + dead PID = aborted
shared_urls.jsonFile at outputs/eval_runs/{run_id}/shared_urls.json mapping shared nodeset name β†’ auto_host URL. Run subprocess reads it on startup to attach to parent's singletons rather than loading its own copy
env panel (BaseEnvPanel)Per-nodeset control-plane panel for env-side runtime knobs only (suite / split / episode, play / pause / stop / reset) β€” model/ckpt/adapter belong on node configs. Declared via the BaseNodeSet.env_panel ClassVar; served at /api/env-panels/*; bridged into server-mode subprocesses by RemoteEnvPanelProxy over /env-panel/*. Renamed from "controller" (2026-06-11) to disambiguate from robotics and MVC controllers
EnvWorkerPoolN-worker pool driving env subprocesses for batch eval. Async context manager β€” __aenter__ populates worker_count WorkerHandles, acquire() leases one per episode, __aexit__ unloads tagged subprocesses (see ADR-eval-002)
WorkerHandleOne slot in the EnvWorkerPool. Carries env_panel_overrides and server_url_overrides β€” populated with the tagged copies at worker_count>1 so the leased LoopRunner routes set-episode/play to its own subprocess
env_panel_overridesPer-LoopRunner dict {nodeset_name: BaseEnvPanel} consulted by executor.get_env_panel(name). Empty at canvas Play / single-worker eval; populated by EnvWorkerPool at worker_count>1
server_url_overridesPer-LoopRunner dict {nodeset_name: server_url} consulted by executor.get_server_url(name); the proxy node's forward() swaps in the override at call time
default_per_step_budget_secClassVar[float] on BaseNodeSet (default 30.0 β€” set generously so shared-singleton VLM contention under high worker_count doesn't burn the wall-clock; override on nodesets whose step latency diverges). Per-episode timeout in batch eval is max_steps Γ— per_step_budget_sec

Β§9Observability & Logs

Real-time streaming (viewer_data / nav_step over WebSocket) and post-hoc execution logs (JSONL under outputs/).

GraphOutSink node (type graphOut, class GraphOutNode) that buffers its input into state["_last_inputs"] for the WebSocket broadcast at each iteration boundary (when IterOut fires); _broadcast_step consolidates these into the nav_step event. (Formerly named outputPort.)
ExecutionLoggerPer-run logger that captures structured NodeLogEntry records (port I/O, timing, voluntary inner log). Ring buffer in memory + JSONL file on disk in outputs/ (see ADR-observability-003)
NodeLogEntryPydantic model for one node firing: timestamp, execution_id, step, node_id/type/label, duration_ms, inputs, outputs, inner_log, port_wire_types, error
_self_logInstance method on BaseCanvasNode β€” nodes call self._self_log(key, value) inside forward() to record domain-specific internals (e.g. assembled LLM prompts, API responses, token counts)
log_serializeRecursive serializer that truncates large values for JSONL storage: strings >1KB β†’ summary, numpy arrays β†’ shape+dtype, bytes β†’ length
exec_logWebSocket event type broadcast per node firing during canvas execution. Contains summary: step, node_id, node_type, duration_ms, error. Full data available via REST /api/logs/{id}
ErrorBusSingleton in-process pub/sub at app/errors.py that every backend producer publishes to. Maintains a 200-entry ring buffer + 500-deep async dispatch queue (see ADR-observability-004)
ErrorEnvelopeCanonical schema published by ErrorBus. Fields: id, ts, severity, source, code, title, message, scope, details, hint. scope carries node_id / node_type / origin / step / execution_id / endpoint / method
error_eventWebSocket event type broadcast for every published ErrorEnvelope. Routed by store.ts into useErrorStore; on (re)connect the frontend calls GET /api/errors to backfill envelopes published while disconnected
Report tabFourth tab in the bottom-panel OutputDrawer. Time-ordered list of envelopes with severity filter chips, source pill, click-to-expand. Companion floating ErrorToast layer pops error/warning envelopes top-right
LogBridgeHandlerlogging.Handler subclass installed on the root logger at INFO+ that converts every Python log record into an ErrorEnvelope with source="log". Skips loops/noise sources

Β§10VLN Domain

Task-side vocabulary β€” datasets, action space, metrics. Independent of the architecture above; swapping to a non-VLN benchmark would replace this section but leave Β§Β§1–9 intact.

EpisodeA single navigation task: start position + natural language instruction + goal
SplitDataset partition: train, val_seen, val_unseen, test
ActionDiscrete navigation command (standard/actions.py): 0=STOP, 1=FORWARD, 2=TURN_LEFT, 3=TURN_RIGHT. One instance of the generalized DISCRETE_ACTION wire type (Β§4)
R2RRoom-to-Room β€” VLN dataset with natural language navigation instructions. Base schema for MP3D episodes
R4RRoom-for-Room β€” concatenated R2R paths (first + second path ids + 9 combined instructions)
RxRRoom-across-Room β€” multilingual (en / hi / te) VLN dataset with word-level timed instructions + optional dense camera pose traces. Both MP3D (discrete) and Habitat-CE (continuous) nodesets surface val_unseen_* splits via the same language-suffix convention
RxR-CERxR continuous-environment variant used on the Habitat nodeset. Data: data/habitat/datasets/RxR_VLNCE_v0/{split}/{split}_guide.json.gz
REVERIERemote Embodied Visual referring Expression β€” VLN + object grounding with per-viewpoint 2D bounding boxes
CVDN / NDHCooperative Vision-and-Dialog Navigation β€” dialog-based navigation datasets where the instruction is a multi-turn Q&A
VLN-CEVision-and-Language Navigation in Continuous Environments β€” the benchmark
SPLSuccess weighted by Path Length β€” primary VLN-CE metric
SRSuccess Rate β€” fraction of episodes where agent stopped within 3m of goal
nDTWNormalized Dynamic Time Warping β€” measures path fidelity to reference trajectory
SDTWSuccess-weighted DTW β€” nDTW multiplied by success