diff --git a/CHANGELOG.md b/CHANGELOG.md index 89bde17..4086db8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,15 @@ Format loosely follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - No unreleased changes yet. +## [1.0.11] - 2026-05-28 + +### Fixed + +- Kept dashboard graph neighborhoods functional when a user's installed + local graph export is valid but older than the packaged runtime graph. The + monitor still refuses to extract a mismatched packaged SQLite index, but now + falls back to the local `graph.json` instead of showing an empty graph. + ## [1.0.10] - 2026-05-28 ### Fixed @@ -1599,6 +1608,7 @@ pass. Full test suite: **1316 passed, 2 skipped**. - 5 dead imports removed (`os`, `Mapping`, `timedelta` from `ctx_lifecycle`; `Path` from `intake_gate`, `intake_pipeline`). +[1.0.11]: https://github.com/stevesolun/ctx/releases/tag/v1.0.11 [1.0.10]: https://github.com/stevesolun/ctx/releases/tag/v1.0.10 [1.0.9]: https://github.com/stevesolun/ctx/releases/tag/v1.0.9 [1.0.8]: https://github.com/stevesolun/ctx/releases/tag/v1.0.8 diff --git a/docs/index.md b/docs/index.md index a6d0ce2..277871e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -201,7 +201,7 @@ ones are flagged. New ones self-ingest. --- - **v1.0.10** — MIT, CI-matrixed (Ubuntu 3.12 plus Windows/macOS 3.11/3.12), + **v1.0.11** — MIT, CI-matrixed (Ubuntu 3.12 plus Windows/macOS 3.11/3.12), 3,915 tests collected. Ships console scripts including `ctx-init`, `ctx-monitor` (local dashboard with graph + wiki + load/unload for skills, agents, and MCP servers, plus Harness Setup for user-owned LLMs), diff --git a/pyproject.toml b/pyproject.toml index 7d87cbf..1bdfc2c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "claude-ctx" -version = "1.0.10" +version = "1.0.11" description = "Skill and agent recommendation system for Claude Code — knowledge graph, wiki, and intake quality gates" authors = [{ name = "Steve Solun" }] license = "MIT" diff --git a/src/__init__.py b/src/__init__.py index 6d44801..8994d14 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1,3 +1,3 @@ """ctx — skill and agent recommendation for Claude Code.""" -__version__ = "1.0.10" +__version__ = "1.0.11" diff --git a/src/ctx/__init__.py b/src/ctx/__init__.py index 5c85e4b..790051e 100644 --- a/src/ctx/__init__.py +++ b/src/ctx/__init__.py @@ -30,7 +30,7 @@ ctx.utils - low-level primitives (safe names, atomic IO) """ -__version__ = "1.0.10" +__version__ = "1.0.11" # Public library surface — anything listed here is safe for third- diff --git a/src/ctx_monitor.py b/src/ctx_monitor.py index de00ed9..0d47fc4 100644 --- a/src/ctx_monitor.py +++ b/src/ctx_monitor.py @@ -3256,15 +3256,6 @@ def _graph_neighborhood( ) if indexed is not None: return indexed - manifest_export_id = _dashboard_graph_manifest_export_id() - packaged_export_id = _packaged_graph_export_id() - if ( - not _dashboard_graph_index_path().is_file() - and manifest_export_id is not None - and packaged_export_id is not None - and manifest_export_id != packaged_export_id - ): - return {"nodes": [], "edges": [], "center": None} try: G = _load_dashboard_graph() except Exception: # noqa: BLE001 — graph is advisory; blank on error diff --git a/src/tests/test_ctx_monitor.py b/src/tests/test_ctx_monitor.py index b58eecb..c99334b 100644 --- a/src/tests/test_ctx_monitor.py +++ b/src/tests/test_ctx_monitor.py @@ -2145,10 +2145,12 @@ def test_dashboard_index_extraction_skips_packaged_export_mismatch( assert cm._ensure_dashboard_graph_index() is None -def test_graph_neighborhood_skips_full_graph_on_packaged_export_mismatch( +def test_graph_neighborhood_uses_local_graph_on_packaged_export_mismatch( fake_claude: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: + import networkx as nx + graph_dir = fake_claude / "skill-wiki" / "graphify-out" graph_dir.mkdir(parents=True) (graph_dir / "graph-export-manifest.json").write_text( @@ -2156,17 +2158,13 @@ def test_graph_neighborhood_skips_full_graph_on_packaged_export_mismatch( encoding="utf-8", ) monkeypatch.setattr(cm, "_packaged_graph_export_id", lambda: "new-packaged-export") - monkeypatch.setattr( - cm, - "_load_dashboard_graph", - lambda: (_ for _ in ()).throw(AssertionError("full graph loaded")), - ) + G = nx.Graph() + G.add_node("mcp-server:github", label="GitHub", type="mcp-server", tags=["git"]) + monkeypatch.setattr(cm, "_load_dashboard_graph", lambda: G) - assert cm._graph_neighborhood("github", entity_type="mcp-server") == { - "nodes": [], - "edges": [], - "center": None, - } + result = cm._graph_neighborhood("github", entity_type="mcp-server") + assert result["center"] == "mcp-server:github" + assert result["nodes"][0]["data"]["type"] == "mcp-server" def test_dashboard_index_extraction_works_with_installed_graph_report( @@ -3372,6 +3370,7 @@ def fake_load_graph(): "available": True, }) monkeypatch.setattr(cm, "_load_dashboard_graph", fake_load_graph) + monkeypatch.setattr(cm, "_top_degree_seeds_from_index", lambda _limit=18: []) monkeypatch.setattr(cm, "_GRAPH_CACHE_VALUE", None) html_out = cm._render_graph(None) @@ -3394,6 +3393,7 @@ def _bad(*_a, **_k): # braces in case a downstream path still routes through it. monkeypatch.setitem(sys.modules, "ctx.core.graph.resolve_graph", fake) monkeypatch.setitem(sys.modules, "resolve_graph", fake) + monkeypatch.setattr(cm, "_graph_stats", lambda: {"available": False}) monkeypatch.setattr(cm, "_GRAPH_CACHE_VALUE", None) monkeypatch.setattr(cm, "_GRAPH_CACHE_KEY", None) html_out = cm._render_graph(None)