domain-context-graph 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- domain_context_graph-0.4.0/.github/workflows/publish.yaml +74 -0
- domain_context_graph-0.4.0/.gitignore +13 -0
- domain_context_graph-0.4.0/AGENTS.md +92 -0
- domain_context_graph-0.4.0/PKG-INFO +186 -0
- domain_context_graph-0.4.0/README.md +163 -0
- domain_context_graph-0.4.0/TODO.md +17 -0
- domain_context_graph-0.4.0/pyproject.toml +43 -0
- domain_context_graph-0.4.0/src/dcg/__init__.py +41 -0
- domain_context_graph-0.4.0/src/dcg/adapters/__init__.py +8 -0
- domain_context_graph-0.4.0/src/dcg/adapters/base.py +156 -0
- domain_context_graph-0.4.0/src/dcg/adapters/graphify.py +233 -0
- domain_context_graph-0.4.0/src/dcg/adapters/registry.py +18 -0
- domain_context_graph-0.4.0/src/dcg/cli.py +206 -0
- domain_context_graph-0.4.0/src/dcg/core/__init__.py +63 -0
- domain_context_graph-0.4.0/src/dcg/core/builders.py +68 -0
- domain_context_graph-0.4.0/src/dcg/core/model.py +113 -0
- domain_context_graph-0.4.0/src/dcg/core/ontology.py +386 -0
- domain_context_graph-0.4.0/src/dcg/core/packs/code.yaml +27 -0
- domain_context_graph-0.4.0/src/dcg/core/packs/core.yaml +65 -0
- domain_context_graph-0.4.0/src/dcg/core/packs/dcg-development.yaml +22 -0
- domain_context_graph-0.4.0/src/dcg/core/packs/security.yaml +9 -0
- domain_context_graph-0.4.0/src/dcg/core/project.py +247 -0
- domain_context_graph-0.4.0/src/dcg/core/purge.py +9 -0
- domain_context_graph-0.4.0/src/dcg/core/stack.py +643 -0
- domain_context_graph-0.4.0/src/dcg/core/store.py +408 -0
- domain_context_graph-0.4.0/src/dcg/core/uid.py +28 -0
- domain_context_graph-0.4.0/src/dcg/ingest/__init__.py +58 -0
- domain_context_graph-0.4.0/src/dcg/ingest/discovery.py +69 -0
- domain_context_graph-0.4.0/src/dcg/ingest/models.py +132 -0
- domain_context_graph-0.4.0/src/dcg/ingest/report.py +47 -0
- domain_context_graph-0.4.0/src/dcg/ingest/runner.py +295 -0
- domain_context_graph-0.4.0/src/dcg/mcp/__init__.py +6 -0
- domain_context_graph-0.4.0/src/dcg/mcp/__main__.py +4 -0
- domain_context_graph-0.4.0/src/dcg/mcp/dcg_ingest_mcp.py +89 -0
- domain_context_graph-0.4.0/src/dcg/mcp/dcg_mcp.py +79 -0
- domain_context_graph-0.4.0/src/dcg/mcp/helpers.py +12 -0
- domain_context_graph-0.4.0/src/dcg/mcp/state.py +20 -0
- domain_context_graph-0.4.0/src/dcg/mcp/tools/__init__.py +1 -0
- domain_context_graph-0.4.0/src/dcg/mcp/tools/ingest.py +161 -0
- domain_context_graph-0.4.0/src/dcg/mcp/tools/project.py +37 -0
- domain_context_graph-0.4.0/src/dcg/mcp/tools/query.py +145 -0
- domain_context_graph-0.4.0/src/dcg/mcp/tools/stack.py +99 -0
- domain_context_graph-0.4.0/src/dcg/ops/__init__.py +1 -0
- domain_context_graph-0.4.0/src/dcg/ops/ingest.py +167 -0
- domain_context_graph-0.4.0/src/dcg/ops/lifecycle.py +86 -0
- domain_context_graph-0.4.0/src/dcg/ops/ontology.py +37 -0
- domain_context_graph-0.4.0/src/dcg/ui/__init__.py +116 -0
- domain_context_graph-0.4.0/src/dcg/ui/index.html +12 -0
- domain_context_graph-0.4.0/src/dcg/ui/package-lock.json +5172 -0
- domain_context_graph-0.4.0/src/dcg/ui/package.json +41 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/App.tsx +35 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/__tests__/store.test.ts +65 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/components/AppShell.tsx +45 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/components/AttributeRow.tsx +16 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/components/CreateEntityDialog.tsx +82 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/components/DetailPanel.tsx +20 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/components/DomainFilter.tsx +65 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/components/EntityDetail.tsx +229 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/components/EntityForm.tsx +117 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/components/GraphCanvas.tsx +119 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/components/LayerDetail.tsx +53 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/components/LayerSwitcher.tsx +34 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/components/RelationDetail.tsx +55 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/components/RelationRow.tsx +43 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/components/SearchInput.tsx +26 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/components/Sidebar.tsx +13 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/components/StackTopology.tsx +147 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/components/StatusBar.tsx +24 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/components/Toolbar.tsx +88 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/components/TypeFilter.tsx +36 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/components/ViewModeToggle.tsx +30 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/declarations.d.ts +5 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/graph/__tests__/transform.test.ts +114 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/graph/layouts.ts +36 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/graph/styles.ts +90 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/graph/transform.ts +140 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/index.css +1 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/main.tsx +10 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/mcp/McpProvider.tsx +57 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/mcp/StaticProvider.tsx +24 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/mcp/__tests__/types.test.ts +45 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/mcp/client.ts +51 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/mcp/hooks.ts +115 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/mcp/mutations.ts +128 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/mcp/static-client.ts +140 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/mcp/types.ts +137 -0
- domain_context_graph-0.4.0/src/dcg/ui/src/store.ts +88 -0
- domain_context_graph-0.4.0/src/dcg/ui/tsconfig.json +20 -0
- domain_context_graph-0.4.0/src/dcg/ui/vite.config.ts +21 -0
- domain_context_graph-0.4.0/tests/__init__.py +0 -0
- domain_context_graph-0.4.0/tests/unit/__init__.py +0 -0
- domain_context_graph-0.4.0/tests/unit/test_adapter_graphify.py +485 -0
- domain_context_graph-0.4.0/tests/unit/test_adapter_registry.py +27 -0
- domain_context_graph-0.4.0/tests/unit/test_cli.py +130 -0
- domain_context_graph-0.4.0/tests/unit/test_compose.py +921 -0
- domain_context_graph-0.4.0/tests/unit/test_gap_implementations.py +451 -0
- domain_context_graph-0.4.0/tests/unit/test_ingest_cli.py +126 -0
- domain_context_graph-0.4.0/tests/unit/test_ingest_discovery.py +158 -0
- domain_context_graph-0.4.0/tests/unit/test_ingest_models.py +214 -0
- domain_context_graph-0.4.0/tests/unit/test_ingest_runner.py +367 -0
- domain_context_graph-0.4.0/tests/unit/test_ingest_tools.py +198 -0
- domain_context_graph-0.4.0/tests/unit/test_integration_composition.py +179 -0
- domain_context_graph-0.4.0/tests/unit/test_mcp_http.py +38 -0
- domain_context_graph-0.4.0/tests/unit/test_mcp_query.py +66 -0
- domain_context_graph-0.4.0/tests/unit/test_mcp_server.py +110 -0
- domain_context_graph-0.4.0/tests/unit/test_mcp_stack.py +117 -0
- domain_context_graph-0.4.0/tests/unit/test_ontology.py +389 -0
- domain_context_graph-0.4.0/tests/unit/test_project.py +216 -0
- domain_context_graph-0.4.0/tests/unit/test_store.py +449 -0
- domain_context_graph-0.4.0/tests/unit/test_uid.py +55 -0
- domain_context_graph-0.4.0/utility/README.md +91 -0
- domain_context_graph-0.4.0/utility/neo4j_export.py +269 -0
- domain_context_graph-0.4.0/utility/requirements.txt +2 -0
- domain_context_graph-0.4.0/utility/wikidata_import.py +0 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
id-token: write
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
name: Run tests
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
matrix:
|
|
17
|
+
python-version: ["3.10", "3.12"]
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: ${{ matrix.python-version }}
|
|
24
|
+
|
|
25
|
+
- name: Install package with dev dependencies
|
|
26
|
+
run: pip install -e ".[dev]"
|
|
27
|
+
|
|
28
|
+
- name: Run tests
|
|
29
|
+
run: pytest --tb=short -q
|
|
30
|
+
|
|
31
|
+
build:
|
|
32
|
+
name: Build package
|
|
33
|
+
needs: test
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v4
|
|
37
|
+
|
|
38
|
+
- uses: actions/setup-python@v5
|
|
39
|
+
with:
|
|
40
|
+
python-version: "3.12"
|
|
41
|
+
|
|
42
|
+
- name: Install build tools
|
|
43
|
+
run: pip install --upgrade build
|
|
44
|
+
|
|
45
|
+
- name: Build sdist and wheel
|
|
46
|
+
run: python -m build
|
|
47
|
+
|
|
48
|
+
- name: Verify package version matches release tag
|
|
49
|
+
run: |
|
|
50
|
+
PKG_VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
|
|
51
|
+
TAG_VERSION="${GITHUB_REF_NAME#v}"
|
|
52
|
+
if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then
|
|
53
|
+
echo "::error::Version mismatch: pyproject.toml=$PKG_VERSION tag=$TAG_VERSION"
|
|
54
|
+
exit 1
|
|
55
|
+
fi
|
|
56
|
+
echo "Version $PKG_VERSION matches tag"
|
|
57
|
+
|
|
58
|
+
- uses: actions/upload-artifact@v4
|
|
59
|
+
with:
|
|
60
|
+
name: dist
|
|
61
|
+
path: dist/
|
|
62
|
+
|
|
63
|
+
publish:
|
|
64
|
+
name: Publish to PyPI
|
|
65
|
+
needs: build
|
|
66
|
+
runs-on: ubuntu-latest
|
|
67
|
+
environment: pypi
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/download-artifact@v4
|
|
70
|
+
with:
|
|
71
|
+
name: dist
|
|
72
|
+
path: dist/
|
|
73
|
+
|
|
74
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# DCG Development Guide
|
|
2
|
+
|
|
3
|
+
## Project
|
|
4
|
+
|
|
5
|
+
`domain-context-graph` (import as `dcg`) — a Wikibase-compatible knowledge graph protocol for grounding AI in verified domain knowledge. Python >=3.10, built with hatchling.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
python -m venv .venv
|
|
11
|
+
.venv/bin/pip install -e ".[dev,ui,ingest]"
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Data Sources
|
|
15
|
+
|
|
16
|
+
DCG operates in two modes. Always use the right one:
|
|
17
|
+
|
|
18
|
+
- **Single project** (`--project <path>`) — a directory containing `graph_card.json` (metadata) and `graphs/default.json` (graph data). Use for isolated domain graphs.
|
|
19
|
+
- **Stack manifest** (`--stack <path/to/dcg-stack.yml>`) — composes multiple project directories as layers with cross-layer resolution. Manifests support multi-parent `extends` (list) and a `joins` section for cross-layer join rules. Use when working with multi-layer graphs (e.g., security + product + code).
|
|
20
|
+
|
|
21
|
+
The `--stack` path is relative to the manifest file's parent directory for layer `source` fields.
|
|
22
|
+
|
|
23
|
+
## CLI Commands
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
dcg init <name> [--path .] [--description ""] # Create a new domain project
|
|
27
|
+
dcg compose <manifest> # Validate/inspect a stack manifest
|
|
28
|
+
dcg compact <path> # Compact layers in a project
|
|
29
|
+
dcg query <path> [--type Function] [--domain X] # Query entities (single project)
|
|
30
|
+
dcg ui [<path>] [--stack <manifest>] [--port 8080] # Launch graph explorer web UI
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`dcg ui` accepts either a positional project path or `--stack` (mutually exclusive). At least one is required.
|
|
34
|
+
|
|
35
|
+
## MCP Server
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
dcg-mcp --project <path> # Single project
|
|
39
|
+
dcg-mcp --stack <manifest> [--layer <name>] # Stack mode
|
|
40
|
+
dcg-mcp --stack <manifest> --no-strict # Skip strict ontology validation
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`--project` and `--stack` are mutually exclusive and required. The `--no-strict` flag disables strict ontology validation — use it for read-only access to data that may not meet current strict rules. The UI passes this automatically for stack mode.
|
|
44
|
+
|
|
45
|
+
## Architecture
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
src/dcg/
|
|
49
|
+
core/ # GraphStore, ontology, compose (DcgStack, JoinRule), merge, UID generation
|
|
50
|
+
mcp/ # MCP server (FastMCP), tools (query, ingest, stack, project)
|
|
51
|
+
ops/ # Higher-level operations: ingest pipelines, lifecycle, ontology mgmt
|
|
52
|
+
ui/ # NiceGUI web explorer — app, MCP client, transform, components
|
|
53
|
+
cli.py # CLI entry point
|
|
54
|
+
project.py # DomainProject — file-based persistence (graph_card.json + graphs/)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Key classes
|
|
58
|
+
|
|
59
|
+
- `GraphStore` — in-memory graph with entities, relations, layered history
|
|
60
|
+
- `DomainProject` — manages a project directory (`graph_card.json` for metadata + `graphs/` for graph data)
|
|
61
|
+
- `DcgStack` — composes multiple projects as layers; `from_project()` wraps a single project as a 1-layer stack
|
|
62
|
+
- `JoinRule` — declarative cross-layer join rule; cross-layer relations are materialized at stack level, not stored in layer data
|
|
63
|
+
- `McpClient` (ui) — async stdio MCP client wrapper; uses `_call()` for single values, `_call_list()` for lists (FastMCP splits list returns into one TextContent per element)
|
|
64
|
+
|
|
65
|
+
### Entity/relation format
|
|
66
|
+
|
|
67
|
+
- Entity UID: `dcg:sha256:<hash>` (content-addressed) or `dcg:meta:<Name>` (type definitions)
|
|
68
|
+
- Relation UID: `dcg:rel:sha256:<hash>`
|
|
69
|
+
- Entity: `{"id": str, "label": str, "description": str, "attributes": [{"property": str, "ref"|"string"|"quantity": value}]}`
|
|
70
|
+
- Relation: `{"dcg:type": "relation", "uid": str, "source": str, "target": str, "property": str}`
|
|
71
|
+
|
|
72
|
+
## Testing
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
.venv/bin/pytest # Run all tests
|
|
76
|
+
.venv/bin/pytest tests/unit/ -v # Verbose
|
|
77
|
+
.venv/bin/pytest -k test_compose # Filter by name
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Tests live in `tests/unit/`. No conftest.py — fixtures are defined per-file. Async tests use `pytest-asyncio` with `mode=strict`.
|
|
81
|
+
|
|
82
|
+
## Rules
|
|
83
|
+
|
|
84
|
+
- **`graph_card.json` is metadata-only.** It holds project name, description, and ontology declarations. Entities and relations live in `graphs/default.json` (and other named graphs). Never store graph data in `graph_card.json`.
|
|
85
|
+
- **No `ontology.yaml`.** Ontology definitions are inlined in `graph_card.json` under the `ontology` key. The separate `ontology.yaml` file has been removed.
|
|
86
|
+
- **Stack ontology loads before project data.** `DcgStack.load()` injects the manifest's ontology declarations into each project's store before calling `project.load()`. This is load-order sensitive — do not move ontology injection after project loading.
|
|
87
|
+
- **Cross-layer relations are read-only.** They are materialized at stack level from `JoinRule` definitions in the manifest's `joins` section. Do not store cross-layer relations in individual layer data.
|
|
88
|
+
- **Stack manifests support multi-parent `extends`.** The `extends` field in a layer entry accepts either a single string or a list of layer names. Resolution follows BFS topological order; DAG cycles are rejected at load time.
|
|
89
|
+
- **FastMCP list serialization quirk.** MCP tools returning `list[dict]` are split into one TextContent per element, not a single JSON array. The `McpClient._call_list()` method handles this. Use `_call()` for single-value returns, `_call_list()` for list returns.
|
|
90
|
+
- **`DomainProject.load()` does not restore layers.** Only entities and relations are loaded from `graphs/default.json`. Layer history is not persisted through load/save cycles.
|
|
91
|
+
- **No backward compatibility before v1.0.** Breaking changes are expected. No deprecation shims or re-exports for removed code.
|
|
92
|
+
- **Internal docs go in the workspace.** Specs, plans, and design docs belong in `projects/dcg/` at the workspace root — not in this repo. Only public-facing documentation goes here.
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: domain-context-graph
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Domain Context Graph protocol for grounding AI in verified domain knowledge.
|
|
5
|
+
License-Expression: Apache-2.0
|
|
6
|
+
Keywords: ai-grounding,domain-graph,domain-model,graph-protocol,llm-context
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Topic :: Database :: Database Engines/Servers
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
13
|
+
Requires-Python: >=3.10
|
|
14
|
+
Requires-Dist: mcp>=1.27
|
|
15
|
+
Requires-Dist: pyyaml>=6.0
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
18
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
19
|
+
Provides-Extra: ingest
|
|
20
|
+
Requires-Dist: requests>=2.28; extra == 'ingest'
|
|
21
|
+
Provides-Extra: ui
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# Domain Context Graph (DCG)
|
|
25
|
+
|
|
26
|
+
**An open protocol for structuring domain knowledge so AI systems reason about your product — not just your code.**
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## The Problem
|
|
31
|
+
|
|
32
|
+
AI coding assistants write confident code that violates business rules nobody documented. Security scanners flag vulnerabilities without knowing which domain owns the affected service. Incident responders trace call graphs without understanding blast radius across business capabilities.
|
|
33
|
+
|
|
34
|
+
- **LLM training data is generic.** Models know what "payments" means in general — not what *your* Payments domain is, who owns it, or what depends on it.
|
|
35
|
+
- **Code graphs capture structure, not semantics.** They see imports and call chains — not that two modules serve the same bounded context.
|
|
36
|
+
- **Documentation decays instantly.** Wikis are stale, unstructured, and not machine-queryable.
|
|
37
|
+
- **Knowledge is tool-siloed.** Your security scanner's vulnerability data can't connect to your code graph's ownership data because there's no shared schema.
|
|
38
|
+
|
|
39
|
+
DCG fills this gap: a **standard, machine-readable protocol** for domain knowledge that any AI system can consume — versioned, git-backed, and federated across teams and repos.
|
|
40
|
+
|
|
41
|
+
## Core Concepts
|
|
42
|
+
|
|
43
|
+
- **Wikibase-compatible entities** — same JSON format used by Wikidata's 100M+ items. Labels, descriptions, aliases, and attributes with full snak structure.
|
|
44
|
+
- **Content-addressed identity** — entity UIDs are deterministic hashes (`dcg:sha256:...`). Same entity always gets the same ID, regardless of who creates it or when.
|
|
45
|
+
- **Two-axis classification** — every entity has a structural type (`instance of` Function/Class/Endpoint) and domain membership (`part of` Payments/Security). These are orthogonal.
|
|
46
|
+
- **Retraction and purge** — entities can be retracted (soft-deleted) and later permanently purged from the graph.
|
|
47
|
+
- **Composition** — stack multiple domain graphs via `dcg-stack.yml` manifests with `extends` chains. Query across layers; entities resolve upward through the chain.
|
|
48
|
+
- **Federation** — multiple graphs reference each other's entities via cross-graph resolution. Each team owns their graph independently.
|
|
49
|
+
|
|
50
|
+
## Install
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install domain-context-graph
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
With git-backed persistence:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install domain-context-graph[git]
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Quick Start
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from dcg.core import GraphStore, entity_uid, builders as kb
|
|
66
|
+
|
|
67
|
+
store = GraphStore()
|
|
68
|
+
|
|
69
|
+
# Define a domain
|
|
70
|
+
payments_uid = entity_uid(name="Payments")
|
|
71
|
+
store.add_entity(kb.entity(
|
|
72
|
+
uid=payments_uid,
|
|
73
|
+
label="Payments",
|
|
74
|
+
description="Payment processing domain",
|
|
75
|
+
attributes=[kb.attribute("instance of", kb.ref_value("dcg:meta:Domain"))],
|
|
76
|
+
))
|
|
77
|
+
|
|
78
|
+
# Place a code entity in that domain
|
|
79
|
+
fn_uid = entity_uid(name="charge_card", path="src/payments/charge.py")
|
|
80
|
+
store.add_entity(kb.entity(
|
|
81
|
+
uid=fn_uid,
|
|
82
|
+
label="charge_card",
|
|
83
|
+
attributes=[
|
|
84
|
+
kb.attribute("instance of", kb.ref_value("dcg:meta:Function")),
|
|
85
|
+
kb.attribute("part of", kb.ref_value(payments_uid)),
|
|
86
|
+
kb.attribute("file path", kb.string_value("src/payments/charge.py")),
|
|
87
|
+
],
|
|
88
|
+
))
|
|
89
|
+
|
|
90
|
+
# Query
|
|
91
|
+
functions = store.query(instance_of="dcg:meta:Function")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## CLI
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
dcg init <name> [--path .] [--description "..."] # Create a new domain graph project
|
|
98
|
+
dcg serve --project <path> # Start MCP server (single project)
|
|
99
|
+
dcg serve --stack <manifest> # Start MCP server (multi-layer stack)
|
|
100
|
+
dcg compose <manifest> # Validate a dcg-stack.yml manifest
|
|
101
|
+
dcg purge <path> # Remove retracted entities and relations
|
|
102
|
+
dcg query <path> [--type Function] [--domain Pay] # Query entities
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## MCP Server
|
|
106
|
+
|
|
107
|
+
DCG includes a built-in [Model Context Protocol](https://modelcontextprotocol.io) server with 28 tools for reading, writing, and querying domain graphs.
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Single project
|
|
111
|
+
dcg serve --project ./my-graph
|
|
112
|
+
|
|
113
|
+
# Multi-layer stack (cross-layer queries)
|
|
114
|
+
dcg serve --stack ./dcg-stack.yml
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Tools include `dcg_create_entity`, `dcg_create_domain`, `dcg_connect`, `dcg_query`, `dcg_snapshot`, `dcg_bulk_add`, and more. Stack-mode adds `dcg_stack_info`, `dcg_query_stack`, and `dcg_resolve_cross_layer`.
|
|
118
|
+
|
|
119
|
+
## Composition
|
|
120
|
+
|
|
121
|
+
Stack multiple domain graphs with a `dcg-stack.yml` manifest:
|
|
122
|
+
|
|
123
|
+
```yaml
|
|
124
|
+
stack: my-appsec-stack
|
|
125
|
+
layers:
|
|
126
|
+
- name: security
|
|
127
|
+
source: ./graphs/security-domain
|
|
128
|
+
|
|
129
|
+
- name: product
|
|
130
|
+
source: ./graphs/product-domain
|
|
131
|
+
extends: security
|
|
132
|
+
|
|
133
|
+
- name: code
|
|
134
|
+
source: ./graphs/code
|
|
135
|
+
extends: product
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The `extends` chain defines resolution order. When querying the `code` layer for an entity, DCG walks `code` → `product` → `security` until found. Cross-layer queries deduplicate by UID (nearest layer wins).
|
|
139
|
+
|
|
140
|
+
## Package Structure
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
src/dcg/
|
|
144
|
+
__init__.py # Public API re-exports
|
|
145
|
+
cli.py # CLI entry point (dcg command)
|
|
146
|
+
project.py # DomainProject — manifest-based project manager
|
|
147
|
+
core/
|
|
148
|
+
uid.py # Content-addressed entity/relation IDs
|
|
149
|
+
model.py # Entity, Relation, Attribute dataclasses
|
|
150
|
+
ontology.py # Type and property registries
|
|
151
|
+
builders.py # Wikibase JSON entity/attribute construction
|
|
152
|
+
store.py # GraphStore — in-memory implementation
|
|
153
|
+
compose.py # DcgStack — multi-project composition
|
|
154
|
+
federation.py # Cross-graph registry and resolution
|
|
155
|
+
purge.py # Retraction purge
|
|
156
|
+
git_store.py # GitGraphStore — dulwich-backed persistence
|
|
157
|
+
mcp/
|
|
158
|
+
server.py # FastMCP server (28 tools)
|
|
159
|
+
helpers.py # Shared MCP utilities
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Specification
|
|
163
|
+
|
|
164
|
+
| Document | Description |
|
|
165
|
+
|----------|-------------|
|
|
166
|
+
| [RFC DCG-002](spec/rfc.md) | Formal protocol specification (IETF RFC 2119). Defines Core, Persistent, and Federated conformance levels. |
|
|
167
|
+
| [Design Spec](spec/design.md) | Full architecture, entity model, ontology, and integration patterns. |
|
|
168
|
+
|
|
169
|
+
The RFC is the authoritative source. This Python package is one implementation — others can implement the same spec in any language.
|
|
170
|
+
|
|
171
|
+
## Extensibility
|
|
172
|
+
|
|
173
|
+
- **Custom domains** — `register_global_type()` to add domain-specific types
|
|
174
|
+
- **Custom properties** — `register_property()` with Wikidata P-ID aliases
|
|
175
|
+
- **Custom backends** — implement `GraphStoreProtocol` for any storage
|
|
176
|
+
- **Federation** — implement `GraphRegistry` and `BoundaryResolver` for cross-graph resolution
|
|
177
|
+
|
|
178
|
+
## Related Projects
|
|
179
|
+
|
|
180
|
+
| Project | Description |
|
|
181
|
+
|---------|-------------|
|
|
182
|
+
| [appsec-ctx-graph](https://github.me/atishio/appsec-ctx-graph) | 3-layer security + product + code domain graph built on DCG |
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
Apache-2.0
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Domain Context Graph (DCG)
|
|
2
|
+
|
|
3
|
+
**An open protocol for structuring domain knowledge so AI systems reason about your product — not just your code.**
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## The Problem
|
|
8
|
+
|
|
9
|
+
AI coding assistants write confident code that violates business rules nobody documented. Security scanners flag vulnerabilities without knowing which domain owns the affected service. Incident responders trace call graphs without understanding blast radius across business capabilities.
|
|
10
|
+
|
|
11
|
+
- **LLM training data is generic.** Models know what "payments" means in general — not what *your* Payments domain is, who owns it, or what depends on it.
|
|
12
|
+
- **Code graphs capture structure, not semantics.** They see imports and call chains — not that two modules serve the same bounded context.
|
|
13
|
+
- **Documentation decays instantly.** Wikis are stale, unstructured, and not machine-queryable.
|
|
14
|
+
- **Knowledge is tool-siloed.** Your security scanner's vulnerability data can't connect to your code graph's ownership data because there's no shared schema.
|
|
15
|
+
|
|
16
|
+
DCG fills this gap: a **standard, machine-readable protocol** for domain knowledge that any AI system can consume — versioned, git-backed, and federated across teams and repos.
|
|
17
|
+
|
|
18
|
+
## Core Concepts
|
|
19
|
+
|
|
20
|
+
- **Wikibase-compatible entities** — same JSON format used by Wikidata's 100M+ items. Labels, descriptions, aliases, and attributes with full snak structure.
|
|
21
|
+
- **Content-addressed identity** — entity UIDs are deterministic hashes (`dcg:sha256:...`). Same entity always gets the same ID, regardless of who creates it or when.
|
|
22
|
+
- **Two-axis classification** — every entity has a structural type (`instance of` Function/Class/Endpoint) and domain membership (`part of` Payments/Security). These are orthogonal.
|
|
23
|
+
- **Retraction and purge** — entities can be retracted (soft-deleted) and later permanently purged from the graph.
|
|
24
|
+
- **Composition** — stack multiple domain graphs via `dcg-stack.yml` manifests with `extends` chains. Query across layers; entities resolve upward through the chain.
|
|
25
|
+
- **Federation** — multiple graphs reference each other's entities via cross-graph resolution. Each team owns their graph independently.
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install domain-context-graph
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
With git-backed persistence:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install domain-context-graph[git]
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from dcg.core import GraphStore, entity_uid, builders as kb
|
|
43
|
+
|
|
44
|
+
store = GraphStore()
|
|
45
|
+
|
|
46
|
+
# Define a domain
|
|
47
|
+
payments_uid = entity_uid(name="Payments")
|
|
48
|
+
store.add_entity(kb.entity(
|
|
49
|
+
uid=payments_uid,
|
|
50
|
+
label="Payments",
|
|
51
|
+
description="Payment processing domain",
|
|
52
|
+
attributes=[kb.attribute("instance of", kb.ref_value("dcg:meta:Domain"))],
|
|
53
|
+
))
|
|
54
|
+
|
|
55
|
+
# Place a code entity in that domain
|
|
56
|
+
fn_uid = entity_uid(name="charge_card", path="src/payments/charge.py")
|
|
57
|
+
store.add_entity(kb.entity(
|
|
58
|
+
uid=fn_uid,
|
|
59
|
+
label="charge_card",
|
|
60
|
+
attributes=[
|
|
61
|
+
kb.attribute("instance of", kb.ref_value("dcg:meta:Function")),
|
|
62
|
+
kb.attribute("part of", kb.ref_value(payments_uid)),
|
|
63
|
+
kb.attribute("file path", kb.string_value("src/payments/charge.py")),
|
|
64
|
+
],
|
|
65
|
+
))
|
|
66
|
+
|
|
67
|
+
# Query
|
|
68
|
+
functions = store.query(instance_of="dcg:meta:Function")
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## CLI
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
dcg init <name> [--path .] [--description "..."] # Create a new domain graph project
|
|
75
|
+
dcg serve --project <path> # Start MCP server (single project)
|
|
76
|
+
dcg serve --stack <manifest> # Start MCP server (multi-layer stack)
|
|
77
|
+
dcg compose <manifest> # Validate a dcg-stack.yml manifest
|
|
78
|
+
dcg purge <path> # Remove retracted entities and relations
|
|
79
|
+
dcg query <path> [--type Function] [--domain Pay] # Query entities
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## MCP Server
|
|
83
|
+
|
|
84
|
+
DCG includes a built-in [Model Context Protocol](https://modelcontextprotocol.io) server with 28 tools for reading, writing, and querying domain graphs.
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Single project
|
|
88
|
+
dcg serve --project ./my-graph
|
|
89
|
+
|
|
90
|
+
# Multi-layer stack (cross-layer queries)
|
|
91
|
+
dcg serve --stack ./dcg-stack.yml
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Tools include `dcg_create_entity`, `dcg_create_domain`, `dcg_connect`, `dcg_query`, `dcg_snapshot`, `dcg_bulk_add`, and more. Stack-mode adds `dcg_stack_info`, `dcg_query_stack`, and `dcg_resolve_cross_layer`.
|
|
95
|
+
|
|
96
|
+
## Composition
|
|
97
|
+
|
|
98
|
+
Stack multiple domain graphs with a `dcg-stack.yml` manifest:
|
|
99
|
+
|
|
100
|
+
```yaml
|
|
101
|
+
stack: my-appsec-stack
|
|
102
|
+
layers:
|
|
103
|
+
- name: security
|
|
104
|
+
source: ./graphs/security-domain
|
|
105
|
+
|
|
106
|
+
- name: product
|
|
107
|
+
source: ./graphs/product-domain
|
|
108
|
+
extends: security
|
|
109
|
+
|
|
110
|
+
- name: code
|
|
111
|
+
source: ./graphs/code
|
|
112
|
+
extends: product
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The `extends` chain defines resolution order. When querying the `code` layer for an entity, DCG walks `code` → `product` → `security` until found. Cross-layer queries deduplicate by UID (nearest layer wins).
|
|
116
|
+
|
|
117
|
+
## Package Structure
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
src/dcg/
|
|
121
|
+
__init__.py # Public API re-exports
|
|
122
|
+
cli.py # CLI entry point (dcg command)
|
|
123
|
+
project.py # DomainProject — manifest-based project manager
|
|
124
|
+
core/
|
|
125
|
+
uid.py # Content-addressed entity/relation IDs
|
|
126
|
+
model.py # Entity, Relation, Attribute dataclasses
|
|
127
|
+
ontology.py # Type and property registries
|
|
128
|
+
builders.py # Wikibase JSON entity/attribute construction
|
|
129
|
+
store.py # GraphStore — in-memory implementation
|
|
130
|
+
compose.py # DcgStack — multi-project composition
|
|
131
|
+
federation.py # Cross-graph registry and resolution
|
|
132
|
+
purge.py # Retraction purge
|
|
133
|
+
git_store.py # GitGraphStore — dulwich-backed persistence
|
|
134
|
+
mcp/
|
|
135
|
+
server.py # FastMCP server (28 tools)
|
|
136
|
+
helpers.py # Shared MCP utilities
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Specification
|
|
140
|
+
|
|
141
|
+
| Document | Description |
|
|
142
|
+
|----------|-------------|
|
|
143
|
+
| [RFC DCG-002](spec/rfc.md) | Formal protocol specification (IETF RFC 2119). Defines Core, Persistent, and Federated conformance levels. |
|
|
144
|
+
| [Design Spec](spec/design.md) | Full architecture, entity model, ontology, and integration patterns. |
|
|
145
|
+
|
|
146
|
+
The RFC is the authoritative source. This Python package is one implementation — others can implement the same spec in any language.
|
|
147
|
+
|
|
148
|
+
## Extensibility
|
|
149
|
+
|
|
150
|
+
- **Custom domains** — `register_global_type()` to add domain-specific types
|
|
151
|
+
- **Custom properties** — `register_property()` with Wikidata P-ID aliases
|
|
152
|
+
- **Custom backends** — implement `GraphStoreProtocol` for any storage
|
|
153
|
+
- **Federation** — implement `GraphRegistry` and `BoundaryResolver` for cross-graph resolution
|
|
154
|
+
|
|
155
|
+
## Related Projects
|
|
156
|
+
|
|
157
|
+
| Project | Description |
|
|
158
|
+
|---------|-------------|
|
|
159
|
+
| [appsec-ctx-graph](https://github.me/atishio/appsec-ctx-graph) | 3-layer security + product + code domain graph built on DCG |
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
Apache-2.0
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# DCG — TODO
|
|
2
|
+
|
|
3
|
+
## dcg CLI (`~/Documents/kit/dcg`)
|
|
4
|
+
|
|
5
|
+
### Remove hardcoded `dcg ingest`
|
|
6
|
+
|
|
7
|
+
**Why:** `dcg ingest` is not generic — it has Wikidata SPARQL queries and the entire Gartner WAAP taxonomy hardcoded in `src/dcg/ingest.py`. It only produces a security domain graph and cannot be configured for other domains.
|
|
8
|
+
|
|
9
|
+
**What to do:**
|
|
10
|
+
|
|
11
|
+
- [ ] Remove `ingest.py` from `src/dcg/`
|
|
12
|
+
- [ ] Remove the `ingest` subcommand from the CLI entrypoint
|
|
13
|
+
- [ ] Remove the `requests` optional dependency (`domain-context-graph[ingest]`)
|
|
14
|
+
- [ ] Move Wikidata+WAAP import logic into `dcg-security-domain` repo as a standalone bootstrap script (e.g., `scripts/bootstrap.py`) — that's where domain-specific seeding belongs
|
|
15
|
+
- [ ] Update `dcg --help` / README to reflect removal
|
|
16
|
+
|
|
17
|
+
**Principle:** `dcg` CLI should be domain-agnostic. Domain-specific data sources belong in the domain project repos, not in the core tool.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "domain-context-graph"
|
|
7
|
+
version = "0.4.0"
|
|
8
|
+
description = "Domain Context Graph protocol for grounding AI in verified domain knowledge."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "Apache-2.0"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
dependencies = [
|
|
13
|
+
"pyyaml>=6.0",
|
|
14
|
+
"mcp>=1.27",
|
|
15
|
+
]
|
|
16
|
+
keywords = ["domain-graph", "ai-grounding", "llm-context", "graph-protocol", "domain-model"]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 3 - Alpha",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"License :: OSI Approved :: Apache Software License",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
23
|
+
"Topic :: Database :: Database Engines/Servers",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.optional-dependencies]
|
|
27
|
+
ingest = ["requests>=2.28"]
|
|
28
|
+
ui = []
|
|
29
|
+
dev = [
|
|
30
|
+
"pytest>=7.0",
|
|
31
|
+
"pytest-cov>=4.0",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.scripts]
|
|
35
|
+
dcg = "dcg.cli:main"
|
|
36
|
+
dcg-mcp = "dcg.mcp:main"
|
|
37
|
+
dcg-ingest-mcp = "dcg.mcp.dcg_ingest_mcp:main"
|
|
38
|
+
|
|
39
|
+
[tool.hatch.build.targets.wheel]
|
|
40
|
+
packages = ["src/dcg"]
|
|
41
|
+
|
|
42
|
+
[tool.pytest.ini_options]
|
|
43
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""DCG — Domain Context Graph."""
|
|
2
|
+
|
|
3
|
+
from dcg.core import (
|
|
4
|
+
entity_uid,
|
|
5
|
+
relation_uid,
|
|
6
|
+
Entity,
|
|
7
|
+
Relation,
|
|
8
|
+
SCHEMA_VERSION,
|
|
9
|
+
TYPE_REGISTRY,
|
|
10
|
+
PROPERTY_REGISTRY,
|
|
11
|
+
register_global_type,
|
|
12
|
+
register_property,
|
|
13
|
+
register_alias,
|
|
14
|
+
resolve_property,
|
|
15
|
+
GraphStore,
|
|
16
|
+
GraphStoreProtocol,
|
|
17
|
+
StackLoader,
|
|
18
|
+
DomainProject,
|
|
19
|
+
purge_retracted,
|
|
20
|
+
builders,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"entity_uid",
|
|
25
|
+
"relation_uid",
|
|
26
|
+
"Entity",
|
|
27
|
+
"Relation",
|
|
28
|
+
"SCHEMA_VERSION",
|
|
29
|
+
"TYPE_REGISTRY",
|
|
30
|
+
"PROPERTY_REGISTRY",
|
|
31
|
+
"register_global_type",
|
|
32
|
+
"register_property",
|
|
33
|
+
"register_alias",
|
|
34
|
+
"resolve_property",
|
|
35
|
+
"GraphStore",
|
|
36
|
+
"GraphStoreProtocol",
|
|
37
|
+
"StackLoader",
|
|
38
|
+
"DomainProject",
|
|
39
|
+
"purge_retracted",
|
|
40
|
+
"builders",
|
|
41
|
+
]
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""DCG adapters — pluggable backends for loading layers from external sources."""
|
|
2
|
+
from .base import AdapterProxy, LayerAdapterProtocol
|
|
3
|
+
from .graphify import GraphifyAdapter
|
|
4
|
+
from .registry import register
|
|
5
|
+
|
|
6
|
+
register("graphify", GraphifyAdapter)
|
|
7
|
+
|
|
8
|
+
__all__ = ["AdapterProxy", "GraphifyAdapter", "LayerAdapterProtocol"]
|