pkmrag 0.9.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. pkmrag-0.9.0/.env.example +52 -0
  2. pkmrag-0.9.0/.github/workflows/ci.yml +44 -0
  3. pkmrag-0.9.0/.gitignore +67 -0
  4. pkmrag-0.9.0/.python-version +1 -0
  5. pkmrag-0.9.0/AGENTS.md +95 -0
  6. pkmrag-0.9.0/LICENSE +21 -0
  7. pkmrag-0.9.0/PKG-INFO +290 -0
  8. pkmrag-0.9.0/README.md +247 -0
  9. pkmrag-0.9.0/SECURITY.md +25 -0
  10. pkmrag-0.9.0/assets/apple-touch-icon.png +0 -0
  11. pkmrag-0.9.0/assets/favicon.ico +0 -0
  12. pkmrag-0.9.0/assets/favicon.svg +1 -0
  13. pkmrag-0.9.0/assets/obsidian-ribbon-icon.svg +8 -0
  14. pkmrag-0.9.0/assets/pkmrag-avatar-500.png +0 -0
  15. pkmrag-0.9.0/assets/pkmrag-icon-512.png +0 -0
  16. pkmrag-0.9.0/assets/pkmrag-icon.svg +1 -0
  17. pkmrag-0.9.0/assets/pkmrag-logo-dark.svg +1 -0
  18. pkmrag-0.9.0/assets/pkmrag-logo-text-dark.svg +1 -0
  19. pkmrag-0.9.0/assets/pkmrag-logo-text.svg +1 -0
  20. pkmrag-0.9.0/assets/pkmrag-logo.svg +1 -0
  21. pkmrag-0.9.0/assets/pkmrag-social-preview.png +0 -0
  22. pkmrag-0.9.0/assets/pkmrag-social-preview.svg +1 -0
  23. pkmrag-0.9.0/benchmarks/golden_10.json +62 -0
  24. pkmrag-0.9.0/benchmarks/golden_50_obsidian_help.json +352 -0
  25. pkmrag-0.9.0/benchmarks/vault/Concepts/Hybrid Search.md +16 -0
  26. pkmrag-0.9.0/benchmarks/vault/Concepts/Lexical BM25.md +10 -0
  27. pkmrag-0.9.0/benchmarks/vault/Concepts/Property Graphs.md +19 -0
  28. pkmrag-0.9.0/benchmarks/vault/Concepts/Reciprocal Rank Fusion.md +13 -0
  29. pkmrag-0.9.0/benchmarks/vault/Daily/2026-09-27.md +15 -0
  30. pkmrag-0.9.0/benchmarks/vault/Index.md +19 -0
  31. pkmrag-0.9.0/benchmarks/vault/Projects/FastMCP Server.md +19 -0
  32. pkmrag-0.9.0/benchmarks/vault/Projects/Orbit Core.md +32 -0
  33. pkmrag-0.9.0/benchmarks/vault/Projects/Storage Layer.md +16 -0
  34. pkmrag-0.9.0/benchmarks/vault/Research/GraphRAG Paradigms.md +21 -0
  35. pkmrag-0.9.0/benchmarks/vault/Research/Model Context Protocol.md +11 -0
  36. pkmrag-0.9.0/benchmarks/vault/Research/Vector Retrieval.md +12 -0
  37. pkmrag-0.9.0/docs/adr/0001-embedded-in-process-storage.md +34 -0
  38. pkmrag-0.9.0/docs/adr/0002-pluggable-dialect-strategy.md +34 -0
  39. pkmrag-0.9.0/docs/adr/0003-reciprocal-rank-fusion-ranking.md +35 -0
  40. pkmrag-0.9.0/docs/adr/0004-mcp-as-primary-interface.md +36 -0
  41. pkmrag-0.9.0/docs/adr/0005-openai-compatible-inference-layer.md +32 -0
  42. pkmrag-0.9.0/docs/adr/0006-l1-query-cache-and-on-demand-digestion.md +42 -0
  43. pkmrag-0.9.0/docs/architecture.md +75 -0
  44. pkmrag-0.9.0/docs/subsystems/benchmarks.md +90 -0
  45. pkmrag-0.9.0/docs/subsystems/caching.md +93 -0
  46. pkmrag-0.9.0/docs/subsystems/discovery.md +42 -0
  47. pkmrag-0.9.0/docs/subsystems/graph-engine.md +62 -0
  48. pkmrag-0.9.0/docs/subsystems/http-transport.md +157 -0
  49. pkmrag-0.9.0/docs/subsystems/hybrid-search.md +50 -0
  50. pkmrag-0.9.0/docs/subsystems/inference.md +51 -0
  51. pkmrag-0.9.0/docs/subsystems/ingestion.md +49 -0
  52. pkmrag-0.9.0/docs/subsystems/local-inference.md +110 -0
  53. pkmrag-0.9.0/docs/subsystems/mcp.md +81 -0
  54. pkmrag-0.9.0/docs/subsystems/observability.md +115 -0
  55. pkmrag-0.9.0/docs/subsystems/obsidian-plugin.md +151 -0
  56. pkmrag-0.9.0/docs/subsystems/search-engine.md +47 -0
  57. pkmrag-0.9.0/package.json +15 -0
  58. pkmrag-0.9.0/plugins/obsidian/esbuild.config.mjs +49 -0
  59. pkmrag-0.9.0/plugins/obsidian/icon.svg +8 -0
  60. pkmrag-0.9.0/plugins/obsidian/main.js +1752 -0
  61. pkmrag-0.9.0/plugins/obsidian/manifest.json +11 -0
  62. pkmrag-0.9.0/plugins/obsidian/package-lock.json +637 -0
  63. pkmrag-0.9.0/plugins/obsidian/package.json +35 -0
  64. pkmrag-0.9.0/plugins/obsidian/scripts/install.mjs +134 -0
  65. pkmrag-0.9.0/plugins/obsidian/src/client.ts +291 -0
  66. pkmrag-0.9.0/plugins/obsidian/src/client_events.ts +40 -0
  67. pkmrag-0.9.0/plugins/obsidian/src/commands.ts +97 -0
  68. pkmrag-0.9.0/plugins/obsidian/src/daemon.ts +255 -0
  69. pkmrag-0.9.0/plugins/obsidian/src/extension.ts +114 -0
  70. pkmrag-0.9.0/plugins/obsidian/src/main.ts +237 -0
  71. pkmrag-0.9.0/plugins/obsidian/src/settings.ts +217 -0
  72. pkmrag-0.9.0/plugins/obsidian/src/settings_llm.ts +113 -0
  73. pkmrag-0.9.0/plugins/obsidian/src/status_bar.ts +110 -0
  74. pkmrag-0.9.0/plugins/obsidian/src/types.ts +163 -0
  75. pkmrag-0.9.0/plugins/obsidian/src/view.ts +242 -0
  76. pkmrag-0.9.0/plugins/obsidian/src/view_gaps.ts +88 -0
  77. pkmrag-0.9.0/plugins/obsidian/src/view_inferences.ts +83 -0
  78. pkmrag-0.9.0/plugins/obsidian/src/view_offline.ts +74 -0
  79. pkmrag-0.9.0/plugins/obsidian/src/view_progress.ts +39 -0
  80. pkmrag-0.9.0/plugins/obsidian/src/view_search.ts +124 -0
  81. pkmrag-0.9.0/plugins/obsidian/src/view_setup_wizard.ts +77 -0
  82. pkmrag-0.9.0/plugins/obsidian/src/view_unindexed.ts +54 -0
  83. pkmrag-0.9.0/plugins/obsidian/styles.css +201 -0
  84. pkmrag-0.9.0/plugins/obsidian/tests/client.test.ts +224 -0
  85. pkmrag-0.9.0/plugins/obsidian/tests/compliance.test.ts +279 -0
  86. pkmrag-0.9.0/plugins/obsidian/tsconfig.json +19 -0
  87. pkmrag-0.9.0/plugins/obsidian/versions.json +3 -0
  88. pkmrag-0.9.0/pyproject.toml +90 -0
  89. pkmrag-0.9.0/src/pkmrag/__init__.py +5 -0
  90. pkmrag-0.9.0/src/pkmrag/cache/__init__.py +8 -0
  91. pkmrag-0.9.0/src/pkmrag/cache/manager.py +98 -0
  92. pkmrag-0.9.0/src/pkmrag/cache/sqlite_cache.py +264 -0
  93. pkmrag-0.9.0/src/pkmrag/cli.py +294 -0
  94. pkmrag-0.9.0/src/pkmrag/cli_views.py +274 -0
  95. pkmrag-0.9.0/src/pkmrag/config.py +204 -0
  96. pkmrag-0.9.0/src/pkmrag/dialects/__init__.py +14 -0
  97. pkmrag-0.9.0/src/pkmrag/dialects/base.py +46 -0
  98. pkmrag-0.9.0/src/pkmrag/dialects/commonmark.py +149 -0
  99. pkmrag-0.9.0/src/pkmrag/dialects/obsidian.py +172 -0
  100. pkmrag-0.9.0/src/pkmrag/dialects/registry.py +60 -0
  101. pkmrag-0.9.0/src/pkmrag/discovery/__init__.py +7 -0
  102. pkmrag-0.9.0/src/pkmrag/discovery/engine.py +278 -0
  103. pkmrag-0.9.0/src/pkmrag/doctor.py +200 -0
  104. pkmrag-0.9.0/src/pkmrag/eval/__init__.py +16 -0
  105. pkmrag-0.9.0/src/pkmrag/eval/harness.py +145 -0
  106. pkmrag-0.9.0/src/pkmrag/eval/metrics.py +104 -0
  107. pkmrag-0.9.0/src/pkmrag/eval/models.py +62 -0
  108. pkmrag-0.9.0/src/pkmrag/eval/views.py +124 -0
  109. pkmrag-0.9.0/src/pkmrag/graph/__init__.py +6 -0
  110. pkmrag-0.9.0/src/pkmrag/graph/paths.py +199 -0
  111. pkmrag-0.9.0/src/pkmrag/graph/schema.py +64 -0
  112. pkmrag-0.9.0/src/pkmrag/graph/store.py +290 -0
  113. pkmrag-0.9.0/src/pkmrag/graph/traversal.py +191 -0
  114. pkmrag-0.9.0/src/pkmrag/inference/__init__.py +21 -0
  115. pkmrag-0.9.0/src/pkmrag/inference/base.py +69 -0
  116. pkmrag-0.9.0/src/pkmrag/inference/factory.py +51 -0
  117. pkmrag-0.9.0/src/pkmrag/inference/limiter.py +134 -0
  118. pkmrag-0.9.0/src/pkmrag/inference/mock.py +45 -0
  119. pkmrag-0.9.0/src/pkmrag/inference/ollama.py +37 -0
  120. pkmrag-0.9.0/src/pkmrag/inference/provider.py +259 -0
  121. pkmrag-0.9.0/src/pkmrag/ingest/__init__.py +8 -0
  122. pkmrag-0.9.0/src/pkmrag/ingest/pipeline.py +228 -0
  123. pkmrag-0.9.0/src/pkmrag/ingest/reindexer.py +258 -0
  124. pkmrag-0.9.0/src/pkmrag/mcp/__init__.py +8 -0
  125. pkmrag-0.9.0/src/pkmrag/mcp/auth.py +92 -0
  126. pkmrag-0.9.0/src/pkmrag/mcp/events.py +47 -0
  127. pkmrag-0.9.0/src/pkmrag/mcp/http_ops.py +255 -0
  128. pkmrag-0.9.0/src/pkmrag/mcp/http_server.py +273 -0
  129. pkmrag-0.9.0/src/pkmrag/mcp/server.py +213 -0
  130. pkmrag-0.9.0/src/pkmrag/mcp/server_state.py +143 -0
  131. pkmrag-0.9.0/src/pkmrag/mcp/tools.py +271 -0
  132. pkmrag-0.9.0/src/pkmrag/mcp/tools_sync.py +92 -0
  133. pkmrag-0.9.0/src/pkmrag/mcp/tools_vault.py +213 -0
  134. pkmrag-0.9.0/src/pkmrag/mcp/views.py +99 -0
  135. pkmrag-0.9.0/src/pkmrag/models.py +255 -0
  136. pkmrag-0.9.0/src/pkmrag/parser/__init__.py +19 -0
  137. pkmrag-0.9.0/src/pkmrag/parser/indexer.py +132 -0
  138. pkmrag-0.9.0/src/pkmrag/parser/markdown.py +227 -0
  139. pkmrag-0.9.0/src/pkmrag/plugin.py +233 -0
  140. pkmrag-0.9.0/src/pkmrag/plugin_assets/icon.svg +8 -0
  141. pkmrag-0.9.0/src/pkmrag/plugin_assets/main.js +1752 -0
  142. pkmrag-0.9.0/src/pkmrag/plugin_assets/manifest.json +11 -0
  143. pkmrag-0.9.0/src/pkmrag/plugin_assets/styles.css +201 -0
  144. pkmrag-0.9.0/src/pkmrag/search/__init__.py +21 -0
  145. pkmrag-0.9.0/src/pkmrag/search/chunker.py +236 -0
  146. pkmrag-0.9.0/src/pkmrag/search/embedder.py +80 -0
  147. pkmrag-0.9.0/src/pkmrag/search/fusion.py +135 -0
  148. pkmrag-0.9.0/src/pkmrag/search/service.py +188 -0
  149. pkmrag-0.9.0/src/pkmrag/search/vector_store.py +146 -0
  150. pkmrag-0.9.0/src/pkmrag/telemetry/__init__.py +28 -0
  151. pkmrag-0.9.0/src/pkmrag/telemetry/collector.py +75 -0
  152. pkmrag-0.9.0/src/pkmrag/telemetry/spans.py +105 -0
  153. pkmrag-0.9.0/src/pkmrag/telemetry/tracer.py +101 -0
  154. pkmrag-0.9.0/src/pkmrag/telemetry/views.py +102 -0
  155. pkmrag-0.9.0/src/pkmrag/vault_config.py +120 -0
  156. pkmrag-0.9.0/tests/conftest.py +43 -0
  157. pkmrag-0.9.0/tests/test_benchmark.py +56 -0
  158. pkmrag-0.9.0/tests/test_benchmark_obsidian_help.py +102 -0
  159. pkmrag-0.9.0/tests/test_cache.py +188 -0
  160. pkmrag-0.9.0/tests/test_chunker.py +92 -0
  161. pkmrag-0.9.0/tests/test_cli.py +93 -0
  162. pkmrag-0.9.0/tests/test_cli_discover.py +130 -0
  163. pkmrag-0.9.0/tests/test_dialects.py +180 -0
  164. pkmrag-0.9.0/tests/test_discovery.py +173 -0
  165. pkmrag-0.9.0/tests/test_doctor.py +102 -0
  166. pkmrag-0.9.0/tests/test_embedder.py +37 -0
  167. pkmrag-0.9.0/tests/test_eval_cli.py +109 -0
  168. pkmrag-0.9.0/tests/test_eval_metrics.py +167 -0
  169. pkmrag-0.9.0/tests/test_fusion.py +72 -0
  170. pkmrag-0.9.0/tests/test_graph_paths.py +118 -0
  171. pkmrag-0.9.0/tests/test_graph_scoping.py +77 -0
  172. pkmrag-0.9.0/tests/test_http_ops.py +105 -0
  173. pkmrag-0.9.0/tests/test_inference.py +224 -0
  174. pkmrag-0.9.0/tests/test_inference_telemetry.py +114 -0
  175. pkmrag-0.9.0/tests/test_inference_validation_retry.py +106 -0
  176. pkmrag-0.9.0/tests/test_ingest.py +255 -0
  177. pkmrag-0.9.0/tests/test_mcp_auth.py +88 -0
  178. pkmrag-0.9.0/tests/test_mcp_http.py +166 -0
  179. pkmrag-0.9.0/tests/test_mcp_server.py +122 -0
  180. pkmrag-0.9.0/tests/test_mcp_sync.py +85 -0
  181. pkmrag-0.9.0/tests/test_mcp_tools.py +265 -0
  182. pkmrag-0.9.0/tests/test_ollama.py +63 -0
  183. pkmrag-0.9.0/tests/test_plugin.py +164 -0
  184. pkmrag-0.9.0/tests/test_reindexer.py +219 -0
  185. pkmrag-0.9.0/tests/test_search.py +124 -0
  186. pkmrag-0.9.0/tests/test_search_tracing.py +97 -0
  187. pkmrag-0.9.0/tests/test_server_state.py +54 -0
  188. pkmrag-0.9.0/tests/test_telemetry.py +161 -0
  189. pkmrag-0.9.0/tests/test_trace_cli.py +78 -0
  190. pkmrag-0.9.0/tests/test_vault_config.py +69 -0
  191. pkmrag-0.9.0/tests/test_vector_store.py +64 -0
  192. pkmrag-0.9.0/uv.lock +2288 -0
