fix(graphrag): crash on project rename/path change (DF-009)

session_events.py::_on_projects_changed (runs on every project
create/rename/delete) called self.structure._refresh_project_combo() —
but that method only ever existed on GraphRenderer, not on
StructureGraphView itself (self.structure). Renaming a project or
changing its working-directory path raised AttributeError and crashed
the app.

Add StructureGraphView.refresh_project_list(), matching the existing
schedule_rescan/set_project/prewarm forwarding pattern, and call that
instead. Add a regression test
(test_refresh_project_list_forwards_to_renderer).

Logged as DF-009 in Task Tracking Template.xlsx — root cause, fix and
regression test recorded (row was empty in this local copy despite
being reported as already logged there).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 09:46:33 +09:00
co-authored by Claude Sonnet 5
parent a20c7a2d69
commit f6c196ca87
4 changed files with 26 additions and 1 deletions
@@ -55,6 +55,25 @@ def test_structure_graph_view_builds(ctx):
assert view.qa is not None
def test_refresh_project_list_forwards_to_renderer(ctx):
"""Crash bug: ``presentation/shell/session_events.py::_on_projects_changed``
called ``self.structure._refresh_project_combo()`` — a method that only
ever existed on ``GraphRenderer``, not on ``StructureGraphView`` itself —
so creating/renaming/deleting a project (anywhere in the app) raised
``AttributeError`` and crashed. ``refresh_project_list()`` is the public
forwarding method callers must use instead (matching ``schedule_rescan``/
``set_project``/``prewarm``'s existing forwarding pattern)."""
from cowork_local.presentation.graph.structure_graph_view import StructureGraphView
view = StructureGraphView(ctx)
assert not hasattr(view, "_refresh_project_combo")
combo = view.renderer.project_combo
before = combo.count()
view.refresh_project_list() # must not raise
assert combo.count() == before # re-populated from the same project list, same size
def test_render_populates_the_scene_and_emits_graph_rendered(ctx, tmp_path):
from cowork_local.presentation.graph.graph_renderer import GraphRenderer