Migrate from pip-install-e + setuptools to a uv workspace with a
committed uv.lock for deterministic deps. Switch both members to
hatchling, and move package sources into nested standard layout
(l4d2host/l4d2host/, l4d2web/l4d2web/) so builds work from a
read-only source tree — setuptools wrote egg-info to source under
the old layout, which broke uv sync on the root-owned /opt/left4me/src.
Local dev install: `pip install -e ./l4d2host -e ./l4d2web` -> `uv sync`.
.envrc switches from `layout python python3.13` to `use uv`. Python
pinned to 3.13 via .python-version.
l4d2web now declares its cross-dep on l4d2host explicitly via
[tool.uv.sources] (workspace = true). l4d2web/alembic.ini and
l4d2web/alembic/ stay at the project root (standard alembic layout).
Test fixes:
- tests/__init__.py added to both test dirs so pytest doesn't shadow
l4d2host as a namespace package via outer-dir walk.
- 3 CWD-relative paths in tests (l4d2web/static/css/{tokens,layout}.css
and js/sse.js) anchored to Path(__file__) so they survive layout
changes.
- Two test_install.py tests now monkeypatch HOME to tmp_path so they
stop silently mutating ~/.steam/sdk32 on every run.
628 tests pass under sandboxed `uv run pytest`.
Per docs/superpowers/plans/2026-05-15-uv-workspace-execution.md;
prereq for the ckn-bw bundle's uv-sync action (queued).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
82 lines
3.4 KiB
Markdown
82 lines
3.4 KiB
Markdown
# left4me
|
|
|
|
`left4me` is a local L4D2 server management platform with two planned components:
|
|
|
|
1. `l4d2host` + `l4d2ctl` (host library + CLI)
|
|
2. `l4d2-web-app` (Flask web app for users, blueprints, servers, jobs, and logs)
|
|
|
|
## Status
|
|
|
|
Implementation plans remain the source of truth for architecture and task sequencing:
|
|
|
|
- `docs/superpowers/plans/2026-04-22-l4d2-host-lib-v1.md`
|
|
- `docs/superpowers/plans/2026-04-23-l4d2-web-app-v1.md`
|
|
|
|
## Locked v1 Decisions
|
|
|
|
- Naming is strictly `l4d2` (not `l4d`).
|
|
- Host library and web app are separate components.
|
|
- Host CLI write commands are fixed to:
|
|
- `install`
|
|
- `initialize <name> -f <spec.yaml>`
|
|
- `start <name>`
|
|
- `stop <name>`
|
|
- `delete <name>`
|
|
- Host CLI read commands are available for the web/host boundary:
|
|
- `status <name> --json`
|
|
- `logs <name> --lines <n> --follow/--no-follow`
|
|
- The web app calls host operations through `l4d2ctl`, not direct `l4d2host` imports.
|
|
- Deployment uses `/var/lib/left4me` for runtime state, `/opt/left4me` for repository contents and the virtualenv, `/etc/left4me` for environment files, and global units under `/usr/local/lib/systemd/system`.
|
|
- Overlay handling is directory-based; the web app populates each overlay (workshop downloads, managed-global refresh).
|
|
- No lock manager, no rollback, no preflight checks in host library.
|
|
- CLI propagates subprocess failures via stderr and return code.
|
|
- `delete` on missing instance is no-op success.
|
|
- Blueprint model (web app):
|
|
- user-private in v1
|
|
- servers are live-linked to blueprint
|
|
- no per-server overrides
|
|
- delete blueprint blocked when linked servers exist
|
|
- blueprint changes apply on next action
|
|
- server can reassign blueprint anytime
|
|
|
|
## Planned Repository Layout
|
|
|
|
- `l4d2host/`
|
|
- `l4d2web/`
|
|
- `deploy/`
|
|
- `docs/superpowers/plans/`
|
|
|
|
## Deployment
|
|
|
|
See `deploy/README.md` for the Linux test deployment contract, including the runtime user, target filesystem layout, systemd units, privileged helpers, sudoers rules, admin bootstrap, and overlay reference rules.
|
|
|
|
## Local development
|
|
|
|
This repo is a [uv](https://docs.astral.sh/uv/) workspace (`l4d2host` + `l4d2web` as members) with a committed `uv.lock` and a `.python-version` pinning Python 3.13 (matching the Debian Trixie production target).
|
|
|
|
One-time prereq: install `uv` (macOS: `brew install uv`; Linux: `curl -LsSf https://astral.sh/uv/install.sh | sh` — `uv` is not yet in Debian stable's apt).
|
|
|
|
1. `direnv allow` once per fresh checkout (and after any `.envrc` change). `.envrc` uses `use uv`, which runs `uv sync` and activates `.venv/` on `cd`.
|
|
2. Without direnv: `uv sync` at the repo root creates `.venv/`, installs both workspace members editable, and pulls in dev deps (pytest) from the lockfile.
|
|
3. Tests: `uv run pytest` (or just `pytest` once the venv is on PATH).
|
|
|
|
## Tech Stack (planned)
|
|
|
|
- Python 3.13+ (workspace uses uv + hatchling)
|
|
- Typer, PyYAML, pytest
|
|
- Flask, SQLAlchemy, Alembic
|
|
- HTMX (vendored locally), custom CSS, SSE
|
|
- systemd units, kernel overlayfs (mounted via the `left4me-overlay` privileged helper), steamcmd
|
|
|
|
## Recommended Implementation Order
|
|
|
|
1. Implement `l4d2host` plan first.
|
|
2. Implement `l4d2web` plan second.
|
|
3. Keep tests green task-by-task (TDD flow from plans).
|
|
4. Keep commits small and aligned with plan tasks.
|
|
|
|
## Contributing Notes
|
|
|
|
- Follow plan task order unless explicitly re-planned.
|
|
- Keep contracts above unchanged unless the user asks to change them.
|
|
- Update plan docs when scope or behavior changes.
|