Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions docs/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ A module file has two sections:
| `inputs_optional` | list | no | Optional input ports (silently skipped if not wired) |
| `outputs` | list | no | Output port names exposed to the parent dataflow |

Unknown fields in the module header are rejected whenever Dora loads the
module, including `dora expand`, `dora build`, and `dora run`.

### `nodes:` list

Standard node definitions, with one special syntax: **`_mod/port_name`** references a module input port. When expanded, `_mod/port_name` is replaced with whatever the parent wired to that port.
Expand Down Expand Up @@ -151,7 +154,7 @@ Parameters are also injected as environment variables (`PARAM_SPEED`, `PARAM_MOD
2. Prefix all internal node IDs with `{module_id}.` (e.g., `nav_stack.planner`)
3. Replace `_mod/port_name` references with the actual sources from the parent's input map
4. Rewrite internal cross-references (e.g., `planner/path` becomes `nav_stack.planner/path`)
5. Map module-declared outputs to internal node outputs, so `nav_stack/cmd_vel` resolves to `nav_stack.controller/cmd_vel`. An inner node may produce a declared output from its node-level `outputs:`, from an `operator:`/`operators:` block, or from a legacy `custom:` block. For an output produced by one operator of a multi-operator `operators:` node, the resolved reference keeps the operator segment that runtime nodes require: `nav_stack/cmd_vel` resolves to `nav_stack.runtime/controller/cmd_vel`
5. Map module-declared outputs to direct child outputs, so `nav_stack/cmd_vel` resolves to `nav_stack.controller/cmd_vel`. A direct child may be a standard node, a runtime `operator:`/`operators:` node, a legacy `custom:` node, or a nested module. For an output produced by one operator of a multi-operator `operators:` node, the resolved reference keeps the operator segment that runtime nodes require: `nav_stack/cmd_vel` resolves to `nav_stack.runtime/controller/cmd_vel`
6. Replace the module node with the expanded flat nodes
7. Substitute `params:` values in `args:` fields and inject as env vars

Expand Down Expand Up @@ -188,6 +191,11 @@ nodes:

After expansion, node IDs are fully qualified: `outer.inner.some_node`.

Only outputs declared by a nested module are visible to its parent. A parent
module can wire or re-export `inner/processed` from the example above because
`processed` is listed in `inner_module.yml`'s `module.outputs`; it cannot reach
private outputs produced by nodes inside `inner_module.yml`.

## Optional Inputs

Declare inputs as optional when a module should work with or without certain connections:
Expand Down Expand Up @@ -229,11 +237,10 @@ dora expand --module modules/transform_module.yml

This checks:
- Valid YAML structure
- Module header is present with `name`, `inputs`, `outputs`
- Module header is present with required `name`, optional `inputs`/`outputs`, and no unknown header fields
- All `_mod/` references correspond to declared inputs or optional inputs
- Every declared output is produced by some inner node (counting `operator:`/`operators:` and legacy `custom:` outputs)
- No duplicate node IDs
- Internal wiring is consistent
- Every declared output is produced by a direct child node or by a nested module's declared output (counting `operator:`/`operators:` and legacy `custom:` outputs)
- Nested module files exist, are relative paths, are acyclic, and stay within the nesting depth limit

## Security

Expand Down
Loading