A workspace root is an mlf.toml with a [workspace] section and no [package] — members = ["app", "shared"] lists per-member subdirectories, each with its own [package]. Settings declared under [workspace.publish] and [workspace.dependencies] cascade into any member that doesn't override them (section-level replacement, not field-level merging).
ProjectKind::load distinguishes the two shapes and returns either a single ResolvedPackage or the full member list. mlf publish dispatches based on that: single package → existing flow; workspace → publishes every member in declaration order. --package filters to one member by its [package].name.
Each member runs through the full validator + DNS reconcile + apply + manifest pipeline independently — every member produces its own lol.mlf.package record. RemoteState::load_at lets the orchestrator target a specific package root without relying on CWD, so running from the workspace root publishes every member cleanly.