Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ graphify-dotnet/
│ │ ├── SvgExporter.cs # graph.svg
│ │ ├── WikiExporter.cs # wiki/ markdown articles
│ │ ├── ObsidianExporter.cs # obsidian-vault/
│ │ └── Neo4jExporter.cs # cypher.txt or direct push
│ │ ├── Neo4jExporter.cs # cypher.txt or direct push
│ │ └── LadybugExporter.cs # graph.ladybug.cypher
│ ├── Cache/ # SHA256 caching
│ │ ├── ICacheProvider.cs # Cache interface
│ │ ├── SemanticCache.cs # File hash cache
Expand Down Expand Up @@ -304,6 +305,11 @@ public interface IGraphExporter
- Generate `cypher.txt` with CREATE statements
- Optional direct push via Bolt protocol

#### LadybugExporter
- Generate `graph.ladybug.cypher` with Ladybug-specific DDL (`CREATE NODE TABLE`, `CREATE REL TABLE`)
- Metadata stored as native `MAP(STRING, STRING)` instead of JSON strings
- Embedded database compatibility — no server required

**Python Mapping**: `export.py`

## AI Integration
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ dotnet run --project src/Graphify.Cli -- run .
|   JSON | [docs/format-json.md](docs/format-json.md) |
|   SVG | [docs/format-svg.md](docs/format-svg.md) |
|   Neo4j Cypher | [docs/format-neo4j.md](docs/format-neo4j.md) |
|   Ladybug | [docs/format-ladybug.md](docs/format-ladybug.md) |
|   Obsidian Vault | [docs/format-obsidian.md](docs/format-obsidian.md) |
|   Wiki | [docs/format-wiki.md](docs/format-wiki.md) |
|   Report | [docs/format-report.md](docs/format-report.md) |
Expand Down
4 changes: 2 additions & 2 deletions docs/cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ graphify run [path] [options]
|-----------------|---------|-------------|
| `path` | `.` | Path to the project to analyze |
| `--output`, `-o` | `graphify-out` | Output directory |
| `--format`, `-f` | `json,html,report` | Export formats (comma-separated) |
| `--format`, `-f` | `json,html,report` | Export formats (comma-separated): `json`, `html`, `svg`, `neo4j`, `ladybug`, `obsidian`, `wiki`, `report` |
| `--verbose`, `-v` | `false` | Enable detailed progress output |
| `--provider`, `-p` | *(from config)* | AI provider: `azureopenai`, `ollama`, `copilotsdk` |
| `--endpoint` | *(from config)* | AI service endpoint URL |
Expand All @@ -41,7 +41,7 @@ graphify run
graphify run ./your-project

# All export formats with verbose output
graphify run . --format json,html,svg,neo4j,obsidian,wiki,report -v
graphify run . --format json,html,svg,neo4j,ladybug,obsidian,wiki,report -v

# Use Ollama locally
graphify run . --provider ollama --model codellama
Expand Down
39 changes: 30 additions & 9 deletions docs/export-formats.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
| **JSON** | `graph.json` | Custom tools, CI pipelines, APIs | Programmatic | Developers, tooling |
| **SVG** | `graph.svg` | Documentation, README embeds, print | Static | Everyone |
| **Neo4j** | `graph.cypher` | Advanced queries, large datasets, analysis | Database queries | Analysts, power users |
| **Ladybug** | `graph.ladybug.cypher` | Embedded local analytics, research | Database queries | Analysts, researchers |
| **Obsidian** | `obsidian/` folder | Personal knowledge management | Note linking | Knowledge workers |
| **Wiki** | `wiki/` folder | Team documentation, AI agents, onboarding | Browser navigation | Everyone |
| **Report** | `GRAPH_REPORT.md` | Quick insights, architecture review | Reading | Everyone |
Expand Down Expand Up @@ -199,7 +200,20 @@ Cypher script for importing into Neo4j database.

[Learn more →](format-neo4j.md)

### 5. Obsidian Vault Export
### 5. Ladybug Export

**Produces:** `graph.ladybug.cypher`

Ladybug-compatible Cypher script with structured DDL (`CREATE NODE TABLE`, `CREATE REL TABLE`) and native `MAP(STRING, STRING)` metadata storage.

