Skip to content

fix(registry): recover local graphs after registered data directories disappear - #1080

Merged
4 commits merged into
tirth8205:stagingfrom
azizur100389:codex/fix-missing-data-dir
Nov 6, 2026
Merged

4 commits merged into
tirth8205:stagingfrom
azizur100389:codex/fix-missing-data-dir

Conversation

@azizur100389

@azizur100389 azizur100389 commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Linked issue

Closes #1057.

What & why

When a registered external data directory disappears, get_data_dir can recreate it and strand an existing local graph. If the registered directory is missing and the local graph.db exists, warn and fall through to the normal environment/local resolution for both read-only and write callers. Fresh relocations without local graphs and existing registered directories retain their priority. The repos command now displays registered data directories and marks missing ones. Includes usage documentation.

How it was tested

Following the same staged regression/baseline methodology used in my earlier PRs (#274, #276, #279, #353 and #354), against the current contribution target staging at 6b12d11625cbec3b6773e076cb3d136464fa90e5.

  • New regression tests: 8/8 passed on Windows, Python 3.13.14. The reported bug reproduces on unchanged staging before the fix.
  • Initial affected-module run: 215 passed, 3 baseline failures. Every failure also reproduces on unchanged staging (compared by JUnit test identity). The final expanded regression module passed separately; no new affected-module failures.
  • ruff check code_review_graph tests/test_missing_registered_data_dir.py: clean.
  • bandit -r code_review_graph/ -c pyproject.toml: zero findings.
  • mypy code_review_graph/ --ignore-missing-imports --no-strict-optional: the same three existing Windows fcntl.LOCK_EX/LOCK_NB/flock errors in daemon.py as unchanged staging; no new errors.
  • Schema remains version 13 on both Python and VS Code sides.
  • GitHub CI: 17 checks passed on the final commit. Python 3.10–3.13, browser tests, Windows native tests, and the Linux/macOS/Windows MCP client checks are green. Python 3.13 full-suite result: 4276 passed, 804 skipped, 46 deselected, 2 xfailed, 2 xpassed; 85.91% coverage (65% required). The manual upgrade job is skipped by design.

Exact test commands (using a local virtual environment with .[dev], as uv is not installed):

python -m pytest tests/test_missing_registered_data_dir.py -q --tb=short
python -m pytest tests/test_missing_registered_data_dir.py tests/test_incremental.py tests/test_registry.py tests/test_cli.py -q --tb=short
$env:GIT_CEILING_DIRECTORIES = $env:TEMP.Replace('\', '/')
python -m pytest --tb=short -q -m 'not browser and not upgrade' --cov=code_review_graph --cov-report=term --cov-fail-under=65

Full local Windows suite completed: 4,151 passed, 110 failed, 819 skipped, 46 deselected, 2 xfailed, 2 xpassed; 86% coverage. Unchanged staging: 4,143 passed, 110 failed, with identical skip/xfail/xpass counts. Failure identities match unchanged staging exactly; no new failures. The Git ceiling isolates temporary test repositories from an unrelated enclosing home-directory Git repository; PATH/PYTHONPATH point to each checkout under test. Browser tests passed in CI; browser and opt-in upgrade suites were excluded locally.

@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

code-review-graph review

Overall risk: 0.55 (MEDIUM) — 45 changed function(s)/class(es), 40 affected flow(s), 1 test gap(s) (0 with no tested caller found, 1 reached only through a caller)

Risk-scored changes

Risk Level Symbol Location Tested
0.55 medium code_review_graph/incremental.py::get_data_dir code_review_graph/incremental.py:438 yes
0.40 medium tests/test_repos_unreachable_data_dir.py::_git_repo tests/test_repos_unreachable_data_dir.py:27 (test)
0.35 low code_review_graph/cli.py::_dispatch code_review_graph/cli.py:1663 indirect
0.35 low tests/test_swept_data_dir_entry_points.py::_make_repo tests/test_swept_data_dir_entry_points.py:46 (test)
0.30 low tests/test_registered_data_dir_recovery.py::_no_env_overrides tests/test_registered_data_dir_recovery.py:38 (test)
0.30 low tests/test_repos_unreachable_data_dir.py::dead_mount_stat tests/test_repos_unreachable_data_dir.py:90 (test)
0.30 low tests/test_swept_data_dir_entry_points.py::_no_env_overrides tests/test_swept_data_dir_entry_points.py:41 (test)
0.25 low tests/test_swept_data_dir_entry_points.py::test_pretooluse_hook_enriches_from_local_graph tests/test_swept_data_dir_entry_points.py:79 (test)
0.25 low tests/test_swept_data_dir_entry_points.py::test_graph_query_cli_command_reads_local_graph tests/test_swept_data_dir_entry_points.py:117 (test)
0.20 low tests/test_repos_unreachable_data_dir.py::test_repos_lists_every_entry_when_a_data_dir_parent_is_unsea... tests/test_repos_unreachable_data_dir.py:55 (test)

Affected execution flows

  • process — criticality 0.74, 538 node(s) across 14 file(s)
  • _run — criticality 0.74, 565 node(s) across 16 file(s)
  • build_or_update_graph_tool — criticality 0.73, 619 node(s) across 24 file(s)
  • main — criticality 0.72, 925 node(s) across 40 file(s)
  • query_graph_tool — criticality 0.69, 97 node(s) across 11 file(s)
  • ...and 35 more affected flow(s)

Reached only through a caller

No test names these directly, but a tested caller reaches them along the call path shown. That is a path in the call graph, not a record of execution -- the caller's tests may never take this branch. Treat it as where to look, not as coverage: these count as gaps and are scored as untested.

  • code_review_graph/cli.py::_dispatch (code_review_graph/cli.py:1663) — via code_review_graph/cli.py::main, 1 hop(s)

Powered by code-review-graph — local-first analysis; no code leaves the CI runner.

@azizur100389
azizur100389 marked this pull request as ready for review October 1, 2026 16:46
@tirth8205

Copy link
Copy Markdown
Owner

Thank you for this PR. I tested the fallback, the repos listing and the CLI commands with a removed data folder. The fallback works well.

Before I can merge it, please fix these:

  1. The repos command can crash now. Path.is_dir() raises an error on Python 3.10 to 3.13. This happens when the data folder cannot be read, for example when its parent has no permission or a network share is stale. Then repos stops with a traceback and hides the other repos. Staging listed all of them. Where: code_review_graph/cli.py:1922. Example: build with --data-dir under a folder, register a second repo, run chmod 000 on that folder, then run repos. Failing test: tests/test_repos_unreachable_data_dir.py. Using os.path.isdir() or catching OSError should fix it.

The failing tests are on the branch review/pr-1080 in this repo. You can copy them from there. If a test there is marked xfail, please remove that mark with your fix.

After you push the fix, I will test it again.

@azizur100389

Copy link
Copy Markdown
Contributor Author

Hi @tirth8205, the review issues have been fixed and pushed, with regression tests covering the reported cases.

The repos command now catches OSError when inspecting an unreachable registered data directory and continues listing the other repositories. Your regression tests were added and the relevant xfail marks removed.

I rechecked CI today: all 17 checks are passing, with the upgrade-path check intentionally skipped. The branch is also up to date with staging and has no merge conflicts.

Could you please retest the updated PR when you have a chance? Thank you!

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

No active review issues block approval of the registered data-directory recovery changes.

No open issues 🎉

What changed in this PR

Addresses #1057 by preserving access to an existing local graph when a registered external data directory disappears, while retaining normal priority for existing directories and fresh relocations.

Changes:

  • Falls back to environment/local resolution with a warning for both read-only and write callers.
  • Displays registered data directories in repos, marking missing or inaccessible paths without interrupting the listing.
  • Adds recovery and entry-point regression tests, plus usage documentation.
File Description
tests/​test_swept_data_dir_entry_points.py Covers recovery through hooks, context tools, search, and exports.
tests/​test_repos_unreachable_data_dir.py Checks listing resilience to permission and mount errors.
tests/​test_registered_data_dir_recovery.py Covers resolution edge cases and CLI/MCP integration.
tests/​test_missing_registered_data_dir.py Tests fallback, relocation priority, and directory display.
docs/​USAGE.md Documents recovery behavior and missing-directory markers.
code_review_graph/​incremental.py Avoids recreating missing registrations when a local graph exists.
code_review_graph/​cli.py Shows registered data paths and handles inspection errors.

Review effort: Balanced

@tirth8205 tirth8205 closed this pull request by merging all changes into tirth8205:staging in 0160eb0 Nov 6, 2026
gowrishacv pushed a commit to gowrishacv/code-review-graph that referenced this pull request Nov 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

get_data_dir recreates a registered data dir that no longer exists, stranding the real graph

3 participants