fix(core): honor BASIC_MEMORY_CONFIG_DIR across remaining call sites#744
fix(core): honor BASIC_MEMORY_CONFIG_DIR across remaining call sites#744groksrc wants to merge 3 commits intofix/fastembed-cache-default-pathfrom
Conversation
|
Claude finished @groksrc's task in 2m 35s —— View job PR Review: fix(core): honor BASIC_MEMORY_CONFIG_DIR across remaining call sites
SummaryThis is a clean, well-scoped follow-up to #743. Each of the five hardcoded Overall: LGTM with minor feedback below. Code Quality Checklist
Findings1. Stale docstring —
|
Several modules were hardcoding ``Path.home() / ".basic-memory"`` when
resolving Basic Memory state, which ignored ``BASIC_MEMORY_CONFIG_DIR``
and caused split state when users isolated config and the database
under a redirected data directory:
- utils.setup_logging — log file
- ignore_utils.get_bmignore_path — .bmignore
- sync.watch_service.WatchService.status_path — watch-status.json
- services.project_service.get_system_status — watch-status.json read
- cli.commands.cloud.rclone_commands.get_project_bisync_state — bisync
state dir
Route each call site through resolve_data_dir() (or the already-threaded
config, where available) so all of these follow the same override.
Also simplify resolve_data_dir() to use Path.home() directly. Path.home()
already reads $HOME on POSIX and %USERPROFILE% on Windows, so the explicit
os.getenv("HOME", ...) dance was redundant and made tests fragile when
they patched os.name to simulate Windows on non-Windows hosts.
Adds regression tests for each call site that exercise the redirected
BASIC_MEMORY_CONFIG_DIR path.
Fixes #742
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Drew Cain <groksrc@gmail.com>
269b0b9 to
e39b8e1
Compare
``test_setup_logging_honors_basic_memory_config_dir`` was monkeypatching
``utils.os.name`` to ``"posix"`` to force ``setup_logging`` onto the
shared-log-filename branch, which let the test assert on the exact
path. That globally redirected ``os.name``, and on Windows CI that
broke ``Path(str)`` dispatch inside ``resolve_data_dir``:
pathlib.UnsupportedOperation: cannot instantiate 'PosixPath' on
your system
The regression guard only cares that the log file lives under the
redirected ``BASIC_MEMORY_CONFIG_DIR`` — not at ``Path.home()``. It
does not care whether the filename is the shared ``basic-memory.log``
(POSIX) or the per-process ``basic-memory-<pid>.log`` (Windows).
Drop the ``os.name`` patch, assert on ``log_path.parent`` equalling
the custom dir, and sanity-check the filename pattern without pinning
the pid suffix. Same intent, portable.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Drew Cain <groksrc@gmail.com>
|
Claude finished @groksrc's task in 2m 47s —— View job PR Review: fix(core): honor BASIC_MEMORY_CONFIG_DIR across remaining call sites
What changed in the latest commit (
|
| Item | Status |
|---|---|
| Follows Basic Memory coding conventions | ✅ |
| Python 3.12+ type annotations and async patterns | ✅ |
| FastAPI / Typer conventions followed | ✅ |
| 100-char line length maintained | ✅ |
| No commented-out code | ✅ |
| Unit tests for all 5 changed call sites | ✅ |
| Edge-case coverage (env var absent) | ✅ |
| 100% test coverage claim is accurate | # pragma: no cover on now-exercised lines (see below) |
| Documentation / docstrings updated | |
| Preserves local-first architecture | ✅ |
| No hardcoded secrets | ✅ |
| Windows path compatibility | ✅ (latest commit fixed the test) |
| No emojis/unicode in console/log output | ✅ |
Outstanding Findings (3 items, carried from previous reviews — not yet addressed)
1. Stale docstring — utils.py:265
# Current (stale)
log_to_file: Write to ~/.basic-memory/basic-memory.log with rotation
# Should be
log_to_file: Write to <basic-memory data dir>/basic-memory.log with rotation (honors BASIC_MEMORY_CONFIG_DIR)2. Stale docstring — ignore_utils.py:183
# Current (stale)
1. ~/.basic-memory/.bmignore (user's global ignore patterns)
# Should be
1. <basic-memory data dir>/.bmignore (user's global ignore patterns, honors BASIC_MEMORY_CONFIG_DIR)3. # pragma: no cover on now-exercised lines — project_service.py:1141–1147
if watch_status_path.exists():
try: # pragma: no cover ← now exercised — remove this
watch_status = json.loads( # pragma: no cover ← now exercised — remove this
watch_status_path.read_text(encoding="utf-8")
)
except Exception: # pragma: no cover ← keep — still hard to test
passtest_get_system_status_reads_watch_status_from_config_dir creates the watch-status file and calls get_system_status(), so the try: / json.loads / .read_text lines are exercised. Remove # pragma: no cover from those two lines only; leave it on except Exception:.
Note: I attempted to push these three fixes directly but lacked write access to the branch (403). The changes are minimal and mechanical — any of the "Fix this →" links above will apply them via Claude Code.
Overall: The five functional changes are correct and well-tested. The latest commit correctly resolves the Windows test-compatibility issue. Three minor cleanup items remain before merge.
- utils.setup_logging: update stale docstring to reflect the new log path (``<basic-memory data dir>/basic-memory.log``, honors BASIC_MEMORY_CONFIG_DIR). The implementation was fixed but the ``Args:`` block still referenced ``~/.basic-memory/``. - ignore_utils.load_gitignore_patterns: same treatment — the "combines patterns from" bullet list still called out ``~/.basic-memory/.bmignore``. - project_service.get_system_status: drop ``# pragma: no cover`` from the ``try`` and ``json.loads(...)`` lines. The new ``test_get_system_status_reads_watch_status_from_config_dir`` test writes a valid watch-status.json and asserts on the parsed payload, so those lines are now exercised. Keeps the pragma on the ``except Exception: pass`` branch, which is still hard to test without injecting a read failure. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Drew Cain <groksrc@gmail.com>
|
Claude finished @groksrc's task in 58s —— View job PR Review: fix(core): honor BASIC_MEMORY_CONFIG_DIR across remaining call sites
What changed in the latest commit (
|
| Finding | Status |
|---|---|
Stale docstring utils.py:265 |
✅ Fixed — now reads <basic-memory data dir>/basic-memory.log with rotation (honors BASIC_MEMORY_CONFIG_DIR) |
Stale docstring ignore_utils.py:183 |
✅ Fixed — now reads <basic-memory data dir>/.bmignore (user's global ignore patterns, honors BASIC_MEMORY_CONFIG_DIR) |
# pragma: no cover on now-exercised lines project_service.py:1142–1143 |
✅ Fixed — pragmas removed from try: and json.loads lines; except Exception: retains its annotation |
Code Quality Checklist
| Item | Status |
|---|---|
| Follows Basic Memory coding conventions | ✅ |
| Python 3.12+ type annotations and async patterns | ✅ |
| FastAPI / Typer conventions followed | ✅ |
| 100-char line length maintained | ✅ |
| No commented-out code | ✅ |
| Unit tests for all 5 changed call sites | ✅ |
| Edge-case coverage (env var absent) | ✅ |
| 100% test coverage claim is accurate | ✅ (pragmas cleaned up) |
| Documentation / docstrings updated | ✅ (both stale docstrings corrected) |
| Preserves local-first architecture | ✅ |
| No hardcoded secrets | ✅ |
| Windows path compatibility | ✅ |
| No emojis/unicode in console/log output | ✅ |
Summary
All previous findings resolved. The PR is clean:
- Five hardcoded
Path.home() / ".basic-memory"call sites now correctly route throughresolve_data_dir()or the threaded config object - Five regression tests (all named
*_honors_basic_memory_config_dir) guard each fix - Deferred import in
setup_loggingcorrectly handles theconfig.py → utils.pycircular-import constraint - Two docstrings updated to reflect the new behavior
# pragma: no covercleaned up to match actual coverage
LGTM — ready to merge.
Summary
Follow-up to #741 / #743. Several modules were hardcoding
Path.home() / ".basic-memory"when resolving Basic Memory state, which ignoredBASIC_MEMORY_CONFIG_DIRand caused split state when users isolated config and the database under a redirected data directory:utils.setup_logging— log fileignore_utils.get_bmignore_path—.bmignoresync.watch_service.WatchService.status_path—watch-status.jsonservices.project_service.get_system_status—watch-status.jsonreadcli.commands.cloud.rclone_commands.get_project_bisync_state— bisync state dirRoute each call site through
resolve_data_dir()(introduced in #743) or the already-threaded config where one is available, so all of these follow the same override.Fixes #742.
What changed
src/basic_memory/utils.py—setup_logging()now usesresolve_data_dir() / log_filenamevia a deferred import (avoids theconfig.py → utils.pycycle).src/basic_memory/ignore_utils.py—get_bmignore_path()usesresolve_data_dir() / ".bmignore".src/basic_memory/sync/watch_service.py—WatchService.status_pathusesapp_config.data_dir_path / WATCH_STATUS_JSON.src/basic_memory/services/project_service.py—get_system_status()usesself.config_manager.config.data_dir_path / WATCH_STATUS_JSON.src/basic_memory/cli/commands/cloud/rclone_commands.py—get_project_bisync_state()usesresolve_data_dir() / "bisync-state" / project_name.Test plan
*_honors_basic_memory_config_dirfor easy grep:test_setup_logging_honors_basic_memory_config_dirtest_get_bmignore_path_honors_basic_memory_config_dir(+ default-path coverage)test_watch_service_status_path_honors_basic_memory_config_dirtest_get_system_status_reads_watch_status_from_config_dirtest_get_project_bisync_state_honors_basic_memory_config_dirtest_setup_logging_*Windows/POSIX tests andtest_get_project_bisync_stateto clearBASIC_MEMORY_CONFIG_DIRexplicitly, so their behavior doesn't depend on ambient env state.tests/sync,tests/services,tests/utils,tests/test_config.py(broader sanity check).🤖 Generated with Claude Code