Background
The root `pyproject.toml` exists for the unified test runner: `uv run --extra test pytest test/`. Its `[project.optional-dependencies] test` block is the test environment.
But its main `dependencies = [...]` array is a hand-maintained superset of every server + bot dep. Nothing actually installs from the root pyproject at runtime — the Dockerfile does `uv sync --project bot` and `uv sync --project server`. So the duplication serves no purpose and creates a sync burden.
Proposed change
Remove the runtime `dependencies` from the root pyproject and keep only what the test runner needs. server/ and container/bot/ become the single source of truth for runtime deps.
```toml
[project]
name = "woltspace"
requires-python = ">=3.11"
[project.optional-dependencies]
test = ["pytest", "pytest-asyncio"]
```
If the test runner needs to import server/bot code (it does — pytest collection runs against `test/` which imports both services), use uv path deps so the test extra also pulls in the per-service envs:
```toml
[tool.uv.sources]
woltspace-server = { path = "server" }
wolt-bot = { path = "container/bot" }
[project.optional-dependencies]
test = ["pytest", "pytest-asyncio", "woltspace-server", "wolt-bot"]
```
Then `uv lock` at root to produce a root `uv.lock` for reproducibility.
Why this is worth doing
Out of scope
- Restructuring tests themselves
- Changing the documented `uv run --extra test pytest test/` invocation (must still work)
Test plan
Background
The root `pyproject.toml` exists for the unified test runner: `uv run --extra test pytest test/`. Its `[project.optional-dependencies] test` block is the test environment.
But its main `dependencies = [...]` array is a hand-maintained superset of every server + bot dep. Nothing actually installs from the root pyproject at runtime — the Dockerfile does `uv sync --project bot` and `uv sync --project server`. So the duplication serves no purpose and creates a sync burden.
Proposed change
Remove the runtime `dependencies` from the root pyproject and keep only what the test runner needs. server/ and container/bot/ become the single source of truth for runtime deps.
```toml
[project]
name = "woltspace"
requires-python = ">=3.11"
[project.optional-dependencies]
test = ["pytest", "pytest-asyncio"]
```
If the test runner needs to import server/bot code (it does — pytest collection runs against `test/` which imports both services), use uv path deps so the test extra also pulls in the per-service envs:
```toml
[tool.uv.sources]
woltspace-server = { path = "server" }
wolt-bot = { path = "container/bot" }
[project.optional-dependencies]
test = ["pytest", "pytest-asyncio", "woltspace-server", "wolt-bot"]
```
Then `uv lock` at root to produce a root `uv.lock` for reproducibility.
Why this is worth doing
Out of scope
Test plan