### Elasticsearch Version

8.2.0 (likely others)

### Installed Plugins

_No response_

### Java Version

_bundled_

### OS Version

Cloud

### Problem Description

I saw a NPE in `MlAssignmentNotifier#auditMlTasks` which looks to be due to the `PersistentTasksCustomMetadata` being completely missing (i.e. `null`) rather than simply empty.

### Steps to Reproduce

Unknown

### Logs (if relevant)

```
[instance-0000000000] uncaught exception in thread [elasticsearch[instance-0000000000][generic][T#5]]
java.lang.NullPointerException: Cannot invoke "org.elasticsearch.persistent.PersistentTasksCustomMetadata.tasks()" because "currentTasks" is null
	at org.elasticsearch.xpack.ml.MlAssignmentNotifier.auditMlTasks(MlAssignmentNotifier.java:96) ~[?:?]
	at org.elasticsearch.xpack.ml.MlAssignmentNotifier.auditChangesToMlTasks(MlAssignmentNotifier.java:76) ~[?:?]
	at org.elasticsearch.xpack.ml.MlAssignmentNotifier.lambda$clusterChanged$0(MlAssignmentNotifier.java:64) ~[?:?]
	at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingRunnable.run(ThreadContext.java:714) ~[elasticsearch-8.2.0.jar:8.2.0]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[?:?]
	at java.lang.Thread.run(Thread.java:833) [?:?]
```
x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/MlAssignmentNotifier.java
public void clusterChanged(ClusterChangedEvent event) {
        if (event.localNodeMaster() == false) {
            return;
        }
        if (event.metadataChanged() == false) {
            return;
        }
        threadPool.executor(executorName()).execute(() -> auditChangesToMlTasks(event));
    }
    private void auditChangesToMlTasks(ClusterChangedEvent event) {
        PersistentTasksCustomMetadata previousTasks = event.previousState().getMetadata().custom(PersistentTasksCustomMetadata.TYPE);
        PersistentTasksCustomMetadata currentTasks = event.state().getMetadata().custom(PersistentTasksCustomMetadata.TYPE);
        if (Objects.equals(previousTasks, currentTasks)) {
            return;
        }
        auditMlTasks(event.previousState().nodes(), event.state().nodes(), previousTasks, currentTasks, false);
    }
    /**
     * Creates an audit warning for all currently unassigned ML
     * tasks, even if a previous audit warning has been created.
     * Care must be taken not to call this method frequently.
     */
    public void auditUnassignedMlTasks(DiscoveryNodes nodes, PersistentTasksCustomMetadata tasks) {
        auditMlTasks(nodes, nodes, tasks, tasks, true);
    }
    private void auditMlTasks(
        DiscoveryNodes previousNodes,
        DiscoveryNodes currentNodes,
        PersistentTasksCustomMetadata previousTasks,
        PersistentTasksCustomMetadata currentTasks,