@@ -0,0 +1,52 @@
1
+ # ==============================================================================
2
+ # PKMRAG — Environment Configuration
3
+ # Copy this file to .env and adjust variables as needed:
4
+ # cp .env.example .env
5
+ # ==============================================================================
6
+
7
+ # LLM Inference (Phase 4 Semantic Gap Detection)
8
+ # ------------------------------------------------------------------------------
9
+ # API key for the inference provider (Groq, OpenAI, OpenRouter, etc.)
10
+ OPENAI_API_KEY=your-api-key-here
11
+
12
+ # Alternatively, set a PKMRAG-specific API key override (ORBIT_LLM_API_KEY also supported)
13
+ # PKMRAG_LLM_API_KEY=your-pkmrag-api-key
14
+
15
+ # OpenAI-compatible API base URL
16
+ # Defaults to OpenAI's public API: https://api.openai.com/v1
17
+ # For Groq: https://api.groq.com/openai/v1
18
+ # For local Ollama: http://localhost:11434/v1
19
+ # For local vLLM / LiteLLM: http://localhost:8000/v1
20
+ # For OpenRouter: https://openrouter.ai/api/v1
21
+ OPENAI_BASE_URL=https://api.openai.com/v1
22
+
23
+ # Model identifier to use for classification
24
+ # Defaults to gpt-4o-mini
25
+ # Groq examples: llama-3.1-8b-instant, llama-3.3-70b-versatile
26
+ # Local examples: llama3.1, mistral-nemo, qwen2.5:7b
27
+ PKMRAG_LLM_MODEL=gpt-4o-mini
28
+
29
+ # LLM Rate Limiting
30
+ # ------------------------------------------------------------------------------
31
+ # Maximum requests per minute (RPM) to LLM provider (0 for unlimited)
32
+ # Default: 30
33
+ PKMRAG_LLM_RPM=30
34
+
35
+ # Maximum tokens per minute (TPM) to LLM provider (0 for unlimited)
36
+ # Default: 8000
37
+ PKMRAG_LLM_TPM=8000
38
+
39
+ # Maximum retries on HTTP 429 rate limit errors
40
+ # PKMRAG_LLM_MAX_RETRIES=3
41
+
42
+ # Storage & Directory Overrides (Optional)
43
+ # ------------------------------------------------------------------------------
44
+ # Default path to your Obsidian vault (used by `pkmrag install-plugin` and testing)
45
+ # PKMRAG_VAULT_PATH=/path/to/your/vault
46
+
47
+ # Default LadybugDB storage directory (defaults to <vault>/.pkmrag/graph)
48
+ # PKMRAG_DB_DIR=/custom/path/to/graph
49
+
50
+ # Default LanceDB vector storage directory (defaults to <vault>/.pkmrag/vectors)
51
+ # PKMRAG_VECTOR_DIR=/custom/path/to/vectors
52
+
@@ -0,0 +1,44 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: astral-sh/setup-uv@v5
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: "3.12"
18
+ - run: uv sync --extra dev
19
+ - run: uv run pytest --cov=pkmrag --cov-report=term-missing
20
+ - name: Run retrieval evaluation quality gates
21
+ run: uv run pkmrag eval --min-mrr 0.80 --min-recall 0.80
22
+
23
+ lint:
24
+ runs-on: ubuntu-latest
25
+ steps:
26
+ - uses: actions/checkout@v4
27
+ - uses: astral-sh/setup-uv@v5
28
+ - uses: actions/setup-python@v5
29
+ with:
30
+ python-version: "3.12"
31
+ - run: uv sync --extra dev
32
+ - run: uv run ruff check .
33
+ - run: uv run ruff format --check .
34
+
35
+ typecheck:
36
+ runs-on: ubuntu-latest
37
+ steps:
38
+ - uses: actions/checkout@v4
39
+ - uses: astral-sh/setup-uv@v5
40
+ - uses: actions/setup-python@v5
41
+ with:
42
+ python-version: "3.12"
43
+ - run: uv sync --extra dev
44
+ - run: uv run mypy src tests
@@ -0,0 +1,67 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ share/python-wheels/
20
+ *.egg-info/
21
+ .installed.cfg
22
+ *.egg
23
+ MANIFEST
24
+
25
+ # Virtual Environments
26
+ .venv/
27
+ env/
28
+ venv/
29
+ ENV/
30
+ env.bak/
31
+ venv.bak/
32
+
33
+ # Testing & Linting
34
+ .pytest_cache/
35
+ .ruff_cache/
36
+ .mypy_cache/
37
+ .coverage
38
+ htmlcov/
39
+
40
+ # Local databases & storage (PKMRAG data)
41
+ *.kuzu/
42
+ *.lance/
43
+ *.db
44
+ *.sqlite
45
+ *.sqlite3
46
+ .pkmrag/
47
+ .orbit/
48
+
49
+ # IDE & OS
50
+ .vscode/
51
+ .idea/
52
+ *.swp
53
+ *.swo
54
+ .DS_Store
55
+
56
+ # Secrets & Environment Variables
57
+ .env
58
+ .env.*
59
+ !.env.example
60
+
61
+ # Scratch files
62
+ scratch/
63
+
64
+ # Node & Obsidian Plugin
65
+ node_modules/
66
+ plugins/obsidian/dist/
67
+
@@ -0,0 +1 @@
1
+ 3.12
pkmrag-0.9.0/AGENTS.md ADDED
@@ -0,0 +1,95 @@
1
+ # AGENTS.md — PKMRAG
2
+
3
+ ## What This Is
4
+
5
+ A local-first Hybrid GraphRAG engine for linked personal knowledge bases (PKMs).
6
+ Obsidian serves as the primary reference dialect, with a pluggable dialect layer for CommonMark, Logseq, Foam, and other linked systems.
7
+ 3-tier architecture: deterministic graph (LadybugDB) → semantic search (LanceDB) → AI gap detection (LLM).
8
+ Exposed as an MCP server — no chat UI.
9
+
10
+ ## Project Layout
11
+
12
+ ```
13
+ src/pkmrag/
14
+ cli.py # Typer CLI entry point
15
+ cli_views.py # Rich terminal display renderers
16
+ config.py # Settings, defaults, env vars
17
+ models.py # Pydantic data models (shared across modules)
18
+ doctor.py # `pkmrag doctor` health checks
19
+ dialects/ # Pluggable markdown dialect parsing (obsidian, commonmark)
20
+ cache/ # SQLite L1 query cache and dependency tracking
21
+ parser/ # Markdown parsing + vault file indexing
22
+ graph/ # LadybugDB graph store, schema DDL, and traversal
23
+ ingest/ # Vault → graph and vector ingestion pipeline & single-note reindexer
24
+ search/ # Chunking, FastEmbed, LanceDB vector store, RRF fusion, service
25
+ inference/ # LLM inference client (OpenAI, Ollama) and token-bucket rate limiter
26
+ discovery/ # Semantic gap discovery and relationship inference engine
27
+ eval/ # Retrieval evaluation harness and IR metrics (MRR, Recall, MAP)
28
+ telemetry/ # OpenTelemetry spans, collector, visual tree, tracer lifecycle
29
+ mcp/ # FastMCP server, tool handlers, and stdio transport
30
+ vault_config.py # Per-vault configuration reader/writer (<vault>/.pkmrag/config.json)
31
+ plugin.py # Obsidian plugin installer & bundler CLI
32
+ plugin_assets/ # Bundled standalone Obsidian plugin assets (manifest, main.js, styles)
33
+
34
+ tests/ # Mirrors src/pkmrag/ structure
35
+ benchmarks/ # Ground-truth evaluation benchmarks (golden_10, vault)
36
+ ```
37
+
38
+
39
+ ## Hard Rules
40
+
41
+ 1. **Max 300 lines per file.** If a file approaches this, split it. No exceptions.
42
+ 2. **No overengineering.** Solve the problem in front of you. Don't add abstractions for hypothetical future needs.
43
+ 3. **Simple > clever.** If a colleague can't understand it in 30 seconds, rewrite it.
44
+ 4. **Prefer focused libraries over hand-rolled code.** If a well-maintained library solves the exact problem, use it — don't rewrite what's already battle-tested. But don't pull in a heavy framework for a single utility; the dependency's weight should be proportional to the value it provides.
45
+ 5. **Type everything.** `mypy --strict` must pass. No `Any` escapes except for third-party lib boundaries.
46
+ 6. **Pydantic for data boundaries.** All structured data crossing module boundaries uses Pydantic models defined in `models.py` (or a module-local `models.py` if domain-specific).
47
+ 7. **Tests are mandatory.** Every new module gets a corresponding `tests/test_<module>.py`. Test behavior, not implementation.
48
+ 8. **Preserve existing comments and docstrings** unless directly contradicted by the change.
49
+ 9. **Keep docs current but minimal.** Update `README.md` and `AGENTS.md` when features or layout change. Don't pad them — if it's obvious from the code, don't document it.
50
+
51
+ ## Style
52
+
53
+ - **Formatter/linter:** `ruff` (line-length 100). Run `uv run ruff check --fix . && uv run ruff format .`
54
+ - **Type checker:** `uv run mypy src/`
55
+ - **Tests:** `uv run pytest`
56
+ - Docstrings: one-line summary in `"""..."""`. Multi-line only when non-obvious.
57
+ - Imports: `from __future__ import annotations` at top of every module.
58
+ - Use `Path` from `pathlib`, never raw string paths for filesystem ops.
59
+
60
+ ## Architecture Decisions (Don't Undo These)
61
+
62
+ - **Embedded DBs only.** LadybugDB + LanceDB + SQLite. No servers, no Docker, no network DBs.
63
+ - **Dialect-agnostic core.** The property graph, vector store, and MCP tools operate on abstract knowledge primitives (Note, Tag, Folder, LINKS_TO). All syntax parsing lives in pluggable `dialects/` (Obsidian, CommonMark, Logseq). Never introduce dialect-specific branching into storage, search, or MCP tools.
64
+ - **Incremental sync.** Ingestion compares file hashes; only changed files are reprocessed.
65
+ - **Inferred edges are separate from ground truth.** AI-discovered relationships go in their own table/label, tagged with confidence + model + timestamp. Never pollute human-curated graph data.
66
+ - **MCP over custom UI.** The primary interface is an MCP server (stdio + SSE), not a chat frontend.
67
+
68
+ ## When Adding New Features
69
+
70
+ 1. Ensure new functionality aligns with the architectural design and existing subsystems.
71
+ 2. Put code in the right subpackage. Create a new one if needed — flat files over deep nesting.
72
+ 3. Add CLI commands in `cli.py` using Typer. Keep handlers thin — delegate to engine modules.
73
+ 4. Wire up tests before marking done.
74
+
75
+ ## Common Commands
76
+
77
+ ```bash
78
+ uv run pkmrag doctor # Sanity check both DBs
79
+ uv run pkmrag ingest <path> # Ingest a vault (all, graph, or vector)
80
+ uv run pkmrag search "query" --near <note># Hybrid search with graph boost
81
+ uv run pkmrag search "query" --trace # Hybrid search with visual execution trace tree
82
+ uv run pkmrag discover <path> # Discover semantic gaps and infer relationships
83
+ uv run pkmrag discover <path> -p ollama # Offline semantic discovery via local Ollama
84
+ uv run pkmrag eval # Automated IR retrieval evaluation against golden benchmark
85
+ uv run pkmrag serve <path> # Start stdio MCP server for Claude/Cursor
86
+ uv run pkmrag serve <path> -t http # Start HTTP/SSE MCP & REST daemon on port 3747
87
+ uv run pkmrag mcp-config <path> # Output MCP JSON client configuration
88
+ uv run pkmrag install-plugin # Install Obsidian companion plugin to vault (via PKMRAG_VAULT_PATH)
89
+ uv run pkmrag install-plugin --symlink # Symlink plugin files for live development
90
+ uv run ruff check --fix . # Lint
91
+
92
+ uv run ruff format . # Format
93
+ uv run mypy src tests # Type check
94
+ uv run pytest # Test
95
+ ```
pkmrag-0.9.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Project Orbit Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
pkmrag-0.9.0/PKG-INFO ADDED
@@ -0,0 +1,290 @@
1
+ Metadata-Version: 2.5
2
+ Name: pkmrag
3
+ Version: 0.9.0
4
+ Summary: Local-first Hybrid GraphRAG retrieval engine and MCP server for linked knowledge bases
5
+ Project-URL: Homepage, https://github.com/pkmrag/pkmrag
6
+ Project-URL: Documentation, https://github.com/pkmrag/pkmrag#readme
7
+ Project-URL: Repository, https://github.com/pkmrag/pkmrag
8
+ Project-URL: Issues, https://github.com/pkmrag/pkmrag/issues
9
+ Author: PKMRAG Contributors
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: graphrag,knowledge-graph,lancedb,mcp,obsidian,pkm,rag,vector-search
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
18
+ Classifier: Topic :: Text Processing :: Markup :: Markdown
19
+ Requires-Python: >=3.12
20
+ Requires-Dist: fastembed>=0.3.0
21
+ Requires-Dist: httpx>=0.27.0
22
+ Requires-Dist: ladybug>=0.20.0
23
+ Requires-Dist: lancedb>=0.38.0
24
+ Requires-Dist: mcp>=1.2.0
25
+ Requires-Dist: opentelemetry-api>=1.25.0
26
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.25.0
27
+ Requires-Dist: opentelemetry-sdk>=1.25.0
28
+ Requires-Dist: pyarrow>=17.0.0
29
+ Requires-Dist: pydantic-settings>=2.15.0
30
+ Requires-Dist: pydantic>=2.8.0
31
+ Requires-Dist: python-dotenv>=1.2.3
32
+ Requires-Dist: pyyaml>=6.0.0
33
+ Requires-Dist: rich>=13.0.0
34
+ Requires-Dist: typer>=0.12.0
35
+ Provides-Extra: dev
36
+ Requires-Dist: mypy>=1.10.0; extra == 'dev'
37
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
38
+ Requires-Dist: pytest-xdist>=3.8.0; extra == 'dev'
39
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
40
+ Requires-Dist: ruff>=0.5.0; extra == 'dev'
41
+ Requires-Dist: types-pyyaml>=6.0.0; extra == 'dev'
42
+ Description-Content-Type: text/markdown
43
+
44
+ <p align="center">
45
+ <picture>
46
+ <source media="(prefers-color-scheme: dark)" srcset="assets/pkmrag-logo-text-dark.svg">
47
+ <img alt="PKMRAG" src="assets/pkmrag-logo-text.svg" width="520">
48
+ </picture>
49
+ </p>
50
+
51
+ <p align="center">
52
+ <strong>Embedded, Local-First Hybrid GraphRAG Retrieval Engine & MCP Server</strong>
53
+ </p>
54
+
55
+ <p align="center">
56
+ <a href="https://github.com/dev-hashemi/project-orbit/actions"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/dev-hashemi/project-orbit/ci.yml?branch=main&style=flat&label=CI&logo=githubactions&logoColor=white"></a>
57
+ <a href="https://github.com/dev-hashemi/project-orbit"><img alt="Coverage" src="https://img.shields.io/badge/coverage-89%25-brightgreen?style=flat&logo=pytest"></a>
58
+ <a href="https://www.python.org/downloads/"><img alt="Python" src="https://img.shields.io/badge/python-%3E%3D3.12-3776AB?style=flat&logo=python&logoColor=white"></a>
59
+ <a href="https://github.com/dev-hashemi/project-orbit/releases"><img alt="Version" src="https://img.shields.io/github/v/tag/dev-hashemi/project-orbit?style=flat&label=version&logo=github&logoColor=white"></a>
60
+ <a href="LICENSE"><img alt="License" src="https://img.shields.io/badge/license-MIT-green?style=flat&logo=opensourceinitiative&logoColor=white"></a>
61
+ <a href="http://mypy-lang.org/"><img alt="Mypy" src="https://img.shields.io/badge/types-mypy_strict-2A6DB5?style=flat&logo=python&logoColor=white"></a>
62
+ </p>
63
+
64
+ PKMRAG is an open-source, local-first retrieval engine designed for linked personal knowledge bases (PKMs). While Obsidian serves as our primary reference dialect, PKMRAG operates on an abstract knowledge model supporting any linked document system (Logseq, Foam, CommonMark docs) via pluggable dialects. It combines an explicit structural property graph with an Arrow-backed vector and keyword search index, exposing contextual intelligence to frontier AI reasoning tools via the Model Context Protocol (MCP).
65
+
66
+ 📖 **Technical Documentation:** [System Architecture & Subsystems](docs/architecture.md)
67
+
68
+ ---
69
+
70
+ ## 🏛️ Architecture Overview
71
+
72
+ PKMRAG replaces brute-force triple extraction with a targeted, 3-tier discovery pipeline:
73
+
74
+ ```mermaid
75
+ %%{init: {'theme': 'dark', 'themeVariables': { 'darkMode': true, 'background': 'transparent', 'mainBkg': '#1e293b', 'primaryColor': '#1e293b', 'primaryBorderColor': '#3b82f6', 'primaryTextColor': '#f8fafc', 'lineColor': '#38bdf8', 'edgeLabelBackground': '#1e293b' }}}%%
76
+ flowchart TD
77
+ Vault["📂 Linked Knowledge Base<br/><i>Obsidian, Logseq, CommonMark</i>"]
78
+
79
+ Vault --> T1["🏗️ Tier 1: Deterministic Parser ($0 Cost)"]
80
+ T1 --> BaseGraph[("LadybugDB Property Graph<br/><i>Wikilinks, Tags, Hierarchy</i>")]
81
+
82
+ Vault --> T2["🔍 Tier 2: Hybrid Semantic Index"]
83
+ T2 --> Lance[("LanceDB Vector & FTS Index<br/><i>Dense Embeddings + BM25</i>")]
84
+
85
+ BaseGraph --> T3["🧠 Tier 3: Semantic Gap Detector"]
86
+ Lance --> T3
87
+ T3 -->|"High vector similarity + graph distance ≥ 3"| Candidates["Unlinked Candidate Note Pairs"]
88
+ Candidates -->|"Targeted LLM Inference"| TypedEdges["Typed Relationships<br/><code>[:EXTENDS]</code>, <code>[:CONTRADICTS]</code>, <code>[:PREREQUISITE_FOR]</code>"]
89
+ TypedEdges --> BaseGraph
90
+
91
+ style T1 fill:#0f172a,stroke:#3b82f6,color:#e2e8f0
92
+ style T2 fill:#0f172a,stroke:#8b5cf6,color:#e2e8f0
93
+ style T3 fill:#7c2d12,stroke:#f97316,color:#e2e8f0
94
+ linkStyle default stroke:#38bdf8,stroke-width:2px;
95
+ ```
96
+
97
+ ---
98
+
99
+ ## 🚀 Key Architectural Principles
100
+
101
+ - **Zero-Daemon, Embedded Storage:** Runs entirely in-process using embedded C++ and Apache Arrow engines: **LadybugDB** for property graph traversals, **LanceDB** for hybrid vector/BM25 search, and **SQLite WAL** for sub-0.5ms L1 query caching. No Docker, no network databases.
102
+ - **Dialect-Agnostic Core:** Storage, retrieval, and MCP tools operate on abstract knowledge primitives (`Note`, `Tag`, `Folder`, `LINKS_TO`). Syntax parsing is completely encapsulated in pluggable dialects.
103
+ - **Model Context Protocol (MCP):** Serves as a high-precision retrieval data plane for AI agents (**Claude Code**, **Cursor**, **OpenCode**) without exposing raw filesystem mutation risks.
104
+ - **Scientific Quality Gating:** Retrieval accuracy is benchmarked with zero-cost IR metrics (MRR, Context Recall@5) guarding against semantic regressions.
105
+
106
+ ---
107
+
108
+ ## 🛠️ Quickstart
109
+
110
+ ### 1. Installation
111
+ Install PKMRAG into an isolated global environment using `pipx` or `uv tool`:
112
+ ```bash
113
+ # Recommended for end users
114
+ pipx install pkmrag
115
+ # or
116
+ uv tool install pkmrag
117
+ ```
118
+
119
+ For local development or cloning from source:
120
+ ```bash
121
+ git clone https://github.com/dev-hashemi/project-orbit.git pkmrag
122
+ cd pkmrag
123
+ uv sync
124
+ ```
125
+
126
+ ### 2. Verify Storage & Engine Health
127
+ ```bash
128
+ pkmrag doctor
129
+ ```
130
+ ```text
131
+ ╭─────────────────────────────────────────────╮
132
+ │ PKMRAG v0.9.0 — System Health & Diagnostics │
133
+ ╰─────────────────────────────────────────────╯
134
+ In-Process Data Plane Verification
135
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓
136
+ ┃ Component ┃ Status ┃ Version ┃ Latency ┃ Verification Details ┃
137
+ ┡━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━┩
138
+ │ LadybugDB Property │ PASS │ 0.20.4 │ 0.3ms │ Cypher transactional │
139
+ │ Graph │ │ │ │ read/write verified │
140
+ │ LanceDB Vector Engine │ PASS │ 0.38.0 │ 6.3ms │ Arrow-backed vector │
141
+ │ │ │ │ │ index verified │
142
+ │ Ollama Local Engine │ PASS │ active │ 1.2ms │ Local daemon detected │
143
+ └────────────────────────┴─────────┴─────────┴─────────┴───────────────────────┘
144
+ All systems operational. Engines ready for PKMRAG.
145
+ ```
146
+
147
+ ### 3. Ingest and Search in 30 Seconds
148
+ ```bash
149
+ pkmrag ingest /path/to/vault
150
+ pkmrag search "how does cache invalidation work?" --near "Cache Architecture.md"
151
+ ```
152
+
153
+ ---
154
+
155
+ ## 🔍 Core Capabilities
156
+
157
+ ### Ingestion & Incremental Synchronization
158
+ Ingest notes, links, tags, and semantic vectors with SHA-256 delta sync:
159
+ ```bash
160
+ pkmrag ingest /path/to/vault # Ingest graph topology + semantic vectors
161
+ pkmrag ingest /path/to/vault --target vector # Target specific plane (all, graph, or vector)
162
+ pkmrag ingest /path/to/docs --dialect commonmark # Explicitly select markdown dialect
163
+ pkmrag ingest /path/to/vault --rebuild # Force a clean rebuild
164
+ ```
165
+
166
+ ### Hybrid & Graph-Boosted Retrieval
167
+ Combines dense semantic similarity (`BAAI/bge-small-en-v1.5`), Tantivy BM25 keyword matching, Reciprocal Rank Fusion ($k=60$), and graph proximity multipliers:
168
+ ```bash
169
+ pkmrag search "distributed consensus" # Hybrid search (dense + BM25 via RRF)
170
+ pkmrag search "consensus" --near "Paxos Algorithm.md" # Boosted by graph proximity to anchor note
171
+ pkmrag search "raft" --mode dense --limit 5 # Explicit retrieval mode (hybrid, dense, sparse)
172
+ pkmrag search "storage" --json # Machine-readable JSON output
173
+ ```
174
+
175
+ ### 🧠 Semantic Gap Discovery & Inferred Relationships
176
+ Detects unlinked note pairs with high semantic similarity ($\ge 0.80$) but graph distance $\ge 3$, classifying missing edges via local or remote LLMs:
177
+ ```bash
178
+ pkmrag discover /path/to/vault --dry-run # Preview semantic gaps without calling LLM
179
+ pkmrag discover /path/to/vault --provider ollama # 100% offline local inference (Llama 3.2, Qwen 2.5)
180
+ pkmrag discover /path/to/vault --threshold 0.85 # Custom cosine similarity threshold
181
+ ```
182
+ Inferred edges are stored separately in the LadybugDB `[:INFERRED_REL]` table with confidence, model name, and rationale—preserving human-curated wikilinks.
183
+
184
+ ---
185
+
186
+ ## 🔌 Model Context Protocol (MCP) & HTTP Server
187
+
188
+ PKMRAG exposes a rich tool plane over **stdio** (for CLI/IDE agents) and **HTTP/SSE** (for Obsidian and network clients):
189
+
190
+ ```bash
191
+ # Start stdio MCP server (Claude Code, Cursor, OpenCode)
192
+ pkmrag serve /path/to/vault
193
+
194
+ # Start HTTP/SSE daemon on port 3747 (dual MCP SSE + REST API plane)
195
+ pkmrag serve /path/to/vault --transport http --port 3747
196
+
197
+ # One-command registration for Claude Code:
198
+ claude mcp add pkmrag -- uv run pkmrag serve /path/to/vault
199
+ ```
200
+
201
+ ### Exposed Tools
202
+ - `query_vault`: Hybrid semantic + BM25 keyword retrieval with graph boost and folder/tag filters.
203
+ - `read_note`: Read note content enriched with graph context (tags, forward links, backlinks).
204
+ - `list_notes`: Browse notes in the vault with optional folder filtering and pattern matching.
205
+ - `list_tags` / `search_by_tag`: Rank and query notes by tag topology.
206
+ - `get_outline`: Extract heading hierarchy and line numbers for large notes.
207
+ - `get_note_context`: Inspect incoming backlinks, outgoing citations, 2-hop clusters, and AI-inferred relationships.
208
+ - `find_bridges`: Discover the shortest link path between two notes across the vault.
209
+ - `discover_gaps`: Uncover unlinked note pairs with high vector similarity for bridging.
210
+ - `vault_overview`: Bird's-eye view of vault notes, wikilinks, tags, and central hub notes.
211
+ - `reindex_note`: Targeted sub-40ms single-note incremental reindexing after external edits.
212
+ - `sync_vault`: Incremental delta scan updating modified notes across the vault.
213
+
214
+ ---
215
+
216
+ ## 💎 Obsidian Desktop Plugin (`pkmrag`)
217
+
218
+ A native desktop companion plugin (`plugins/obsidian/`) connecting Obsidian to PKMRAG:
219
+ - **Interactive Setup Wizard:** If installed before the Python core engine, the sidebar automatically guides you through a 2-step setup with 1-click command copying and live verification.
220
+ - **Orbit Insights Sidebar:** Real-time semantic gap recommendations, contradiction warnings with LLM citations, and structural graph context.
221
+ - **Zero-Terminal Workflow & Auto-Daemon:** Transparently starts the background engine daemon on launch and shuts down cleanly on exit.
222
+ - **In-App AI Discovery & Indexing:** Trigger deep AI relationship discovery (`⚡ Discover`) and full vault rebuilds directly from Obsidian without opening a shell.
223
+ - **Settings-Driven LLM & Embedding Models:** Swap between Ollama, OpenAI, Groq, or local endpoints and customize models with 1-click latency verification directly inside Obsidian Settings.
224
+ - **CodeMirror 6 Inline Indicators:** Ambient visual widgets on headings (`🔗 N`, `⚠️`) without document clutter; clicking reveals the sidebar panel.
225
+ - **Proximity Concept Explorer:** Context-anchored hybrid retrieval drawer (`--near <note>`) directly within the editor with 1-click reference insertion.
226
+ - **Knowledge Governance:** Persistent negative feedback cache preventing dismissed links from recurring; transparent restoration drawer and global reset.
227
+ - **Zero-Config Token Security:** Automatically discovers `.pkmrag/server_token` (or legacy `.orbit/server_token`) from active vault.
228
+ - **Live Reactive Updates:** Subscribes to Server-Sent Events (`/api/v1/events`) for background indexing updates.
229
+
230
+ ```bash
231
+ # Install companion plugin into your Obsidian vault:
232
+ pkmrag install-plugin /path/to/vault
233
+
234
+ # Or for plugin developers:
235
+ pkmrag install-plugin /path/to/vault --symlink
236
+ ```
237
+
238
+ See [docs/subsystems/obsidian-plugin.md](docs/subsystems/obsidian-plugin.md) for installation and developer guides.
239
+
240
+
241
+ ---
242
+
243
+ ## 🎯 Benchmarks & Distributed Tracing
244
+
245
+ ### Information Retrieval Quality Gates
246
+ Evaluated against the in-repo Golden 10 ground truth benchmark dataset (`benchmarks/golden_10.json`):
247
+ - **MRR (Mean Reciprocal Rank):** `0.950` (Target $\ge 0.80$, PASS)
248
+ - **Context Recall@5:** `0.950` (Target $\ge 0.80$, PASS)
249
+ - **Hits@1:** `90.0%` | **Hits@3:** `100.0%` | **Hits@5:** `100.0%`
250
+ - **Mean Average Precision (MAP@5):** `0.925`
251
+
252
+ ```bash
253
+ pkmrag eval --min-mrr 0.85 --min-recall 0.80 # CI regression gate
254
+ ```
255
+
256
+ ### OpenTelemetry Distributed Tracing
257
+ Inspect execution timelines and token consumption in real time with in-memory OpenTelemetry spans:
258
+ ```bash
259
+ pkmrag search "storage" --near "LadybugDB.md" --trace
260
+ ```
261
+ ```text
262
+ ╭───────── Trace ID: 66d44d13f5b480b5... ─────────╮
263
+ │ 🛰️ Trace: pkmrag.search 18.42ms (HIT, hybrid) │
264
+ │ ├── cache.lookup 0.15ms (HIT) │
265
+ │ ├── lancedb.search 8.12ms │
266
+ │ ├── ladybug.hops 4.20ms (dist: 1) │
267
+ │ └── rrf.fuse 0.18ms │
268
+ ╰─────────────────────────────────────────────────╯
269
+ ```
270
+ - **Zero Daemons Required:** Spans are collected in-memory and rendered locally.
271
+ - **LLM Token Auditing:** Tracks prompt and completion tokens per inference call.
272
+ - **Remote OTLP Exporter:** Optional live trace streaming to Langfuse, Jaeger, or Datadog via `.env`.
273
+
274
+ ---
275
+
276
+ ## 🧪 Development & Quality Gates
277
+
278
+ ```bash
279
+ # Unit & integration tests + Golden 10 benchmark
280
+ uv run pytest
281
+
282
+ # Strict type checking
283
+ uv run mypy src tests
284
+
285
+ # Linting & code formatting
286
+ uv run ruff check . && uv run ruff format --check .
287
+
288
+ # Retrieval evaluation against benchmark
289
+ uv run pkmrag eval
290
+ ```