fix(release): align ruff pin to 0.15.14 + hoist COCA imports out of hot paths

Two release-blocking fixes for v3.3.6:

1. CI ruff pin drift
   .github/workflows/ci.yml installed ruff==0.15.9 while pyproject.toml
   [dev] extras and .pre-commit-config.yaml both pin 0.15.14. Ruff's
   formatter output can change between minor versions, so a contributor
   running `pip install -e ".[dev]"` and formatting locally with 0.15.14
   would produce output the 0.15.9 lint job rejects. Same failure mode
   that surfaced on PR #1579 (2026-05-22). Aligning CI to 0.15.14 keeps
   the three pin sites in lock-step.

2. COCA filter imports inside per-drawer hot paths
   PR #1605 (COCA content-word filter, shipping in 3.3.6) introduced
   `from .entity_detector import _get_coca_filter` and
   `from .palace import _candidate_entity_words` inside
   _extract_entities_for_metadata (called per drawer) and
   build_closet_lines (called per closet). Python caches module imports
   so the runtime cost after the first call is small, but the import
   machinery still runs Python bytecode every invocation — gemini
   flagged this on the original PR. Hoisting to module-level removes
   the per-call import overhead.

   The hoist is identical to PR #1612, which targets develop. Folding
   it into the release so 3.3.6 doesn't ship the perf regression that
   3.3.7 would immediately have to fix.

Verification: ruff check + format clean on 0.15.14, full pytest
(2258 passed / 12 skipped) on Linux Py 3.9 / 3.11 / 3.13 via
`pip install -e ".[dev]"` (CI-matching).
This commit is contained in:
Milla J
2026-05-24 15:04:56 -07:00
parent f5ea021cec
commit 62a555cd80
3 changed files with 4 additions and 6 deletions
+1 -1
View File
@@ -53,6 +53,6 @@ jobs:
# Keep this pin identical to the `ruff==` pin in pyproject.toml
# ([project.optional-dependencies].dev and [dependency-groups].dev)
# so CI and `pip install -e ".[dev]"` format/lint identically.
- run: pip install "ruff==0.15.9"
- run: pip install "ruff==0.15.14"
- run: ruff check .
- run: ruff format --check .
+2 -3
View File
@@ -19,10 +19,12 @@ from datetime import datetime
from collections import defaultdict
from typing import Optional
from .entity_detector import _get_coca_filter
from .palace import (
NORMALIZE_VERSION,
SKIP_DIRS,
MineValidationError,
_candidate_entity_words,
_open_collection_or_explain,
_validate_palace_fts5_after_mine,
build_closet_lines,
@@ -867,9 +869,6 @@ def _extract_entities_for_metadata(content: str) -> str:
if re.search(r"(?<!\w)" + re.escape(name) + r"(?!\w)", content, re.IGNORECASE):
matched.add(name)
from .entity_detector import _get_coca_filter
from .palace import _candidate_entity_words
coca_filter = _get_coca_filter()
window = content[:_ENTITY_EXTRACT_WINDOW]
words = _candidate_entity_words(window)
+1 -2
View File
@@ -15,6 +15,7 @@ from typing import Optional
from .backends import BackendClosedError, CollectionNotInitializedError, PalaceNotFoundError
from .backends.chroma import ChromaBackend
from .entity_detector import _get_coca_filter
logger = logging.getLogger("mempalace_mcp")
@@ -264,8 +265,6 @@ def build_closet_lines(source_file, drawer_ids, content, wing, room, drawer_meta
# Extract proper nouns (2+ occurrences). Uses i18n-aware patterns so
# non-Latin names (Cyrillic, accented Latin, etc.) are also detected.
from .entity_detector import _get_coca_filter
coca_filter = _get_coca_filter()
words = _candidate_entity_words(window)
word_freq = {}