Push A (single-machine): - HLC + event-sourced SQLite (events table is source of truth, projections rebuildable) - Pydantic v2 domain models (Project, Task, Assignment, Session, Group, Update) - rclaude subprocess wrapper (local_sessions via _claude-projects --sessions) - Typer CLI: init, project, task, assign, pull, status, broadcast, serve, sync - FastAPI + Jinja2 + HTMX dashboard - 26 unit tests passing Push B (HTTP API + sync substrate): - /api/v1/* JSON routes (projects, tasks, assignments, sessions, status, broadcast, sync) - CLI refactored as thin httpx client over the API — single business-logic codepath - web/service.py: every business op defined once; HTML routes + API routes both call into it - sync.py: peer-to-peer sync via /api/v1/sync/events with HLC + uuid-based dedup - 32 tests passing including two-Clare convergence test Push C (cross-host deployment): - apricot install via uv (Python 3.12.12) - systemd --user unit for clare-serve on apricot - Cross-host sync demoed plum (10.9.0.3) ↔ apricot (10.9.0.2) over wg - .local → .lan rename for forge URLs Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2.1 KiB
2.1 KiB
Clare — agent rules
This is ~/Code/@projects/@clare/ — Tier 3 (feature platform, consumes packages, does not publish).
Hard rules
- rclaude is the only transport. Never shell out to
tmuxorsshdirectly. Every fleet action goes throughsubprocess.run(["rclaude", ...])viaclare.rclaude. If a feature needs a new transport verb, add it to rclaude first (at~/Code/@scripts/session-tools/bin/rclaude). - Events are the source of truth. Every state change appends to
events. Projection tables (projects,tasks, ...) are read-models; never write to them directly outsideclare.events.apply_event. - Every event carries an HLC. Use
clare.hlc.HLC.tick(machine_id)for new local events;update(remote)on receive (Push B). - Strict types at boundaries. All CLI args, event payloads, and rclaude-output rows are validated by Pydantic v2 models with
strict=True. NoAnyin production code. - No fallbacks / no mocks in production paths. If
rclaudeisn't on PATH, Clare errors at startup with a clear message — it does not silently degrade. - DB-touching functions take
conn. No module-level connection. Tests injectsqlite3.connect(":memory:"). uvis the package manager. Don't addrequirements.txt; modifypyproject.tomland letuvresolve.
Layout
src/clare/
├── hlc.py · clock substrate (load-bearing for future sync)
├── domain.py · Pydantic read-models (Project, Task, ...)
├── events.py · event types + projection updaters
├── db.py · SQLite schema + migrations
├── config.py · TOML loader (machine_id, groups)
├── rclaude.py · subprocess wrapper + TSV parsing
├── scheduler.py · pure task-ranking logic
├── pull.py · triage/sessions refresh → events
├── cli.py · Typer entrypoint
└── web/ · FastAPI + Jinja2 + HTMX
Status
Push A: single-machine. Sync (peer pull/push, /api/sync) is deferred to Push B.
See DESIGN.md for architectural decisions, INFRA.md for storage paths.