Compare commits

...
11 Commits
Author SHA1 Message Date
KaifAhmad1 2ce5067aa3 docs(changelog): add entry for #471 native KnowledgeGraph support in KGVisualizer 2026-04-16 12:18:38 +05:30
KaifAhmad1 d056e47ab7 feat(kg): add KnowledgeGraph dataclass and native KGVisualizer support (#471)
- Add semantica/kg/knowledge_graph.py with KnowledgeGraph dataclass
  (entities, relationships, metadata) plus __len__ and __bool__ helpers
- Export KnowledgeGraph from semantica/kg/__init__.py
- Add KGVisualizer._convert_knowledge_graph() for explicit, non-mutating
  conversion from KnowledgeGraph to internal dict format
- Route isinstance(graph, KnowledgeGraph) through _convert_knowledge_graph
  inside _normalize_graph so all five visualize_* entry points accept
  KnowledgeGraph directly without any manual conversion
- Add TestFormalKnowledgeGraphType (15 tests)

Closes #471
2026-04-16 12:15:59 +05:30
Mohd KaifandClaude Sonnet 4.6 8eafd2d024 fix(explorer): replace KeyError/ValueError with HTTPException across all routes, fix temporal pattern method, add SPA root handler (#463)
- routes/graph.py: raise HTTPException(404) for missing nodes; wrap path_finder call in try/except → HTTPException(404)
- routes/decisions.py: raise HTTPException(404) on chain, compliance, precedents sub-routes
- routes/annotations.py: raise HTTPException(404) on create (missing node) and delete (missing annotation)
- routes/enrich.py: raise HTTPException(404/503/422) for missing nodes, unavailable services, and extraction errors
- routes/temporal.py: fix TemporalPatternDetector method name detect_patterns → detect_temporal_patterns
- explorer/app.py: root / now serves built index.html when available, falls back to minimal HTML shell; add HTMLResponse import
- tests/explorer/test_explorer_api.py: test_extract accepts 503 (spacy/transformers not installed is a valid service state)

All 45 explorer API integration tests pass.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 00:19:19 +05:30
Mohd Kaif 7ba93f6772 Add initialization file for Claude 2026-04-14 23:25:20 +05:30
Mohd Kaif d466203761 Add initialization file for Claude skills 2026-04-14 23:24:39 +05:30
Mohd Kaif 730dea7911 Add initialization comment to semantica file 2026-04-14 23:24:00 +05:30
Mohd KaifandClaude Sonnet 4.6 47764c3033 Utils Explorer Welcome Message, Version Bump & Plugin README Overhaul (#462)
* Clarify plugin README install and usage steps

* feat(explorer): add welcome message to root endpoint and bump version to 0.4.0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs(plugins): update all plugin READMEs for v0.4.0 with full platform list

- Rewrite main community guide with platform table (8 plugins), skills/agents
  inventory, Knowledge Explorer section, and per-platform install steps
- Add v0.4.0 badge and Knowledge Explorer section to VS Code, Cline,
  Continue, Windsurf, and OpenClaw READMEs
- Fix inconsistent tool count (12 → 17) across all READMEs
- Bump Python requirement from 3.8+ to 3.10+ across all plugins

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: add PR description for utils → main

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: remove PR_DESCRIPTION.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 20:32:04 +05:30
Mohd KaifandClaude Sonnet 4.6 055d2fd98d docs: reorganise README integrations and agentic frameworks sections (#461)
- Remove duplicate integrations table from bottom of README
- Move Agentic Frameworks section to top alongside AI tools table
- Show only Agno as supported; list LangChain, LangGraph, CrewAI, LlamaIndex, AutoGen, OpenAI Agents SDK, Google ADK as coming soon
- Add logo icons for all agentic frameworks matching existing plugin style

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 15:08:18 +05:30
Mohd Kaif ce66681715 Delete RELEASE_NOTES.md 2026-04-14 14:11:59 +05:30
Mohd Kaif 655b553262 Delete STRATEGIES_SUMMARY.md 2026-04-14 14:11:37 +05:30
Mohd KaifandClaude Sonnet 4.6 60bf8ec75e feat(integrations): add OpenClaw plugin and integration module (#460)
- Add integrations/openclaw/ with OpenClawKGTool (REST) and
  OpenClawMCPConfig (mcporter.json generator)
- Add plugins/.openclaw-plugin/ bundle (plugin.json, marketplace.json,
  README) with MCP + native tool support
- Add OpenClaw badge to README header
- Reorganize "Works With Every AI Tool" table into labeled groups:
  Native Plugin Bundle, MCP Server + Plugin, MCP Server, REST API

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 12:27:25 +05:30
31 changed files with 1211 additions and 731 deletions
+1
View File
@@ -0,0 +1 @@
# Initialization
+1
View File
@@ -0,0 +1 @@
# Intialization
+1
View File
@@ -0,0 +1 @@
# Initialization
+2
View File
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
- **Enhancement: Native `KnowledgeGraph` type support in `KGVisualizer`** (PR `kg` by @KaifAhmad1, closes #471): Added `semantica/kg/knowledge_graph.py` — a formal `KnowledgeGraph` dataclass (`entities`, `relationships`, `metadata`) that is now the canonical in-memory type produced and consumed by the Semantica KG pipeline. Exported from `semantica.kg`. `KGVisualizer` gains `_convert_knowledge_graph()` — an authoritative, non-mutating conversion path from `KnowledgeGraph` to the internal dict format — and `_normalize_graph()` now routes `isinstance(graph, KnowledgeGraph)` through it as an explicit fast-path before duck-typing. All five public entry points (`visualize_network`, `visualize_communities`, `visualize_centrality`, `visualize_entity_types`, `visualize_relationship_matrix`) accept `KnowledgeGraph` directly; no manual conversion required. All existing callers passing dicts or duck-typed objects are unaffected. 15 new tests in `TestFormalKnowledgeGraphType` (conversion shape, non-mutation, determinism, routing, all five entry points, import availability).
- **Fix: `KGVisualizer` now accepts `KnowledgeGraph` objects in all `visualize_*` methods** (PR `visualization` by @KaifAhmad1, closes #458): All five public methods (`visualize_network`, `visualize_communities`, `visualize_centrality`, `visualize_entity_types`, `visualize_relationship_matrix`) previously called `graph.get("entities", [])`, silently producing no output when passed a non-dict object. Added `_normalize_graph()` which duck-types the input — dicts pass through unchanged; any object exposing `.entities` / `.relationships` attributes (e.g. the result of `GraphBuilder.build()`) is converted to the canonical dict form; anything else raises a clear `ProcessingError` naming the offending type. 21 tests added in `tests/visualization/test_kg_visualizer_normalize_graph.py`.
- **Security: 12 vulnerability fixes across CRITICAL → LOW severity** (PR `security-enhancement` by @KaifAhmad1):
+120 -132
View File
@@ -14,6 +14,7 @@
[![CI](https://github.com/Hawksight-AI/semantica/workflows/CI/badge.svg)](https://github.com/Hawksight-AI/semantica/actions)
[![Discord](https://img.shields.io/badge/Discord-Join%20Community-5865F2?logo=discord&logoColor=white)](https://discord.gg/sV34vps5hH)
[![X](https://img.shields.io/badge/X-Follow%20Semantica-black?logo=x&logoColor=white)](https://x.com/BuildSemantica)
[![OpenClaw](https://img.shields.io/badge/OpenClaw-Plugin-FF3B30?logo=github&logoColor=white)](https://openclaw.ai)
### ⭐ Give us a Star · 🍴 Fork us · 💬 Join our Discord · 🐦 Follow on X
@@ -45,7 +46,7 @@ Semantica is the **context and intelligence layer** you add on top of your exist
- ✅ **Reasoning Engines** — forward chaining, Rete networks, deductive, abductive, and SPARQL. Explainable paths, not black boxes.
- ✅ **Quality & Deduplication** — conflict detection, entity resolution, and pipeline validation built in.
> Works alongside LangChain, LlamaIndex, AutoGen, CrewAI, and any LLM — Semantica is the **accountability layer** on top, not a replacement.
> Works alongside **Agno** and any LLM — Semantica is the **accountability layer** on top, not a replacement. LangChain, LangGraph, CrewAI, and more coming soon.
```bash
pip install semantica
@@ -55,39 +56,68 @@ pip install semantica
## 🔌 Works With Every AI Tool
Semantica ships **native plugin bundles** for Claude Code, Cursor, and Codex, an **MCP server** (`python -m semantica.mcp_server`) for Windsurf, Cline, Continue, VS Code, and Claude Desktop, and a **REST API** (FastAPI, port 8000) for any other tool.
Semantica ships **native plugin bundles** for Claude Code, Cursor, and Codex, an **MCP server** (`python -m semantica.mcp_server`) for Windsurf, Cline, Continue, VS Code, Claude Desktop, and OpenClaw, and a **REST API** (FastAPI, port 8000) for any other tool.
<table>
<!-- ── Native Plugin Bundle ──────────────────────────────────────────── -->
<tr>
<th colspan="3" align="left">🔌 Native Plugin Bundle</th>
<th colspan="5" align="left">⚡ MCP Server + Plugin</th>
</tr>
<tr>
<td align="center" width="12.5%">
<a href="https://claude.com/product/claude-code"><img src="https://github.com/anthropics.png?size=120" alt="Claude Code" width="48" height="48" /></a><br/>
<strong>Claude Code</strong><br/>
<sub>Native plugin · 17 skills · 3 agents · hooks</sub>
<sub>17 skills · 3 agents · hooks</sub>
</td>
<td align="center" width="12.5%">
<a href="https://cursor.com"><img src="https://www.freelogovectors.net/wp-content/uploads/2025/06/cursor-logo-freelogovectors.net_.png" alt="Cursor" width="48" height="48" /></a><br/>
<strong>Cursor</strong><br/>
<sub>Native plugin · 17 skills · 3 agents</sub>
<sub>17 skills · 3 agents</sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/openai/codex"><img src="https://github.com/openai.png?size=120" alt="Codex CLI" width="48" height="48" /></a><br/>
<strong>Codex CLI</strong><br/>
<sub>Native plugin · 17 skills · 3 agents</sub>
<sub>17 skills · 3 agents</sub>
</td>
<td align="center" width="12.5%">
<a href="https://windsurf.com"><img src="https://exafunction.github.io/public/brand/windsurf-black-symbol.svg" alt="Windsurf" width="48" height="48" /></a><br/>
<strong>Windsurf</strong><br/>
<sub>MCP server + plugin</sub>
<sub><a href="plugins/.windsurf-plugin/">plugin</a></sub>
</td>
<td align="center" width="12.5%">
<a href="https://claude.ai/download"><img src="https://github.com/anthropics.png?size=120" alt="Claude Desktop" width="48" height="48" /></a><br/>
<strong>Claude Desktop</strong><br/>
<sub>MCP server</sub>
<a href="https://github.com/cline/cline"><img src="https://github.com/cline.png?size=120" alt="Cline" width="48" height="48" /></a><br/>
<strong>Cline</strong><br/>
<sub><a href="plugins/.cline-plugin/">plugin</a></sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/continuedev/continue"><img src="https://github.com/continuedev.png?size=120" alt="Continue" width="48" height="48" /></a><br/>
<strong>Continue</strong><br/>
<sub><a href="plugins/.continue-plugin/">plugin</a></sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/microsoft/vscode"><img src="https://github.com/microsoft.png?size=120" alt="VS Code" width="48" height="48" /></a><br/>
<strong>VS Code</strong><br/>
<sub>MCP server + plugin</sub>
<sub><a href="plugins/.vscode-plugin/">plugin</a></sub>
</td>
<td align="center" width="12.5%">
<a href="integrations/openclaw/"><img src="https://github.com/openclaw.png?size=120" alt="OpenClaw" width="48" height="48" /></a><br/>
<strong>OpenClaw</strong><br/>
<sub>MCP + <a href="integrations/openclaw/">plugin</a></sub>
</td>
</tr>
<!-- ── MCP Server only · REST API ───────────────────────────────────── -->
<tr>
<th colspan="1" align="left">☁️ MCP Server</th>
<th colspan="7" align="left">🌐 REST API</th>
</tr>
<tr>
<td align="center" width="12.5%">
<a href="https://claude.ai/download"><img src="https://github.com/anthropics.png?size=120" alt="Claude Desktop" width="48" height="48" /></a><br/>
<strong>Claude Desktop</strong><br/>
<sub>MCP server</sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/features/copilot"><img src="https://github.com/github.png?size=120" alt="GitHub Copilot" width="48" height="48" /></a><br/>
@@ -95,23 +125,11 @@ Semantica ships **native plugin bundles** for Claude Code, Cursor, and Codex, an
<sub>REST API</sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/cline/cline"><img src="https://github.com/cline.png?size=120" alt="Cline" width="48" height="48" /></a><br/>
<strong>Cline</strong><br/>
<sub>MCP server + plugin</sub>
</td>
</tr>
<tr>
<td align="center" width="12.5%">
<a href="https://github.com/RooCodeInc/Roo-Code"><img src="https://github.com/RooCodeInc.png?size=120" alt="Roo Code" width="48" height="48" /></a><br/>
<strong>Roo Code</strong><br/>
<sub>REST API</sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/continuedev/continue"><img src="https://github.com/continuedev.png?size=120" alt="Continue" width="48" height="48" /></a><br/>
<strong>Continue</strong><br/>
<sub>MCP server + plugin</sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/block/goose"><img src="https://github.com/block.png?size=120" alt="Goose" width="48" height="48" /></a><br/>
<strong>Goose</strong><br/>
<sub>REST API</sub>
@@ -136,14 +154,91 @@ Semantica ships **native plugin bundles** for Claude Code, Cursor, and Codex, an
<strong>Zed</strong><br/>
<sub>REST API</sub>
</td>
<td align="center" width="12.5%">
</tr>
<!-- ── Any tool via REST ─────────────────────────────────────────────── -->
<tr>
<th colspan="8" align="left">🔧 Any Tool</th>
</tr>
<tr>
<td align="center" colspan="8">
<img src="https://img.shields.io/badge/109-endpoints-1f6feb?style=flat-square" alt="REST API" width="48" /><br/>
<strong>Any agent</strong><br/>
<sub>REST API</sub>
<sub>109 REST endpoints · FastAPI · port 8000</sub>
</td>
</tr>
</table>
### Agentic Frameworks
Semantica integrates with **Agno** today. Coming soon: LangChain, LangGraph, CrewAI, LlamaIndex, AutoGen, OpenAI Agents SDK, Google ADK, and more.
<table>
<tr>
<th colspan="8" align="left">✅ Supported</th>
</tr>
<tr>
<td align="center" width="12.5%">
<a href="https://github.com/agno-agi/agno"><img src="https://github.com/agno-agi.png?size=120" alt="Agno" width="48" height="48" /></a><br/>
<strong>Agno</strong><br/>
<sub>First-class · <code>pip install semantica[agno]</code></sub>
</td>
</tr>
<tr>
<th colspan="8" align="left">🔜 Coming Soon</th>
</tr>
<tr>
<td align="center" width="12.5%">
<a href="https://github.com/langchain-ai/langchain"><img src="https://github.com/langchain-ai.png?size=120" alt="LangChain" width="48" height="48" /></a><br/>
<strong>LangChain</strong><br/>
<sub>Coming soon</sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/langchain-ai/langgraph"><img src="https://github.com/langchain-ai.png?size=120" alt="LangGraph" width="48" height="48" /></a><br/>
<strong>LangGraph</strong><br/>
<sub>Coming soon</sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/crewAIInc/crewAI"><img src="https://github.com/crewAIInc.png?size=120" alt="CrewAI" width="48" height="48" /></a><br/>
<strong>CrewAI</strong><br/>
<sub>Coming soon</sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/run-llama/llama_index"><img src="https://github.com/run-llama.png?size=120" alt="LlamaIndex" width="48" height="48" /></a><br/>
<strong>LlamaIndex</strong><br/>
<sub>Coming soon</sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/microsoft/autogen"><img src="https://github.com/microsoft.png?size=120" alt="AutoGen" width="48" height="48" /></a><br/>
<strong>AutoGen</strong><br/>
<sub>Coming soon</sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/openai/openai-agents-python"><img src="https://github.com/openai.png?size=120" alt="OpenAI Agents SDK" width="48" height="48" /></a><br/>
<strong>OpenAI Agents</strong><br/>
<sub>Coming soon</sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/google/adk-python"><img src="https://github.com/google.png?size=120" alt="Google ADK" width="48" height="48" /></a><br/>
<strong>Google ADK</strong><br/>
<sub>Coming soon</sub>
</td>
</tr>
</table>
> **Agno — First-Class Integration** · `pip install semantica[agno]`
>
> Five integration modules live in [`integrations/agno/`](integrations/agno/):
>
> | Module | Class | What it does |
> |---|---|---|
> | `context_store.py` | `AgnoContextStore` | Graph-backed agent memory — store and retrieve structured context |
> | `knowledge_graph.py` | `AgnoKnowledgeGraph` | Implements Agno's `AgentKnowledge` protocol; full extraction pipeline |
> | `decision_kit.py` | `AgnoDecisionKit` | 6 decision-intelligence tools for Agno agents |
> | `kg_toolkit.py` | `AgnoKGToolkit` | 7 KG pipeline tools (build, query, enrich, export) |
> | `shared_context.py` | `AgnoSharedContext` | Shared context graph for multi-agent team coordination |
### Plugin Bundles (Claude Code · Cursor · Codex)
Native plugin bundles live under [`plugins/`](plugins/). Each directory contains a `plugin.json`, `marketplace.json`, and `README.md`.
@@ -157,6 +252,7 @@ Native plugin bundles live under [`plugins/`](plugins/). Each directory contains
| Cline | [`plugins/.cline-plugin/`](plugins/.cline-plugin/) | 17 skills · 3 agents · MCP config |
| Continue | [`plugins/.continue-plugin/`](plugins/.continue-plugin/) | 17 skills · 3 agents · MCP config |
| VS Code | [`plugins/.vscode-plugin/`](plugins/.vscode-plugin/) | 17 skills · 3 agents · MCP config |
| OpenClaw | [`plugins/.openclaw-plugin/`](plugins/.openclaw-plugin/) | 17 skills · 3 agents · MCP config |
**17 domain skills:**
@@ -848,53 +944,6 @@ if result.valid:
- **`semantica.llms`** — Groq, OpenAI, Novita AI, HuggingFace, LiteLLM
- **[`explorer/`](explorer/)** — **Semantica Knowledge Explorer** — browser UI for live graph inspection, decisions, entity resolution, and ontology browsing (`npm run dev` in `explorer/`)
---
## 🔌 Integrations
### AI Coding Tools & IDEs
Start the Semantica server (`python -m semantica.server`, port 8000) and point any tool at `http://localhost:8000`. Tools marked **Native plugin** also get 17 skills, 3 agents, and hook config out of the box.
| Tool | Connection | Notes |
|---|---|---|
| [Claude Code](https://claude.com/product/claude-code) | **Native plugin** | `plugins/.claude-plugin/` — 17 skills, 3 agents, `hooks.json` |
| [Cursor](https://cursor.com) | **Native plugin** | `plugins/.cursor-plugin/` — same 17 skills + 3 agents |
| [Codex CLI](https://github.com/openai/codex) | **Native plugin** | `plugins/.codex-plugin/` — same 17 skills + 3 agents |
| [Windsurf](https://windsurf.com) | **MCP server** + plugin | `plugins/.windsurf-plugin/` · add `python -m semantica.mcp_server` to `~/.codeium/windsurf/mcp_config.json` |
| [Claude Desktop](https://claude.ai/download) | **MCP server** | Add `python -m semantica.mcp_server` to `claude_desktop_config.json` |
| [VS Code](https://github.com/microsoft/vscode) | **MCP server** + plugin | `plugins/.vscode-plugin/` · add to `settings.json` under `mcp.servers` |
| [GitHub Copilot](https://github.com/features/copilot) | REST API | Use via Copilot Chat custom tools |
| [Cline](https://github.com/cline/cline) | **MCP server** + plugin | `plugins/.cline-plugin/` · add server in Cline MCP settings panel |
| [Roo Code](https://github.com/RooCodeInc/Roo-Code) | **MCP server** | Add `python -m semantica.mcp_server` in Roo Code MCP settings |
| [Continue](https://github.com/continuedev/continue) | **MCP server** + plugin | `plugins/.continue-plugin/` · add to `~/.continue/config.json` under `mcpServers` |
| [Goose](https://github.com/block/goose) | REST API | Add to Goose toolset config |
| [Kilo Code](https://github.com/Kilo-Org/kilocode) | REST API | Add as custom REST tool |
| [Aider](https://github.com/Aider-AI/aider) | REST API | Pass context from the API into prompts |
| [Amazon Q Developer](https://github.com/aws/amazon-q-developer-cli) | REST API | Use via Q Developer custom tools |
| [Zed](https://zed.dev) | REST API | Integrate via Zed assistant context |
| Any agent | REST API | 109 endpoints — drop-in with any HTTP client |
### REST API Server
Run `python -m semantica.server` (or `python -m semantica`) — FastAPI on port 8000 with the following route groups:
| Route group | Module | Endpoints |
|---|---|---|
| `/api/graph` | `routes/graph.py` | Nodes, edges, traversal, graph topology |
| `/api/analytics` | `routes/analytics.py` | Centrality, communities, metrics |
| `/api/decisions` | `routes/decisions.py` | Decision CRUD, precedent search, causal chains |
| `/api/temporal` | `routes/temporal.py` | Point-in-time queries, snapshots, timelines |
| `/api/export` | `routes/export_import.py` | Import/export in RDF, Parquet, JSON, CSV, GraphML |
| `/api/annotations` | `routes/annotations.py` | Entity and edge annotation |
| `/api/enrich` | `routes/enrich.py` | Graph enrichment — embeddings, vectors, metadata |
| `/api/sparql` | `routes/sparql.py` | SPARQL query execution |
| `/api/provenance` | `routes/provenance.py` | Data lineage and audit trails |
| `/api/vocabulary` | `routes/vocabulary.py` | Ontology, SKOS concepts, schema definitions |
| `/ws` | `ws.py` | WebSocket — real-time graph mutation events |
| `/health` | `server.py` | Health check |
### Graph Databases
- **Neo4j** — Cypher queries via `semantica.graph_store`
- **FalkorDB** — native support; `DecisionQuery` and `CausalChainAnalyzer` work directly with FalkorDB row/header shapes
@@ -925,67 +974,6 @@ Run `python -m semantica.server` (or `python -m semantica`) — FastAPI on port
- **HuggingFace** — local and hosted models via `HuggingFaceProvider`
- **Ollama** — local models including remote server support
### Agentic Frameworks
Semantica complements — not replaces — every major agentic framework. Use it as the accountability layer on top.
<table>
<tr>
<td align="center" width="12.5%">
<a href="https://github.com/agno-agi/agno"><img src="https://github.com/agno-agi.png?size=120" alt="Agno" width="40" height="40" /></a><br/>
<strong>Agno</strong><br/>
<sub>First-class · <code>pip install semantica[agno]</code></sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/langchain-ai/langchain"><img src="https://github.com/langchain-ai.png?size=120" alt="LangChain" width="40" height="40" /></a><br/>
<strong>LangChain</strong><br/>
<sub>Context layer</sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/langchain-ai/langgraph"><img src="https://github.com/langchain-ai.png?size=120" alt="LangGraph" width="40" height="40" /></a><br/>
<strong>LangGraph</strong><br/>
<sub>Stateful agent graph</sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/run-llama/llama_index"><img src="https://github.com/run-llama.png?size=120" alt="LlamaIndex" width="40" height="40" /></a><br/>
<strong>LlamaIndex</strong><br/>
<sub>GraphRAG retriever</sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/microsoft/autogen"><img src="https://github.com/microsoft.png?size=120" alt="AutoGen" width="40" height="40" /></a><br/>
<strong>AutoGen</strong><br/>
<sub>Shared context graph</sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/crewAIInc/crewAI"><img src="https://github.com/crewAIInc.png?size=120" alt="CrewAI" width="40" height="40" /></a><br/>
<strong>CrewAI</strong><br/>
<sub>Decision + provenance</sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/openai/openai-agents-python"><img src="https://github.com/openai.png?size=120" alt="OpenAI Agents SDK" width="40" height="40" /></a><br/>
<strong>OpenAI Agents</strong><br/>
<sub>Context + KG tools</sub>
</td>
<td align="center" width="12.5%">
<a href="https://github.com/google/adk-python"><img src="https://github.com/google.png?size=120" alt="Google ADK" width="40" height="40" /></a><br/>
<strong>Google ADK</strong><br/>
<sub>Context layer</sub>
</td>
</tr>
</table>
> **Agno — First-Class Integration** · `pip install semantica[agno]`
>
> Five integration modules live in [`integrations/agno/`](integrations/agno/):
>
> | Module | Class | What it does |
> |---|---|---|
> | `context_store.py` | `AgnoContextStore` | Graph-backed agent memory — store and retrieve structured context |
> | `knowledge_graph.py` | `AgnoKnowledgeGraph` | Implements Agno's `AgentKnowledge` protocol; full extraction pipeline |
> | `decision_kit.py` | `AgnoDecisionKit` | 6 decision-intelligence tools for Agno agents |
> | `kg_toolkit.py` | `AgnoKGToolkit` | 7 KG pipeline tools (build, query, enrich, export) |
> | `shared_context.py` | `AgnoSharedContext` | Shared context graph for multi-agent team coordination |
---
## 🛠️ Installation
-282
View File
@@ -1,282 +0,0 @@
# Semantica v0.3.0 — Release Notes
**Released:** 2026-03-10
**PyPI:** `pip install semantica`
**Tag:** [v0.3.0](https://github.com/Hawksight-AI/semantica/releases/tag/v0.3.0)
**Classification:** Production/Stable
> First stable, full public release of Semantica. Covers everything shipped across three release stages: 0.3.0-alpha (2026-02-19), 0.3.0-beta (2026-03-07), and 0.3.0 stable (2026-03-10).
---
## Contributors
| Contributor | Role |
|------------|------|
| [@KaifAhmad1](https://github.com/KaifAhmad1) | Lead maintainer — context graph, decision intelligence, KG algorithms, semantic extraction, pipeline, provenance, bug fixes, release management |
| [@ZohaibHassan16](https://github.com/ZohaibHassan16) | Deduplication v2 suite (candidate generation, two-stage scoring, semantic dedup), incremental/delta processing, benchmark suite |
| [@Sameer6305](https://github.com/Sameer6305) | Apache AGE backend, PgVector store, Snowflake connector, Apache Arrow export |
| [@tibisabau](https://github.com/tibisabau) | ArangoDB AQL export, Apache Parquet export |
| [@d4ndr4d3](https://github.com/d4ndr4d3) | ResourceScheduler deadlock fix |
---
## v0.3.0 — Stable (2026-03-10)
### Context Graph Feature Completeness
**Temporal Validity Windows** (by @KaifAhmad1)
Nodes and edges now carry first-class `valid_from` / `valid_until` ISO datetime fields. These are stored directly on `ContextNode` and `ContextEdge` dataclasses — not in metadata — and survive full serialisation round-trips through `save_to_file()` / `load_from_file()` and `to_dict()` / `from_dict()`.
- `ContextNode.is_active(at_time=None)` and `ContextEdge.is_active(at_time=None)` — returns `True` if the node/edge is live at the given time (defaults to now). Handles both tz-aware and tz-naive datetime inputs correctly.
- `ContextGraph.find_active_nodes(node_type=None, at_time=None)` — filters the entire graph and returns only nodes within their validity window.
- `add_node(valid_from=..., valid_until=...)` and `add_edge(valid_from=..., valid_until=...)` — pass validity fields directly in the call signature.
- Bug fix: `is_active()` previously crashed with `TypeError` when passed a tz-aware `datetime` (e.g. `datetime.now(timezone.utc)`). Fixed by normalising all inputs to tz-naive UTC via a new `_parse_iso_dt()` helper.
- Bug fix: validity fields were silently lost in `add_nodes()`, `add_edges()`, `to_dict()`, and `from_dict()`. All four paths now correctly preserve and restore them.
**Weighted Multi-Hop BFS** (by @KaifAhmad1)
`ContextGraph.get_neighbors(node_id, hops=1, relationship_types=None, min_weight=0.0)` now accepts a `min_weight` threshold. Any edge with weight below the threshold is skipped during BFS traversal, allowing callers to confine multi-hop queries to high-confidence causal links. Default `0.0` is fully backward-compatible.
**Cross-Graph Navigation** (by @KaifAhmad1)
Separate `ContextGraph` instances can now be linked and navigated between — hierarchically, like separate knowledge domains that reference each other.
- `link_graph(other_graph, source_node_id, target_node_id, link_type="CROSS_GRAPH") -> str` — creates a navigable bridge and returns a `link_id`. Records a dedicated `"cross_graph_link"` typed marker node internally (not a phantom `"entity"`) and a marker edge.
- `navigate_to(link_id) -> (other_graph, target_node_id)` — jumps to the target graph and entry node for a given link.
- `graph_id` field — each `ContextGraph` now carries a stable UUID so instances can identify each other across save/load.
- `save_to_file()` — now writes a `links` section alongside nodes and edges, containing `link_id`, `source_node_id`, `target_node_id`, and `other_graph_id` for every cross-graph link.
- `load_from_file()` — restores `graph_id` and populates `_unresolved_links` from the `links` section.
- `resolve_links(registry: Dict[str, ContextGraph]) -> int` — reconnects unresolved links post-load. Pass `{graph_id: graph_instance}` for each linked graph; returns the count of successfully resolved links. `navigate_to()` raises a clear `KeyError` with a `resolve_links()` hint if called before resolution.
- Bug fix: the previous implementation auto-created the synthetic marker target as an `"entity"` node (phantom pollution). Fixed by explicitly pre-creating a `"cross_graph_link"` typed `ContextNode` before the marker edge.
- 14 new tests in `tests/context/test_cross_graph_navigation.py` covering all scenarios including full save/load round-trips with partial registry resolution.
**Other Fixes** (by @KaifAhmad1)
- `PipelineBuilder.add_step()` return type annotation corrected from `"PipelineBuilder"` to `"PipelineStep"` — the implementation was already correct; only the annotation and docstring were stale.
- `test_hybrid_search_performance` timing computation fixed — now accumulates a true `search_times` list instead of reusing the last loop iteration's `start_time`; threshold relaxed to `< 5.0s` for real `sentence-transformers` (384-dim) latency on development machines.
**Test Coverage Added**
- 14 cross-graph navigation tests (`tests/context/test_cross_graph_navigation.py`)
- **Total: 335 context tests, 886+ tests across all modules — 0 failures**
---
## v0.3.0-beta — Beta (2026-03-07)
### Semantic Extraction Fixes
**Multi-Founder LLM Extraction & Reasoner Inference Fix** (PR #354, by @KaifAhmad1)
- `_parse_relation_result` in `methods.py` — unmatched subjects/objects now produce a synthetic `UNKNOWN` entity instead of silently dropping the relation. All co-founders returned by the LLM are preserved in the output.
- Duplicate relation fix — an orphaned legacy block that appended every relation twice has been removed.
- `extraction_method` parameter added — typed extraction paths now correctly record `"llm_typed"` in relation metadata instead of `"llm"`.
- `_match_pattern` in `reasoner.py` rewritten — splits patterns on `?var` placeholders first, then escapes only literal segments. Pre-bound variables resolve to exact literals, repeated variables use backreferences, non-greedy `.+?` prevents over-consumption of separators.
- Added `tests/reasoning/test_reasoner.py` (4 tests) and `tests/semantic_extract/test_relation_extractor.py` (6 tests).
**TTL Export Alias Fix** (PR #355, by @KaifAhmad1)
- `RDFExporter` now accepts `"ttl"`, `"nt"`, `"xml"`, `"rdf"`, and `"json-ld"` as format aliases in `export_to_rdf()`. Aliases resolve before format validation — zero public API changes.
- Added `tests/export/test_rdf_exporter.py` (8 tests).
### Incremental / Delta Processing
**Native Delta Computation** (PR #349, by @ZohaibHassan16, reviewed and fixed by @KaifAhmad1)
- Native SPARQL-based diff between graph snapshots — only changed triples flow through the pipeline.
- `delta_mode` configuration in `PipelineBuilder` for near-real-time workloads.
- Version snapshot management with graph URI tracking and metadata storage.
- `prune_versions()` for automatic snapshot retention cleanup.
- Bug fixes: corrected SPARQL variable order, fixed class references, resolved duplicate dictionary keys.
### Deduplication v2
**Candidate Generation v2** (PR #338, by @ZohaibHassan16)
- New opt-in strategies: `blocking_v2` and `hybrid_v2`, replacing O(N²) pair enumeration.
- Multi-key blocking with normalised token prefixes, type-aware keys, and optional phonetic (Soundex) blocking.
- Deterministic `max_candidates_per_entity` budgeting with stable sorting.
- **63.6% faster** in worst-case scenarios (0.259s → 0.094s for 100 entities).
**Two-Stage Scoring Prefilter** (PR #339, by @ZohaibHassan16)
- Fast gates for type mismatch, name-length ratio, and token overlap eliminate expensive semantic scoring for obvious non-matches.
- Configurable thresholds: `min_length_ratio`, `min_token_overlap_ratio`, `required_shared_token`.
- **1825% faster** batch processing with prefilter enabled (`prefilter_enabled=False` by default).
**Semantic Relationship Deduplication v2** (PR #340, by @ZohaibHassan16, fixes by @KaifAhmad1)
- Canonicalisation engine with predicate synonym mapping (`works_for``employed_by`).
- O(1) hash matching for exact canonical signatures.
- Weighted scoring: 60% predicate + 40% object composition with explainable `semantic_match_score`.
- **6.98x faster** than legacy mode (83ms vs 579ms).
- `dedup_triplets()` infinite recursion bug fixed; function is now a first-class API in `methods.py`.
**Deduplication v2 Migration Guide** (PR #344, by @ZohaibHassan16, fixes by @KaifAhmad1)
- Comprehensive `MIGRATION_V2.md` documenting all v2 strategies with code examples.
- Full backward compatibility maintained — legacy mode remains the default.
### Export Formats
**ArangoDB AQL Export** (PR #342, by @tibisabau)
- Full AQL INSERT statement generation for vertices and edges.
- Configurable collection names with validation and sanitisation; batch processing (default: 1000).
- `export_arango()` convenience function; `.aql` auto-detection in the unified exporter.
- 17 tests, 100% pass rate.
**Apache Parquet Export** (PR #343, by @tibisabau)
- Columnar storage format with configurable compression: snappy, gzip, brotli, zstd, lz4, none.
- Explicit Apache Arrow schemas with type safety; field normalisation for varied naming conventions.
- `export_parquet()` convenience function; `.parquet` auto-detection.
- Analytics-ready for pandas, Spark, Snowflake, BigQuery, Databricks.
- 25 tests, 100% pass rate.
### Bug Fixes & Test Suite Stabilisation
**Test Suite Fixes** (by @KaifAhmad1)
Context module:
- `retrieve_decision_precedents` — gated entity extraction on `use_hybrid_search=True` correctly.
- `_extract_entities_from_query` — now uses `word[0].isupper()` to capture camelCase identifiers like `CreditCard`.
- Added missing `expand_context` (BFS traversal) and `_get_decision_query` methods.
- Fixed `hybrid_retrieval`, `dynamic_context_traversal`, and `multi_hop_context_assembly` for correct single-pass BFS.
- Fixed `_retrieve_from_vector` fallback to `result["metadata"]["content"]` to prevent empty content and negative re-ranking scores.
KG module:
- `calculate_pagerank` — added `alpha`/`max_iter` aliases; return format changed to `{"centrality": scores, "rankings": sorted_list}`.
- `community_detector._to_networkx` — now returns a NetworkX graph directly when one is passed (previously lost all edges).
- Added 9 domain-specific tracking methods to `AlgorithmTrackerWithProvenance`.
- Created `provenance_tracker.py` with `ProvenanceTracker` (`track_entity`, `get_all_sources`, `clear`).
Pipeline module:
- Retry loop fixed — now correctly iterates to `max_retries`.
- `RecoveryAction` dataclass and `handle_failure(error, policy, retry_count)` added with LINEAR, EXPONENTIAL, and FIXED strategies.
- `add_step()` fixed to return the created `PipelineStep`.
- `validate` added as alias for `validate_pipeline` in `PipelineValidator`.
Other:
- Fixed `NameError` for missing `Type` import in `utils/helpers.py`.
- Vector store performance threshold relaxed (100ms → 500ms per decision for development machines).
- Windows cp1252 encoding fix in test files (emoji → ASCII).
- `ProvenanceTracker` added to `semantica/kg/__init__.py` exports.
**Results: ~840 tests passing, 36 skipped (external services), 0 failed**
---
## v0.3.0-alpha — Alpha (2026-02-19)
### Context & Decision Intelligence
**Context Engineering Enhancement** (PR #307, by @KaifAhmad1)
The foundational 0.3.0 feature — complete overhaul of the context module for production-grade decision intelligence:
- Full decision lifecycle: `record_decision()``add_decision()``add_causal_relationship()``trace_decision_chain()``analyze_decision_impact()``analyze_decision_influence()``find_similar_decisions()`
- `AgentContext` unified wrapper with granular feature flags: `decision_tracking`, `kg_algorithms`, `graph_expansion`; methods: `store()`, `retrieve()`, `get_conversation_history()`, `get_statistics()`, `capture_cross_system_inputs()`
- `AgentMemory` with working, conversation, and long-term memory tiers
- `PolicyEngine` with versioned policy nodes, compliance checking (`check_decision_rules()`), and `PolicyException` model
- Hybrid precedent search combining vector, structural, and category similarity with configurable weights
- Decision influence analysis via centrality measures and causal chain tracking
- GraphStore validation preventing runtime failures; secure logging
- 9 critical bug fixes across logging, security, audit trails, API compatibility, Cypher queries, centrality access, validation
**Context Decision Tracking Fixes** (PR #315, by @KaifAhmad1)
- Fixed empty/None decision ID handling in `add_decision()`
- Fixed None metadata handling preventing `TypeError`
- Fixed causal chain depth logic and node exclusion
- Fixed nonexistent node handling in `add_causal_relationship()`
- Fixed precedent search direction in `find_precedents()`
- Added missing `properties` field in `to_dict()`; added `from_dict()` method
- Fixed UUID generation across all decision models
- All 71 context tests passing
### Knowledge Graph Algorithms
**Improved Graph Algorithms** (PR #292, by @KaifAhmad1)
- 30+ graph algorithms across 7 categories
- Node embeddings: Node2Vec, DeepWalk, Word2Vec via `NodeEmbedder`
- Similarity: cosine, Euclidean, Manhattan, Correlation via `SimilarityCalculator`
- Path finding: Dijkstra, A*, BFS, K-shortest paths via `PathFinder`
- Link prediction: preferential attachment, Jaccard, Adamic-Adar via `LinkPredictor`
- Centrality: degree, betweenness, closeness, PageRank via `CentralityAnalyzer`
- Community detection: Louvain, Leiden, label propagation via `CommunityDetector`
- Connectivity: components, bridges, density via `ConnectivityAnalyzer`
- `GraphBuilderWithProvenance` and `AlgorithmTrackerWithProvenance` with full execution metadata
**Improved Vector Store for Decision Tracking** (PR #293, by @KaifAhmad1)
- `DecisionEmbeddingPipeline` with semantic and structural embeddings
- `HybridSimilarityCalculator` with configurable weights (semantic: 0.7, structural: 0.3)
- `ContextRetriever` with multi-hop reasoning
- Convenience API: `quick_decision()`, `find_precedents()`, `explain()`, `similar_to()`, `batch_decisions()`, `filter_decisions()`
- 34+ tests; performance: 0.028s per decision, 0.031s search, ~0.8KB memory per decision
### Graph Database Backends
**Apache AGE Backend Security Fixes** (PR #311, by @Sameer6305, fixes by @KaifAhmad1)
- `AgeStore` class with `GraphStore` API compatibility (openCypher via SQL on PostgreSQL)
- SQL injection vulnerabilities fixed with input validation
- psycopg2-binary dependency and migration guide added
- Fixed parameter replacement and test mock leakage
**PgVector Store Support** (PR #303, by @Sameer6305, @KaifAhmad1)
- Native PostgreSQL vector storage using the pgvector extension
- Multiple distance metrics: cosine, L2/Euclidean, inner product
- HNSW and IVFFlat indexing for approximate nearest neighbour search
- JSONB metadata storage with flexible filtering; batch operations
- Connection pooling with psycopg3/psycopg2 fallback
- SQL injection protection via `psycopg_sql.SQL()`; idempotent index and table management
- 36+ tests with Docker integration
### Infrastructure
**ResourceScheduler Deadlock Fix** (PR #299, #301, by @d4ndr4d3, @KaifAhmad1)
- Replaced `threading.Lock()` with `threading.RLock()` to fix nested lock acquisition deadlock in `allocate_resources()`
- Added `ValidationError` when no resources can be allocated
- Progress tracking updates moved outside lock scope
- 6 regression tests for deadlock prevention
**Security Configuration** (by @KaifAhmad1)
- Dependabot bi-weekly security updates with manual review
- Automated security scans (Bandit, Safety, Semgrep) on schedule
- Security-critical package grouping; zero auto-merge policy
---
## Summary by the Numbers
| Metric | Value |
|--------|-------|
| Total tests passing | **886+** |
| Test failures | **0** |
| Context tests | 335 |
| KG tests | ~430 |
| Semantic extraction tests | 70 (9 skipped — external LLM APIs) |
| Reasoning tests | 19 |
| Real-world scenario tests | 85 |
| PyPI classifier | Production/Stable |
| Python support | 3.8 3.12 |
---
## Upgrade
```bash
pip install --upgrade semantica
```
No breaking changes. All new parameters have safe defaults and all new methods are additive.
See [CHANGELOG.md](CHANGELOG.md) for the full line-by-line diff.
-105
View File
@@ -1,105 +0,0 @@
# Deduplication & Conflict Resolution Strategies Summary
## Quick Reference by Use Case
| Use Case | Deduplication Method | Merge Strategy | Conflict Detection | Conflict Resolution |
|----------|---------------------|----------------|-------------------|---------------------|
| **Finance** |
| `01_Financial_Data_Integration_MCP` | `DuplicateDetector` (incremental) | `keep_highest_confidence` | `temporal` | `most_recent` |
| `02_Fraud_Detection` | `ClusterBuilder` (graph_based) | `merge_all` | `logical` | `expert_review` |
| **Biomedical** |
| `01_Drug_Discovery_Pipeline` | `EntityResolver` (semantic) | - | `relationship` | `voting` |
| `02_Genomic_Variant_Analysis` | `DuplicateDetector` (group) | `keep_most_complete` | `value` | `credibility_weighted` |
| **Cybersecurity** |
| `01_Real_Time_Anomaly_Detection` | `DuplicateDetector` (pairwise) | `keep_first` | `entity` | `first_seen` |
| `02_Threat_Intelligence_Hybrid_RAG` | `EntityResolver` (exact) | - | `type` | `highest_confidence` |
| **Blockchain** |
| `01_DeFi_Protocol_Intelligence` | `DuplicateDetector` (group) | `keep_last` | `relationship` | `voting` |
| `02_Transaction_Network_Analysis` | `ClusterBuilder` (hierarchical) | `keep_most_complete` | `temporal` | `most_recent` |
| **Intelligence** |
| `01_Criminal_Network_Analysis` | `EntityResolver` (fuzzy) | - | `value` | `credibility_weighted` |
| `02_Intelligence_Analysis_Orchestrator_Worker` | `DuplicateDetector` (batch) | `merge_all` | `entity` | `voting` |
| **Renewable Energy** |
| `01_Energy_Market_Analysis` | `DuplicateDetector` (pairwise) | `keep_highest_confidence` | `temporal` | `most_recent` |
| **Supply Chain** |
| `01_Supply_Chain_Data_Integration` | `DuplicateDetector` (incremental) | `keep_most_complete` | `value` | `credibility_weighted` |
---
## Strategy Rationale by Domain
### Finance
- **Financial Data Integration**: Incremental for streaming data; most_recent for time-sensitive financial data
- **Fraud Detection**: Graph-based clustering for fraud groups; expert_review for fraud assessment
### Biomedical
- **Drug Discovery**: Semantic matching for drug compounds; voting for research source aggregation
- **Genomic Variants**: Group method for related variants; credibility weighting for research sources
### Cybersecurity
- **Real-Time Anomaly**: Pairwise for real-time streams; keep_first for first detection priority
- **Threat Intelligence**: Exact matching for IOCs; highest_confidence for threat classification
### Blockchain
- **DeFi Protocols**: Group method for related protocols; keep_last for latest protocol info
- **Transaction Networks**: Hierarchical clustering for nested groups; temporal for time-sensitive data
### Intelligence
- **Criminal Networks**: Fuzzy matching for intelligence data; credibility weighting for intelligence sources
- **Intelligence Analysis**: Batch for multi-source integration; merge_all to combine all intelligence sources
### Renewable Energy
- **Energy Markets**: Pairwise for real-time market data; most_recent for time-sensitive energy data
### Supply Chain
- **Supply Chain Integration**: Incremental for continuous updates; credibility weighting for supply chain sources
---
## Method Distribution
### Deduplication Methods (9 total)
- `pairwise`: 2 notebooks (real-time processing)
- `batch`: 3 notebooks (large datasets)
- `incremental`: 2 notebooks (streaming/continuous)
- `group`: 2 notebooks (related entities)
- `graph_based` (ClusterBuilder): 2 notebooks (interconnected entities)
- `hierarchical` (ClusterBuilder): 1 notebook (nested groups)
- `exact` (EntityResolver): 1 notebook (exact matching)
- `semantic` (EntityResolver): 2 notebooks (semantic similarity)
- `fuzzy` (EntityResolver): 1 notebook (fuzzy matching)
### Merge Strategies (5 total)
- `keep_first`: 1 notebook (first detection priority)
- `keep_last`: 1 notebook (latest information)
- `keep_most_complete`: 5 notebooks (preserve all details)
- `keep_highest_confidence`: 2 notebooks (most reliable data)
- `merge_all`: 3 notebooks (combine all information)
### Conflict Detection Methods (6 total)
- `value`: 4 notebooks (property value conflicts)
- `type`: 2 notebooks (type/classification conflicts)
- `entity`: 2 notebooks (entity-wide conflicts)
- `relationship`: 3 notebooks (relationship conflicts)
- `temporal`: 3 notebooks (time-sensitive conflicts)
- `logical`: 2 notebooks (logical inconsistencies)
### Conflict Resolution Strategies (6 total)
- `voting`: 5 notebooks (majority vote)
- `credibility_weighted`: 4 notebooks (source credibility)
- `most_recent`: 3 notebooks (latest data)
- `first_seen`: 1 notebook (first detection)
- `highest_confidence`: 2 notebooks (most confident)
- `expert_review`: 1 notebook (manual review)
---
## Key Patterns
1. **Real-Time Systems**: Use `pairwise` + `keep_first` + `first_seen`
2. **Time-Sensitive Data**: Use `temporal` + `most_recent`
3. **Multi-Source Integration**: Use `batch` + `merge_all` + `voting`
4. **Medical/Research**: Use `credibility_weighted` for authoritative sources
5. **Fraud/Security**: Use `graph_based` + `logical` + `expert_review`
6. **Exact Matching Required**: Use `exact` strategy (IOCs, identifiers)
+2 -2
View File
@@ -1,11 +1,11 @@
{
"name": "semantica-explorer",
"name": "semantica-knowledge-explorer",
"version": "0.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "semantica-explorer",
"name": "semantica-knowledge-explorer",
"version": "0.0.0",
"dependencies": {
"@monaco-editor/react": "^4.7.0",
+137
View File
@@ -0,0 +1,137 @@
# Semantica × OpenClaw Integration
Connect [OpenClaw](https://openclaw.ai) — the open-source personal AI agent — to Semantica's full knowledge-graph and decision-intelligence stack.
Two integration paths are available:
| Path | When to use |
|---|---|
| **MCP (recommended)** | OpenClaw Gateway is running; zero extra code needed |
| **REST / native tool** | Embedding Semantica directly in a SOUL.md agent config |
---
## Path 1 — MCP Server (recommended)
### 1. Start the Semantica MCP server
```bash
python -m semantica.mcp_server
```
### 2. Add to `mcporter.json`
```json
{
"mcpServers": {
"semantica": {
"command": "python",
"args": ["-m", "semantica.mcp_server"],
"transport": "stdio"
}
}
}
```
### 3. Restart the OpenClaw Gateway
```bash
openclaw gateway restart
```
All **12 Semantica tools** are now available to any OpenClaw agent:
| Tool | What it does |
|---|---|
| `extract_entities` | Named entity recognition from text |
| `extract_relations` | Relation / triplet extraction from text |
| `record_decision` | Record a decision with causal links |
| `query_decisions` | Search recorded decisions |
| `find_precedents` | Find past decisions similar to a query |
| `get_causal_chain` | Trace cause-effect chains from a node |
| `add_entity` | Add a node to the knowledge graph |
| `add_relationship` | Add an edge between two nodes |
| `run_reasoning` | Forward-chain rules over facts |
| `get_graph_analytics` | Centrality, communities, topology stats |
| `export_graph` | Export graph (JSON, RDF, GraphML, …) |
| `get_graph_summary` | High-level graph overview |
**3 resources** are also exposed: `semantica://graph/summary`, `semantica://decisions/list`, `semantica://schema/info`.
---
## Path 2 — Native Tool (REST)
Use `OpenClawKGTool` when you prefer a direct Python integration without the MCP gateway.
### Install
```bash
pip install semantica[openclaw] # pulls in 'requests'
```
### Quick start
```python
from integrations.openclaw import OpenClawKGTool
tool = OpenClawKGTool(base_url="http://localhost:8000")
# Extract knowledge from text
entities = tool.extract_entities("OpenClaw is an open-source AI agent built in Python.")
relations = tool.extract_relations("Alice manages the OpenClaw project at Hawksight.")
# Record and query decisions
tool.record_decision("Deploy model v2 to production", context="latency improved by 40%")
precedents = tool.find_precedents("roll back production deployment")
# Graph analytics
summary = tool.get_graph_summary()
analytics = tool.get_graph_analytics()
# Export
ttl = tool.export_graph(fmt="ttl")
```
### Generate `mcporter.json` programmatically
```python
from integrations.openclaw import OpenClawMCPConfig
cfg = OpenClawMCPConfig()
print(cfg.to_json()) # → paste into mcporter.json
```
---
## SOUL.md agent snippet
Add Semantica to any OpenClaw agent by referencing the tool in your `SOUL.md`:
```markdown
## Tools
- name: semantica_kg
description: >
Semantica knowledge-graph tool. Supports entity extraction, decision
recording, graph querying, causal chain analysis, reasoning, and
multi-format export.
endpoint: http://localhost:8000
auth: none
## Instructions
You have access to `semantica_kg`. Use it to:
- Extract entities and relations from any text the user provides.
- Record important decisions and retrieve precedents before recommending actions.
- Run graph analytics and export results when the user asks for a summary.
```
---
## Requirements
- Python 3.8+
- `pip install semantica` (core)
- `pip install semantica[openclaw]` (adds `requests` for the REST path)
- OpenClaw ≥ latest — [openclaw.ai](https://openclaw.ai)
+57
View File
@@ -0,0 +1,57 @@
"""
Semantica × OpenClaw Integration
==================================
First-class integration between the Semantica semantic intelligence stack and
`OpenClaw <https://openclaw.ai>`_ the open-source personal AI agent platform.
OpenClaw connects to external tools via MCP (Model Context Protocol). This
integration exposes the full Semantica MCP surface (12 tools, 3 resources) to
any OpenClaw agent and also ships a lightweight ``OpenClawKGTool`` that can be
dropped directly into an OpenClaw SOUL.md tool-list as a native tool.
Public surface
--------------
OpenClawKGTool Thin wrapper around the Semantica REST API usable as an
OpenClaw native tool (no MCP gateway required)
OpenClawMCPConfig Helper that emits the ``mcporter.json`` snippet needed to
wire Semantica's MCP server into an OpenClaw gateway
Quick start
-----------
pip install semantica
>>> from integrations.openclaw import OpenClawKGTool, OpenClawMCPConfig
>>> print(OpenClawMCPConfig().to_json()) # paste into mcporter.json
>>> tool = OpenClawKGTool(base_url="http://localhost:8000")
>>> result = tool.extract("OpenClaw is an open-source AI agent framework.")
MCP quick start
---------------
Run the Semantica MCP server once::
python -m semantica.mcp_server
Then add the printed config snippet to your OpenClaw ``mcporter.json`` and
restart the OpenClaw Gateway::
openclaw gateway restart
All 12 Semantica tools are then available as native OpenClaw agent tools.
Compatibility
-------------
Requires ``semantica >= 0.3.0``. The MCP path requires ``python >= 3.8`` and
a running ``semantica.mcp_server`` instance. The REST path requires a running
``semantica.server`` instance (``python -m semantica.server``, port 8000 by
default).
"""
from .mcp_tool import OpenClawKGTool, OpenClawMCPConfig
__all__ = [
"OpenClawKGTool",
"OpenClawMCPConfig",
]
__version__ = "0.1.0"
+253
View File
@@ -0,0 +1,253 @@
"""
OpenClaw Semantica bridge
============================
Two integration paths:
1. **MCP (recommended)** ``OpenClawMCPConfig`` emits the ``mcporter.json``
snippet that wires Semantica's MCP server into the OpenClaw Gateway.
All 12 Semantica MCP tools become native OpenClaw agent tools with no
extra code.
2. **REST** ``OpenClawKGTool`` is a plain Python class that calls the
Semantica REST API (port 8000) and can be registered as an OpenClaw
native tool via SOUL.md ``tools:`` entries.
"""
from __future__ import annotations
import json
from typing import Any, Dict, List, Optional
# ---------------------------------------------------------------------------
# MCP config helper
# ---------------------------------------------------------------------------
class OpenClawMCPConfig:
"""
Generates the ``mcporter.json`` entry needed to connect Semantica's MCP
server to the OpenClaw Gateway.
Parameters
----------
server_command:
Shell command used to launch the Semantica MCP server.
Defaults to ``"python -m semantica.mcp_server"``.
transport:
MCP transport protocol. OpenClaw supports ``"stdio"`` (default)
and ``"sse"``.
name:
Key used in ``mcporter.json``. Defaults to ``"semantica"``.
Example
-------
>>> cfg = OpenClawMCPConfig()
>>> print(cfg.to_json())
# → paste into ~/.openclaw/mcporter.json, then:
# → openclaw gateway restart
"""
def __init__(
self,
server_command: str = "python -m semantica.mcp_server",
transport: str = "stdio",
name: str = "semantica",
) -> None:
self.server_command = server_command
self.transport = transport
self.name = name
def to_dict(self) -> Dict[str, Any]:
"""Return the config as a plain dict."""
parts = self.server_command.split()
return {
"mcpServers": {
self.name: {
"command": parts[0],
"args": parts[1:],
"transport": self.transport,
}
}
}
def to_json(self, indent: int = 2) -> str:
"""Return the config as a JSON string."""
return json.dumps(self.to_dict(), indent=indent)
def __repr__(self) -> str: # pragma: no cover
return f"OpenClawMCPConfig(name={self.name!r}, transport={self.transport!r})"
# ---------------------------------------------------------------------------
# REST-based native tool
# ---------------------------------------------------------------------------
class OpenClawKGTool:
"""
A Semantica knowledge-graph tool callable from an OpenClaw agent.
Wraps the Semantica REST API so that an OpenClaw agent configured with
this tool (via SOUL.md ``tools:`` entries or programmatic registration)
can extract entities, record decisions, query the graph, and more
without requiring the MCP gateway.
Parameters
----------
base_url:
Base URL of the running Semantica REST server.
Defaults to ``"http://localhost:8000"``.
timeout:
Request timeout in seconds. Defaults to ``30``.
Notes
-----
``requests`` is used for HTTP calls. It is listed as an optional
dependency under ``semantica[openclaw]``; install it with::
pip install semantica[openclaw]
"""
TOOL_NAME = "semantica_kg"
TOOL_DESCRIPTION = (
"Semantica knowledge-graph tool. "
"Supports entity extraction, decision recording, graph querying, "
"causal chain analysis, reasoning, and multi-format export."
)
def __init__(self, base_url: str = "http://localhost:8000", timeout: int = 30) -> None:
self.base_url = base_url.rstrip("/")
self.timeout = timeout
self._session: Any = None
# ------------------------------------------------------------------
# Internal helpers
# ------------------------------------------------------------------
def _get_session(self) -> Any:
if self._session is None:
try:
import requests
self._session = requests.Session()
except ImportError as exc:
raise ImportError(
"The 'requests' package is required for OpenClawKGTool. "
"Install it with: pip install semantica[openclaw]"
) from exc
return self._session
def _post(self, endpoint: str, payload: Dict[str, Any]) -> Dict[str, Any]:
session = self._get_session()
url = f"{self.base_url}{endpoint}"
response = session.post(url, json=payload, timeout=self.timeout)
response.raise_for_status()
return response.json()
def _get(self, endpoint: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
session = self._get_session()
url = f"{self.base_url}{endpoint}"
response = session.get(url, params=params or {}, timeout=self.timeout)
response.raise_for_status()
return response.json()
# ------------------------------------------------------------------
# Extraction
# ------------------------------------------------------------------
def extract(self, text: str) -> Dict[str, Any]:
"""Extract entities and relations from *text*."""
return self._post("/extract", {"text": text})
def extract_entities(self, text: str) -> List[Dict[str, Any]]:
"""Return only the entity list from *text*."""
result = self.extract(text)
return result.get("entities", [])
def extract_relations(self, text: str) -> List[Dict[str, Any]]:
"""Return only the relation list from *text*."""
result = self.extract(text)
return result.get("relations", [])
# ------------------------------------------------------------------
# Graph mutation
# ------------------------------------------------------------------
def add_entity(self, label: str, entity_type: str = "Entity", **properties: Any) -> Dict[str, Any]:
"""Add a node to the knowledge graph."""
return self._post("/entities", {"label": label, "type": entity_type, **properties})
def add_relationship(
self,
source: str,
target: str,
relation_type: str,
**properties: Any,
) -> Dict[str, Any]:
"""Add an edge between *source* and *target*."""
return self._post(
"/relationships",
{"source": source, "target": target, "type": relation_type, **properties},
)
# ------------------------------------------------------------------
# Decisions
# ------------------------------------------------------------------
def record_decision(
self,
decision_text: str,
context: Optional[str] = None,
**metadata: Any,
) -> Dict[str, Any]:
"""Record a decision in the graph."""
payload: Dict[str, Any] = {"decision": decision_text}
if context:
payload["context"] = context
payload.update(metadata)
return self._post("/decisions", payload)
def query_decisions(self, query: str, limit: int = 10) -> List[Dict[str, Any]]:
"""Search recorded decisions."""
result = self._get("/decisions/search", {"q": query, "limit": limit})
return result.get("decisions", [])
def find_precedents(self, decision_text: str, top_k: int = 5) -> List[Dict[str, Any]]:
"""Find past decisions similar to *decision_text*."""
result = self._post("/decisions/precedents", {"decision": decision_text, "top_k": top_k})
return result.get("precedents", [])
# ------------------------------------------------------------------
# Analytics & reasoning
# ------------------------------------------------------------------
def get_causal_chain(self, node_id: str, depth: int = 3) -> Dict[str, Any]:
"""Retrieve the causal chain rooted at *node_id*."""
return self._get("/causal-chain", {"node_id": node_id, "depth": depth})
def run_reasoning(self, rules: List[str], facts: List[str]) -> Dict[str, Any]:
"""Run the Semantica forward-chaining reasoner."""
return self._post("/reason", {"rules": rules, "facts": facts})
def get_graph_analytics(self) -> Dict[str, Any]:
"""Return graph-level analytics (centrality, communities, etc.)."""
return self._get("/analytics")
# ------------------------------------------------------------------
# Export
# ------------------------------------------------------------------
def export_graph(self, fmt: str = "json") -> str:
"""Export the graph in *fmt* (``json``, ``ttl``, ``graphml``, …)."""
result = self._get("/export", {"format": fmt})
return result.get("data", "")
# ------------------------------------------------------------------
# Summary
# ------------------------------------------------------------------
def get_graph_summary(self) -> Dict[str, Any]:
"""Return a high-level summary of the current graph."""
return self._get("/graph/summary")
def __repr__(self) -> str: # pragma: no cover
return f"OpenClawKGTool(base_url={self.base_url!r})"
+171 -167
View File
@@ -1,195 +1,171 @@
# Semantica Plugins (Community Guide)
Semantica ships a shared plugin bundle under `plugins/` with skills, agents, and hooks for knowledge graphs, context graphs, decision intelligence, reasoning, explainability, provenance, ontology, and export workflows.
> **v0.4.0** — 17 domain skills · 3 agents · 8 platform plugins · Knowledge Explorer UI
This README covers installation across every supported platform.
Semantica ships a shared plugin bundle under `plugins/` that works across every major AI coding assistant. Connect any supported platform to Semantica's knowledge graph engine for semantic extraction, decision intelligence, reasoning, provenance, ontology, and export workflows.
## Supported Platforms
---
| Platform | Method | Config file |
|---|---|---|
| Claude Code | Native plugin bundle | `plugins/.claude-plugin/plugin.json` |
| Cursor | Native plugin bundle | `plugins/.cursor-plugin/plugin.json` |
| Codex CLI | Native plugin bundle | `plugins/.codex-plugin/plugin.json` |
| Windsurf | MCP server + plugin bundle | `plugins/.windsurf-plugin/plugin.json` |
| Cline (VS Code) | MCP server + plugin bundle | `plugins/.cline-plugin/plugin.json` |
| Continue | MCP server | `plugins/.continue-plugin/plugin.json` |
| VS Code | MCP server | `plugins/.vscode-plugin/plugin.json` |
| Claude Desktop | MCP server | — (see MCP section below) |
| Any MCP client | MCP server | `python -m semantica.mcp_server` |
## Platform Plugins
Semantica provides a dedicated plugin for each platform. Every plugin shares the same `skills/`, `agents/`, and `hooks/` bundle — only the manifest format differs.
| # | Platform | Plugin Folder | Setup |
|---|----------|--------------|-------|
| 1 | **Claude Code** | `.claude-plugin/` | `claude --plugin-dir ./plugins` |
| 2 | **Cursor** | `.cursor-plugin/` | Cursor Marketplace → refresh |
| 3 | **Codex** | `.codex-plugin/` | Marketplace UI → install |
| 4 | **Cline** | `.cline-plugin/` | Cline MCP settings |
| 5 | **Windsurf** | `.windsurf-plugin/` | `mcp_config.json` |
| 6 | **Continue** | `.continue-plugin/` | `~/.continue/config.json` |
| 7 | **OpenClaw** | `.openclaw-plugin/` | `mcporter.json` |
| 8 | **VS Code** | `.vscode-plugin/` | `settings.json` MCP entry |
---
## What's Included
```
plugins/
├── skills/ # 17 domain skills (slash commands)
├── agents/ # 3 specialized agents
├── hooks/ # hooks.json
├── .claude-plugin/ # Claude Code manifest + marketplace
├── .cursor-plugin/ # Cursor manifest + marketplace
├── .codex-plugin/ # Codex manifest + marketplace
├── .cline-plugin/ # Cline manifest + marketplace
├── .windsurf-plugin/ # Windsurf manifest + marketplace
├── .continue-plugin/ # Continue manifest + marketplace
├── .openclaw-plugin/ # OpenClaw manifest + marketplace
└── .vscode-plugin/ # VS Code manifest + marketplace
```
### Skills (17)
`extract` · `ingest` · `query` · `ontology` · `validate` · `deduplicate` · `embed` · `reason` · `decision` · `causal` · `temporal` · `provenance` · `policy` · `explain` · `export` · `change` · `visualize`
### Agents (3)
`decision-advisor` · `explainability` · `kg-assistant`
---
## Prerequisites
1. Clone the repository:
```bash
git clone https://github.com/Hawksight-AI/semantica.git
cd semantica
pip install semantica # Python 3.10+
```
2. Ensure the plugin bundle exists at:
---
```text
plugins/
skills/ ← 17 domain skills
agents/ ← 3 specialized agents
hooks/ ← hooks.json
.claude-plugin/ ← Claude Code manifest
.cursor-plugin/ ← Cursor manifest
.codex-plugin/ ← Codex CLI manifest
.windsurf-plugin/← Windsurf manifest + MCP config
.cline-plugin/ ← Cline manifest + MCP config
.continue-plugin/← Continue manifest + MCP config
.vscode-plugin/ ← VS Code manifest + MCP config
## Knowledge Explorer (v0.4.0)
Launch the interactive graph dashboard:
```bash
semantica-explorer --graph my_graph.json --port 8000
```
## Plugin Contents
Open **http://localhost:5174** to explore:
- `skills/`: 17 domain skills (`causal`, `decision`, `explain`, `reason`, `temporal`, etc.)
- `agents/`: specialized agents (`decision-advisor`, `explainability`, `kg-assistant`)
- `hooks/hooks.json`: plugin hook configuration
- `.claude-plugin/plugin.json`: Claude manifest
- `.cursor-plugin/plugin.json`: Cursor manifest
- `.codex-plugin/plugin.json`: Codex manifest
- `*/marketplace.json`: local marketplace definitions
- **Graph** — interactive canvas with ForceAtlas2 layout, path highlight, community coloring
- **Decisions** — causal chains and outcome analysis
- **Reasoning** — run deductive / abductive rules
- **SPARQL** — Monaco editor for graph queries
- **Vocabulary** — ontology concept tree
- **Lineage** — provenance lineage diagram
- **Import / Export** — JSON, RDF, Parquet, GraphML
## Install and Use in Claude Code
---
### Local install (fastest)
## Installation by Platform
From the repository root:
### Claude Code
```bash
claude --plugin-dir ./plugins
```
If your Claude setup uses plugin commands in-session, use:
Or inside a session:
```bash
/plugin install ./plugins
```
### Install from a GitHub marketplace
Verify:
Add a marketplace hosted in git:
```bash
/plugin marketplace add <owner>/semantica
```
Install Semantica from that marketplace:
```bash
/plugin install semantica@<marketplace-name>
```
### Verify in Claude
Run one of these in chat:
```text
/semantica:decision list
/semantica:explain decision <decision_id>
```
If the plugin is installed correctly, Claude should recognize the `/semantica:*` skills.
---
## Install and Use in Codex
### Cursor
Cursor reads `.cursor-plugin/plugin.json` and `.cursor-plugin/marketplace.json` automatically. Publish the `plugins/` directory and refresh in Cursor Marketplace to pick up updates.
Verify:
```
/semantica:visualize topology
/semantica:reason deductive "IF Person(x) THEN Mortal(x)"
```
---
### Codex
1. Ensure your repo marketplace exists at `.agents/plugins/marketplace.json`.
2. Point the plugin entry `source.path` to `./plugins` (or your chosen plugin directory).
2. Set `source.path` to `./plugins` in the plugin entry.
3. Restart Codex and install from the marketplace UI.
Codex manifest used by this bundle:
Verify:
- `.codex-plugin/plugin.json`
### Verify in Codex
After install, run a Semantica skill command in chat, for example:
```text
```
/semantica:causal chain --subject <decision_id> --depth 3
```
## Install and Use in Cursor
---
Cursor reads plugin metadata from:
### Cline
- `.cursor-plugin/plugin.json`
- `.cursor-plugin/marketplace.json`
If you maintain a team/community plugin repo, publish this `plugins/` directory and refresh/reinstall in Cursor Marketplace to pick up updates.
### Verify in Cursor
Try one of these commands:
```text
/semantica:reason deductive "IF Person(x) THEN Mortal(x)"
/semantica:visualize topology
```
## First Commands to Try
After installing on any platform, these are good smoke tests:
1. `/semantica:decision record <category> "<scenario>" "<reasoning>" <outcome> <confidence>`
2. `/semantica:decision list`
3. `/semantica:causal chain --subject <decision_id> --depth 3`
4. `/semantica:explain decision <decision_id>`
5. `/semantica:validate graph`
## MCP Server (Windsurf · Cline · Continue · VS Code · Claude Desktop · Any tool)
Semantica includes a full MCP server (`semantica/mcp_server.py`) that exposes 12 tools and 3 resources over stdio — compatible with any MCP-aware tool.
### Start the server
```bash
python -m semantica.mcp_server
```
### Configure in your tool
**Claude Desktop** — `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
```json
{
"mcpServers": {
"semantica": {
"command": "python",
"args": ["-m", "semantica.mcp_server"]
}
}
}
```
**Windsurf** — `~/.codeium/windsurf/mcp_config.json`:
```json
{
"mcpServers": {
"semantica": {
"command": "python",
"args": ["-m", "semantica.mcp_server"]
}
}
}
```
**Cline** — Cline MCP settings panel → Add server:
In Cline MCP settings, add:
```json
{
"semantica": {
"command": "python",
"args": ["-m", "semantica.mcp_server"]
"args": ["-m", "semantica.mcp_server"],
"env": {}
}
}
```
**Continue** — `~/.continue/config.json`:
---
### Windsurf
Add to `~/.codeium/windsurf/mcp_config.json`:
```json
{
"mcpServers": {
"semantica": {
"command": "python",
"args": ["-m", "semantica.mcp_server"]
}
}
}
```
---
### Continue
Add to `~/.continue/config.json`:
```json
{
@@ -203,7 +179,50 @@ python -m semantica.mcp_server
}
```
**VS Code** — `settings.json`:
All 17 Semantica skills appear in the `@semantica` context provider dropdown.
---
### OpenClaw
Add to `~/.openclaw/mcporter.json`:
```json
{
"mcpServers": {
"semantica": {
"command": "python",
"args": ["-m", "semantica.mcp_server"],
"transport": "stdio"
}
}
}
```
Then restart the gateway:
```bash
openclaw gateway restart
```
---
### VS Code
Add to `settings.json` (GitHub Copilot Chat):
```json
{
"github.copilot.chat.mcp.servers": {
"semantica": {
"command": "python",
"args": ["-m", "semantica.mcp_server"]
}
}
}
```
Or for the VS Code MCP extension:
```json
{
@@ -216,40 +235,25 @@ python -m semantica.mcp_server
}
```
### Available MCP tools
---
| Tool | Description |
|---|---|
| `extract_entities` | Named entity recognition from text |
| `extract_relations` | Relation and triplet extraction from text |
| `record_decision` | Record a decision with full context and metadata |
| `query_decisions` | Query recorded decisions by natural language or category |
| `find_precedents` | Find past decisions similar to a scenario |
| `get_causal_chain` | Trace upstream/downstream causal chain from a decision |
| `add_entity` | Add a node/entity to the knowledge graph |
| `add_relationship` | Add a directed edge between two entities |
| `run_reasoning` | Run IF/THEN rules over facts to derive new facts |
| `get_graph_analytics` | PageRank centrality and community detection |
| `export_graph` | Export graph as Turtle, JSON-LD, N-Triples, or JSON |
| `get_graph_summary` | Node count, decision count, graph status |
## First Commands to Try
### Available MCP resources
After installing on any platform:
| URI | Description |
|---|---|
| `semantica://graph/summary` | High-level graph statistics |
| `semantica://decisions/list` | All recorded decisions |
| `semantica://schema/info` | Server info and capability list |
```
/semantica:decision record <category> "<scenario>" "<reasoning>" <outcome> <confidence>
/semantica:decision list
/semantica:causal chain --subject <decision_id> --depth 3
/semantica:explain decision <decision_id>
/semantica:validate graph
/semantica:visualize topology
```
### Environment variables
| Variable | Description |
|---|---|
| `SEMANTICA_KG_PATH` | Path to a persisted graph to load on start |
| `SEMANTICA_LOG_LEVEL` | Log level: DEBUG, INFO, WARNING (default: WARNING) |
---
## Community Notes
- Keep plugin name/version/keywords updated in each manifest before publishing.
- Keep skill frontmatter consistent (`name` + `description`) for reliable discovery.
- For open-source sharing, include this folder as-is so skills, agents, and hooks remain bundled.
- Keep `name` / `version` / `keywords` updated in each manifest before publishing.
- Keep skill frontmatter (`name` + `description`) consistent for reliable discovery.
- Include `plugins/` as-is when sharing — skills, agents, and hooks must stay bundled.
+11 -3
View File
@@ -1,6 +1,6 @@
# Semantica — Cline Plugin
Adds all 17 Semantica skills, 3 agents, and hook configuration to Cline (VS Code extension).
> **v0.4.0**Adds all 17 Semantica skills, 3 agents, and hook configuration to Cline (VS Code extension).
## MCP Server Setup (recommended)
@@ -16,9 +16,17 @@ In Cline settings, add a new MCP server:
}
```
Cline will discover all 12 Semantica tools automatically on connection.
Cline will discover all 17 Semantica skills and 3 agents automatically on connection.
## Knowledge Explorer
```bash
semantica-explorer --graph my_graph.json --port 8000
```
Open `http://localhost:5174` for the interactive dashboard.
## Requirements
- Python 3.8+
- Python 3.10+
- `pip install semantica`
+11 -3
View File
@@ -1,6 +1,6 @@
# Semantica — Continue Plugin
Adds Semantica as an MCP server and context provider to [Continue.dev](https://continue.dev).
> **v0.4.0**Adds Semantica as an MCP server and context provider to [Continue.dev](https://continue.dev).
## MCP Server Setup
@@ -18,9 +18,17 @@ Add to `~/.continue/config.json`:
}
```
Continue will show all Semantica tools in the `@semantica` context provider dropdown.
Continue will show all 17 Semantica skills in the `@semantica` context provider dropdown.
## Knowledge Explorer
```bash
semantica-explorer --graph my_graph.json --port 8000
```
Open `http://localhost:5174` for the interactive graph dashboard.
## Requirements
- Python 3.8+
- Python 3.10+
- `pip install semantica`
+62
View File
@@ -0,0 +1,62 @@
# Semantica — OpenClaw Plugin
> **v0.4.0** — Adds all 17 Semantica skills, 3 agents, and the full MCP integration to [OpenClaw](https://openclaw.ai) — the open-source personal AI agent platform.
## MCP Server Setup (recommended)
### 1. Start the Semantica MCP server
```bash
python -m semantica.mcp_server
```
### 2. Add to `mcporter.json`
Paste the following into your OpenClaw `mcporter.json` (usually `~/.openclaw/mcporter.json`):
```json
{
"mcpServers": {
"semantica": {
"command": "python",
"args": ["-m", "semantica.mcp_server"],
"transport": "stdio"
}
}
}
```
### 3. Restart the OpenClaw Gateway
```bash
openclaw gateway restart
```
OpenClaw will automatically discover all 17 Semantica tools and 3 agents.
## Skills
All 17 skills under [`plugins/skills/`](../skills/) are available once the plugin is loaded:
`extract` · `ingest` · `query` · `ontology` · `validate` · `deduplicate` · `embed` · `reason` · `decision` · `causal` · `temporal` · `provenance` · `policy` · `explain` · `export` · `change` · `visualize`
## Native Tool (REST, no MCP gateway)
For agents that cannot use the MCP gateway, use the `OpenClawKGTool` REST wrapper:
```python
from integrations.openclaw import OpenClawKGTool
tool = OpenClawKGTool(base_url="http://localhost:8000")
entities = tool.extract_entities("Alice manages the project.")
tool.record_decision("Deploy model v2 to production")
summary = tool.get_graph_summary()
```
See [`integrations/openclaw/README.md`](../../integrations/openclaw/README.md) for the full guide, including SOUL.md agent snippets.
## Requirements
- Python 3.10+
- `pip install semantica`
- OpenClaw — [openclaw.ai](https://openclaw.ai)
+18
View File
@@ -0,0 +1,18 @@
{
"name": "semantica-openclaw",
"plugins": [
{
"name": "semantica",
"description": "Semantica plugin for OpenClaw: knowledge graph skills, decision intelligence, reasoning, extraction, and visualization.",
"source": "./",
"category": "Productivity",
"tags": [
"knowledge-graph",
"reasoning",
"semantica",
"openclaw",
"mcp"
]
}
]
}
+46
View File
@@ -0,0 +1,46 @@
{
"name": "semantica-openclaw",
"displayName": "Semantica OpenClaw Plugin",
"description": "Semantica plugin for OpenClaw: knowledge graph skills, decision intelligence, reasoning, extraction, and visualization via MCP and native REST tool.",
"version": "0.1.0",
"author": {
"name": "Semantica Contributors"
},
"homepage": "https://github.com/Hawksight-AI/semantica",
"repository": "https://github.com/Hawksight-AI/semantica",
"license": "MIT",
"keywords": [
"semantica",
"knowledge graph",
"openclaw",
"context graphs",
"decision intelligence",
"explainability",
"causal analysis",
"provenance",
"ontology",
"graph analytics",
"semantic extraction",
"visualization",
"reasoning",
"mcp"
],
"skills": "../skills",
"agents": "../agents",
"hooks": "../hooks/hooks.json",
"mcp": {
"server": "python -m semantica.mcp_server",
"transport": "stdio"
},
"openclaw": {
"mcporter": {
"mcpServers": {
"semantica": {
"command": "python",
"args": ["-m", "semantica.mcp_server"],
"transport": "stdio"
}
}
}
}
}
+14 -2
View File
@@ -1,6 +1,6 @@
# Semantica — VS Code Plugin
Adds Semantica as an MCP server to VS Code (via GitHub Copilot Chat or any MCP-aware extension).
> **v0.4.0**Adds Semantica as an MCP server to VS Code (via GitHub Copilot Chat or any MCP-aware extension).
## MCP Server Setup
@@ -30,7 +30,19 @@ Or if using the VS Code MCP extension directly:
}
```
VS Code will discover all 17 Semantica skills and 3 agents automatically on connection.
## Knowledge Explorer
Launch the interactive graph dashboard from the terminal:
```bash
semantica-explorer --graph my_graph.json --port 8000
```
Open `http://localhost:5174` to explore nodes, edges, decisions, SPARQL, lineage, and more.
## Requirements
- Python 3.8+
- Python 3.10+
- `pip install semantica`
+14 -4
View File
@@ -1,6 +1,6 @@
# Semantica — Windsurf Plugin
Adds all 17 Semantica skills, 3 agents, and hook configuration to Windsurf.
> **v0.4.0**Adds all 17 Semantica skills, 3 agents, and hook configuration to Windsurf.
## MCP Server Setup (recommended)
@@ -17,13 +17,23 @@ Add to your Windsurf MCP config (`~/.codeium/windsurf/mcp_config.json`):
}
```
Windsurf will then have access to all 12 Semantica tools (extract, record_decision, query_decisions, find_precedents, get_causal_chain, add_entity, add_relationship, run_reasoning, get_graph_analytics, export_graph, and more) directly in the AI panel.
Windsurf will have access to all 17 Semantica skills (`extract`, `record_decision`, `query_decisions`, `find_precedents`, `get_causal_chain`, `add_entity`, `add_relationship`, `run_reasoning`, `get_graph_analytics`, `export_graph`, and more) directly in the AI panel.
## Skills
All 17 skills under `plugins/skills/` are available as slash commands once the plugin is loaded.
All 17 skills under `plugins/skills/` are available as slash commands once the plugin is loaded:
`extract` · `ingest` · `query` · `ontology` · `validate` · `deduplicate` · `embed` · `reason` · `decision` · `causal` · `temporal` · `provenance` · `policy` · `explain` · `export` · `change` · `visualize`
## Knowledge Explorer
```bash
semantica-explorer --graph my_graph.json --port 8000
```
Open `http://localhost:5174` for the interactive graph dashboard.
## Requirements
- Python 3.8+
- Python 3.10+
- `pip install semantica`
+1 -1
View File
@@ -10,7 +10,7 @@ Main exports:
- Config: Configuration management
"""
__version__ = "0.3.0"
__version__ = "0.4.0"
__author__ = "Semantica Contributors"
__license__ = "MIT"
+12 -1
View File
@@ -10,7 +10,7 @@ from typing import Optional
from fastapi import FastAPI, HTTPException, Request, WebSocket, WebSocketDisconnect
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse, JSONResponse
from fastapi.responses import FileResponse, HTMLResponse, JSONResponse
from fastapi.staticfiles import StaticFiles
from .. import __version__
@@ -127,6 +127,17 @@ def create_app(session: Optional[GraphSession] = None) -> FastAPI:
except WebSocketDisconnect:
manager.disconnect(websocket)
@app.get("/", include_in_schema=False)
async def root():
index_path = Path(__file__).resolve().parent.parent / "static" / "index.html"
if index_path.is_file():
return FileResponse(index_path)
return HTMLResponse(
'<!doctype html><html lang="en"><head><meta charset="UTF-8">'
'<title>Semantica Knowledge Explorer</title></head>'
'<body><div id="root"></div></body></html>'
)
@app.get("/api/health")
async def health():
return {"status": "healthy"}
+3 -3
View File
@@ -8,7 +8,7 @@ modify Semantica core.
import asyncio
from typing import Optional
from fastapi import APIRouter, Depends, Query
from fastapi import APIRouter, Depends, HTTPException, Query
from ..dependencies import get_session
from ..schemas import AnnotationCreate, AnnotationResponse
@@ -35,7 +35,7 @@ async def create_annotation(
"""Create a new annotation on a node."""
node = await asyncio.to_thread(session.get_node, body.node_id)
if node is None:
raise KeyError(body.node_id)
raise HTTPException(status_code=404, detail=f"Node '{body.node_id}' not found")
ann_data = body.model_dump()
ann_id = await asyncio.to_thread(session.add_annotation, ann_data)
@@ -61,5 +61,5 @@ async def delete_annotation(
"""Delete an annotation by ID."""
deleted = await asyncio.to_thread(session.delete_annotation, annotation_id)
if not deleted:
raise KeyError(annotation_id)
raise HTTPException(status_code=404, detail=f"Annotation '{annotation_id}' not found")
return None
+5 -5
View File
@@ -5,7 +5,7 @@ Decision routes using ContextGraph-native fallbacks.
import asyncio
from typing import Optional
from fastapi import APIRouter, Depends, Query
from fastapi import APIRouter, Depends, HTTPException, Query
from ..dependencies import get_session
from ..schemas import CausalChainResponse, ComplianceResponse, DecisionResponse
@@ -59,7 +59,7 @@ async def get_decision(
):
node = await asyncio.to_thread(session.get_node, decision_id)
if node is None:
raise KeyError(decision_id)
raise HTTPException(status_code=404, detail=f"Decision '{decision_id}' not found")
return _node_to_decision(node)
@@ -70,7 +70,7 @@ async def get_causal_chain(
):
node = await asyncio.to_thread(session.get_node, decision_id)
if node is None:
raise KeyError(decision_id)
raise HTTPException(status_code=404, detail=f"Decision '{decision_id}' not found")
neighbors = await asyncio.to_thread(session.get_neighbors, decision_id, 5)
chain = [
@@ -94,7 +94,7 @@ async def get_precedents(
):
node = await asyncio.to_thread(session.get_node, decision_id)
if node is None:
raise KeyError(decision_id)
raise HTTPException(status_code=404, detail=f"Decision '{decision_id}' not found")
properties = node.get("properties", {})
category = str(properties.get("category", ""))
@@ -132,7 +132,7 @@ async def check_compliance(
):
node = await asyncio.to_thread(session.get_node, decision_id)
if node is None:
raise KeyError(decision_id)
raise HTTPException(status_code=404, detail=f"Decision '{decision_id}' not found")
edges, _ = await asyncio.to_thread(session.get_edges, skip=0, limit=999_999)
violation_types = {"violates", "non_compliant", "breaches"}
+10 -9
View File
@@ -6,7 +6,7 @@ import asyncio
import re
from typing import Dict, List, Optional, Tuple
from fastapi import APIRouter, Depends
from fastapi import APIRouter, Depends, HTTPException
from ..dependencies import get_session
from ..schemas import (
@@ -173,11 +173,12 @@ async def extract_entities(
relations=[_safe_dict(relation) for relation in rel_list],
)
except ImportError:
raise ValueError(
"semantic_extract module not available. Ensure spacy and transformers are installed."
raise HTTPException(
status_code=503,
detail="semantic_extract module not available. Ensure spacy and transformers are installed.",
)
except Exception as exc:
raise ValueError(f"Extraction failed: {exc}")
raise HTTPException(status_code=422, detail=f"Extraction failed: {exc}")
@router.post("/api/enrich/links", response_model=LinkPredictionResponse)
@@ -187,11 +188,11 @@ async def predict_links(
):
predictor = session.link_predictor
if predictor is None:
raise ValueError("LinkPredictor not available; KG extras may not be installed.")
raise HTTPException(status_code=503, detail="LinkPredictor not available; KG extras may not be installed.")
node = await asyncio.to_thread(session.get_node, body.node_id)
if node is None:
raise KeyError(body.node_id)
raise HTTPException(status_code=404, detail=f"Node '{body.node_id}' not found")
nodes, _ = await asyncio.to_thread(session.get_nodes, skip=0, limit=999_999)
edges, _ = await asyncio.to_thread(session.get_edges, skip=0, limit=999_999)
@@ -248,9 +249,9 @@ async def detect_duplicates(
duplicate_list = duplicates if isinstance(duplicates, list) else getattr(duplicates, "duplicates", [])
return DedupResponse(duplicates=[_safe_dict(item) for item in duplicate_list], total_flagged=len(duplicate_list))
except ImportError:
raise ValueError("Deduplication module not available.")
raise HTTPException(status_code=503, detail="Deduplication module not available.")
except Exception as exc:
raise ValueError(f"Dedup scan failed: {exc}")
raise HTTPException(status_code=422, detail=f"Dedup scan failed: {exc}")
@router.post("/api/reason", response_model=ReasoningResponse)
@@ -295,7 +296,7 @@ async def merge_nodes(
node = await asyncio.to_thread(session.get_node, primary_id)
if node is None:
raise ValueError(f"Primary node {primary_id} not found")
raise HTTPException(status_code=404, detail=f"Primary node '{primary_id}' not found")
def _do_merge() -> tuple[list[str], int]:
removed: list[str] = []
+7 -4
View File
@@ -6,7 +6,7 @@ import asyncio
from enum import Enum
from typing import Optional
from fastapi import APIRouter, Depends, Query
from fastapi import APIRouter, Depends, HTTPException, Query
from ..dependencies import get_session
from ..schemas import (
@@ -83,7 +83,7 @@ async def get_node(
):
node = await asyncio.to_thread(session.get_node, node_id)
if node is None:
raise KeyError(node_id)
raise HTTPException(status_code=404, detail=f"Node '{node_id}' not found")
return _node_response(node)
@@ -150,7 +150,7 @@ async def find_path(
):
path_finder = session.path_finder
if path_finder is None:
raise ValueError("PathFinder not available; KG extras may not be installed.")
raise HTTPException(status_code=503, detail="PathFinder not available; KG extras may not be installed.")
graph_dict = await asyncio.to_thread(session.build_graph_dict)
path_fn = (
@@ -158,7 +158,10 @@ async def find_path(
if algorithm == _PathAlgorithm.dijkstra
else path_finder.bfs_shortest_path
)
result = await asyncio.to_thread(path_fn, graph_dict, node_id, target)
try:
result = await asyncio.to_thread(path_fn, graph_dict, node_id, target)
except Exception as exc:
raise HTTPException(status_code=404, detail=f"No path found from '{node_id}' to '{target}': {exc}")
path_nodes = result.get("path", []) if isinstance(result, dict) else (result or [])
total_weight = result.get("total_weight", 0.0) if isinstance(result, dict) else 0.0
+1 -1
View File
@@ -103,7 +103,7 @@ async def temporal_patterns(
detector = TemporalPatternDetector()
graph_dict = await asyncio.to_thread(session.build_graph_dict)
patterns = await asyncio.to_thread(detector.detect_patterns, graph_dict)
patterns = await asyncio.to_thread(detector.detect_temporal_patterns, graph_dict)
if isinstance(patterns, dict):
patterns = patterns.get("patterns", [])
return TemporalPatternResponse(patterns=patterns if isinstance(patterns, list) else [])
+2
View File
@@ -126,12 +126,14 @@ from .temporal_query import (
TemporalPatternDetector,
TemporalVersionManager,
)
from .knowledge_graph import KnowledgeGraph
from .temporal_model import BiTemporalFact, TemporalBound
from .temporal_normalizer import TemporalNormalizer
from .temporal_query_rewriter import TemporalQueryRewriter, TemporalQueryResult
__all__ = [
# Core Classes
"KnowledgeGraph",
"GraphBuilder",
"GraphBuilderWithProvenance",
"EntityResolver",
+46
View File
@@ -0,0 +1,46 @@
"""
KnowledgeGraph dataclass canonical in-memory representation.
This is the formal type produced by the Semantica KG pipeline and consumed
by visualizers, exporters, and other downstream components. It is a thin,
immutable-friendly wrapper around three plain collections so that isinstance
checks, type hints, and IDEs can surface the type rather than relying on
bare dicts.
Keeping this in its own file avoids circular imports between the kg and
visualization sub-packages.
"""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any, Dict, List
@dataclass
class KnowledgeGraph:
"""
Canonical in-memory knowledge graph.
Attributes:
entities: List of entity dicts with at minimum ``id`` and ``type`` keys.
relationships: List of relationship dicts with at minimum ``source``,
``target``, and ``type`` keys.
metadata: Arbitrary graph-level metadata (e.g. build timestamps,
entity-resolution flags).
"""
entities: List[Dict[str, Any]] = field(default_factory=list)
relationships: List[Dict[str, Any]] = field(default_factory=list)
metadata: Dict[str, Any] = field(default_factory=dict)
# ------------------------------------------------------------------
# Convenience helpers
# ------------------------------------------------------------------
def __len__(self) -> int:
"""Return the number of entities (mirrors the most common 'size' query)."""
return len(self.entities)
def __bool__(self) -> bool:
return bool(self.entities or self.relationships)
+41 -6
View File
@@ -53,6 +53,14 @@ except (ImportError, OSError):
from ..utils.exceptions import ProcessingError
from ..utils.logging import get_logger
# Optional import — keeps the visualizer usable even if the kg sub-package
# is not installed, and avoids circular-import risk at module level.
try:
from ..kg.knowledge_graph import KnowledgeGraph as _KnowledgeGraph
except Exception: # pragma: no cover
_KnowledgeGraph = None # type: ignore[assignment,misc]
from ..utils.progress_tracker import get_progress_tracker
from .utils.color_schemes import ColorPalette, ColorScheme
from .utils.export_formats import (
@@ -118,18 +126,45 @@ class KGVisualizer:
"Install with: pip install plotly"
)
def _normalize_graph(self, graph: Any) -> Dict[str, Any]:
def _convert_knowledge_graph(self, kg: Any) -> Dict[str, Any]:
"""
Normalize graph input to the expected dict format.
Convert a KnowledgeGraph instance to the internal dict format.
Accepts either:
- A dict with "entities" and "relationships" keys (canonical format)
- Any object that exposes .entities and .relationships attributes
(e.g. a KnowledgeGraph dataclass returned by GraphBuilder.build())
Non-mutating. Preserves node types, labels, properties, edge types,
weights, and direction.
Args:
kg: A ``KnowledgeGraph`` instance.
Returns:
Dict with "entities", "relationships", and "metadata" keys.
"""
entities = getattr(kg, "entities", None) or []
relationships = getattr(kg, "relationships", None) or []
metadata = getattr(kg, "metadata", None) or {}
return {
"entities": list(entities),
"relationships": list(relationships),
"metadata": dict(metadata),
}
def _normalize_graph(self, graph: Any) -> Dict[str, Any]:
"""
Normalize graph input to the expected dict format.
Accepts:
- A ``KnowledgeGraph`` instance (routed through ``_convert_knowledge_graph``)
- A dict with "entities" and "relationships" keys (canonical format)
- Any object that exposes .entities and .relationships attributes
(duck-typed, e.g. custom dataclasses)
Returns:
Dict with "entities", "relationships", and "metadata" keys.
"""
# Explicit fast-path for the formal KnowledgeGraph type
if _KnowledgeGraph is not None and isinstance(graph, _KnowledgeGraph):
return self._convert_knowledge_graph(graph)
if isinstance(graph, dict):
return graph
+1 -1
View File
@@ -372,7 +372,7 @@ class TestEnrichment:
def test_extract(self, client):
response = client.post("/api/enrich/extract", json={"text": "Alice works at Acme Corp."})
assert response.status_code in (200, 422)
assert response.status_code in (200, 422, 503)
def test_link_prediction(self, client):
response = client.post("/api/enrich/links", json={"node_id": "python", "top_n": 5})
@@ -283,5 +283,166 @@ class TestAllVisualizeMethodsAcceptKGObject(unittest.TestCase):
self.viz._normalize_graph.assert_called_once_with(self.kg)
# ---------------------------------------------------------------------------
# Issue #471 — formal KnowledgeGraph type support
# ---------------------------------------------------------------------------
class TestFormalKnowledgeGraphType(unittest.TestCase):
"""
Regression tests for issue #471.
The formal ``semantica.kg.KnowledgeGraph`` dataclass must be accepted by
every public visualize_* method without requiring any manual conversion.
"""
@classmethod
def setUpClass(cls):
try:
from semantica.kg.knowledge_graph import KnowledgeGraph
cls.KnowledgeGraph = KnowledgeGraph
except ImportError:
cls.KnowledgeGraph = None
def _make_kg(self):
if self.KnowledgeGraph is None:
self.skipTest("semantica.kg.KnowledgeGraph not available")
return self.KnowledgeGraph(
entities=ENTITIES,
relationships=RELATIONSHIPS,
metadata={"version": "test"},
)
def test_convert_knowledge_graph_entities(self):
kg = self._make_kg()
viz = _make_viz()
result = viz._convert_knowledge_graph(kg)
self.assertEqual(result["entities"], ENTITIES)
def test_convert_knowledge_graph_relationships(self):
kg = self._make_kg()
viz = _make_viz()
result = viz._convert_knowledge_graph(kg)
self.assertEqual(result["relationships"], RELATIONSHIPS)
def test_convert_knowledge_graph_metadata(self):
kg = self._make_kg()
viz = _make_viz()
result = viz._convert_knowledge_graph(kg)
self.assertEqual(result["metadata"], {"version": "test"})
def test_convert_knowledge_graph_does_not_mutate(self):
kg = self._make_kg()
original_entities = list(kg.entities)
original_relationships = list(kg.relationships)
viz = _make_viz()
viz._convert_knowledge_graph(kg)
self.assertEqual(kg.entities, original_entities)
self.assertEqual(kg.relationships, original_relationships)
def test_convert_knowledge_graph_is_deterministic(self):
kg = self._make_kg()
viz = _make_viz()
self.assertEqual(viz._convert_knowledge_graph(kg), viz._convert_knowledge_graph(kg))
def test_normalize_graph_routes_kg_type(self):
kg = self._make_kg()
viz = _make_viz()
viz._convert_knowledge_graph = MagicMock(return_value=GRAPH_DICT)
viz._normalize_graph(kg)
viz._convert_knowledge_graph.assert_called_once_with(kg)
def test_normalize_graph_returns_dict_for_kg_type(self):
kg = self._make_kg()
viz = _make_viz()
result = viz._normalize_graph(kg)
self.assertIsInstance(result, dict)
self.assertIn("entities", result)
self.assertIn("relationships", result)
def _run_visualize_network(self, graph_arg):
mock_fig = MagicMock()
mock_go = sys.modules["plotly.graph_objects"]
mock_go.Figure.return_value = mock_fig
mock_go.Scatter.return_value = MagicMock()
mock_go.Layout.return_value = MagicMock()
viz = _make_viz()
fake_pos = {"e1": (0.0, 0.0), "e2": (1.0, 1.0)}
viz.force_layout = MagicMock()
viz.force_layout.compute_layout.return_value = fake_pos
viz.hierarchical_layout = MagicMock()
viz.circular_layout = MagicMock()
with (
patch(
"semantica.visualization.kg_visualizer.ColorPalette.get_entity_type_colors",
return_value={"Person": "#ff0000"},
),
patch(
"semantica.visualization.kg_visualizer.ColorPalette.get_colors",
return_value=["#ff0000"],
),
):
return viz.visualize_network(graph_arg, output="interactive")
def test_visualize_network_accepts_knowledge_graph(self):
self.assertIsNotNone(self._run_visualize_network(self._make_kg()))
def test_visualize_communities_accepts_knowledge_graph(self):
kg = self._make_kg()
viz = _make_viz()
viz._normalize_graph = MagicMock(return_value=GRAPH_DICT)
viz._visualize_network_plotly = MagicMock(return_value=MagicMock())
communities = {"node_assignments": {"e1": 0, "e2": 1}, "num_communities": 2}
with patch(
"semantica.visualization.kg_visualizer.ColorPalette.get_community_colors",
return_value=["#ff0000", "#00ff00"],
):
viz.visualize_communities(kg, communities=communities)
viz._normalize_graph.assert_called_once_with(kg)
def test_visualize_centrality_accepts_knowledge_graph(self):
kg = self._make_kg()
viz = _make_viz()
viz._normalize_graph = MagicMock(return_value=GRAPH_DICT)
viz._visualize_network_plotly = MagicMock(return_value=MagicMock())
viz.visualize_centrality(kg, centrality={"centrality": {}})
viz._normalize_graph.assert_called_once_with(kg)
def test_visualize_entity_types_accepts_knowledge_graph(self):
kg = self._make_kg()
viz = _make_viz()
viz._normalize_graph = MagicMock(return_value=GRAPH_DICT)
sys.modules["plotly.express"].bar.return_value = MagicMock()
viz.visualize_entity_types(kg)
viz._normalize_graph.assert_called_once_with(kg)
def test_visualize_relationship_matrix_accepts_knowledge_graph(self):
kg = self._make_kg()
viz = _make_viz()
viz._normalize_graph = MagicMock(return_value=GRAPH_DICT)
sys.modules["plotly.graph_objects"].Figure.return_value = MagicMock()
sys.modules["plotly.graph_objects"].Heatmap.return_value = MagicMock()
viz.visualize_relationship_matrix(kg)
viz._normalize_graph.assert_called_once_with(kg)
def test_knowledge_graph_importable_from_kg_module(self):
if self.KnowledgeGraph is None:
self.skipTest("semantica.kg.KnowledgeGraph not available")
try:
import semantica.kg as _kg_module
_ = _kg_module.KnowledgeGraph
except (ImportError, AttributeError) as exc:
self.fail(f"KnowledgeGraph not exported from semantica.kg: {exc}")
def test_knowledge_graph_empty_defaults(self):
kg = self.KnowledgeGraph()
self.assertEqual(kg.entities, [])
self.assertEqual(kg.relationships, [])
self.assertFalse(bool(kg))
def test_knowledge_graph_len(self):
kg = self._make_kg()
self.assertEqual(len(kg), len(ENTITIES))
if __name__ == "__main__":
unittest.main()