node-walk 0.1.1__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. node_walk-0.2.0/CHANGELOG.md +80 -0
  2. {node_walk-0.1.1 → node_walk-0.2.0}/PKG-INFO +29 -4
  3. {node_walk-0.1.1 → node_walk-0.2.0}/README.md +28 -3
  4. node_walk-0.2.0/plans/traversable-graph.md +351 -0
  5. {node_walk-0.1.1 → node_walk-0.2.0}/pyproject.toml +9 -0
  6. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/__init__.py +1 -1
  7. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/cli/main.py +35 -0
  8. node_walk-0.2.0/src/node_walk/web/__init__.py +3 -0
  9. node_walk-0.2.0/src/node_walk/web/app.js +704 -0
  10. node_walk-0.2.0/src/node_walk/web/index.html +157 -0
  11. node_walk-0.2.0/src/node_walk/web/server.py +337 -0
  12. node_walk-0.2.0/src/node_walk/web/style.css +555 -0
  13. node_walk-0.2.0/tests/test_web_server.py +246 -0
  14. {node_walk-0.1.1 → node_walk-0.2.0}/.github/workflows/ci.yml +0 -0
  15. {node_walk-0.1.1 → node_walk-0.2.0}/.github/workflows/release.yml +0 -0
  16. {node_walk-0.1.1 → node_walk-0.2.0}/.gitignore +0 -0
  17. {node_walk-0.1.1 → node_walk-0.2.0}/LICENSE +0 -0
  18. {node_walk-0.1.1 → node_walk-0.2.0}/plans/plan.md +0 -0
  19. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/analysis/__init__.py +0 -0
  20. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/analysis/base.py +0 -0
  21. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/analysis/python/__init__.py +0 -0
  22. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/analysis/python/analyzer.py +0 -0
  23. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/analysis/python/scope.py +0 -0
  24. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/analysis/python/visitor.py +0 -0
  25. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/analysis/python_analyzer.py +0 -0
  26. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/cli/__init__.py +0 -0
  27. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/indexer.py +0 -0
  28. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/ir/__init__.py +0 -0
  29. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/ir/enums.py +0 -0
  30. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/ir/models.py +0 -0
  31. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/query/__init__.py +0 -0
  32. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/query/engine.py +0 -0
  33. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/query/tree_formatter.py +0 -0
  34. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/storage/__init__.py +0 -0
  35. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/storage/base.py +0 -0
  36. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/storage/repository.py +0 -0
  37. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/storage/schema.py +0 -0
  38. {node_walk-0.1.1 → node_walk-0.2.0}/src/node_walk/storage/sqlite_store.py +0 -0
  39. {node_walk-0.1.1 → node_walk-0.2.0}/tests/fixtures/nested_project/base.py +0 -0
  40. {node_walk-0.1.1 → node_walk-0.2.0}/tests/fixtures/nested_project/impl.py +0 -0
  41. {node_walk-0.1.1 → node_walk-0.2.0}/tests/fixtures/simple_project/services.py +0 -0
  42. {node_walk-0.1.1 → node_walk-0.2.0}/tests/test_ir.py +0 -0
  43. {node_walk-0.1.1 → node_walk-0.2.0}/tests/test_python_analyzer.py +0 -0
  44. {node_walk-0.1.1 → node_walk-0.2.0}/tests/test_query_engine.py +0 -0
  45. {node_walk-0.1.1 → node_walk-0.2.0}/tests/test_storage.py +0 -0