- ✅ Embedded database — no server required
- ✅ Native `MAP` type for metadata (no JSON strings)
- ✅ Columnar storage optimized for analytical queries
- ✅ Structured schema with typed properties

[Learn more →](format-ladybug.md)

### 6. Obsidian Vault Export

**Produces:** `obsidian/` folder

Expand All @@ -212,7 +226,7 @@ Personal knowledge management vault with interconnected notes.

[Learn more →](format-obsidian.md)

### 6. Wiki Export
### 7. Wiki Export

**Produces:** `wiki/` folder

Expand All @@ -225,7 +239,7 @@ Documentation site structure, agent-crawlable.

[Learn more →](format-wiki.md)

### 7. Graph Analysis Report
### 8. Graph Analysis Report

**Produces:** `GRAPH_REPORT.md`

Expand All @@ -245,7 +259,7 @@ There's no performance penalty for generating multiple formats in one run:

```bash
# Fast and efficient — all generated in ~2 seconds
graphify run ./src --format json,html,svg,neo4j,obsidian,wiki,report
graphify run ./src --format json,html,svg,neo4j,ladybug,obsidian,wiki,report
```

**Recommended combinations:**
Expand All @@ -255,8 +269,9 @@ graphify run ./src --format json,html,svg,neo4j,obsidian,wiki,report
| Quick start | `html, report` |
| Documentation | `html, svg, report` |
| Knowledge base | `obsidian, wiki, report` |
| Analysis | `json, neo4j` |
| Everything | `json, html, svg, neo4j, obsidian, wiki, report` |
| Analysis | `json, neo4j, ladybug` |
| Embedded analytics | `ladybug, report` |
| Everything | `json, html, svg, neo4j, ladybug, obsidian, wiki, report` |

## Format Sizes

Expand All @@ -268,6 +283,7 @@ Approximate file/folder sizes for 1000-node graphs:
| HTML | ~1 MB (self-contained) |
| SVG | ~1 MB |
| Neo4j Cypher | ~200 KB |
| Ladybug Cypher | ~250 KB |
| Obsidian | ~2 MB (many files) |
| Wiki | ~3 MB (many files) |
| Report | ~100 KB |
Expand All @@ -286,6 +302,9 @@ git add graph.json
# Store folders for team collaboration
git add obsidian/ wiki/

# Store Ladybug script for embedded analytics
git add graph.ladybug.cypher

# Ignore HTML (it's static, can be regenerated)
echo "graph.html" >> .gitignore
```
Expand All @@ -299,11 +318,11 @@ Update formats whenever code changes significantly:
graphify run ./src

# Full refresh (all formats)
graphify run ./src --format json,html,svg,neo4j,obsidian,wiki,report
graphify run ./src --format json,html,svg,neo4j,ladybug,obsidian,wiki,report

# In CI/CD: commit updated exports
graphify run ./src
git add graph.* GRAPH_REPORT.md obsidian/ wiki/
git add graph.* GRAPH_REPORT.md obsidian/ wiki/ graph.ladybug.cypher
git commit -m "chore: update architecture exports"
git push
```
Expand All @@ -316,8 +335,9 @@ git push
| SVG | Static (no interactivity) | Use HTML for exploration |
| JSON | Requires programming knowledge | Use HTML or Report for browsing |
| Neo4j | Requires Neo4j setup | Use HTML for quick exploration |
| Ladybug | Requires Ladybug runtime to execute | Generate alongside Report for reading |
| Obsidian | Requires Obsidian app | Use Wiki for browser access |
| Wiki | Manual navigation (no DB queries) | Use Neo4j for complex analysis |
| Wiki | Manual navigation (no DB queries) | Use Neo4j or Ladybug for complex analysis |
| Report | Text only (no interaction) | Use HTML for exploration |

## See Also
Expand All @@ -326,6 +346,7 @@ git push
- [JSON Graph Export](format-json.md)
- [SVG Graph Export](format-svg.md)
- [Neo4j Cypher Export](format-neo4j.md)
- [Ladybug Export](format-ladybug.md)
- [Obsidian Vault Export](format-obsidian.md)
- [Wiki Export](format-wiki.md)
- [Graph Analysis Report](format-report.md)
174 changes: 174 additions & 0 deletions docs/format-ladybug.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# Ladybug Export

