diff --git a/mlflow/tracking/fluent.py b/mlflow/tracking/fluent.py
index 14c98dff0e9b6..6ffa788c34534 100644
--- a/mlflow/tracking/fluent.py
+++ b/mlflow/tracking/fluent.py
@@ -219,8 +219,10 @@ def __enter__(self):
         return self

     def __exit__(self, exc_type, exc_val, exc_tb):
-        status = RunStatus.FINISHED if exc_type is None else RunStatus.FAILED
-        end_run(RunStatus.to_string(status))
+        active_run_stack = _active_run_stack.get()
+        if self in active_run_stack:  # Is this run still active?
+            status = RunStatus.FINISHED if exc_type is None else RunStatus.FAILED
+            end_run(RunStatus.to_string(status))
         return exc_type is None

diff --git a/tests/tracking/fluent/test_fluent.py b/tests/tracking/fluent/test_fluent.py
index 486f78665e84b..77e6ed61bfd73 100644
--- a/tests/tracking/fluent/test_fluent.py
+++ b/tests/tracking/fluent/test_fluent.py
@@ -1659,3 +1659,21 @@ def test_subprocess_inherit_registry_uri(tmp_path):
         text=True,
     )
     assert sqlite_uri in stdout
+
+
+def test_end_run_inside_start_run_context_manager():
+    client = MlflowClient()
+
+    with mlflow.start_run() as parent_run:
+        with mlflow.start_run(nested=True) as child_run:
+            mlflow.end_run("FAILED")
+            assert client.get_run(child_run.info.run_id).info.status == RunStatus.to_string(
+                RunStatus.FAILED
+            )
+
+        assert client.get_run(parent_run.info.run_id).info.status == RunStatus.to_string(
+            RunStatus.RUNNING
+        )
+    assert client.get_run(parent_run.info.run_id).info.status == RunStatus.to_string(
+        RunStatus.FINISHED
+    )

[BUG] end_run() within nested run context affects parent run as well
### Issues Policy acknowledgement