@@ -0,0 +1,80 @@
1
+ # Changelog
2
+
3
+ All notable changes to **node-walk** will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ---
9
+
10
+ ## [Unreleased]
11
+
12
+ ---
13
+
14
+ ## [0.2.0] - 2026-08-23
15
+ ### Added
16
+ - **`node-walk serve` command**: Launches an embedded local HTTP server (`localhost:7777` by default) and auto-opens the browser to the interactive graph explorer. Accepts `--port`, `--host`, and `--no-open` flags.
17
+ - **Graph Explorer UI** (`src/node_walk/web/`): A single-page browser application (no build step, no npm) that renders the full code graph using Cytoscape.js (CDN):
18
+ - Force-directed layout with manual drag support.
19
+ - Nodes coloured and shaped by `SymbolKind`; edges styled and coloured by `RelationshipType`.
20
+ - Click node → highlight it and direct neighbours + show detail panel (name, kind, file, lines, signature, docstring, source snippet).
21
+ - Double-click node → lazy 1-hop neighbour expansion via `/api/neighbors`.
22
+ - Right-click context menu: expand neighbours, focus subtree, hide node, reset focus.
23
+ - Debounced search bar backed by `/api/search` → centres and selects the top match.
24
+ - Filter panel (checkboxes) to show/hide nodes by `SymbolKind` and edges by `RelationshipType`; `CONTAINS` edges hidden by default.
25
+ - Tooltip on hover for nodes and edges.
26
+ - Fit-to-viewport and re-layout buttons.
27
+ - Status bar showing visible node/edge counts and selected symbol name.
28
+ - **Web API** (`src/node_walk/web/server.py`): Zero-dependency HTTP server (Python `http.server`) exposing:
29
+ - `GET /api/graph[?kinds=…&rels=…]` — full graph for initial render, with optional kind/relationship filters.
30
+ - `GET /api/symbol/{id}` — symbol detail including source snippet, caller/callee counts.
31
+ - `GET /api/neighbors/{id}[?direction=out|in|both&rels=…]` — 1-hop neighbours for lazy canvas expansion.
32
+ - `GET /api/search?q=…` — fuzzy symbol search (reuses `QueryEngine.find_symbol`).
33
+ - `GET /api/stats` — graph statistics.
34
+ - **API tests** (`tests/test_web_server.py`): Full test suite covering all five endpoints (schema validation, filter params, 404 handling, score ranges) plus a full smoke round-trip and static file serving tests.
35
+
36
+ ### Changed
37
+ - **`pyproject.toml`**: Added `force-include` entries so `index.html`, `style.css`, and `app.js` are bundled in the installed wheel.
38
+ - **`node-walk help`**: Added "Browser Explorer" section listing the `serve` command.
39
+
40
+
41
+ ## [0.1.1] - 2026-08-20
42
+
43
+ ### Added
44
+ - **Dotted-Path Symbol Search**: Support searching for scoped symbols (e.g. `ModelAdapter.chat`, `UserService.create_user`) matching child symbols within parents without needing full module paths.
45
+ - **Fuzzy / Typo Matching**: Added `difflib.SequenceMatcher` fallback across symbols to handle typos (e.g. `ModelAdpater.chat`, `creat_user`), returning match scores and `(fuzzy)` indicators.
46
+ - **Graph Visualizations**: Added ASCII tree, Graphviz DOT (`.dot`), and Mermaid diagram formatters in `tree_formatter.py`.
47
+ - **`graph` Command**: Added `node-walk graph <symbol>` for general BFS neighborhood exploration with customizable direction (`out`, `in`, `both`) and format (`tree`, `dot`, `mermaid`, `table`).
48
+ - **Formatting Options**: Added `--format` / `-f` (`tree`, `dot`, `mermaid`, `table`) and `--output` / `-o` flags to `trace` and `blast-radius` commands.
49
+ - **Automated Versioning in CI**: Updated GitHub Actions release workflow with dynamic version resolution (tag triggers or `patch`/`minor`/`major` dispatch inputs).
50
+
51
+ ### Changed
52
+ - **Branding**: Renamed project and CLI binaries from `CodeGraph` to `node-walk`.
53
+ - **Packaging**: Switched `pyproject.toml` to dynamic versioning via Hatchling reading from `src/node_walk/__init__.py`.
54
+ - **CLI Resolution**: Auto-select top candidate when an unambiguous high-confidence match is found instead of prompting unnecessarily.
55
+ - **Documentation**: Updated `README.md` to reflect all currently supported features, traversal modes, and CLI commands.
56
+
57
+ ---
58
+
59
+ ## [0.1.0] - 2026-08-20
60
+
61
+ ### Added
62
+ - **Tree-sitter Python Analyzer**: High-speed AST analysis extracting files, classes, methods, functions, constants, variables, fields, docstrings, signatures, and call sites.
63
+ - **Language-Independent Code IR**: Pydantic v2 data models for `Symbol`, `Relationship`, `FileInfo`, `SourceLocation`, and `AnalysisResult`.
64
+ - **Typed Semantic Relationships**: Support for `CONTAINS`, `IMPORTS`, `CALLS`, `REFERENCES`, `EXTENDS`, `IMPLEMENTS`, and `OVERRIDES`.
65
+ - **SQLite Storage Backend**: Local SQLite database with WAL mode, foreign keys, and 10 query indexes.
66
+ - **Recursive CTE Query Engine**: In-database bounded graph traversals (`walk`, `trace`, `blast_radius`) using recursive SQL CTEs.
67
+ - **Rich CLI**: Typer-based command-line interface with custom themed tables and syntax highlighting:
68
+ - `index`: Analyze and index a codebase.
69
+ - `find`: Search symbols by name or qualified name.
70
+ - `definition`: Show symbol definition and metadata.
71
+ - `source`: Extract and display the exact source code block of any symbol.
72
+ - `callers` & `callees`: Discover direct upstream and downstream call sites.
73
+ - `refs`: Locate symbol references.
74
+ - `implementations`: Find concrete classes extending or implementing interfaces/ABCs.
75
+ - `imports`: Inspect imported modules and symbols.
76
+ - `trace`: Follow outgoing dependency chains.
77
+ - `blast-radius`: Follow incoming dependent chains.
78
+ - `stats`: Display database statistics and symbol/relationship breakdowns.
79
+ - `export`: Export the complete semantic graph to JSON.
80
+ - `help`: Custom command cheat sheet.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: node-walk
3
- Version: 0.1.1
3
+ Version: 0.2.0
4
4
  Summary: Semantic code intelligence — local-first graph of your codebase for humans and LLMs