> Embedded graph database export for local OLAP queries using Ladybug.

## Quick Start

Install Ladybug: https://docs.ladybugdb.com/installation/

```bash
# 1. Generate the Cypher export script
graphify run ./my-project --format ladybug
# or
dotnet run --project src/Graphify.Cli -- run . --format ladybug -o graphify-out

# 2. Import into a Ladybug database (creates a 'graph.db' directory)
lbug graphify-out/graph.db < graphify-out/graph.ladybug.cypher

# 3. Visualize using Ladybug Explorer (use '--user 0:0' if rootless docker)
docker run -p 8000:8000 \
-v $(pwd)/graphify-out:/database \
-e LBUG_FILE=graph.db \
--rm ghcr.io/ladybugdb/explorer:latest
```

Open [http://localhost:8000](http://localhost:8000) to explore your graph.

## What it Produces

The **Ladybug format** generates a single `graph.ladybug.cypher` file containing:
- **DDL** — `CREATE NODE TABLE GraphNode` and `CREATE REL TABLE GraphEdge` with Ladybug's structured schema.
- **Node `CREATE` statements** — One per node with all properties, including metadata as a native `MAP(STRING, STRING)`.
- **Edge `MATCH/CREATE` statements** — Using `MATCH` to link existing nodes for referential integrity.
- **Query examples** — Annotated Cypher snippets to get you started.

## Visualization with Ladybug Explorer

Ladybug Explorer provides a rich web interface to query and visualize your graph.

### 1. Create the Database
Ladybug is an embedded database. Before you can visualize, you must execute the generated script to build the database files:

```bash
lbug my_project.db < graphify-out/graph.ladybug.cypher
```

### 2. Launch Explorer
Run the Explorer via Docker, mapping your database directory into the container:

```bash
docker run -p 8000:8000 \
-v $(pwd)/my_project.db:/database \
-e LBUG_FILE=my_project.db \
--rm ghcr.io/ladybugdb/explorer:latest
```

- **`-p 8000:8000`**: Exposes the web interface on port 8000.
- **`-v $(pwd)/my_project.db:/database`**: Mounts your local database directory to the container's `/database` path.
- **`-e LBUG_FILE=my_project.db`**: Tells the Explorer which database directory to load from the `/database` volume.

## Schema Design

### Node Table: `GraphNode`

| Property | Type | Description |
|----------|------|-------------|
| `id` | `STRING PRIMARY KEY` | Unique node identifier |
| `label` | `STRING` | Human-readable name |
| `nodeType` | `STRING` | Type: Class, Function, Module, Concept, etc. |
| `filePath` | `STRING` | Absolute source file path (if any) |
| `relativePath` | `STRING` | Path relative to project root |
| `language` | `STRING` | Programming language: CSharp, Python, etc. |
| `community` | `INT64` | Community ID from clustering (nullable) |
| `confidence` | `STRING` | Extraction confidence: Extracted, Inferred, Ambiguous |
| `metadata` | `MAP(STRING, STRING)` | Variable key-value metadata from extraction |

### Relationship Table: `GraphEdge`

| Property | Type | Description |
|----------|------|-------------|
| `_SRC` / `_DST` | internal | Source and target node references (auto-managed) |
| `relationship` | `STRING` | Relation type: calls, imports, contains, etc. |
| `weight` | `DOUBLE` | Edge weight (default 1.0) |
| `confidence` | `STRING` | Confidence level |
| `metadata` | `MAP(STRING, STRING)` | Variable key-value metadata from extraction |

## Querying Your Graph

After importing, run Cypher queries optimized for Ladybug's structured model. Here are some useful examples for analyzing codebases:

### 1. Architectural Insights
```cypher
// Find high-degree "God Nodes" (potential refactoring targets)
MATCH (n:GraphNode)-[e:GraphEdge]->()
RETURN n.label, n.nodeType, COUNT(e) AS outgoing_degree
ORDER BY outgoing_degree DESC LIMIT 10;

// Find nodes that are highly depended upon (critical components)
MATCH ()-[e:GraphEdge]->(n:GraphNode)
RETURN n.label, n.nodeType, COUNT(e) AS incoming_degree
ORDER BY incoming_degree DESC LIMIT 10;

// Identify circular dependencies (A -> B -> A)
MATCH (a:GraphNode)-[:GraphEdge]->(b:GraphNode)-[:GraphEdge]->(a)
WHERE a.id < b.id
RETURN a.label, b.label;
```

### 2. Dependency & Impact Analysis
```cypher
// Impact Analysis: What depends on 'MyService' (up to 3 levels deep)?
MATCH (target:GraphNode {label: 'MyService'})<-[:GraphEdge*1..3]-(dependent)
RETURN DISTINCT dependent.label, dependent.nodeType, dependent.community;

// Find all external dependencies (nodes without a filePath)
MATCH (n:GraphNode)
WHERE n.filePath IS NULL OR n.filePath = ''
RETURN n.label, n.nodeType;

// Shortest path between two distant components
MATCH (a:GraphNode {label: 'AuthService'}), (b:GraphNode {label: 'PaymentGateway'})
MATCH p = (a)-[:GraphEdge* SHORTEST]->(b)
RETURN p;
```

### 3. Community & Structure Analysis
```cypher
// Analyze community sizes (detect logical clusters)
MATCH (n:GraphNode)
RETURN n.community, COUNT(*) AS size
ORDER BY size DESC;

// Find "Bridge" nodes that connect different communities
MATCH (a:GraphNode)-[e:GraphEdge]->(b:GraphNode)
WHERE a.community <> b.community
RETURN a.label, a.community, b.label, b.community, e.relationship
LIMIT 20;

// Find God Nodes within a specific community
MATCH (n:GraphNode)
WHERE n.community = 5
MATCH (n)-[e:GraphEdge]->()
RETURN n.label, COUNT(e) AS score
ORDER BY score DESC LIMIT 5;
```

### 4. Quality & Metadata
```cypher
// Find "Orphan" nodes (nodes with no connections)
MATCH (n:GraphNode)
WHERE NOT (n)-[:GraphEdge]-()
RETURN n.label, n.filePath;

// Access native node metadata map
MATCH (n:GraphNode)
WHERE size(map_extract(n.metadata, 'source_location')) > 0
RETURN n.label, map_extract(n.metadata, 'source_location')[1] AS line;

// Access native edge metadata map (e.g., find merging source)
MATCH (s)-[e:GraphEdge]->(t)
WHERE size(map_extract(e.metadata, 'source_file')) > 0
RETURN s.label, e.relationship, t.label, map_extract(e.metadata, 'source_file')[1] AS origin;
```

## Best For

- **Local analytics** — No server required; run queries on your machine.
- **Interactive Exploration** — Best visual experience when paired with Ladybug Explorer.
- **Large graphs** — Ladybug's columnar storage scales to billions of nodes.

## See Also

- [Export Formats Overview](export-formats.md)
- [Neo4j Cypher Export](format-neo4j.md) — Server-based graph database alternative.
- [Ladybug Documentation](https://docs.ladybugdb.com/)
7 changes: 7 additions & 0 deletions src/Graphify.Cli/PipelineRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,13 @@ await Parallel.ForEachAsync(
await WriteLineAsync($" Exported Neo4j Cypher: {cypherPath}");
break;

case "ladybug":
var ladybugExporter = new LadybugExporter();
var ladybugPath = Path.Combine(outputDir, "graph.ladybug.cypher");
await ladybugExporter.ExportAsync(graph, ladybugPath, cancellationToken);
await WriteLineAsync($" Exported Ladybug Cypher: {ladybugPath}");
break;

case "obsidian":
var obsidianExporter = new ObsidianExporter();
var obsidianPath = Path.Combine(outputDir, "obsidian");
Expand Down
2 changes: 1 addition & 1 deletion src/Graphify.Cli/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ static void AddPipelineOptions(Command cmd,
};
formatOpt = new Option<string>("--format", "-f")
{
Description = "Export formats (comma-separated): json, html, svg, neo4j, obsidian, wiki, report",
Description = "Export formats (comma-separated): json, html, svg, neo4j, ladybug, obsidian, wiki, report",
DefaultValueFactory = _ => "json,html,report"
};
verboseOpt = new Option<bool>("--verbose", "-v")
Expand Down
Loading
Loading