feat: sibling tasks (#9504)
### Description
This PR does 2 things:
- Adds a `sibling` attribute for task definitions that has the ability
to bring another task into the graph without depending on it. This is
currently only an attribute that can be set by us inside Rust, but I
hope this use case proves useful enough to eventually make this a public
API.
- Switches MFE proxy injection over to use `siblings` where each dev
task gets a `"siblings": ["mfe-pkg#proxy"]` to ensure the proxy gets
run.
A sibling relationship acts similar to `dependsOn` except that it will
not wait for the task to exit before starting and the sibling's task
hash will not affect the current task's hash.
Currently it's very hard to get `web#proxy` to run if the user runs a
command like `turbo dev --filter=docs` as just adding `web` to the
filter will mean `web#dev` gets picked up which isn't what we desire. As
you can see in `run/builder.rs` this also removes the need of
microfrontend knowledge from building the task graph.
### Testing Instructions
Added unit tests for sibling behavior as well as unit tests for MFE task
injection.
Manual testing for the MFE behavior to make sure proxy still gets picked
up.
---------
Co-authored-by: Nicholas Yang <nicholas.yang@vercel.com>