5
5
  Author: CodeGraph Contributors
6
6
  License: MIT
@@ -38,8 +38,9 @@ Local-first · Lightweight · Fast indexing · SQLite backed · CLI & Visualizat
38
38
  - **Smart Symbol Search**: Find symbols by simple name (`chat`), qualified dotted path (`ModelAdapter.chat`), or fuzzy typo matching (`ModelAdpater.chat`).
39
39
  - **Exact Source Retrieval**: View definitions, signatures, and exact source ranges instantly.
40
40
  - **Relationship Navigation**: Find callers, callees, references, class implementations / ABCs, and imports.
41
- - **Graph Traversal & Visualization**: Trace outgoing call chains and incoming blast radiuses rendered directly in terminal (ASCII tree), exported to Graphviz (`.dot`), or generated as Mermaid diagrams.
42
- - **Lightweight & Self-Contained**: Pure Python + Tree-sitter + SQLite. Zero external database services or cloud dependencies.
41
+ - **Graph Traversal & Visualization**: Trace outgoing call chains and incoming blast radiuses rendered in terminal (ASCII tree), exported to Graphviz (`.dot`), or generated as Mermaid diagrams.
42
+ - **Browser Graph Explorer**: `node-walk serve` launches a local interactive Cytoscape.js graph — click nodes, expand neighbours, search symbols, filter by kind/relationship, and inspect source — all without leaving the browser.
43
+ - **Lightweight & Self-Contained**: Pure Python + Tree-sitter + SQLite + stdlib `http.server`. Zero external database services, cloud dependencies, or build steps.
43
44
 
44
45
  ---
45
46
 
@@ -111,7 +112,25 @@ node-walk blast-radius UserService.create_user --format tree
111
112
  node-walk graph ModelAdapter --depth 3 --format tree
112
113
  ```
113
114
 
114
- ### 5. Utilities
115
+ ### 5. Browser Graph Explorer
116
+ ```bash
117
+ # Launch the interactive graph explorer in your browser
118
+ node-walk serve # default: http://localhost:7777
119
+ node-walk serve --port 8888 # custom port
120
+ node-walk serve --no-open # start server only, don't auto-open
121
+ ```
122
+
123
+ The explorer visualises **all** symbols and relationships as a force-directed interactive graph:
124
+
125
+ | Action | Result |
126
+ |---|---|
127
+ | Click node | Highlight node + direct neighbours; open detail panel |
128
+ | Double-click node | Lazy-expand 1-hop neighbours from the server |
129
+ | Right-click node | Context menu: expand, focus subtree, hide, reset |
130
+ | Search bar | Debounced fuzzy search → centre + select result |
131
+ | Filter panel | Toggle visibility by SymbolKind / RelationshipType |
132
+
133
+ ### 6. Utilities
115
134
  ```bash
116
135
  # Show database statistics (symbol kinds, relationship counts)
117
136
  node-walk stats
@@ -147,3 +166,9 @@ pytest tests/ -v
147
166
  ## Graph Storage & Lifecycle
148
167
 
149
168
  The generated graph is stored in `.node_walk/graph.db` inside your indexed repository. It is disposable and can be re-indexed at any time with `node-walk index .`.
