[turbopack] Store TaskDirtyCause in Dirtyness and pass to NativeFunction::span (#94057)
### What?
Track the cause of task invalidation in turbo-tasks and surface it to
the tracing span when a task executes, so traces can show *why* a task
was re-run.
A new `task_dirty_cause` Cargo feature gates the storage and parameter
plumbing for this information. The existing `trace_task_dirty` feature
now depends on it.
### Why?
When investigating Turbopack performance and incremental-recompute
behavior, traces show which tasks ran but not what invalidated them.
Recording the `TaskDirtyCause` on the `turbo_tasks::function` span makes
it possible to attribute task re-runs to their triggering change (cell
update, output change, collectible change, etc.) directly from a trace.
### How?
- Replace `Dirtyness::Dirty(TaskPriority)` with a struct variant `Dirty
{ parent_priority, cause: TaskDirtyCause }`. The `cause` field is only
present when the `task_dirty_cause` feature is enabled.
- Move `TaskDirtyCause` from `turbo-tasks-backend` into `turbo-tasks` so
the span signature in `turbo-tasks` can reference it.
- Replace `OutputChange { task_description }` with `OutputChange {
function: FunctionId }`, and add a new `ResolveOutputChange { function:
FunctionId }` variant used when the task's output is
`OutputValue::Output(_)`. This avoids constructing a `String` for the
cause at invalidation time.
- `NativeFunction::span` now accepts a feature-gated `cause:
Option<&TaskDirtyCause>` argument and records it as a `cause` field on
the `turbo_tasks::function` span. The cause is read from the dirty state
in `try_start_task_execution` before execution starts.
- Split the `trace_task_dirty` feature: the new `task_dirty_cause`
feature owns the storage/parameter plumbing, and `trace_task_dirty` now
depends on it. This lets consumers opt into the storage cost without the
full tracing overhead, and keeps the default build unaffected.
Closes PACK-
<!-- NEXT_JS_LLM_PR -->