- [X] I have read and agree to submit bug reports in accordance with the [issues policy](https://www.github.com/mlflow/mlflow/blob/master/ISSUE_POLICY.md)

### Where did you encounter this bug?

Local machine

### MLflow version

- Client: 2.15.5
- Tracking server: 2.12.2

### System information

- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: Ubuntu 22.04
- **Python version**: 3.10

### Describe the problem

Executing this code terminates both the nested and parent run, but from the documentation it should terminate only the nested one.

```
import mlflow

mlflow.set_experiment("nested_run_debugging")
with mlflow.start_run():
    for i in range(10):
        with mlflow.start_run(nested=True):
            mlflow.log_param("index", i)
            if i == 3:
                mlflow.end_run("FAILED")
```

![image](https://github.com/user-attachments/assets/aa0d0dce-60a7-4671-93e6-4e38b9a4761e)

### Tracking information

<!-- PLEASE KEEP BACKTICKS AND CHECK PREVIEW -->
```shell
REPLACE_ME
```

### Code to reproduce issue

<!-- PLEASE KEEP BACKTICKS AND CHECK PREVIEW -->

```
import mlflow

mlflow.set_experiment("nested_run_debugging")
with mlflow.start_run():
    for i in range(10):
        with mlflow.start_run(nested=True):
            mlflow.log_param("index", i)
            if i == 3:
                mlflow.end_run("FAILED")
```

### Stack trace

<!-- PLEASE KEEP BACKTICKS AND CHECK PREVIEW -->
```
REPLACE_ME
```

### Other info / logs

<!-- PLEASE KEEP BACKTICKS AND CHECK PREVIEW -->
```
REPLACE_ME
```

### What component(s) does this bug affect?

- [ ] `area/artifacts`: Artifact stores and artifact logging
- [ ] `area/build`: Build and test infrastructure for MLflow
- [ ] `area/deployments`: MLflow Deployments client APIs, server, and third-party Deployments integrations
- [ ] `area/docs`: MLflow documentation pages
- [ ] `area/examples`: Example code
- [ ] `area/model-registry`: Model Registry service, APIs, and the fluent client calls for Model Registry
- [ ] `area/models`: MLmodel format, model serialization/deserialization, flavors
- [ ] `area/recipes`: Recipes, Recipe APIs, Recipe configs, Recipe Templates
- [ ] `area/projects`: MLproject format, project running backends
- [ ] `area/scoring`: MLflow Model server, model deployment tools, Spark UDFs
- [X] `area/server-infra`: MLflow Tracking server backend
- [ ] `area/tracking`: Tracking Service, tracking client APIs, autologging

### What interface(s) does this bug affect?

- [ ] `area/uiux`: Front-end, user experience, plotting, JavaScript, JavaScript dev server
- [ ] `area/docker`: Docker use across MLflow's components, such as MLflow Projects and MLflow Models
- [ ] `area/sqlalchemy`: Use of SQLAlchemy in the Tracking Service or Model Registry
- [ ] `area/windows`: Windows support

### What language(s) does this bug affect?

- [ ] `language/r`: R APIs and clients
- [ ] `language/java`: Java APIs and clients
- [ ] `language/new`: Proposals for new client languages

### What integration(s) does this bug affect?

- [ ] `integrations/azure`: Azure and Azure ML integrations
- [ ] `integrations/sagemaker`: SageMaker integrations
- [ ] `integrations/databricks`: Databricks integrations
[BUG] end_run() within nested run context affects parent run as well
### Issues Policy acknowledgement

- [X] I have read and agree to submit bug reports in accordance with the [issues policy](https://www.github.com/mlflow/mlflow/blob/master/ISSUE_POLICY.md)

### Where did you encounter this bug?

Local machine

### MLflow version

- Client: 2.15.5
- Tracking server: 2.12.2

### System information

- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: Ubuntu 22.04
- **Python version**: 3.10

### Describe the problem

Executing this code terminates both the nested and parent run, but from the documentation it should terminate only the nested one.

```
import mlflow

mlflow.set_experiment("nested_run_debugging")
with mlflow.start_run():
    for i in range(10):
        with mlflow.start_run(nested=True):
            mlflow.log_param("index", i)
            if i == 3:
                mlflow.end_run("FAILED")
```

![image](https://github.com/user-attachments/assets/aa0d0dce-60a7-4671-93e6-4e38b9a4761e)

### Tracking information

<!-- PLEASE KEEP BACKTICKS AND CHECK PREVIEW -->
```shell
REPLACE_ME
```

### Code to reproduce issue

<!-- PLEASE KEEP BACKTICKS AND CHECK PREVIEW -->

```
import mlflow

mlflow.set_experiment("nested_run_debugging")
with mlflow.start_run():
    for i in range(10):
        with mlflow.start_run(nested=True):
            mlflow.log_param("index", i)
            if i == 3:
                mlflow.end_run("FAILED")
```

### Stack trace

<!-- PLEASE KEEP BACKTICKS AND CHECK PREVIEW -->
```
REPLACE_ME
```

### Other info / logs

<!-- PLEASE KEEP BACKTICKS AND CHECK PREVIEW -->
```
REPLACE_ME
```

### What component(s) does this bug affect?

- [ ] `area/artifacts`: Artifact stores and artifact logging
- [ ] `area/build`: Build and test infrastructure for MLflow
- [ ] `area/deployments`: MLflow Deployments client APIs, server, and third-party Deployments integrations
- [ ] `area/docs`: MLflow documentation pages
- [ ] `area/examples`: Example code
- [ ] `area/model-registry`: Model Registry service, APIs, and the fluent client calls for Model Registry
- [ ] `area/models`: MLmodel format, model serialization/deserialization, flavors
- [ ] `area/recipes`: Recipes, Recipe APIs, Recipe configs, Recipe Templates
- [ ] `area/projects`: MLproject format, project running backends
- [ ] `area/scoring`: MLflow Model server, model deployment tools, Spark UDFs
- [X] `area/server-infra`: MLflow Tracking server backend
- [ ] `area/tracking`: Tracking Service, tracking client APIs, autologging

### What interface(s) does this bug affect?

- [ ] `area/uiux`: Front-end, user experience, plotting, JavaScript, JavaScript dev server
- [ ] `area/docker`: Docker use across MLflow's components, such as MLflow Projects and MLflow Models
- [ ] `area/sqlalchemy`: Use of SQLAlchemy in the Tracking Service or Model Registry
- [ ] `area/windows`: Windows support

### What language(s) does this bug affect?

- [ ] `language/r`: R APIs and clients
- [ ] `language/java`: Java APIs and clients
- [ ] `language/new`: Proposals for new client languages

### What integration(s) does this bug affect?

- [ ] `integrations/azure`: Azure and Azure ML integrations
- [ ] `integrations/sagemaker`: SageMaker integrations
- [ ] `integrations/databricks`: Databricks integrations

no.

`with mlflow.start_run(nested=True):`

means when the code exit the `with` block, the started run is ended.

if you use `mlflow.start_run(...)` without `with`, then it will not be ended automatically.
oh , I got your point,

in your case, it unexpectedly terminates the parent run at the step 3 in the loop, then it leads to all subsequential nested runs become top-level runs.
I will file a fix later.
no.

`with mlflow.start_run(nested=True):`

means when the code exit the `with` block, the started run is ended.

if you use `mlflow.start_run(...)` without `with`, then it will not be ended automatically.
oh , I got your point,

in your case, it unexpectedly terminates the parent run at the step 3 in the loop, then it leads to all subsequential nested runs become top-level runs.
I will file a fix later.


diff --git a/mlflow/openai/_openai_autolog.py b/mlflow/openai/_openai_autolog.py
index 294153c1bf38a..757bf5360765b 100644
--- a/mlflow/openai/_openai_autolog.py
+++ b/mlflow/openai/_openai_autolog.py
@@ -4,7 +4,7 @@
 import os
 from contextlib import contextmanager
 from copy import deepcopy
-from typing import Iterator
+from typing import Any, Iterator

 from packaging.version import Version

@@ -92,6 +92,29 @@ def _get_span_type(task) -> str:
     return span_type_mapping.get(task, SpanType.UNKNOWN)

+def _try_parse_raw_response(response: Any) -> Any:
+    """
+    As documented at https://github.com/openai/openai-python/tree/52357cff50bee57ef442e94d78a0de38b4173fc2?tab=readme-ov-file#accessing-raw-response-data-eg-headers,
+    a `LegacyAPIResponse` (https://github.com/openai/openai-python/blob/52357cff50bee57ef442e94d78a0de38b4173fc2/src/openai/_legacy_response.py#L45)
+    object is returned when the `create` method is invoked with `with_raw_response`.
+    """
+    try:
+        from openai._legacy_response import LegacyAPIResponse
+    except ImportError:
+        _logger.debug("Failed to import `LegacyAPIResponse` from `openai._legacy_response`")
+        return response
+
+    if isinstance(response, LegacyAPIResponse):
+        try:
+            # `parse` returns either a `pydantic.BaseModel` or a `openai.Stream` object
+            # depending on whether the request has a `stream` parameter set to `True`.
+            return response.parse()
+        except Exception as e:
+            _logger.debug(f"Failed to parse {response} (type: {response.__class__}): {e}")
+
+    return response
+
+
 def patched_call(original, self, *args, **kwargs):
     from openai import Stream
     from openai.types.chat.chat_completion_chunk import ChatCompletionChunk
@@ -150,7 +173,7 @@ def patched_call(original, self, *args, **kwargs):

     # Execute the original function
     try:
-        result = original(self, *args, **kwargs)
+        raw_result = original(self, *args, **kwargs)
     except Exception as e:
         # We have to end the trace even the exception is raised
         if config.log_traces and request_id:
@@ -161,6 +184,8 @@ def patched_call(original, self, *args, **kwargs):
                 _logger.warning(f"Encountered unexpected error when ending trace: {inner_e}")
         raise e

+    result = _try_parse_raw_response(raw_result)
+
     if isinstance(result, Stream):
         # If the output is a stream, we add a hook to store the intermediate chunks
         # and then log the outputs as a single artifact when the stream ends
@@ -241,7 +266,7 @@ def _stream_output_logging_hook(stream: Iterator) -> Iterator:
     if run_id is not None and (active_run is None or active_run.info.run_id != run_id):
         mlflow_client.set_terminated(run_id)

-    return result
+    return raw_result

 def patched_agent_get_chat_completion(original, self, *args, **kwargs):

diff --git a/tests/openai/test_openai_autolog.py b/tests/openai/test_openai_autolog.py
index 0ad67fbafd1ce..b354d43ca002d 100644
--- a/tests/openai/test_openai_autolog.py
+++ b/tests/openai/test_openai_autolog.py
@@ -362,3 +362,41 @@ def test_autolog_use_active_run_id(client, log_models):
     assert traces[1].info.request_metadata[TraceMetadataKey.SOURCE_RUN] == run_2.info.run_id
     assert traces[2].info.request_metadata[TraceMetadataKey.SOURCE_RUN] == run_2.info.run_id
     assert traces[3].info.request_metadata[TraceMetadataKey.SOURCE_RUN] == run_3.info.run_id
+
+
+def test_autolog_raw_response(client):
+    mlflow.openai.autolog()
+
+    with mlflow.start_run():
+        resp = client.chat.completions.with_raw_response.create(
+            model="gpt-4o-mini",
+            messages=[{"role": "user", "content": "test"}],
+        )
+        resp = resp.parse()  # ensure the raw response is returned
+
+    assert resp.choices[0].message.content == '[{"role": "user", "content": "test"}]'
+    trace = mlflow.get_last_active_trace()
+    assert len(trace.data.spans) == 1
+    span = trace.data.spans[0]
+    assert isinstance(span.outputs, dict)
+    assert (
+        span.outputs["choices"][0]["message"]["content"] == '[{"role": "user", "content": "test"}]'
+    )
+
+
+def test_autolog_raw_response_stream(client):
+    mlflow.openai.autolog()
+
+    with mlflow.start_run():
+        resp = client.chat.completions.with_raw_response.create(
+            model="gpt-4o-mini",
+            messages=[{"role": "user", "content": "test"}],
+            stream=True,
+        )
+        resp = resp.parse()  # ensure the raw response is returned
+
+    assert [c.choices[0].delta.content for c in resp] == ["Hello", " world"]
+    trace = mlflow.get_last_active_trace()
+    assert len(trace.data.spans) == 1
+    span = trace.data.spans[0]
+    assert span.outputs == "Hello world"

[BUG] MLflow Tracing Fails to Parse Response Objects When Using OpenAI via DSPy
### Issues Policy acknowledgement

- [X] I have read and agree to submit bug reports in accordance with the [issues policy](https://www.github.com/mlflow/mlflow/blob/master/ISSUE_POLICY.md)

### Where did you encounter this bug?

Databricks

### MLflow version

- Client: 2.17.2
- Tracking server: 2.17.2

### System information

- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**:
Linux 1106-084218-ernmjrfp-10-199-84-236 5.15.0-1071-aws #77~20.04.1-Ubuntu SMP Thu Oct 3 19:39:59 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 22.04.5 LTS
Release:	22.04
Codename:	jammy

- **Python version**:
Python 3.11.0rc1

- **yarn version, if running the dev UI**:
apt 2.4.13 (amd64)

### Describe the problem

When using the DSPy package to interact with OpenAI, along with MLflow's OpenAI flavor, MLflow tracing fails to properly parse the content of the response objects. This issue makes it difficult to fully track or log the API responses, which can affect model output tracking and result analysis. I am seeking a solution to ensure that MLflow tracing can correctly parse and record the response object content, allowing the OpenAI flavor to function as expected.

During my experiments, the returned result appears to be a Python Response object like the image below.

---

Here is the expected result for the Response field that I found in the official documentation:
![image](https://github.com/user-attachments/assets/42e5f6e2-6f37-4b4a-90e1-7a78d6293985)

### Tracking information

```shell
System information: Linux #77~20.04.1-Ubuntu SMP Thu Oct 3 19:39:59 UTC 2024
Python version: 3.11.0rc1
MLflow version: 2.17.2
MLflow module location: /local_disk0/.ephemeral_nfs/envs/pythonEnv-afd7f4c1-1092-44e0-9961-2b8d23b8f152/lib/python3.11/site-packages/mlflow/__init__.py
Tracking URI: databricks
Registry URI: databricks-uc
Databricks runtime version: 15.4
MLflow environment variables:
  MLFLOW_CONDA_HOME: /databricks/conda
  MLFLOW_DEPLOYMENTS_TARGET: databricks
  MLFLOW_GATEWAY_URI: databricks
  MLFLOW_PYTHON_EXECUTABLE: /databricks/spark/scripts/mlflow_python.sh
  MLFLOW_TRACKING_URI: databricks
MLflow dependencies:
  Flask: 2.2.5
  Jinja2: 3.1.2
  aiohttp: 3.8.5
  alembic: 1.14.0
  azure-storage-file-datalake: 12.14.0
  boto3: 1.34.39
  botocore: 1.34.39
  docker: 7.1.0
  google-cloud-storage: 2.10.0
  graphene: 3.4.3
  gunicorn: 20.1.0
  langchain: 0.1.20
  markdown: 3.4.1
  matplotlib: 3.7.2
  mlflow-skinny: 2.17.2
  numpy: 1.23.5
  pandas: 1.5.3
  pyarrow: 14.0.1
  pydantic: 2.9.2
  scikit-learn: 1.3.0
  scipy: 1.11.1
  sqlalchemy: 1.4.39
  tiktoken: 0.8.0
  virtualenv: 20.24.2
```

### Code to reproduce issue

# Load data
```Python
import random
from typing import Literal
from dspy.datasets import DataLoader
from datasets import load_dataset

# Load the Banking77 dataset and save to ./data.
CLASSES = load_dataset("PolyAI/banking77", split="train", trust_remote_code=True, cache_dir="/Volumes/ai_default/stockllm/sample").features['label'].names
kwargs = dict(fields=("text", "label"), input_keys=("text",), split="train", trust_remote_code=True, cache_dir="/Volumes/ai_default/stockllm/sample")
# Load the first 2000 examples from the dataset, and assign a hint to each *training* example.
trainset = [
    dspy.Example(x, hint=CLASSES[x.label], label=CLASSES[x.label]).with_inputs("text", "hint")
    for x in DataLoader().from_huggingface(dataset_name="PolyAI/banking77", **kwargs)[:2000]
]
random.Random(0).shuffle(trainset)
```
# Inference
```Python
import mlflow

mlflow.start_run()
mlflow.openai.autolog()
import dspy

dspy.settings.experimental = True
dspy.configure(lm=dspy.LM('gpt-4o-mini-2024-07-18', api_key=openai_api_key))

# Define the DSPy module for classification. It will use the hint at training time, if available.
signature = dspy.Signature("text -> label").with_updated_fields('label', type_=Literal[tuple(CLASSES)])
classify = dspy.ChainOfThoughtWithHint(signature)
classify(text="<Some questions ...>")
```

### Stack trace

There's no error message for my issues.
```
REPLACE_ME
```

### Other info / logs

There is not logs for my issues
```
REPLACE_ME
```

### What component(s) does this bug affect?

- [ ] `area/artifacts`: Artifact stores and artifact logging
- [ ] `area/build`: Build and test infrastructure for MLflow
- [ ] `area/deployments`: MLflow Deployments client APIs, server, and third-party Deployments integrations
- [ ] `area/docs`: MLflow documentation pages
- [ ] `area/examples`: Example code
- [ ] `area/model-registry`: Model Registry service, APIs, and the fluent client calls for Model Registry
- [ ] `area/models`: MLmodel format, model serialization/deserialization, flavors
- [ ] `area/recipes`: Recipes, Recipe APIs, Recipe configs, Recipe Templates
- [ ] `area/projects`: MLproject format, project running backends
- [ ] `area/scoring`: MLflow Model server, model deployment tools, Spark UDFs
- [ ] `area/server-infra`: MLflow Tracking server backend
- [X] `area/tracking`: Tracking Service, tracking client APIs, autologging

### What interface(s) does this bug affect?

- [ ] `area/uiux`: Front-end, user experience, plotting, JavaScript, JavaScript dev server
- [ ] `area/docker`: Docker use across MLflow's components, such as MLflow Projects and MLflow Models
- [ ] `area/sqlalchemy`: Use of SQLAlchemy in the Tracking Service or Model Registry
- [ ] `area/windows`: Windows support

### What language(s) does this bug affect?

- [ ] `language/r`: R APIs and clients
- [ ] `language/java`: Java APIs and clients
- [ ] `language/new`: Proposals for new client languages

### What integration(s) does this bug affect?

- [ ] `integrations/azure`: Azure and Azure ML integrations
- [ ] `integrations/sagemaker`: SageMaker integrations
- [X] `integrations/databricks`: Databricks integrations

Thanks for reporting this. It looks like dspy uses litellm, and litellm calls `openai_client.chat.completions.with_raw_response.create`:

```
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/dspy/utils/callback.py", line 202, in wrapper
    return fn(instance, *args, **kwargs)
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/dspy/primitives/program.py", line 23, in __call__
    return self.forward(*args, **kwargs)
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/dspy/predict/chain_of_thought_with_hint.py", line 27, in forward
    return self.module(**kwargs)
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/dspy/utils/callback.py", line 202, in wrapper
    return fn(instance, *args, **kwargs)
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/dspy/primitives/program.py", line 23, in __call__
    return self.forward(*args, **kwargs)
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/dspy/predict/chain_of_thought.py", line 44, in forward
    return self._predict(signature=signature, **kwargs)
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/dspy/utils/callback.py", line 202, in wrapper
    return fn(instance, *args, **kwargs)
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/dspy/predict/predict.py", line 154, in __call__
    return self.forward(**kwargs)
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/dspy/predict/predict.py", line 188, in forward
    completions = v2_5_generate(lm, config, signature, demos, kwargs, _parse_values=self._parse_values)
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/dspy/predict/predict.py", line 295, in v2_5_generate
    return adapter(
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/dspy/adapters/base.py", line 20, in __call__
    outputs = lm(**inputs_, **lm_kwargs)
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/dspy/utils/callback.py", line 202, in wrapper
    return fn(instance, *args, **kwargs)
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/dspy/clients/lm.py", line 96, in __call__
    response = completion(
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/dspy/clients/lm.py", line 217, in cached_litellm_completion
    return litellm_completion(
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/dspy/clients/lm.py", line 226, in litellm_completion
    return litellm.completion(
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/litellm/utils.py", line 903, in wrapper
    result = original_function(*args, **kwargs)
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/litellm/main.py", line 1570, in completion
    response = openai_chat_completions.completion(
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/litellm/llms/OpenAI/openai.py", line 790, in completion
    self.make_sync_openai_chat_completion_request(
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/litellm/llms/OpenAI/openai.py", line 631, in make_sync_openai_chat_completion_request
    raw_response = openai_client.chat.completions.with_raw_response.create(
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/openai/_legacy_response.py", line 356, in wrapped
    return cast(LegacyAPIResponse[R], func(*args, **kwargs))
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/mlflow/utils/autologging_utils/safety.py", line 593, in safe_patch_function
    patch_function(call_original, *args, **kwargs)
  File "/local_disk0/.ephemeral_nfs/envs/pythonEnv-b4df211a-5889-49df-bdd9-aaf77bee200f/lib/python3.10/site-packages/mlflow/openai/_openai_autolog.py", line 98, in patched_call
    traceback.print_stack()
```


diff --git a/mlflow/store/artifact/local_artifact_repo.py b/mlflow/store/artifact/local_artifact_repo.py
index f7d78e90fd0ac..42a0dd98938cc 100644
--- a/mlflow/store/artifact/local_artifact_repo.py
+++ b/mlflow/store/artifact/local_artifact_repo.py
@@ -9,6 +9,7 @@
     mkdir,
     relative_path_to_artifact_path,
 )
+from mlflow.utils.uri import validate_path_is_safe

 class LocalArtifactRepository(ArtifactRepository):
@@ -74,8 +75,9 @@ def download_artifacts(self, artifact_path, dst_path=None):
         """
         if dst_path:
             return super().download_artifacts(artifact_path, dst_path)
-        # NOTE: The artifact_path is expected to be in posix format.
+        # NOTE: The artifact_path is expected to be a relative path in posix format.
         # Posix paths work fine on windows but just in case we normalize it here.
+        artifact_path = validate_path_is_safe(artifact_path)
         local_artifact_path = os.path.join(self.artifact_dir, os.path.normpath(artifact_path))
         if not os.path.exists(local_artifact_path):
             raise OSError(f"No such file or directory: '{local_artifact_path}'")
@@ -100,8 +102,9 @@ def list_artifacts(self, path=None):
             return []

     def _download_file(self, remote_file_path, local_path):
-        # NOTE: The remote_file_path is expected to be in posix format.
+        # NOTE: The remote_file_path is expected to be a relative path in posix format.
         # Posix paths work fine on windows but just in case we normalize it here.
+        remote_file_path = validate_path_is_safe(remote_file_path)
         remote_file_path = os.path.join(self.artifact_dir, os.path.normpath(remote_file_path))
         shutil.copy2(remote_file_path, local_path)

diff --git a/tests/store/artifact/test_local_artifact_repo.py b/tests/store/artifact/test_local_artifact_repo.py
index ed0c7693848b8..0cea539777dfb 100644
--- a/tests/store/artifact/test_local_artifact_repo.py
+++ b/tests/store/artifact/test_local_artifact_repo.py
@@ -200,3 +200,8 @@ def test_delete_artifacts(local_artifact_repo):

 def test_delete_artifacts_with_nonexistent_path_succeeds(local_artifact_repo):
     local_artifact_repo.delete_artifacts("nonexistent")
+
+
+def test_download_artifacts_invalid_remote_file_path(local_artifact_repo):
+    with pytest.raises(MlflowException, match="Invalid path"):
+        local_artifact_repo.download_artifacts("/absolute/path/to/file")
diff --git a/tests/utils/test_promptlab_utils.py b/tests/utils/test_promptlab_utils.py
index 326a9dea032e9..fc71bea53ce42 100644
--- a/tests/utils/test_promptlab_utils.py
+++ b/tests/utils/test_promptlab_utils.py
@@ -104,4 +104,4 @@ def test_create_promptlab_run(store):
     # try to load the model
     import mlflow.pyfunc

-    mlflow.pyfunc.load_model(os.path.join(artifact_location, "model"))
+    mlflow.pyfunc.load_model(f"{artifact_location}/model")

[BUG] Security Vulnerability
Please check it here https://huntr.com/bounties/e3d7a994-bfd6-4772-ac9b-9aee1aa16a5f/


diff --git a/src/sqlfluff/rules/references/RF01.py b/src/sqlfluff/rules/references/RF01.py
index 3ef60bbd8ed..ef9fe2c4955 100644
--- a/src/sqlfluff/rules/references/RF01.py
+++ b/src/sqlfluff/rules/references/RF01.py
@@ -37,7 +37,7 @@ class Rule_RF01(BaseRule):

     .. note::

-       This rule is disabled by default for BigQuery, Databricks, Hive,
+       This rule is disabled by default for Athena, BigQuery, Databricks, DuckDB, Hive,
        Redshift, SOQL and SparkSQL due to the support of things like
        structs and lateral views which trigger false positives. It can be
        enabled with the ``force_enable = True`` flag.
@@ -269,6 +269,8 @@ def _dialect_supports_dot_access(dialect: Dialect) -> bool:
         # https://cloud.google.com/bigquery/docs/reference/standard-sql/operators#field_access_operator
         # Databricks:
         # https://docs.databricks.com/en/sql/language-manual/functions/dotsign.html
+        # DuckDB:
+        # https://duckdb.org/docs/sql/data_types/struct#retrieving-from-structs
         # Redshift:
         # https://docs.aws.amazon.com/redshift/latest/dg/query-super.html
         # TODO: all doc links to all referenced dialects
@@ -276,6 +278,7 @@ def _dialect_supports_dot_access(dialect: Dialect) -> bool:
             "athena",
             "bigquery",
             "databricks",
+            "duckdb",
             "hive",
             "redshift",
             "soql",

diff --git a/test/fixtures/rules/std_rule_cases/RF01.yml b/test/fixtures/rules/std_rule_cases/RF01.yml
index 01253a0895b..10276c06530 100644
--- a/test/fixtures/rules/std_rule_cases/RF01.yml
+++ b/test/fixtures/rules/std_rule_cases/RF01.yml
@@ -36,7 +36,7 @@ test_pass_object_referenced_3:
     SELECT * FROM db.sc.tbl2
     WHERE a NOT IN (SELECT tbl2.a FROM db.sc.tbl1)

-test_pass_object_referenced_4:
+test_pass_object_referenced_4a:
   # Test ambiguous column reference caused by use of BigQuery structure fields.
   # Here, 'et2' could either be a schema name or a table name.
   # https://github.com/sqlfluff/sqlfluff/issues/1079
@@ -50,6 +50,17 @@ test_pass_object_referenced_4:
       references.from:
         force_enable: true

+test_pass_object_referenced_4b:
+  # DuckDB allows dot-access to its MAP objects, which requires special handling
+  # to ensure `ex.x` is not interpreted as `{table}.{field}` instead of
+  # `{schema}.{table}`. The following returns `'there'` if executed.
+  pass_str: |
+    SELECT ex.x.hi
+    FROM (SELECT { 'hi': 'there' } AS x) AS ex
+  configs:
+    core:
+      dialect: duckdb
+
 test_pass_object_referenced_5a:
   # Test ambiguous column reference caused by use of BigQuery structure fields.
   # Here, column,field should not trigger the rule as by default this rule is

DuckDB needs to be added to list of dialects supporting dot-based struct access
### Search before asking

- [X] I searched the [issues](https://github.com/sqlfluff/sqlfluff/issues) and found no similar issues.

### What Happened

The following query

```sql
SELECT ex.x.hi
FROM (SELECT { 'hi': 'there' } AS x) AS ex
```

returns an `RF01` with

```
Reference 'ex.x.hi' refers to table/view not found in the FROM clause or found in ancestor statement.
```

### Expected Behaviour

The query above is valid DuckDB, and should return `'there'`, so there should be no errors.

### Observed Behaviour

See above.

### How to reproduce

```python
import sqlfluff; from sqlfluff.core import FluffConfig, Linter
Linter(config=FluffConfig(overrides={"dialect": "duckdb"})).lint_string("SELECT ex.x.hi\nFROM (SELECT { 'hi': 'there' } AS x) AS ex\n")
```

The following patch would fix the problem, I tried to directly open a PR but I guess I need to be a "Collaborator" first!

```diff
diff --git a/src/sqlfluff/rules/references/RF01.py b/src/sqlfluff/rules/references/RF01.py
index 3ef60bbd8..71717aea6 100644
--- a/src/sqlfluff/rules/references/RF01.py
+++ b/src/sqlfluff/rules/references/RF01.py
@@ -269,6 +269,8 @@ class Rule_RF01(BaseRule):
         # https://cloud.google.com/bigquery/docs/reference/standard-sql/operators#field_access_operator
         # Databricks:
         # https://docs.databricks.com/en/sql/language-manual/functions/dotsign.html
+        # DuckDB:
+        # https://duckdb.org/docs/sql/data_types/struct#retrieving-from-structs
         # Redshift:
         # https://docs.aws.amazon.com/redshift/latest/dg/query-super.html
         # TODO: all doc links to all referenced dialects
@@ -276,6 +278,7 @@ class Rule_RF01(BaseRule):
             "athena",
             "bigquery",
             "databricks",
+            "duckdb",
             "hive",
             "redshift",
             "soql",
diff --git a/test/fixtures/rules/std_rule_cases/RF01.yml b/test/fixtures/rules/std_rule_cases/RF01.yml
index 01253a089..10276c065 100644
--- a/test/fixtures/rules/std_rule_cases/RF01.yml
+++ b/test/fixtures/rules/std_rule_cases/RF01.yml
@@ -36,7 +36,7 @@ test_pass_object_referenced_3:
     SELECT * FROM db.sc.tbl2
     WHERE a NOT IN (SELECT tbl2.a FROM db.sc.tbl1)

-test_pass_object_referenced_4:
+test_pass_object_referenced_4a:
   # Test ambiguous column reference caused by use of BigQuery structure fields.
   # Here, 'et2' could either be a schema name or a table name.
   # https://github.com/sqlfluff/sqlfluff/issues/1079
@@ -50,6 +50,17 @@ test_pass_object_referenced_4:
       references.from:
         force_enable: true

+test_pass_object_referenced_4b:
+  # DuckDB allows dot-access to its MAP objects, which requires special handling
+  # to ensure `ex.x` is not interpreted as `{table}.{field}` instead of
+  # `{schema}.{table}`. The following returns `'there'` if executed.
+  pass_str: |
+    SELECT ex.x.hi
+    FROM (SELECT { 'hi': 'there' } AS x) AS ex
+  configs:
+    core:
+      dialect: duckdb
+
 test_pass_object_referenced_5a:
   # Test ambiguous column reference caused by use of BigQuery structure fields.
   # Here, column,field should not trigger the rule as by default this rule is
```

### Dialect

duckdb

### Version

```
$ sqlfluff --version
sqlfluff, version 3.3.0

$ python --version
Python 3.12.8

$ git rev-parse HEAD
4649363f0282d8ff8220b8929a2c1d9f9bb64774
```

### Configuration

N/A

### Are you willing to work on and submit a PR to address the issue?

- [X] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/sqlfluff/sqlfluff/blob/main/CODE_OF_CONDUCT.md)


diff --git a/src/sqlfluff/utils/analysis/select.py b/src/sqlfluff/utils/analysis/select.py
index 27b722acff1..3b9576c2aeb 100644
--- a/src/sqlfluff/utils/analysis/select.py
+++ b/src/sqlfluff/utils/analysis/select.py
@@ -212,7 +212,13 @@ def _get_pivot_table_columns(
 def _get_lambda_argument_columns(
     segment: BaseSegment, dialect: Optional[Dialect]
 ) -> List[BaseSegment]:
-    if not dialect or dialect.name not in ["athena", "sparksql", "duckdb", "trino"]:
+    if not dialect or dialect.name not in [
+        "athena",
+        "sparksql",
+        "duckdb",
+        "trino",
+        "databricks",
+    ]:
         # Only athena and sparksql are known to have lambda expressions,
         # so all other dialects will have zero lambda columns
         return []

diff --git a/test/fixtures/rules/std_rule_cases/RF02.yml b/test/fixtures/rules/std_rule_cases/RF02.yml
index 78c8b9ae814..fdc0e55e7ba 100644
--- a/test/fixtures/rules/std_rule_cases/RF02.yml
+++ b/test/fixtures/rules/std_rule_cases/RF02.yml
@@ -106,6 +106,18 @@ test_allow_unqualified_references_in_sparksql_lambdas:
     core:
       dialect: sparksql

+test_pass_databricks_lambdas:
+  pass_str: |
+    select
+        i.*,
+        aggregate(i.some_column, 0, (acc, x) -> acc + x) as y
+    from some_table as o
+    inner join some_other_table as i
+        on o.id = i.id;
+  configs:
+    core:
+      dialect: databricks
+
 test_allow_unqualified_references_in_athena_lambdas:
   pass_str: |
     select

RF02 issue from (x, acc) in aggregate function
### Search before asking

- [X] I searched the [issues](https://github.com/sqlfluff/sqlfluff/issues) and found no similar issues.

### What Happened

This is more of a question, really. I'm not sure if the issue is with sqlfluff, or if the issue is between the keyboard and the chair. I browsed issues and the web and couldn't find anyone with a similar issue, so I very well could be doing something wrong. I'm getting a linting error RF02 (references.qualification) anytime I'm using an aggregate (or reduce) function. Is there a setting somewhere that I am missing so that these parameters are recognized by sqlfluff as part of the function and not a column of the table?
A couple of example queries included.
![image](https://github.com/user-attachments/assets/6fa9fad7-b942-4624-a4bf-2bdebbf74c37)
![image](https://github.com/user-attachments/assets/3b688ab0-454e-472c-9dde-96c841be6d1e)

### Expected Behaviour

No linting errors within the lambda function when using aggregate

### Observed Behaviour

RF02 (references.qualification) error

### How to reproduce

simple select statement using aggregate(some_column, 0, (acc, x) -> acc + x)

### Dialect

databricks

### Version

sqlfluff, version 3.2.5
python version 3.12.7
dbt-core, dbt-databricks 1.8.5

I am, however, using sqlfluff templater jinja rather than dbt

### Configuration

.sqlfluff:
```yml
[sqlfluff]
# Custom rules
max_line_length = 100

# Supported dialects https://docs.sqlfluff.com/en/stable/dialects.html
# Or run 'sqlfluff dialects'
dialect = databricks

# One of [raw|jinja|python|placeholder]
templater = jinja

# Comma separated list of rules to exclude, or None
# See https://docs.sqlfluff.com/en/stable/configuration.html#enabling-and-disabling-rules
# AM04 (ambiguous.column_count) and ST06 (structure.column_order) are
# two of the more controversial rules included to illustrate usage.
exclude_rules = ambiguous.column_count, structure.column_order, aliasing.table

[sqlfluff:templater:jinja]
load_macros_from_path = ./macros
```

.sqlfluffignore
```yml
/target/
dbt_modules/
dbt_packages/
macros/
```

### Are you willing to work on and submit a PR to address the issue?

- [ ] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/sqlfluff/sqlfluff/blob/main/CODE_OF_CONDUCT.md)


diff --git a/src/sqlfluff/rules/references/RF01.py b/src/sqlfluff/rules/references/RF01.py
index b20bcf3f22a..3ef60bbd8ed 100644
--- a/src/sqlfluff/rules/references/RF01.py
+++ b/src/sqlfluff/rules/references/RF01.py
@@ -29,6 +29,7 @@ class RF01Query(Query):

     aliases: List[AliasInfo] = field(default_factory=list)
     standalone_aliases: List[BaseSegment] = field(default_factory=list)
+    parent_stack: Tuple[BaseSegment, ...] = field(default_factory=tuple)

 class Rule_RF01(BaseRule):
@@ -70,25 +71,8 @@ class Rule_RF01(BaseRule):
     # If any of the parents would have also triggered the rule, don't fire
     # because they will more accurately process any internal references.
     crawl_behaviour = SegmentSeekerCrawler(set(_START_TYPES), allow_recurse=False)
-    _dialects_disabled_by_default = [
-        "bigquery",
-        "databricks",
-        "hive",
-        "redshift",
-        "soql",
-        "sparksql",
-    ]

     def _eval(self, context: RuleContext) -> List[LintResult]:
-        # Config type hints
-        self.force_enable: bool
-
-        if (
-            context.dialect.name in self._dialects_disabled_by_default
-            and not self.force_enable
-        ):
-            return []
-
         violations: List[LintResult] = []
         dml_target_table: Optional[Tuple[str, ...]] = None
         self.logger.debug("Trigger on: %s", context.segment)
@@ -104,7 +88,8 @@ def _eval(self, context: RuleContext) -> List[LintResult]:
         self.logger.debug("DML Reference Table: %s", dml_target_table)
         # Verify table references in any SELECT statements found in or
         # below context.segment in the parser tree.
-        query = RF01Query.from_segment(context.segment, context.dialect)
+        query: RF01Query = RF01Query.from_segment(context.segment, context.dialect)
+        query.parent_stack = context.parent_stack
         self._analyze_table_references(
             query, dml_target_table, context.dialect, violations
         )
@@ -209,7 +194,7 @@ def _get_table_refs(ref, dialect):

     def _resolve_reference(
         self, r, tbl_refs, dml_target_table: Optional[Tuple[str, ...]], query: RF01Query
-    ):
+    ) -> Optional[LintResult]:
         # Does this query define the referenced table?
         possible_references = [tbl_ref[1] for tbl_ref in tbl_refs]
         targets = []
@@ -217,6 +202,19 @@ def _resolve_reference(
             targets += self._alias_info_as_tuples(alias)
         for standalone_alias in query.standalone_aliases:
             targets.append((standalone_alias.raw,))
+
+        if len(targets) == 1 and self._dialect_supports_dot_access(query.dialect):
+            self.force_enable: bool
+            if self.force_enable:
+                # Backwards compatibility.
+                # Nowadays "force_enable" is more of "strict" mode,
+                # for dialects with dot access.
+                pass
+            else:
+                return None
+
+        targets += self._get_implicit_targets(query)
+
         if not object_ref_matches_table(possible_references, targets):
             # No. Check the parent query, if there is one.
             if query.parent:
@@ -235,3 +233,51 @@ def _resolve_reference(
                     "not found in the FROM clause or found in ancestor "
                     "statement.",
                 )
+
+        return None
+
+    @staticmethod
+    def _get_implicit_targets(query: RF01Query) -> List[Tuple[str, ...]]:
+        if query.dialect.name == "sqlite":
+            maybe_create_trigger: Optional[BaseSegment] = next(
+                (
+                    seg
+                    for seg in reversed(query.parent_stack)
+                    if seg.is_type("create_trigger")
+                ),
+                None,
+            )
+            if not maybe_create_trigger:
+                return []
+            for seg in maybe_create_trigger.segments:
+                if seg.is_type("keyword") and seg.raw_normalized() == "INSERT":
+                    return [("new",)]
+                elif seg.is_type("keyword") and seg.raw_normalized() == "UPDATE":
+                    return [("new",), ("old",)]
+                elif seg.is_type("keyword") and seg.raw_normalized() == "DELETE":
+                    return [("old",)]
+                else:
+                    pass  # pragma: no cover
+
+        return []
+
+    @staticmethod
+    def _dialect_supports_dot_access(dialect: Dialect) -> bool:
+        # Athena:
+        # https://docs.aws.amazon.com/athena/latest/ug/filtering-with-dot.html
+        # BigQuery:
+        # https://cloud.google.com/bigquery/docs/reference/standard-sql/operators#field_access_operator
+        # Databricks:
+        # https://docs.databricks.com/en/sql/language-manual/functions/dotsign.html
+        # Redshift:
+        # https://docs.aws.amazon.com/redshift/latest/dg/query-super.html
+        # TODO: all doc links to all referenced dialects
+        return dialect.name in (
+            "athena",
+            "bigquery",
+            "databricks",
+            "hive",
+            "redshift",
+            "soql",
+            "sparksql",
+        )

diff --git a/test/fixtures/rules/std_rule_cases/RF01.yml b/test/fixtures/rules/std_rule_cases/RF01.yml
index 93eed5482d1..01253a0895b 100644
--- a/test/fixtures/rules/std_rule_cases/RF01.yml
+++ b/test/fixtures/rules/std_rule_cases/RF01.yml
@@ -328,3 +328,99 @@ test_pass_trino_lambda_expression:
   configs:
     core:
       dialect: trino
+
+test_athena_ignore_rule_if_single_table:
+  pass_str: |
+    select
+        a.complex.key,
+        a.complex.structure.val
+    from sch.t1
+  configs:
+    core:
+      dialect: athena
+
+test_athena_apply_rule_if_single_table_and_force_enable:
+  fail_str: |
+    select
+        a.complex.key,
+        a.complex.structure.val
+    from sch.t1
+  configs:
+    core:
+      dialect: athena
+    rules:
+      references.from:
+        force_enable: true
+
+test_athena_apply_rule_if_multiple_tables:
+  fail_str: |
+    select
+        a.complex.key,
+        a.complex.structure.val
+    from sch.table1 as t1
+    left join sch.table2 as t2
+    on t1.id = t2.id
+  configs:
+    core:
+      dialect: athena
+
+test_athena_apply_rule_if_one_aliased_table:
+  fail_str: |
+    select
+        a.complex.key,
+        a.complex.structure.val
+    from sch.table1 as t1
+  configs:
+    core:
+      dialect: athena
+
+test_sqlite_create_trigger_after_insert_reference:
+  # https://github.com/sqlfluff/sqlfluff/issues/6402
+  # https://www.sqlite.org/lang_createtrigger.html
+  pass_str: |
+    CREATE TRIGGER x
+    AFTER INSERT
+    ON y
+    BEGIN
+    SELECT 1 WHERE new.xyz = 3;
+    END
+  configs:
+    core:
+      dialect: sqlite
+
+test_sqlite_create_trigger_after_delete_reference:
+  # https://github.com/sqlfluff/sqlfluff/issues/6402
+  # https://www.sqlite.org/lang_createtrigger.html
+  pass_str: |
+    CREATE TRIGGER x
+    AFTER DELETE
+    ON y
+    BEGIN
+    SELECT 1 WHERE old.xyz = 3;
+    END
+  configs:
+    core:
+      dialect: sqlite
+
+test_sqlite_create_trigger_after_update_reference:
+  # https://github.com/sqlfluff/sqlfluff/issues/6402
+  # https://www.sqlite.org/lang_createtrigger.html
+  pass_str: |
+    CREATE TRIGGER x
+    AFTER UPDATE
+    ON y
+    BEGIN
+    SELECT 1 WHERE old.xyz != new.xyz;
+    END;
+  configs:
+    core:
+      dialect: sqlite
+
+test_sqlite_outside_of_trigger:
+  # https://github.com/sqlfluff/sqlfluff/issues/6402
+  # https://www.sqlite.org/lang_createtrigger.html
+  fail_str: |
+    SELECT foo FROM bar WHERE old.xyz != new.xyz;
+  configs:
+    core:
+      dialect: sqlite

Support Request: RF01 rule
### Search before asking

- [X] I searched the [issues](https://github.com/sqlfluff/sqlfluff/issues) and found no similar issues.

### Description

It seems sqlfluff can’t handle the dot notation we use for Redshift SUPER data type. RF01 rule (https://docs.sqlfluff.com/en/stable/rules.html#rule-references.from).

Usage example:

```
w_extract as (
    select
        pj.hash_key,
        pj.snapshot_date,
        trim(cast(pj.metadata_super."amount" as numeric))                                       as amount,
        trim(cast(pj.metadata_super."leadAge" as numeric))                                      as lead_age,
        trim(cast(pj.metadata_super."leadType" as varchar))                                     as lead_type,
        trim(cast(pj.metadata_super."leadValue" as numeric))                                    as lead_value,
        trim(cast(pj.metadata_super."randValue" as numeric))                                    as rand_value,
        trim(cast(pj.metadata_super."callReason" as varchar))                                   as call_reason
    from w_parse_json as pj
)
```
Failures:
```
L:  49 | P:  22 | RF01 | Reference 'pj.metadata_super."amount"' refers to
                       | table/view not found in the FROM clause or found in
                       | ancestor statement. [references.from]
L:  50 | P:  22 | RF01 | Reference 'pj.metadata_super."leadAge"' refers to
                       | table/view not found in the FROM clause or found in
                       | ancestor statement. [references.from]
L:  51 | P:  22 | RF01 | Reference 'pj.metadata_super."leadType"' refers to
                       | table/view not found in the FROM clause or found in
                       | ancestor statement. [references.from]
L:  52 | P:  22 | RF01 | Reference 'pj.metadata_super."leadValue"' refers to
                       | table/view not found in the FROM clause or found in
                       | ancestor statement. [references.from]
L:  53 | P:  22 | RF01 | Reference 'pj.metadata_super."randValue"' refers to
                       | table/view not found in the FROM clause or found in
                       | ancestor statement. [references.from]
L:  54 | P:  22 | RF01 | Reference 'pj.metadata_super."callReason"' refers to
                       | table/view not found in the FROM clause or found in
                       | ancestor statement. [references.from]
```

Can we improve this so this is automatically handled via ```sqlfluff fix```? Currently, this is an unfixable violation and we simply have to ignore it.

### Use case

_No response_

### Dialect

-

### Are you willing to work on and submit a PR to address the issue?

- [X] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/sqlfluff/sqlfluff/blob/main/CODE_OF_CONDUCT.md)

We also see this, for us I suspect this is partially due to casing mattering for some of our keys within the SUPER field. If the identifiers are all unquoted I believe they are interpreted as lower case which means the data is not found
same for `athena` dialect when accessing nesting for `struct` datatype
```sql
select
    a.complex.key,
    a.complex.structure.val
from sch.t1
```
causes
```verilog
L:   2 | P:   7 | RF01 | Reference 'a.complex.key' refers to table/view not found in the FROM clause or found in ancestor statement. [references.from]
L:   3 | P:  15 | RF01 | Reference 'a.complex.structure.val' refers to table/view not found in the FROM clause or found in ancestor statement. [references.from]
```


diff --git a/src/sqlfluff/core/helpers/string.py b/src/sqlfluff/core/helpers/string.py
index 85d21b0bf56..c425e9cc612 100644
--- a/src/sqlfluff/core/helpers/string.py
+++ b/src/sqlfluff/core/helpers/string.py
@@ -38,31 +38,45 @@ def split_colon_separated_string(in_str: str) -> Tuple[Tuple[str, ...], str]:
     >>> split_colon_separated_string("a")
     ((), 'a')

-    NOTE: This also includes some provisions for values which may be
-    Windows paths containing colons and NOT stripping those.
+    NOTE: This also includes some heuristics for legit values containing colon.
     >>> split_colon_separated_string("foo:bar:C:\\Users")
     (('foo', 'bar'), 'C:\\Users')
+    >>> split_colon_separated_string('foo:bar:{"k":"v"}')
+    (('foo', 'bar'), '{"k":"v"}')
+    >>> split_colon_separated_string('foo:bar:[{"k":"v"}]')
+    (('foo', 'bar'), '[{"k":"v"}]')
     """
     config_path: List[str] = []
-    for element in in_str.split(":"):
-        # If the next element begins with a backslash, and the previous
-        # one had length == 1,  then this is probably a windows path.
-        # In which case, rejoin them together.
+    leftover = in_str
+    while ":" in leftover:
+        element, _, value = leftover.partition(":")
         element = element.strip()
-        if (
-            element
-            and element[0] == "\\"
-            and config_path[-1]
-            and len(config_path[-1]) == 1
-        ):
-            config_path[-1] = config_path[-1] + ":" + element
-        else:
-            # Otherwise just add it to the path.
-            config_path.append(element)
-
+        value = value.strip()
+        config_path.append(element)
+        leftover = value
+        if not should_split_on_colon(value):
+            break
+
+    # last part - actual value
+    config_path.append(leftover)
     return tuple(config_path[:-1]), config_path[-1]

+def should_split_on_colon(value: str) -> bool:
+    """Heuristic for legit values containing comma."""
+    if len(value) >= 2 and value[1] == ":" and value[2] == "\\":
+        # Likely a Windows path
+        return False
+    if len(value) >= 2 and (value[0] == "[" and value[-1] == "]"):
+        # Likely a JSON array
+        return False
+    if len(value) >= 2 and (value[0] == "{" and value[-1] == "}"):
+        # Likely a JSON object
+        return False
+
+    return True
+
+
 def split_comma_separated_string(raw: Union[str, List[str]]) -> List[str]:
     """Converts comma separated string to List, stripping whitespace."""
     if isinstance(raw, str):

diff --git a/test/core/config/fluffconfig_test.py b/test/core/config/fluffconfig_test.py
index 35b0619b546..bcd67dda9d4 100644
--- a/test/core/config/fluffconfig_test.py
+++ b/test/core/config/fluffconfig_test.py
@@ -340,6 +340,14 @@ def test__process_inline_config():
     cfg.process_inline_config("-- sqlfluff:jinja:my_path:c:\\foo", "test.sql")
     assert cfg.get("my_path", section="jinja") == "c:\\foo"

+    # Check that JSON objects are not mangled
+    cfg.process_inline_config('-- sqlfluff:jinja:my_dict:{"k":"v"}', "test.sql")
+    assert cfg.get("my_dict", section="jinja") == '{"k":"v"}'
+
+    # Check that JSON arrays are not mangled
+    cfg.process_inline_config('-- sqlfluff:jinja:my_dict:[{"k":"v"}]', "test.sql")
+    assert cfg.get("my_dict", section="jinja") == '[{"k":"v"}]'
+

 @pytest.mark.parametrize(
     "raw_sql",

Improve inline directives for templater context
### Search before asking

- [X] I searched the [issues](https://github.com/sqlfluff/sqlfluff/issues) and found no similar issues.

### Description

I cannot alter jinja context in inline fashion.

Good:

```
[sqlfluff:templater:jinja:context]
my_inline_dict={"k1": "v1", "k2": "v2"}
```

SQL:
```sql
{% for k in my_inline_dict %}
SELECT {{ k }};
{% endfor %}
```

sqlfluff render:
```sql
SELECT k1;

SELECT k2;
```

Bad:
```sql
-- sqlfluff:templater:jinja:context:my_inline_dict:{"k1": "v1", "k2": "v2"}
{% for k in my_inline_dict %}
SELECT {{ k }};
{% endfor %}
```

sqlfluff render:
```
Traceback (most recent call last):
  File "/home/lrogalski/repo/REDACTED/.venv/bin/sqlfluff", line 8, in <module>
    sys.exit(cli())
             ^^^^^
  File "/home/lrogalski/repo/REDACTED/.venv/lib/python3.11/site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/lrogalski/repo/REDACTED/.venv/lib/python3.11/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/home/lrogalski/repo/REDACTED/.venv/lib/python3.11/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/lrogalski/repo/REDACTED/.venv/lib/python3.11/site-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/lrogalski/repo/REDACTED/.venv/lib/python3.11/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/lrogalski/repo/REDACTED/.venv/lib/python3.11/site-packages/sqlfluff/cli/commands.py", line 1451, in render
    raw_sql, file_config, _ = lnt.load_raw_file_and_config(path, lnt.config)
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/lrogalski/repo/REDACTED/.venv/lib/python3.11/site-packages/sqlfluff/core/linter/linter.py", line 147, in load_raw_file_and_config
    file_config.process_raw_file_for_config(raw_file, fname)
  File "/home/lrogalski/repo/REDACTED/.venv/lib/python3.11/site-packages/sqlfluff/core/config.py", line 1164, in process_raw_file_for_config
    self.process_inline_config(raw_line, fname)
  File "/home/lrogalski/repo/REDACTED/.venv/lib/python3.11/site-packages/sqlfluff/core/config.py", line 1150, in process_inline_config
    self.set_value(*config_val)
  File "/home/lrogalski/repo/REDACTED/.venv/lib/python3.11/site-packages/sqlfluff/core/config.py", line 1094, in set_value
    dict_buff.append(dict_buff[-1].get(elem, {}))
                     ^^^^^^^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'get'
```

3.2.4

### Use case

I want to have "local" jinja context in my sql to:
- improve readability
- avoid always-growing and self-conflicting context in .sqlfluff file

### Dialect

ansi

### Are you willing to work on and submit a PR to address the issue?

- [X] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/sqlfluff/sqlfluff/blob/main/CODE_OF_CONDUCT.md)


diff --git a/src/sqlfluff/rules/structure/ST02.py b/src/sqlfluff/rules/structure/ST02.py
index de4c168028d..aef10af3648 100644
--- a/src/sqlfluff/rules/structure/ST02.py
+++ b/src/sqlfluff/rules/structure/ST02.py
@@ -14,6 +14,24 @@
 from sqlfluff.utils.functional import FunctionalContext, Segments, sp

+class FunctionNameSegment(BaseSegment):
+    """Function name, including any prefix bits, e.g. project or schema.
+
+    NOTE: This is a minimal segment definition to allow appropriate fixing.
+    """
+
+    type = "function_name"
+
+
+class FunctionContentsSegment(BaseSegment):
+    """Function Contents.
+
+    NOTE: This is a minimal segment definition to allow appropriate fixing.
+    """
+
+    type = "function_contents"
+
+
 class Rule_ST02(BaseRule):
     """Unnecessary ``CASE`` statement.

@@ -92,13 +110,19 @@ def _coalesce_fix_list(
         """Generate list of fixes to convert CASE statement to COALESCE function."""
         # Add coalesce and opening parenthesis.
         edits = [
-            WordSegment("coalesce", type="function_name_identifier"),
-            SymbolSegment("(", type="start_bracket"),
-            coalesce_arg_1,
-            SymbolSegment(",", type="comma"),
-            WhitespaceSegment(),
-            coalesce_arg_2,
-            SymbolSegment(")", type="end_bracket"),
+            FunctionNameSegment(
+                segments=(WordSegment("coalesce", type="function_name_identifier"),)
+            ),
+            FunctionContentsSegment(
+                segments=(
+                    SymbolSegment("(", type="start_bracket"),
+                    coalesce_arg_1,
+                    SymbolSegment(",", type="comma"),
+                    WhitespaceSegment(),
+                    coalesce_arg_2,
+                    SymbolSegment(")", type="end_bracket"),
+                )
+            ),
         ]

         if preceding_not:

diff --git a/test/rules/std_LT01_ST02_test.py b/test/rules/std_LT01_ST02_test.py
new file mode 100644
index 00000000000..f57efada099
--- /dev/null
+++ b/test/rules/std_LT01_ST02_test.py
@@ -0,0 +1,49 @@
+"""Tests the python routines within LT04 and ST06."""
+
+import pytest
+
+from sqlfluff.core import FluffConfig, Linter
+
+
+@pytest.mark.parametrize(
+    ["in_sql", "out_sql"],
+    [
+        (
+            """
+select
+    case
+        when ended_at is null or date(ended_at) > current_date()
+        then true else false
+    end as is_active
+from foo
+""",
+            """
+select
+    coalesce(ended_at is null or date(ended_at) > current_date(), false) as is_active
+from foo
+""",
+        ),
+    ],
+)
+def test_rules_std_LT01_and_ST02_interaction(in_sql, out_sql) -> None:
+    """Test interaction between LT04 and ST06.
+
+    Test sql with two newlines with leading commas expecting trailing.
+    """
+    # Lint expected rules.
+    cfg = FluffConfig.from_string(
+        """[sqlfluff]
+dialect = ansi
+rules = LT01,ST02
+"""
+    )
+    linter = Linter(config=cfg)
+
+    # Return linted/fixed file.
+    linted_file = linter.lint_string(in_sql, fix=True)
+
+    # Check expected lint errors are raised.
+    assert set([v.rule.code for v in linted_file.violations]) == {"ST02"}
+
+    # Check file is fixed.
+    assert linted_file.fix_string()[0] == out_sql

LT01 & ST02 interaction adds a space between coalesce keyword and opening parenthesis
### Search before asking

- [X] I searched the [issues](https://github.com/sqlfluff/sqlfluff/issues) and found no similar issues.

### What Happened

I have a classic unnecessary case statement:
```
case when ended_at is null or date(ended_at) > current_date() then true else false end as is_active,
```

Which is correctly being flagged by ST02:
```
=== [dbt templater] Sorting Nodes...
=== [dbt templater] Compiling dbt project...
=== [dbt templater] Project Compiled.
== [my_redacted_model.sql] FAIL
L:  31 | P:  23 | ST02 | Unnecessary CASE statement. Use COALESCE function
                       | instead. [structure.simple_case]
```

Applying `sqlfluff fix` "fixes" the offending case statement with malformed SQL:
```
coalesce (ended_at is null or date(ended_at) > current_date(), false) as is_active,

        ^- shouldn't be there
```

which fails a subsequent lint due to the space. Running `sqlfluff` fix twice avoides the error because the offending space is picked up by LT01.

### Expected Behaviour

I would expect ST02 to not add a space between the `coalesce` keyword and the opening parenthesis.

### Observed Behaviour

ST02 adds a space between the `coalesce` keyword and the opening parenthesis.

### How to reproduce

This query reproduces the error for me:

```
with
    subscriptions as (
        select *
        from {{ ref('stg__subscriptions') }}
    ),

    club_subscriptions as (
        select
            case
                when ended_at is null or date(ended_at) > current_date()
                    then true
                else false
            end as is_active
        from subscriptions
    )

select *
from club_subscriptions
```

### Dialect

bigquery, with the dbt templater

### Version

Python: Python 3.10.15

- **sqlfluff**
	```
	"sqlfluff==3.2.3",
    "sqlfluff-templater-dbt==3.2.3",
	```

- **dbt**
	```
    "dbt-adapters==1.7.0",
    "dbt-bigquery==1.8.2",
    "dbt-core==1.8.7",
	```

### Configuration

```
[sqlfluff]
templater = dbt
dialect = bigquery
max_line_length = 120
exclude_rules =
    structure.column_order,
    structure.using,
    references.qualification,
    ambiguous.column_count
warnings = RF04

[sqlfluff:templater:dbt]
project_dir = ./dbt
profiles_dir = ./dbt

[sqlfluff:templater:jinja]
load_macros_from_path = ./dbt/macros

[sqlfluff:indentation]
indented_ctes = true
allow_implicit_indents = true

[sqlfluff:rules:capitalisation.keywords]
capitalisation_policy = lower

[sqlfluff:rules:capitalisation.identifiers]
capitalisation_policy = lower

[sqlfluff:rules:capitalisation.functions]
extended_capitalisation_policy = lower

[sqlfluff:rules:capitalisation.literals]
capitalisation_policy = lower

[sqlfluff:rules:capitalisation.types]
extended_capitalisation_policy = lower

```

### Are you willing to work on and submit a PR to address the issue?

- [ ] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/sqlfluff/sqlfluff/blob/main/CODE_OF_CONDUCT.md)

Awkwardly this isn't an issue with `ST02`. Let's use the following query as an example:

```sql
select
    case
        when ended_at is null or date(ended_at) > current_date()
        then true else false
    end as is_active
from foo
```

If I fix that with _only_ ST02, then I get this (`sqlfluff fix test.sql -r ST02`):

```sql
select
    coalesce(ended_at is null or date(ended_at) > current_date(), false) as is_active
from foo
```

No problem ✅

HOWEVER, if I run it without restricting to just `ST02` (`sqlfluff fix test.sql`), I get the issue you describe:

```sql
select
    coalesce (ended_at is null or date(ended_at) > current_date(),
    false) as is_active
from foo
```

It appears to be an interaction between LT01 and ST02 for reasons I don't quite understand as if I run (`sqlfluff fix test.sql -r LT01,ST02`) I get:

```sql
select
    coalesce (ended_at is null or date(ended_at) > current_date(), false) as is_active
from foo
```

I suspect this is because the typing of the fixes returned by `ST02` is slightly off.


diff --git a/src/sqlfluff/core/templaters/jinja.py b/src/sqlfluff/core/templaters/jinja.py
index bae8649f733..d6ea7841a94 100644
--- a/src/sqlfluff/core/templaters/jinja.py
+++ b/src/sqlfluff/core/templaters/jinja.py
@@ -61,9 +61,8 @@ class UndefinedRecorder:
     """Similar to jinja2.StrictUndefined, but remembers, not fails."""

     # Tell Jinja this object is safe to call and does not alter data.
-    # https://jinja.palletsprojects.com/en/2.9.x/sandbox/#jinja2.sandbox.SandboxedEnvironment.is_safe_callable
-    unsafe_callable = False
     # https://jinja.palletsprojects.com/en/3.0.x/sandbox/#jinja2.sandbox.SandboxedEnvironment.is_safe_callable
+    unsafe_callable = False
     alters_data = False

     def __init__(self, name: str, undefined_set: Set[str]) -> None:
@@ -317,6 +316,11 @@ def _generate_dbt_builtins() -> Dict[str, Any]:
         class RelationEmulator:
             """A class which emulates the `this` class from dbt."""

+            # Tell Jinja this object is safe to call and does not alter data.
+            # https://jinja.palletsprojects.com/en/3.0.x/sandbox/#jinja2.sandbox.SandboxedEnvironment.is_safe_callable
+            unsafe_callable = False
+            alters_data = False
+
             identifier = "this_model"
             schema = "this_schema"
             database = "this_database"

diff --git a/test/core/templaters/jinja_test.py b/test/core/templaters/jinja_test.py
index 0180f1df8d1..30e69597ec2 100644
--- a/test/core/templaters/jinja_test.py
+++ b/test/core/templaters/jinja_test.py
@@ -703,6 +703,7 @@ def assert_structure(yaml_loader, path, code_only=True, include_meta=False):
         ("jinja_c_dbt/dbt_builtins_ref", True, False),
         ("jinja_c_dbt/dbt_builtins_source", True, False),
         ("jinja_c_dbt/dbt_builtins_this", True, False),
+        ("jinja_c_dbt/dbt_builtins_this_callable", True, False),
         ("jinja_c_dbt/dbt_builtins_var_default", True, False),
         ("jinja_c_dbt/dbt_builtins_test", True, False),
         # do directive
diff --git a/test/fixtures/templater/jinja_c_dbt/dbt_builtins_this_callable.sql b/test/fixtures/templater/jinja_c_dbt/dbt_builtins_this_callable.sql
new file mode 100644
index 00000000000..1085e31493d
--- /dev/null
+++ b/test/fixtures/templater/jinja_c_dbt/dbt_builtins_this_callable.sql
@@ -0,0 +1,2 @@
+SELECT col1
+FROM {{ this.render() }}
diff --git a/test/fixtures/templater/jinja_c_dbt/dbt_builtins_this_callable.yml b/test/fixtures/templater/jinja_c_dbt/dbt_builtins_this_callable.yml
new file mode 100644
index 00000000000..5ad4fc0374b
--- /dev/null
+++ b/test/fixtures/templater/jinja_c_dbt/dbt_builtins_this_callable.yml
@@ -0,0 +1,15 @@
+file:
+  statement:
+    select_statement:
+      select_clause:
+      - keyword: SELECT
+      - select_clause_element:
+          column_reference:
+            naked_identifier: col1
+      from_clause:
+        keyword: FROM
+        from_expression:
+          from_expression_element:
+            table_expression:
+              table_reference:
+                naked_identifier: this_model

Unrecoverable failure in Jinja templating: `RelationEmulator` is not safely callable.
### Search before asking

- [X] I searched the [issues](https://github.com/sqlfluff/sqlfluff/issues) and found no similar issues.

- #3998 is similar, but not quite the same as it is related to custom macros.
- #6253 is the source of this issue.

### What Happened

When using `this.some_function()` in DBT models, SQLFLuff crashes with the following error:

```
Unrecoverable failure in Jinja templating:
<sqlfluff.core.templaters.jinja.JinjaTemplater._generate_dbt_builtins.<locals>.RelationEmulator
object at 0x109cfeef0> is not safely callable. Have you
correctly configured your variables?
https://docs.sqlfluff.com/en/latest/perma/variables.html
```

Is there any way to make the object "safely callable"?

### Expected Behaviour

It works.

### Observed Behaviour

It crashes.

### How to reproduce

Just lint a simple model like this:

```sql
{{ this.include(database = False) }}
```

### Dialect

Snowflake (but the issue should apply to all dialects using the Jinja templater)

### Version

==== sqlfluff ====
sqlfluff:                3.2.4 python:                 3.10.7
implementation:        cpython verbosity:                   1
dialect:             snowflake templater:               jinja
rules:                                all

### Configuration

[sqlfluff]
templater = jinja
dialect = snowflake

### Are you willing to work on and submit a PR to address the issue?

- [x] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/sqlfluff/sqlfluff/blob/main/CODE_OF_CONDUCT.md)

I just found [this](https://github.com/pallets/jinja/blob/main/src/jinja2/sandbox.py#L268) in the Jinja codebase.

Perhaps the issue could be fixed by adding `unsafe_callable = False` and `alters_data = False` to `RelationEmulator`?

Not sure what would be the best way to test this though. 🤔

Are there any tests for the Jinja templater which could be updated with this scenario?


diff --git a/src/sqlfluff/cli/commands.py b/src/sqlfluff/cli/commands.py
index 894c39b3c45..84dddbe3aa5 100644
--- a/src/sqlfluff/cli/commands.py
+++ b/src/sqlfluff/cli/commands.py
@@ -715,6 +715,11 @@ def lint(
         github_result_native = []
         for record in result.as_records():
             filepath = record["filepath"]
+
+            # Add a group, titled with the filename
+            if record["violations"]:
+                github_result_native.append(f"::group::{filepath}")
+
             for violation in record["violations"]:
                 # NOTE: The output format is designed for GitHub action:
                 # https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-a-notice-message
@@ -741,6 +746,10 @@ def lint(

                 github_result_native.append(line)

+            # Close the group
+            if record["violations"]:
+                github_result_native.append("::endgroup::")
+
         file_output = "\n".join(github_result_native)

     if file_output:

diff --git a/test/cli/commands_test.py b/test/cli/commands_test.py
index 823ada02985..34f3739aee9 100644
--- a/test/cli/commands_test.py
+++ b/test/cli/commands_test.py
@@ -1652,7 +1652,7 @@ def test__cli__command_lint_serialize_multiple_files(serialize, write_file, tmp_
         # SQLFluff produces trailing newline
         if result[-1] == "":
             del result[-1]
-        assert len(result) == 12
+        assert len(result) == 16
     else:
         raise Exception

@@ -1778,6 +1778,7 @@ def test__cli__command_lint_serialize_github_annotation():
         (
             "test/fixtures/linter/identifier_capitalisation.sql",
             (
+                "::group::{filename}\n"
                 "::error title=SQLFluff,file={filename},"
                 "line=3,col=5,endLine=3,endColumn=8::"
                 "RF02: Unqualified reference 'foo' found in select with more than one "
@@ -1805,12 +1806,14 @@ def test__cli__command_lint_serialize_github_annotation():
                 "line=5,col=18,endLine=5,endColumn=22::"
                 "CP02: Unquoted identifiers must be consistently lower case. "
                 "[capitalisation.identifiers]\n"
+                "::endgroup::\n"
                 # SQLFluff produces trailing newline
             ),
         ),
         (
             "test/fixtures/linter/jinja_spacing.sql",
             (
+                "::group::{filename}\n"
                 "::error title=SQLFluff,file={filename},"
                 "line=3,col=15,endLine=3,endColumn=22::JJ01: "
                 "Jinja tags should have a single whitespace on either "
@@ -1818,6 +1821,7 @@ def test__cli__command_lint_serialize_github_annotation():
                 # .format() method.
                 "side: {{{{foo}}}} "
                 "[jinja.padding]\n"
+                "::endgroup::\n"
             ),
         ),
     ],
@@ -1843,7 +1847,6 @@ def test__cli__command_lint_serialize_github_annotation_native(
         ],
         ret_code=1,
     )
-
     assert result.output == expected_output.format(filename=fpath_normalised)

Include filename in visible GHA output
### Search before asking

- [X] I searched the [issues](https://github.com/sqlfluff/sqlfluff/issues) and found no similar issues.

### Description

When using `github-annotation-native` format, the raw output contains the filename
```
::warning title=SQLFluff,file=migrations/manual/20240912220714_foo.sql,line=2,col=1,endLine=2,endColumn=3::LT02: Line should not be indented. [layout.indent]
```
and the actual annotations work properly, however the output visible in the GH console doesn't show the filename, which makes it a little tricky from the console output. It might be a little redundant, but maybe the messagee should be prefixed with the filename (or else put the filename on top of each section the way we do in other output formats, if that won't confuse GH)

<img width="991" alt="image" src="https://github.com/user-attachments/assets/fd327745-c835-4c7e-85e8-943106c0e308">

### Use case

_No response_

### Dialect

postgres

### Are you willing to work on and submit a PR to address the issue?

- [X] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/sqlfluff/sqlfluff/blob/main/CODE_OF_CONDUCT.md)


diff --git a/src/sqlfluff/rules/references/RF05.py b/src/sqlfluff/rules/references/RF05.py
index 6ea99e91555..2b12a69555b 100644
--- a/src/sqlfluff/rules/references/RF05.py
+++ b/src/sqlfluff/rules/references/RF05.py
@@ -63,6 +63,9 @@ def _get_additional_allowed_characters(self, dialect_name: str) -> str:
         if dialect_name == "bigquery":
             # In BigQuery, also allow hyphens.
             result.update("-")
+        if dialect_name == "snowflake":
+            # In Snowflake, external stage metadata uses $.
+            result.update("$")
         return "".join(result)

     def _eval(self, context: RuleContext) -> Optional[LintResult]:
@@ -101,6 +104,10 @@ def _eval(self, context: RuleContext) -> Optional[LintResult]:
         ):
             return LintResult(memory=context.memory)

+        if self._is_aliased_select_clause_element(context):
+            # If selects are aliased, ignore unaliased column reference
+            return None
+
         # Do some extra processing for quoted identifiers.
         if context.segment.is_type("quoted_identifier"):
             # Update the default policy to quoted
@@ -215,3 +222,13 @@ def _init_ignore_words_list(self) -> List[str]:
             self.ignore_words_list = []

         return self.ignore_words_list
+
+    @staticmethod
+    def _is_aliased_select_clause_element(context: RuleContext) -> bool:
+        for seg in reversed(context.parent_stack):
+            if seg.is_type("alias_expression"):
+                return False
+            if seg.is_type("select_clause_element"):
+                return seg.get_child("alias_expression") is not None
+
+        return False

diff --git a/test/fixtures/rules/std_rule_cases/RF05.yml b/test/fixtures/rules/std_rule_cases/RF05.yml
index cb2976ef844..9d654ff0730 100644
--- a/test/fixtures/rules/std_rule_cases/RF05.yml
+++ b/test/fixtures/rules/std_rule_cases/RF05.yml
@@ -444,3 +444,49 @@ test_fail_table_aliases:
     rules:
       references.special_chars:
         quoted_identifiers_policy: table_aliases
+
+test_pass_special_chars_snowflake_stage_metadata:
+  # https://docs.snowflake.com/en/user-guide/querying-metadata
+  pass_str: |
+    SELECT
+      METADATA$FILENAME
+      , METADATA$FILE_ROW_NUMBER
+      , METADATA$FILE_CONTENT_KEY
+      , METADATA$FILE_LAST_MODIFIED
+      , METADATA$START_SCAN_TIME
+    FROM @ext_stage;
+  configs:
+    core:
+      dialect: snowflake
+
+test_pass_pivot_snowflake:
+  pass_str: |
+    SELECT
+      COL1,
+      COL2,
+      "'PIVOTED1'" AS PIVOTED1,
+      "'PIVOTED2'" AS PIVOTED2
+    FROM TBL
+    PIVOT (
+      MAX(VAL)
+      FOR COL IN ('PIVOTED1', 'PIVOTED2')
+    )
+  configs:
+    core:
+      dialect: snowflake
+
+test_pass_pivot_snowflake_complex:
+  pass_str: |
+    SELECT
+      COL1,
+      COL2,
+      CAST("'PIVOTED1'" AS bigint) AS PIVOTED1,
+      "'PIVOTED2'" AS PIVOTED2
+    FROM TBL
+    PIVOT (
+      MAX(VAL)
+      FOR COL IN ('PIVOTED1', 'PIVOTED2')
+    )
+  configs:
+    core:
+      dialect: snowflake

Incorrect references.special_chars when using pivoted column
### Search before asking

- [X] I searched the [issues](https://github.com/sqlfluff/sqlfluff/issues) and found no similar issues.

### What Happened

When linting valid Snowflake code, following violation is raised incorrectly.

### Expected Behaviour

Since we only select from invalid named column, not creating invalid named column, violation shouldn't be raised.

### Observed Behaviour

```
== [bug2.sql] FAIL
L:   4 | P:   5 | RF05 | Do not use special characters in identifiers.
                       | [references.special_chars]
L:   5 | P:   5 | RF05 | Do not use special characters in identifiers.
                       | [references.special_chars]
```

### How to reproduce

```sql
SELECT
    COL1,
    COL2,
    "'PIVOTED1'" AS PIVOTED1,
    "'PIVOTED2'" AS PIVOTED2
FROM TBL
PIVOT (
    MAX(VAL)
    FOR COL IN ('PIVOTED1', 'PIVOTED2')
)

```

### Dialect

snowflake

### Version

sqlfluff, version 2.3.4
python 3.10.12

### Configuration

N/A

### Are you willing to work on and submit a PR to address the issue?

- [X] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/sqlfluff/sqlfluff/blob/main/CODE_OF_CONDUCT.md)

#5358 and #5359 are likely same underlying root cause.


diff --git a/src/sqlfluff/cli/commands.py b/src/sqlfluff/cli/commands.py
index ad60730e7e9..3addea2382d 100644
--- a/src/sqlfluff/cli/commands.py
+++ b/src/sqlfluff/cli/commands.py
@@ -313,6 +313,17 @@ def core_options(f: Callable) -> Callable:
             " inline directives."
         ),
     )(f)
+    f = click.option(
+        "--stdin-filename",
+        default=None,
+        help=(
+            "When using stdin as an input, load the configuration as if the contents"
+            " of stdin was in a file in the listed location."
+            " This is useful for some editors that pass file contents from the editor"
+            " that might not match the content on disk."
+        ),
+        type=click.Path(allow_dash=False),
+    )(f)
     return f

@@ -576,6 +587,7 @@ def lint(
     persist_timing: Optional[str] = None,
     extra_config_path: Optional[str] = None,
     ignore_local_config: bool = False,
+    stdin_filename: Optional[str] = None,
     **kwargs,
 ) -> None:
     """Lint SQL files via passing a list of files or using stdin.
@@ -624,6 +636,8 @@ def lint(
     with PathAndUserErrorHandler(formatter):
         # add stdin if specified via lone '-'
         if ("-",) == paths:
+            if stdin_filename:
+                lnt.config = lnt.config.make_child_from_path(stdin_filename)
             result = lnt.lint_string_wrapped(sys.stdin.read(), fname="stdin")
         else:
             result = lnt.lint_paths(
@@ -1032,6 +1046,7 @@ def fix(
     extra_config_path: Optional[str] = None,
     ignore_local_config: bool = False,
     show_lint_violations: bool = False,
+    stdin_filename: Optional[str] = None,
     **kwargs,
 ) -> None:
     """Fix SQL files.
@@ -1086,6 +1101,8 @@ def fix(
     with PathAndUserErrorHandler(formatter):
         # handle stdin case. should output formatted sql to stdout and nothing else.
         if fixing_stdin:
+            if stdin_filename:
+                lnt.config = lnt.config.make_child_from_path(stdin_filename)
             _stdin_fix(lnt, formatter, fix_even_unparsable)
         else:
             _paths_fix(
@@ -1123,6 +1140,7 @@ def cli_format(
     persist_timing: Optional[str] = None,
     extra_config_path: Optional[str] = None,
     ignore_local_config: bool = False,
+    stdin_filename: Optional[str] = None,
     **kwargs,
 ) -> None:
     """Autoformat SQL files.
@@ -1185,6 +1203,8 @@ def cli_format(
     with PathAndUserErrorHandler(formatter):
         # handle stdin case. should output formatted sql to stdout and nothing else.
         if fixing_stdin:
+            if stdin_filename:
+                lnt.config = lnt.config.make_child_from_path(stdin_filename)
             _stdin_fix(lnt, formatter, fix_even_unparsable=False)
         else:
             _paths_fix(
@@ -1278,6 +1298,7 @@ def parse(
     extra_config_path: Optional[str] = None,
     ignore_local_config: bool = False,
     parse_statistics: bool = False,
+    stdin_filename: Optional[str] = None,
     **kwargs,
 ) -> None:
     """Parse SQL files and just spit out the result.
@@ -1314,11 +1335,14 @@ def parse(
     # handle stdin if specified via lone '-'
     with PathAndUserErrorHandler(formatter):
         if "-" == path:
+            file_config = lnt.config
+            if stdin_filename:
+                file_config = file_config.make_child_from_path(stdin_filename)
             parsed_strings = [
                 lnt.parse_string(
                     sys.stdin.read(),
                     "stdin",
-                    config=lnt.config,
+                    config=file_config,
                     parse_statistics=parse_statistics,
                 ),
             ]

diff --git a/test/cli/commands_test.py b/test/cli/commands_test.py
index ed3057d4359..c4af7082798 100644
--- a/test/cli/commands_test.py
+++ b/test/cli/commands_test.py
@@ -234,6 +234,103 @@ def test__cli__command_extra_config_fail():
     )

+stdin_cli_input = (
+    "SELECT\n    A.COL1,\n    B.COL2\nFROM TABA AS A\n" "POSITIONAL JOIN TABB AS B;\n"
+)
+
+
+@pytest.mark.parametrize(
+    ("command", "stdin_filepath", "ret_code", "output"),
+    [
+        (
+            parse,
+            "test/fixtures/cli/stdin_filename/without_config/stdin_filename.sql",
+            0,
+            (
+                "[L:  5, P:  1]      |                    join_clause:\n"
+                "[L:  5, P:  1]      |                        keyword:"
+                "                              'POSITIONAL'"
+            ),
+        ),
+        (
+            parse,
+            "test/fixtures/an_ansi_config_here.sql",
+            1,
+            "Parsing errors found and dialect is set to 'ansi'.",
+        ),
+        (
+            lint,
+            "test/fixtures/cli/stdin_filename/stdin_filename.sql",
+            0,
+            "All Finished!",
+        ),
+        (
+            lint,
+            "test/fixtures/cli/stdin_filename/without_config/stdin_filename.sql",
+            0,
+            "All Finished!",
+        ),
+        (
+            lint,
+            "test/fixtures/an_ansi_config_here.sql",
+            1,
+            "Parsing errors found and dialect is set to 'ansi'.",
+        ),
+        (
+            cli_format,
+            "test/fixtures/cli/stdin_filename/stdin_filename.sql",
+            0,
+            stdin_cli_input,
+        ),
+        (
+            cli_format,
+            "test/fixtures/cli/stdin_filename/without_config/stdin_filename.sql",
+            0,
+            stdin_cli_input,
+        ),
+        (
+            cli_format,
+            "test/fixtures/an_ansi_config_here.sql",
+            1,
+            "[1 templating/parsing errors found]",
+        ),
+        (
+            fix,
+            "test/fixtures/cli/stdin_filename/stdin_filename.sql",
+            0,
+            stdin_cli_input,
+        ),
+        (
+            fix,
+            "test/fixtures/cli/stdin_filename/without_config/stdin_filename.sql",
+            0,
+            stdin_cli_input,
+        ),
+        (
+            fix,
+            "test/fixtures/an_ansi_config_here.sql",
+            1,
+            "Unfixable violations detected.",
+        ),
+    ],
+)
+def test__cli__command_stdin_filename_config(command, stdin_filepath, ret_code, output):
+    """Check the script picks up the config from the indicated path."""
+    invoke_assert_code(
+        ret_code=ret_code,
+        args=[
+            command,
+            [
+                "--stdin-filename",
+                stdin_filepath,
+                "-",
+            ],
+        ],
+        cli_input=stdin_cli_input,
+        assert_output_contains=output,
+    )
+
+
 @pytest.mark.parametrize(
     "command",
     [
diff --git a/test/fixtures/cli/stdin_filename/.sqlfluff b/test/fixtures/cli/stdin_filename/.sqlfluff
new file mode 100644
index 00000000000..b326f22fbcf
--- /dev/null
+++ b/test/fixtures/cli/stdin_filename/.sqlfluff
@@ -0,0 +1,2 @@
+[sqlfluff]
+dialect = duckdb

Add support for a `--stdin-filename` cli option
### Search before asking

- [X] I searched the [issues](https://github.com/sqlfluff/sqlfluff/issues) and found no similar issues.

### Description

Tools such as `black` and `ruff` support a `--stdin-filename` option for interpreting configuration options when passing file contents via stdin. I'd suggest adding something similar to this to improve functionality with the vscode-sqlfluff extension.

### Use case

Currently, the usage with the vscode-sqlfluff extension requires passing the contents of the file to the sqlfluff cli via stdin. This removes a number of expected configurations based on the file's location. The `--stdin-filename` option would allow reenabling those configurations as if stdin was a file in that location.

### Dialect

All

### Are you willing to work on and submit a PR to address the issue?

- [X] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/sqlfluff/sqlfluff/blob/main/CODE_OF_CONDUCT.md)


diff --git a/yfinance/scrapers/history.py b/yfinance/scrapers/history.py
index bda169ea..e4bdca2b 100644
--- a/yfinance/scrapers/history.py
+++ b/yfinance/scrapers/history.py
@@ -1426,7 +1426,7 @@ def _fix_bad_div_adjust(self, df, interval, currency):
                 typical_volatility = np.nan
             else:
                 diffs = df2['Close'].iloc[start:end-1].to_numpy() - df2['Low'].iloc[start+1:end].to_numpy()
-                typical_volatility = np.median(np.abs(diffs))
+                typical_volatility = np.mean(np.abs(diffs))

             possibilities = []
             if (drops==0.0).all() and df2['Volume'].iloc[div_idx]==0:
@@ -1681,10 +1681,6 @@ def cluster_dividends(df, column='div', threshold=7):
                         div_status_df.loc[phantom_div_dt, c] = False
         checks.append('phantom')

-        if not div_status_df[checks].any().any():
-            # Perfect
-            return df
-
         # Remove phantoms early
         if 'phantom' in div_status_df.columns:
             f_phantom = div_status_df['phantom']
@@ -1709,6 +1705,29 @@ def cluster_dividends(df, column='div', threshold=7):
             if 'phantom' in checks:
                 checks.remove('phantom')

+        if not div_status_df[checks].any().any():
+            # Maybe failed to detect a too-small div. If div is ~0.01x of previous and next, then
+            # treat as a 0.01x error
+            if len(div_status_df) > 1:
+                for i in range(0, len(div_status_df)):
+                    r_pre, r_post = None, None
+                    if i > 0:
+                        r_pre = div_status_df['%'].iloc[i-1] / div_status_df['%'].iloc[i]
+                    if i < (len(div_status_df)-1):
+                        r_post = div_status_df['%'].iloc[i+1] / div_status_df['%'].iloc[i]
+                    r_pre = r_pre or r_post
+                    r_post = r_post or r_pre
+                    if abs(r_pre-currency_divide)<20 and abs(r_post-currency_divide)<20:
+                        div_dt = div_status_df.index[i]
+                        div_status_df.loc[div_dt, 'div_too_small'] = True
+
+        if not div_status_df[checks].any().any():
+            # Perfect
+            if df_modified:
+                return df2
+            else:
+                return df
+
         # Check if the present div-adjustment contradicts price action
         for i in range(len(div_status_df)):
             div_idx = div_status_df['idx'].iloc[i]
@@ -1789,7 +1808,8 @@ def cluster_dividends(df, column='div', threshold=7):
                                 elif adjDelta_drop > 0.39*adjDiv:
                                     # Still true that applied adjustment exceeds price action,
                                     # just not clear what solution is (if any).
-                                    div_adj_exceeds_prices = True
+                                    if (x['Adj']<1.0).any():
+                                        div_adj_exceeds_prices = True
                                     break

             # Can prune the space:
@@ -1843,22 +1863,6 @@ def cluster_dividends(df, column='div', threshold=7):

         checks += ['adj_exceeds_prices', 'div_date_wrong']

-        if not div_status_df[checks].any().any():
-            # Maybe failed to detect a too-small div. If div is ~0.01x of previous and next, then
-            # treat as a 0.01x error
-            if len(div_status_df) > 1:
-                for i in range(0, len(div_status_df)):
-                    r_pre, r_post = None, None
-                    if i > 0:
-                        r_pre = div_status_df['%'].iloc[i-1] / div_status_df['%'].iloc[i]
-                    if i < (len(div_status_df)-1):
-                        r_post = div_status_df['%'].iloc[i+1] / div_status_df['%'].iloc[i]
-                    r_pre = r_pre or r_post
-                    r_post = r_post or r_pre
-                    if abs(r_pre-currency_divide)<20 and abs(r_post-currency_divide)<20:
-                        div_dt = div_status_df.index[i]
-                        div_status_df.loc[div_dt, 'div_too_small'] = True
-
         for c in checks:
             if not div_status_df[c].any():
                 div_status_df = div_status_df.drop(c, axis=1)
@@ -1887,11 +1891,16 @@ def cluster_dividends(df, column='div', threshold=7):
                 div_pcts['avg yr yield'] = div_pcts['%'] / div_pcts['period']

             for c in checks:
+                if not cluster[c].to_numpy().any():
+                    cluster = cluster.drop(c, axis=1)
+            cluster_checks = [c for c in checks if c in cluster.columns]
+
+            for c in cluster_checks:
                 f_fail = cluster[c].to_numpy()
                 n_fail = np.sum(f_fail)
                 if n_fail in [0, n]:
                     continue
-                pct_fail = np.sum(f_fail) / n
+                pct_fail = n_fail / n
                 if c == 'div_too_big':
                     true_threshold = 1.0
                     fals_threshold = 0.2
@@ -1900,7 +1909,16 @@ def cluster_dividends(df, column='div', threshold=7):
                         continue

                     if 'adj_exceeds_prices' in cluster.columns and (cluster[c] == (cluster[c] & cluster['adj_exceeds_prices'])).all():
-                        # More likely that true-positive. Maybe the div never happened
+                        # Treat div_too_big=False as false positives IFF adj_exceeds_prices=true AND
+                        # true ratio above (lowered) threshold.
+                        true_threshold = 0.5
+                        f_adj_exceeds_prices = cluster['adj_exceeds_prices'].to_numpy()
+                        n = np.sum(f_adj_exceeds_prices)
+                        n_fail = np.sum(f_fail[f_adj_exceeds_prices])
+                        pct_fail = n_fail / n
+                        if pct_fail > true_threshold:
+                            f = fc & div_status_df['adj_exceeds_prices'].to_numpy()
+                            div_status_df.loc[f, c] = True
                         continue

                     if 'div_exceeds_adj' in cluster.columns and cluster['div_exceeds_adj'].all():

Tests failing
Running `python -m unittest discover -s tests` from #1084 causes 5 failures and 1 error.

======================================================================
ERROR: test_resampling (test_price_repair.TestPriceRepairAssumptions.test_resampling)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/dhruvan/yfinance/tests/test_price_repair.py", line 49, in test_resampling
    elif dfr.index[0] == df_truth.index[1]:
                         ~~~~~~~~~~~~~~^^^
  File "/home/dhruvan/yfinance/.venv/lib/python3.12/site-packages/pandas/core/indexes/base.py", line 5389, in __getitem__
    return getitem(key)
           ^^^^^^^^^^^^
  File "/home/dhruvan/yfinance/.venv/lib/python3.12/site-packages/pandas/core/arrays/datetimelike.py", line 381, in __getitem__
    result = cast("Union[Self, DTScalarOrNaT]", super().__getitem__(key))
                                                ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dhruvan/yfinance/.venv/lib/python3.12/site-packages/pandas/core/arrays/_mixins.py", line 284, in __getitem__
    result = self._ndarray[key]
             ~~~~~~~~~~~~~^^^^^
IndexError: index 1 is out of bounds for axis 0 with size 1

======================================================================
FAIL: test_repair_bad_div_adjusts (test_price_repair.TestPriceRepair.test_repair_bad_div_adjusts)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/dhruvan/yfinance/tests/test_price_repair.py", line 668, in test_repair_bad_div_adjusts
    self.assertTrue(f_close.all())
AssertionError: np.False_ is not true

======================================================================
FAIL: test_repair_zeroes_daily (test_price_repair.TestPriceRepair.test_repair_zeroes_daily)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/dhruvan/yfinance/tests/test_price_repair.py", line 384, in test_repair_zeroes_daily
    self.assertTrue(_np.isclose(repaired_df[c], correct_df[c], rtol=1e-8).all())
AssertionError: np.False_ is not true

======================================================================
FAIL: test_setTzCacheLocation (test_utils.TestCache.test_setTzCacheLocation)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/dhruvan/yfinance/tests/test_utils.py", line 52, in test_setTzCacheLocation
    self.assertTrue(os.path.exists(os.path.join(self.tempCacheDir.name, "tkr-tz.db")))
AssertionError: False is not true

======================================================================
FAIL: test_tzCacheRootLookup (test_utils.TestCacheNoPermission.test_tzCacheRootLookup)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/dhruvan/yfinance/tests/test_utils.py", line 81, in test_tzCacheRootLookup
    self.assertTrue(cache.dummy)
AssertionError: False is not true

======================================================================
FAIL: test_tzCacheRootStore (test_utils.TestCacheNoPermission.test_tzCacheRootStore)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/dhruvan/yfinance/tests/test_utils.py", line 70, in test_tzCacheRootStore
    self.assertTrue(cache.dummy)
AssertionError: False is not true

----------------------------------------------------------------------
Ran 109 tests in 308.065s

FAILED (failures=5, errors=1, skipped=2, expected failures=1)

I ran into this too.

I think the first `test_price_repair.TestPriceRepair.test_repair_bad_div_adjusts` and `test_price_repair.TestPriceRepair.test_repair_zeroes_daily` are related to https://github.com/ranaroussi/yfinance/commit/8daa47716766cca2820b9bf78bb9f4487d387c7c as when I checkout the branch before that, it doesn't report the errors.

As for the `test_utils` cache test, it's harder to reproduce as it works on individual tests but fails when run under `python -m unittest discover -s tests`
~If you can just ignore the repair-related tests, fail probably means I improved the algorithm but didn't update the test data.~
There are real bugs in the repair logic, I'll handle.