169
+
170
+ ---
171
+
172
+ ## Changelog
173
+
174
+ See [CHANGELOG.md](file:///c:/Users/nshri/Github/CodeGraph/CHANGELOG.md) for full release history and notes.
@@ -14,8 +14,9 @@ Local-first · Lightweight · Fast indexing · SQLite backed · CLI & Visualizat
14
14
  - **Smart Symbol Search**: Find symbols by simple name (`chat`), qualified dotted path (`ModelAdapter.chat`), or fuzzy typo matching (`ModelAdpater.chat`).
15
15
  - **Exact Source Retrieval**: View definitions, signatures, and exact source ranges instantly.
16
16
  - **Relationship Navigation**: Find callers, callees, references, class implementations / ABCs, and imports.
17
- - **Graph Traversal & Visualization**: Trace outgoing call chains and incoming blast radiuses rendered directly in terminal (ASCII tree), exported to Graphviz (`.dot`), or generated as Mermaid diagrams.
18
- - **Lightweight & Self-Contained**: Pure Python + Tree-sitter + SQLite. Zero external database services or cloud dependencies.
17
+ - **Graph Traversal & Visualization**: Trace outgoing call chains and incoming blast radiuses rendered in terminal (ASCII tree), exported to Graphviz (`.dot`), or generated as Mermaid diagrams.
18
+ - **Browser Graph Explorer**: `node-walk serve` launches a local interactive Cytoscape.js graph — click nodes, expand neighbours, search symbols, filter by kind/relationship, and inspect source — all without leaving the browser.
19
+ - **Lightweight & Self-Contained**: Pure Python + Tree-sitter + SQLite + stdlib `http.server`. Zero external database services, cloud dependencies, or build steps.
19
20
 
20
21
  ---
21
22
 
@@ -87,7 +88,25 @@ node-walk blast-radius UserService.create_user --format tree
87
88
  node-walk graph ModelAdapter --depth 3 --format tree
88
89
  ```
89
90
 
90
- ### 5. Utilities
91
+ ### 5. Browser Graph Explorer
92
+ ```bash
93
+ # Launch the interactive graph explorer in your browser
94
+ node-walk serve # default: http://localhost:7777
95
+ node-walk serve --port 8888 # custom port
96
+ node-walk serve --no-open # start server only, don't auto-open
97
+ ```
98
+
99
+ The explorer visualises **all** symbols and relationships as a force-directed interactive graph:
100
+
101
+ | Action | Result |
102
+ |---|---|
103
+ | Click node | Highlight node + direct neighbours; open detail panel |
104
+ | Double-click node | Lazy-expand 1-hop neighbours from the server |
105
+ | Right-click node | Context menu: expand, focus subtree, hide, reset |
106
+ | Search bar | Debounced fuzzy search → centre + select result |
107
+ | Filter panel | Toggle visibility by SymbolKind / RelationshipType |
108
+
109
+ ### 6. Utilities
91
110
  ```bash
92
111
  # Show database statistics (symbol kinds, relationship counts)
93
112
  node-walk stats
@@ -123,3 +142,9 @@ pytest tests/ -v
123
142
  ## Graph Storage & Lifecycle
124
143
 
125
144
  The generated graph is stored in `.node_walk/graph.db` inside your indexed repository. It is disposable and can be re-indexed at any time with `node-walk index .`.
145
+
146
+ ---
147
+
148
+ ## Changelog
149
+
150
+ See [CHANGELOG.md](file:///c:/Users/nshri/Github/CodeGraph/CHANGELOG.md) for full release history and notes.
@@ -0,0 +1,351 @@
1
+ # Traversable Graph — Feature Plan
2
+
3
+ **Interactive browser-based code graph visualization for node-walk.**
4
+
5
+ Light-touch MVP first, iterate from user feedback.
6
+
7
+ ---
8
+
9
+ ## 1. Goal
10
+
11
+ Let a developer **see and click through** their code graph in a browser — starting from any symbol, expanding neighbors on click, reading source on hover — rather than only navigating via terminal commands.
12
+
13
+ The graph is **local-only**: a tiny embedded HTTP server reads the same `.node_walk/graph.db` that the CLI already produces. No cloud, no build step, no bundler.
14
+
15
+ ---
16
+
17
+ ## 2. What the MVP Does
18
+
19
+ | Capability | Detail |
20
+ |---|---|
21
+ | **Launch from CLI** | `node-walk serve` starts a local HTTP server (default `localhost:7777`) and opens the browser. |
22
+ | **Full graph overview** | On load, render all symbols + relationships from the indexed repo. Nodes are colored by `SymbolKind`, edges by `RelationshipType`. |
23
+ | **Click to focus** | Click a node → highlight it and its direct neighbors, dim everything else. |
24
+ | **Expand / collapse** | Double-click a node → run a 1-hop walk from that node and add newly discovered neighbors to the canvas (lazy expansion). |
25
+ | **Node detail panel** | Select a node → side panel shows: qualified name, kind, file, line range, signature, docstring preview. |
26
+ | **Search bar** | Type a symbol name → fuzzy match (reuses `find_symbol` logic server-side) → center the graph on the result. |
27
+ | **Layout** | Force-directed layout (Cytoscape.js `cose`) with manual drag. |
28
+ | **Edge labels** | Edges show relationship type (`CALLS`, `IMPORTS`, `EXTENDS`, etc.). |
29
+ | **Filter panel** | Checkboxes to show/hide by SymbolKind and RelationshipType. |
30
+
31
+ ### What the MVP Does NOT Do
32
+
33
+ - No live re-indexing (user must `node-walk index` first).
34
+ - No edit-in-place or "go to file in editor" integration.
35
+ - No multi-repo or remote graphs.
36
+ - No persistence of layout state between sessions.
37
+
38
+ ---
39
+
40
+ ## 3. Architecture
41
+
42
+ ```
43
+ ┌────────────────────────────────┐
44
+ │ Browser │
45
+ │ ┌──────────────────────────┐ │
46
+ │ │ Single-Page HTML/JS/CSS │ │
47
+ │ │ Cytoscape.js (CDN) │ │
48
+ │ └──────────┬───────────────┘ │
49
+ │ │ fetch /api/* │
50
+ └─────────────┼──────────────────┘
51
+ │ HTTP (localhost)
52
+ ┌─────────────┼──────────────────┐
53
+ │ node-walk serve │
54
+ │ ┌──────────┴───────────────┐ │
55
+ │ │ Python HTTP server │ │
56
+ │ │ (aiohttp or stdlib) │ │
57
+ │ │ JSON API endpoints │ │
58
+ │ └──────────┬───────────────┘ │
59
+ │ │ │
60
+ │ ┌──────────┴───────────────┐ │
61
+ │ │ QueryEngine │ │
62
+ │ │ SQLiteGraphStore │ │
63
+ │ │ (.node_walk/graph.db) │ │
64
+ │ └──────────────────────────┘ │
65
+ └────────────────────────────────┘
66
+ ```
67
+
68
+ **Zero new Python dependencies for MVP.** The HTTP server uses Python's built-in `http.server` module. The frontend loads Cytoscape.js from CDN. All HTML/CSS/JS is served from a single bundled directory inside the package.
69
+
70
+ ---
71
+
72
+ ## 4. Backend — API Endpoints
73
+
74
+ All endpoints return JSON. The server is a thin wrapper around `QueryEngine`.
75
+
76
+ ### `GET /api/graph`
77
+
78
+ Returns the full graph (all symbols + relationships) for initial render.
79
+
80
+ ```json
81
+ {
82
+ "nodes": [
83
+ {
84
+ "id": "uuid",
85
+ "name": "chat",
86
+ "qualified_name": "jarvis.model.base.ModelAdapter.chat",
87
+ "kind": "METHOD",
88
+ "file_path": "src/jarvis/model/base.py",
89
+ "start_line": 42,
90
+ "end_line": 58,
91
+ "signature": "(self, messages: list[ChatMessage]) -> str",
92
+ "docstring": "Send messages to the model and return response.",
93
+ "parent_id": "uuid-of-ModelAdapter"
94
+ }
95
+ ],
96
+ "edges": [
97
+ {
98
+ "id": "uuid",
99
+ "source": "source-symbol-uuid",
100
+ "target": "target-symbol-uuid",
101
+ "type": "CALLS",
102
+ "resolution": "resolved"
103
+ }
104
+ ],
105
+ "stats": {
106
+ "total_nodes": 127,
107
+ "total_edges": 304
108
+ }
109
+ }
110
+ ```
111
+
112
+ **Query params:**
113
+ - `?kinds=CLASS,METHOD,FUNCTION` — filter node kinds (default: all)
114
+ - `?rels=CALLS,IMPORTS,EXTENDS` — filter edge types (default: all)
115
+
116
+ ### `GET /api/symbol/{id}`
117
+
118
+ Returns full detail for a single symbol (definition, source snippet).
119
+
120
+ ```json
121
+ {
122
+ "symbol": { /* same shape as node above */ },
123
+ "source_lines": ["def chat(self, ...):", " ..."],
124
+ "callers_count": 3,
125
+ "callees_count": 5,
126
+ "refs_count": 8
127
+ }
128
+ ```
129
+
130
+ ### `GET /api/neighbors/{id}`
131
+
132
+ Returns 1-hop neighbors of a symbol (for lazy expand on double-click).
133
+
134
+ ```json
135
+ {
136
+ "nodes": [ /* new nodes not already on canvas */ ],
137
+ "edges": [ /* edges connecting to/from the expanded node */ ]
138
+ }
139
+ ```
140
+
141
+ **Query params:**
142
+ - `?direction=out|in|both` (default: `both`)
143
+ - `?rels=CALLS,IMPORTS` (default: all)
144
+
145
+ ### `GET /api/search?q=<query>`
146
+
147
+ Fuzzy symbol search. Returns top matches with scores.
148
+
149
+ ```json
150
+ {
151
+ "results": [
152
+ {
153
+ "id": "uuid",
154
+ "qualified_name": "pkg.ModelAdapter.chat",
155
+ "kind": "METHOD",
156
+ "score": 0.95
157
+ }
158
+ ]
159
+ }
160
+ ```
161
+
162
+ ### `GET /api/stats`
163
+
164
+ Returns graph statistics (reuses `QueryEngine.stats()`).
165
+
166
+ ---
167
+
168
+ ## 5. Frontend — Single-Page App
169
+
170
+ ### Technology
171
+
172
+ | Component | Choice | Rationale |
173
+ |---|---|---|
174
+ | Graph rendering | **Cytoscape.js** (CDN) | Mature, performant, supports cola/cose layouts, built-in selection/expansion APIs. |
175
+ | Styling | Vanilla CSS | Zero build step. Dark theme by default. |
176
+ | HTTP | `fetch()` | No framework needed. |
177
+
178
+ ### Files
179
+
180
+ All frontend files live under `src/node_walk/web/`:
181
+
182
+ ```
183
+ src/node_walk/web/
184
+ ├── index.html # Single-page shell
185
+ ├── style.css # Dark theme, layout, panels
186
+ └── app.js # Cytoscape init, API calls, interaction handlers
187
+ ```
188
+
189
+ ### UI Layout
190
+
191
+ ```
192
+ ┌───────────────────────────────────────────────────────────────┐
193
+ │ ┌─────────────────────────────────────────┐ ┌───────────┐ │
194
+ │ │ Search bar │ │ Filters │ │
195
+ │ └─────────────────────────────────────────┘ └───────────┘ │
196
+ │ ┌─────────────────────────────────────────┐ ┌───────────┐ │
197
+ │ │ │ │ Detail │ │
198
+ │ │ │ │ Panel │ │
199
+ │ │ Cytoscape Canvas │ │ │ │
200
+ │ │ (interactive graph) │ │ - Name │ │
201
+ │ │ │ │ - Kind │ │
202
+ │ │ │ │ - File │ │
203
+ │ │ │ │ - Lines │ │
204
+ │ │ │ │ - Source │ │
205
+ │ └─────────────────────────────────────────┘ └───────────┘ │
206
+ │ ┌─────────────────────────────────────────────────────────┐ │
207
+ │ │ Status bar: node count · edge count · index path │ │
208
+ │ └─────────────────────────────────────────────────────────┘ │
209
+ └───────────────────────────────────────────────────────────────┘
210
+ ```
211
+
212
+ ### Interactions
213
+
214
+ | User Action | Behavior |
215
+ |---|---|
216
+ | **Click node** | Select → highlight it + direct neighbors. Show detail panel. |
217
+ | **Double-click node** | Lazy expand: fetch `/api/neighbors/{id}`, add new nodes/edges, re-layout locally. |
218
+ | **Right-click node** | Context menu: "Trace from here", "Blast radius", "Hide node", "Focus subtree". |
219
+ | **Hover node** | Tooltip with qualified name + kind. |
220
+ | **Hover edge** | Tooltip with relationship type. |
221
+ | **Search** | Debounced keystroke → `GET /api/search?q=...` → highlight + center on top match. |
222
+ | **Filter checkboxes** | Toggle visibility of SymbolKind / RelationshipType categories. |
223
+ | **Drag node** | Manual positioning (disables auto-layout for that node). |
224
+ | **Scroll** | Zoom in/out. |
225
+ | **Fit button** | Reset viewport to fit all visible nodes. |
226
+
227
+ ### Node Styling (by SymbolKind)
228
+
229
+ | Kind | Shape | Color |
230
+ |---|---|---|
231
+ | CLASS | Round rectangle | `#4FC3F7` (blue) |
232
+ | INTERFACE | Diamond | `#7E57C2` (purple) |
233
+ | FUNCTION | Ellipse | `#66BB6A` (green) |
234
+ | METHOD | Ellipse | `#FFA726` (orange) |
235
+ | MODULE / FILE | Rectangle | `#AB47BC` (violet) |
236
+ | CONSTANT | Small rectangle | `#FFEE58` (yellow) |
237
+ | VARIABLE / FIELD | Small ellipse | `#BDBDBD` (grey) |
238
+
239
+ ### Edge Styling (by RelationshipType)
240
+
241
+ | Type | Style | Color |
242
+ |---|---|---|
243
+ | CALLS | Solid arrow | `#42A5F5` (blue) |
244
+ | IMPORTS | Dashed arrow | `#AB47BC` (purple) |
245
+ | EXTENDS | Bold arrow | `#66BB6A` (green) |
246
+ | IMPLEMENTS | Dashed arrow | `#26A69A` (teal) |
247
+ | REFERENCES | Dotted arrow | `#9E9E9E` (grey) |
248
+ | CONTAINS | Dotted, thin | `#E0E0E0` (light grey) |
249
+
250
+ ---
251
+
252
+ ## 6. Implementation Plan
253
+
254
+ ### Phase 1: Backend API (server.py)
255
+
256
+ **New file:** `src/node_walk/web/server.py`
257
+
258
+ 1. Create a `http.server.HTTPServer` subclass that:
259
+ - Serves static files from `src/node_walk/web/` for `/`, `/style.css`, `/app.js`.
260
+ - Routes `/api/*` requests to handler functions.
261
+ - Opens `SQLiteGraphStore` + `QueryEngine` on startup.
262
+ 2. Implement API handlers:
263
+ - `handle_graph()` → serialize all symbols + relationships to JSON.
264
+ - `handle_symbol(id)` → serialize symbol detail + source snippet.
265
+ - `handle_neighbors(id)` → 1-hop walk, serialize incremental nodes/edges.
266
+ - `handle_search(q)` → `find_symbol()`, serialize matches.
267
+ - `handle_stats()` → `stats()`, serialize.
268
+ 3. Add `serve` command to CLI (`main.py`):
269
+ ```python
270
+ @app.command()
271
+ def serve(
272
+ port: int = 7777,
273
+ no_open: bool = False,
274
+ ):
275
+ """Launch the interactive graph explorer in your browser."""
276
+ ```
277
+ 4. Auto-open `http://localhost:{port}` in the default browser via `webbrowser.open()`.
278
+
279
+ ### Phase 2: Frontend (index.html + style.css + app.js)
280
+
281
+ **New files:** `src/node_walk/web/index.html`, `style.css`, `app.js`
282
+
283
+ 1. **index.html**: Minimal shell — imports Cytoscape.js from CDN, links `style.css` and `app.js`.
284
+ 2. **style.css**: Dark theme, layout grid (graph canvas + side panel), search bar, filter panel, status bar.
285
+ 3. **app.js**:
286
+ - On load: `fetch('/api/graph')` → feed nodes/edges to Cytoscape.
287
+ - Node click → fetch `/api/symbol/{id}` → populate detail panel.
288
+ - Node double-click → fetch `/api/neighbors/{id}` → add to graph, run local layout.
289
+ - Search input → debounced fetch `/api/search` → center + highlight.
290
+ - Filter checkboxes → toggle element visibility via `cy.elements().filter(...)`.
291
+
292
+ ### Phase 3: CLI Integration
293
+
294
+ 1. Add `serve` command to `main.py`.
295
+ 2. Include `src/node_walk/web/` in the package build (`pyproject.toml` package data).
296
+ 3. Update `README.md` and `CHANGELOG.md`.
297
+
298
+ ### Phase 4: Tests
299
+
300
+ 1. **Backend API tests** (`tests/test_web_server.py`):
301
+ - Spin up server in a thread, hit each endpoint, assert JSON schema.
302
+ - Test search endpoint with fuzzy queries.
303
+ - Test neighbors endpoint returns incremental data.
304
+ 2. **Smoke test**: Index a fixture repo, start server, verify `/api/graph` returns valid JSON with expected node/edge counts.
305
+
306
+ ---
307
+
308
+ ## 7. File Manifest
309
+
310
+ | File | Status | Purpose |
311
+ |---|---|---|
312
+ | `src/node_walk/web/__init__.py` | NEW | Package marker |
313
+ | `src/node_walk/web/server.py` | NEW | HTTP server + API handlers |
314
+ | `src/node_walk/web/index.html` | NEW | Single-page HTML shell |
315
+ | `src/node_walk/web/style.css` | NEW | Dark theme + layout |
316
+ | `src/node_walk/web/app.js` | NEW | Cytoscape.js graph logic |
317
+ | `src/node_walk/cli/main.py` | MODIFY | Add `serve` command |
318
+ | `pyproject.toml` | MODIFY | Include `web/` in package data |
319
+ | `tests/test_web_server.py` | NEW | API endpoint tests |
320
+ | `README.md` | MODIFY | Document `serve` command |
321
+ | `CHANGELOG.md` | MODIFY | Add traversable graph entry |
322
+
323
+ ---
324
+
325
+ ## 8. Post-MVP Improvements (Later)
326
+
327
+ These are explicitly **not** in the MVP scope, but worth tracking:
328
+
329
+ | Improvement | Description |
330
+ |---|---|
331
+ | **Compound nodes** | Nest methods inside class nodes (Cytoscape.js compound node support). |
332
+ | **Trace overlay** | Click "Trace" → highlight the full call chain path with animated edges. |
333
+ | **Blast radius heatmap** | Color nodes by blast-radius depth (red = close, blue = far). |
334
+ | **"Open in editor" link** | `vscode://file/{path}:{line}` deep-links from the detail panel. |
335
+ | **Layout persistence** | Save/restore node positions to `.node_walk/layout.json`. |
336
+ | **Incremental re-index** | Watch file changes, re-index modified files, push updates to connected browser via WebSocket. |
337
+ | **Performance: virtual rendering** | For repos with >5k symbols, use Cytoscape.js `webgl` renderer or cluster nodes by module. |
338
+ | **Minimap** | Small overview panel for orientation on large graphs. |
339
+ | **Dark/light toggle** | Theme switcher. |
340
+
341
+ ---
342
+
343
+ ## 9. Constraints & Decisions
344
+
345
+ | Decision | Rationale |
346
+ |---|---|
347
+ | **stdlib `http.server`** over Flask/FastAPI | Zero new dependencies, consistent with "lightweight" philosophy. MVP doesn't need async, middleware, or routing frameworks. |
348
+ | **Cytoscape.js from CDN** | No npm/bundler build step. Single HTML file can load it. Cytoscape is the most mature JS graph library with built-in layouts, selection, and expansion. |
349
+ | **All frontend in 3 files** | Keeps it dead simple. No React, no Vite, no TypeScript. If the MVP proves valuable, we can graduate to a proper SPA later. |
350
+ | **Full graph on initial load** | For repos up to ~2-3k symbols this is fine (Cytoscape handles 5k+ nodes). For larger repos, Phase 2 can add pagination or module-level clustering. |
351
+ | **CONTAINS edges hidden by default** | They dominate the graph and add visual clutter. Users can toggle them on via the filter panel. |
@@ -44,6 +44,15 @@ path = "src/node_walk/__init__.py"
44
44
  [tool.hatch.build.targets.wheel]
45
45
  packages = ["src/node_walk"]
46
46
 
47
+ [tool.hatch.build.targets.wheel.shared-data]
48
+ # Include all static web assets in the installed package
49
+ "src/node_walk/web" = "node_walk/web"
50
+
51
+ [tool.hatch.build.targets.wheel.force-include]
52
+ "src/node_walk/web/index.html" = "node_walk/web/index.html"
53
+ "src/node_walk/web/style.css" = "node_walk/web/style.css"
54
+ "src/node_walk/web/app.js" = "node_walk/web/app.js"
55
+
47
56
  [tool.pytest.ini_options]
48
57
  testpaths = ["tests"]
49
58
  pythonpath = ["src"]
@@ -1,3 +1,3 @@
1
1
  """node-walk — Semantic code intelligence for humans and LLMs."""
2
2
 
3
- __version__ = "0.1.1"
3
+ __version__ = "0.2.0"
@@ -629,11 +629,46 @@ def show_help() -> None:
629
629
  table.add_row("stats", "Show database statistics (file, symbol, edge counts).")
630
630
  table.add_row("export", "Export the entire semantic graph as JSON.")
631
631
 
632
+ table.add_section()
633
+ table.add_row("[bold white]Browser Explorer[/bold white]", "")
634
+ table.add_row("serve", "Launch the interactive graph explorer in your browser.")
635
+
632
636
  console.print(table)
633
637
  console.print("\n[dim]To see options for any command, run: [bold]node-walk <command> --help[/bold][/dim]")
634
638
 
635
639
 
636
640
 
641
+ @app.command()
642
+ def serve(
643
+ port: Annotated[int, typer.Option("--port", "-p", help="Port to listen on.")] = 7777,
644
+ host: Annotated[str, typer.Option("--host", help="Host to bind to.")] = "localhost",
645
+ no_open: Annotated[bool, typer.Option("--no-open", help="Do not open the browser automatically.")] = False,
646
+ ) -> None:
647
+ """Launch the interactive graph explorer in your browser."""
648
+ db = _find_db()
649
+ if db is None:
650
+ err_console.print(
651
+ "[red]No .node_walk/graph.db found.[/red] "
652
+ "Run [bold]node-walk index <path>[/bold] first."
653
+ )
654
+ raise typer.Exit(1)
655
+
656
+ url = f"http://{host}:{port}"
657
+ console.print(
658
+ Panel(
659
+ f"[bold cyan]Graph explorer[/bold cyan] starting at [bold]{url}[/bold]\n"
660
+ f"[dim]DB:[/dim] {db}\n"
661
+ "[dim]Press Ctrl+C to stop.[/dim]",
662
+ title="node-walk serve",
663
+ border_style="cyan",
664
+ )
665
+ )
666
+
667
+ from node_walk.web.server import start_server
668
+
669
+ start_server(db, host=host, port=port, open_browser=not no_open, block=True)
670
+
671
+
637
672
  # ---------------------------------------------------------------------------
638
673
  # Entry point
639
674
  # ---------------------------------------------------------------------------
@@ -0,0 +1,3 @@
1
+ """
2
+ node_walk.web — Embedded HTTP server for the traversable graph explorer.
3
+ """