-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpyproject.toml
More file actions
108 lines (95 loc) · 4.29 KB
/
Copy pathpyproject.toml
File metadata and controls
108 lines (95 loc) · 4.29 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
# The repo root IS the thin `ultan` package AND the workspace root, so the
# install command is the clean `uv tool install git+https://github.com/nickroci/ultan`
# (no #subdirectory). The heavy retrieval stack lives behind the `retrieval`
# extra; the plugin provisioner (scripts/ensure-ultan.sh) installs
# `ultan[retrieval]` so the hook runtime gets the daemon in the same venv,
# while a plain/uvx install (e.g. the MCP server in .claude-plugin/plugin.json)
# stays small and starts fast.
[project]
name = "ultan"
version = "0.4.5"
description = "Ultan — local markdown memory for Claude Code (thin CLI + hooks + lazy daemon launcher)."
requires-python = ">=3.12"
license = { text = "MIT" }
authors = [{ name = "Nicholas Holden", email = "nicholas.holden@banqora.com" }]
# `mcp` is the MCP protocol SDK for the light MCP server (no ML deps); it is
# lazy-imported only by `ultan mcp`, never on the hook hot path. The hook hot
# path is otherwise stdlib plus `stopwordsiso` — a data-only stopword list
# (no transitive deps, ~27ms import) used by the priming-query low-signal
# gate. Import speed and torch-freedom are guarded by tests/test_hook_import.py.
dependencies = [
"mcp>=1.0",
"stopwordsiso>=0.7.0",
]
[project.optional-dependencies]
# Full hook runtime, installed by scripts/ensure-ultan.sh as
# `ultan[retrieval] @ git+…`. agent-mem-daemon transitively pulls
# agent-mem-search (sentence-transformers / torch / numpy / einops) and puts
# the `agent-mem-daemon` console script in the SAME venv, which is where
# ultan/_daemon.py expects it (Path(sys.executable).with_name(...)).
# agent-mem-tools ships the `advisor` / `remember` modules behind
# `ultan advisor` / `ultan remember` (lazy-imported in ultan/__main__.py).
retrieval = [
"agent-mem-daemon",
"agent-mem-tools",
]
[project.scripts]
ultan = "ultan.__main__:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
# Only the thin CLI package ships in the wheel — not daemon/, src/, tools/.
packages = ["ultan"]
[tool.uv.workspace]
# Root (ultan) is the workspace root + a member; tools/search, daemon, and
# tools/ultan (the slash-command logic) are the other members.
members = ["tools/search", "daemon", "tools/ultan"]
[tool.uv.sources]
agent-mem-daemon = { workspace = true }
agent-mem-tools = { workspace = true }
[dependency-groups]
dev = ["pytest>=8.0", "pyright>=1.1.409", "ruff>=0.15", "pylint>=3.3"]
[tool.pytest.ini_options]
testpaths = ["tests"]
[tool.ruff]
line-length = 100
target-version = "py312"
# This (root) job covers only the `ultan` package + its tests. The workspace
# members — daemon, tools/* — are linted/typed by their own CI jobs, so
# exclude them here to avoid double-coverage and conflicting results. skills/
# ships a standalone stdlib script (a verbatim copy of the author's skill),
# not package code.
extend-exclude = [".venv", "build", "dist", "daemon", "tools", "skills", "stubs"]
[tool.ruff.lint]
select = ["E", "F", "I", "W", "C901", "PLR0912", "PLR0915", "PLC0415"]
[tool.ruff.lint.per-file-ignores]
"tests/**" = ["E501", "C901", "PLR0912", "PLR0915", "PLC0415"]
# Lazy imports are the design here: the hook hot path must never pay for the
# heavy stacks (enforced by tests/test_hook_import.py), so subcommand deps
# import inside their dispatch branches.
"ultan/__main__.py" = ["PLC0415"]
"ultan/_mcp.py" = ["PLC0415"]
[tool.pyright]
# Source only — tests stay at standard mode (excluded), matching the other
# packages. The `ultan` package is the plugin hot path, so strict here matters.
include = ["ultan"]
exclude = [".venv", "**/__pycache__", "build", "dist", "tests", "skills"]
# Signatures for the [retrieval]-extra flat modules (advisor/remember) so the
# lazy call sites in ultan/__main__.py type the same in thin and full envs.
stubPath = "stubs"
venvPath = "."
venv = ".venv"
pythonVersion = "3.12"
typeCheckingMode = "strict"
reportMissingTypeStubs = false
reportMissingImports = "warning"
reportUnusedImport = "error"
reportPrivateUsage = "warning"
[tool.pylint.similarities]
# Copy-paste detection (R0801) — the only pylint check we run; see the
# duplicate-code (ultan) pre-commit hook. Tuned to flag genuine copy-paste while
# tolerating short, naturally-similar blocks (imports, signatures, etc).
min-similarity-lines = 8
ignore-comments = true
ignore-docstrings = true