Skip to content
4 changes: 2 additions & 2 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -661,10 +661,10 @@ jobs:
cargo test --manifest-path Cargo.toml

- name: Lint standalone package with Ruff
run: uv run --with ruff ruff check src tests
run: uv run --with 'ruff==0.15.10' ruff check src tests

- name: Check standalone package formatting with Ruff
run: uv run --with ruff ruff format --check src tests
run: uv run --with 'ruff==0.15.10' ruff format --check src tests

- name: Type check standalone package with mypy
run: uv run --with mypy mypy src tests
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1015,15 +1015,15 @@ jobs:

- name: Lint standalone package with Ruff
run: |
uv run --with ruff ruff check src tests
uv run --with 'ruff==0.15.10' ruff check src tests

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Pin the documented standalone Ruff commands

uv help run describes --with as layering the requested package into a separate ephemeral environment. On a fresh package checkout, however, the required standalone commands remain uv run --with ruff ..., so they can resolve a newer Ruff instead of 0.15.10—the exact condition these workflow changes avoid—while CI passes with the pin. Update the package guide and docs/agents/picklescan-package-split.md:127-134, or make those commands invoke the root-locked tool, so canonical local validation matches CI.

AGENTS.md reference: packages/modelaudit-picklescan/AGENTS.md:L39-L45

Useful? React with 👍 / 👎.


- name: Check standalone package import organization with Ruff
run: |
uv run --with ruff ruff check --select I src tests
uv run --with 'ruff==0.15.10' ruff check --select I src tests

- name: Check standalone package formatting with Ruff
run: |
uv run --with ruff ruff format --check src tests
uv run --with 'ruff==0.15.10' ruff format --check src tests

- name: Type check standalone package with mypy
run: |
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Bug Fixes

- Prevent Windows cache identity probes from creating locked temporary files inside scanned directories.

## [0.2.52](https://github.com/promptfoo/modelaudit/compare/v0.2.51...v0.2.52) (2026-07-22)

### Bug Fixes
Expand Down
4 changes: 2 additions & 2 deletions docs/agents/picklescan-package-split.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ Standalone package checks run from `packages/modelaudit-picklescan`:

```bash
uv lock --check
uv run --with ruff ruff check src tests
uv run --with ruff ruff format --check src tests
uv run --with 'ruff==0.15.10' ruff check src tests
uv run --with 'ruff==0.15.10' ruff format --check src tests
uv run --with mypy mypy src tests
uv run --with pytest --with pytest-xdist pytest -n auto tests --tb=short
uv run --with pytest pytest tests -q
Expand Down
38 changes: 31 additions & 7 deletions modelaudit/cache/batch_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from pathlib import Path
from typing import Any

from ..utils.repository_context import REPOSITORY_SCAN_ROOT_CONFIG_KEY
from .adaptive_cache_keys import AdaptiveCacheKeyGenerator
from .cache_manager import CacheManager
from .cache_policy import should_cache_scan_result
Expand Down Expand Up @@ -73,9 +74,21 @@ def batch_lookup(
cache_dir_groups = self._group_by_cache_directory(cache_lookups)

# Process each cache directory concurrently
scan_config = version_context.get("scan_config") if version_context is not None else None
has_repository_scan_root = isinstance(scan_config, dict) and isinstance(
scan_config.get(REPOSITORY_SCAN_ROOT_CONFIG_KEY), str
)
with ThreadPoolExecutor(max_workers=max_workers) as executor:
future_to_group = {
executor.submit(self._process_cache_directory_group, group_files): group_files
(
executor.submit(
self._process_cache_directory_group,
group_files,
version_context=version_context,
)
if has_repository_scan_root
else executor.submit(self._process_cache_directory_group, group_files)
): group_files
for group, group_files in cache_dir_groups.items()
}

Expand Down Expand Up @@ -119,7 +132,10 @@ def _group_by_cache_directory(
return groups

def _process_cache_directory_group(
self, group_files: list[tuple[str, str, os.stat_result]]
self,
group_files: list[tuple[str, str, os.stat_result]],
*,
version_context: dict[str, Any] | None = None,
) -> dict[str, dict[str, Any] | None]:
"""Process all cache files in a single directory efficiently."""
results: dict[str, dict[str, Any] | None] = {}
Expand All @@ -128,11 +144,19 @@ def _process_cache_directory_group(
try:
# Use optimized cache lookup
if self.cache_manager.cache is not None:
cached_result = self.cache_manager.cache.get_cached_result_by_key(
cache_key,
file_path=file_path,
file_stat=stat_result,
)
if version_context is None:
cached_result = self.cache_manager.cache.get_cached_result_by_key(
cache_key,
file_path=file_path,
file_stat=stat_result,
)
else:
cached_result = self.cache_manager.cache.get_cached_result_by_key(
cache_key,
file_path=file_path,
file_stat=stat_result,
version_context=version_context,
)
else:
cached_result = None
results[file_path] = cached_result
Expand Down
Loading
Loading