-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpyproject.toml
More file actions
231 lines (213 loc) · 8.43 KB
/
pyproject.toml
File metadata and controls
231 lines (213 loc) · 8.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
[build-system]
requires = ["setuptools>=61", "wheel", "setuptools-scm>=8"]
build-backend = "setuptools.build_meta"
[project]
# PyPI distribution name. The Python import path is still ``kairix``
# (source layout under kairix/, console script entry remains ``kairix``).
# The dist name here matches the trusted-publisher record on PyPI;
# the short ``kairix`` slot was already reserved by another account
# with no releases, so we publish under the long-form name and users
# can still ``import kairix`` after install.
#
# IMPORTANT: this rename was previously made in v2026.5.10.1 and got
# reverted by the squash merge of #176 (squash merges from develop
# don't preserve commit-level history; develop's pyproject hadn't
# been re-synced after v2026.5.10.1 landed on main). #170 tracks
# automating the post-squash sync; until that lands, double-check
# this line after every release.
name = "Kairix-agentic-knowledge-mgt"
dynamic = ["version"]
description = "Self-contained knowledge retrieval engine — hybrid search, entity graph, temporal reasoning, session briefing"
readme = "README.md"
license = { text = "Apache-2.0" }
requires-python = ">=3.10"
dependencies = [
"requests>=2.33.1,<3",
"httpx>=0.27,<1",
"pyyaml>=6.0,<7",
"usearch>=2.8,<3",
"langgraph>=1.0.10,<2",
"lxml>=6.1.0",
"openai>=1.40,<3",
]
[project.optional-dependencies]
agents = [
# MCP server (Model Context Protocol — exposes kairix tools to agents).
# Floor 1.20 ensures streamable-HTTP transport and stateless mode are GA;
# see Sprint 19 plan WS1 (engineering/SPRINT-19-PLAN.md).
"mcp>=1.20,<2",
]
neo4j = [
# Neo4j Python driver — required for entity graph, multi-hop queries, and curator health
"neo4j>=5.0,<7.0",
]
nlp = [
"spacy>=3.7,<4",
]
rerank = [
# Cross-encoder re-ranking (post-RRF semantic pass). CPU-only, ~22 MB model.
"sentence-transformers>=3.0,<4",
]
dev = [
# Test runner
"pytest>=8.0",
"pytest-cov>=7.1.0",
"pytest-timeout>=2.3",
"pytest-bdd>=7.0",
# Type checking (engineering hub: zero errors, strict mode)
"mypy>=1.9",
"types-requests>=2.33.0.20260408",
"types-PyYAML>=6.0",
# Linting (engineering hub: linting blocks merge)
"ruff==0.15.12",
# Security (engineering hub: bandit zero HIGH/MEDIUM, pip-audit zero CVEs with fixes)
"bandit[toml]>=1.7",
"pip-audit>=2.10.0",
# Secret detection
"detect-secrets>=1.4",
]
[project.scripts]
kairix = "kairix.cli:main"
[project.urls]
Homepage = "https://github.com/quanyeomans/kairix"
Issues = "https://github.com/quanyeomans/kairix/issues"
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "--tb=short -q"
# Test markers — engineering hub test pyramid
# Usage: pytest -m contract | unit | integration | e2e
markers = [
"contract: interface agreement tests (fast, <30s total, zero tolerance for failure)",
"unit: individual component logic (mock externals, fast)",
"integration: multi-component with real database and usearch index",
"e2e: full pipeline against live Azure API (requires KAIRIX_E2E=1)",
"bdd: behaviour-driven acceptance tests (pytest-bdd feature files)",
"slow: tests taking >5s",
]
timeout = 60 # Per-test timeout default (seconds)
[tool.coverage.run]
source = ["kairix"]
relative_files = true
omit = [
"tests/*",
# External I/O adapter — Azure API client; uncovered branches are
# error paths only reachable with a live Azure endpoint.
"kairix/_azure.py",
# Neo4j driver wrapper — connection/session paths require a live
# Neo4j instance; the testable surface (FakeNeo4jClient-driven repo
# methods) has its own coverage in kairix.knowledge.graph.repository.
"kairix/knowledge/graph/client.py",
# CLIs without BDD or integration coverage yet — flagged for backfill.
# Each will move out of this list when tests land.
"kairix/knowledge/contradict/cli.py",
"kairix/knowledge/reflib/cli.py",
"kairix/platform/onboard/cli.py",
"kairix/quality/benchmark/cli.py",
# Wikilinks audit reporter — 0% coverage today, no public callers in
# tests; flagged for backfill or removal.
"kairix/knowledge/wikilinks/audit.py",
]
[tool.coverage.report]
# Engineering hub: ≥80% overall; per-module targets in PRD.md §6
fail_under = 80
show_missing = true
exclude_lines = [
"pragma: no cover",
"if TYPE_CHECKING:",
"raise NotImplementedError",
"\\.\\.\\.", # Abstract method stubs
]
# ── mypy ─────────────────────────────────────────────────────────────────────
# Engineering hub: "mypy — zero errors" (Python standard)
[tool.mypy]
python_version = "3.12"
ignore_missing_imports = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
check_untyped_defs = true
no_implicit_optional = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_return_any = true
strict_equality = true
# Modules not yet fully annotated (will be removed as each phase ships)
[[tool.mypy.overrides]]
module = [
"kairix.core.search.*",
"kairix.core.temporal.*",
"kairix.core.classify.*",
"kairix.knowledge.summaries.*",
"kairix.knowledge.contradict.*",
"kairix.agents.briefing.*",
"kairix.quality.benchmark.*",
]
# Modules not yet fully annotated — will be removed phase by phase
ignore_errors = true
# FastMCP decorator is untyped — suppress locally, CI doesn't have fastmcp installed
[[tool.mypy.overrides]]
module = ["kairix.agents.mcp.server"]
disallow_untyped_decorators = false
# ── ruff ─────────────────────────────────────────────────────────────────────
# Engineering hub: "Linting / code quality: blocks merge"
[tool.ruff]
line-length = 120
target-version = "py310"
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"N", # pep8-naming
"UP", # pyupgrade
"B", # flake8-bugbear
"S", # flake8-bandit (security)
"T20", # flake8-print (no print() in prod code)
"RUF", # ruff-specific
]
ignore = [
"S101", # use of assert (test code)
"S608", # SQL injection false positive — all dynamic SQL uses ? parameter binding
"B008", # function call in default arg (used in CLI argument defaults)
"T201", # print found (allowed in CLI modules — cli.py excluded below)
]
[tool.ruff.lint.per-file-ignores]
"tests/*" = ["S", "T20"] # Tests: allow assert + print
"tests/e2e/*" = ["S", "T20", "I001"] # E2E tests: inline imports required for lazy loading
"kairix/**/cli.py" = ["T201", "S108", "S110", "E501"] # CLI modules: allow print for user output
"kairix/cli.py" = ["T201"]
"kairix/_azure.py" = ["S603", "S607"] # Azure CLI subprocess (az keyvault) is intentional
"kairix/platform/onboard/check.py" = ["S607"] # Trusted system binaries (openclaw, systemctl)
"scripts/*" = ["S", "T20", "B007"] # Scripts: allow subprocess, print, unused loop vars
[tool.ruff.lint.isort]
# Match standalone isort profile="black"
known-first-party = ["kairix"]
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
# ── bandit ───────────────────────────────────────────────────────────────────
# Engineering hub: "bandit — zero HIGH/MEDIUM findings"
[tool.bandit]
exclude_dirs = ["tests", ".venv"]
skips = [
"B101", # assert_used — acceptable in test-adjacent code
]
# Any HIGH finding not listed here blocks the build.
[tool.setuptools.packages.find]
where = ["."]
include = ["kairix*"]
# Benchmark gates — kairix benchmark run exits non-zero if any gate fails.
# E2E test gate: set KAIRIX_E2E=1 to enable live Azure API tests.
[tool.kairix.benchmark.gates]
overall = 0.78
temporal = 0.55
entity = 0.80
contextual_prep = 0.60
# ── setuptools-scm — version derived from git tags ─────────────────────────
# No manual version editing. Tagged commits = clean version (2026.4.28).
# Untagged commits = dev version (2026.4.28.dev3 = 3 commits since tag).
# pip install kairix never installs dev versions unless --pre is passed.
[tool.setuptools_scm]
version_scheme = "guess-next-dev"
local_scheme = "no-local-version"
fallback_version = "0.0.0"