Commit graph

608 commits

Author SHA1 Message Date
Natalie
226fe075a0 feat(@projects): add chat message and task split tables
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-05-18 07:40:45 -07:00
autocommit
63a5636484 refactor(scripts): ♻️ Improve error handling and structure in install.sh for partial installations where uv is not on PATH
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-05-18 07:27:21 -07:00
Natalie
7493a8135a fix(triage): allow priority > 4 since Haiku sometimes returns 5+
The _claude-triage spec says priority is 0-4, but Haiku occasionally
emits higher values (observed in production via apricot pull). Both
TriageRecorded events and the Session.last_triage_priority projection
were rejecting these with pydantic ValidationError; the entire pull
now fails as 500. Relaxing the upper bound on both sides keeps the
spec as documentation but doesn't make Haiku's misbehavior break us.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 06:38:57 -07:00
Natalie
e15bbee6dd fix(pull): dedup session observations by uuid to handle mac-sync'd filesystems 2026-05-18 05:17:42 -07:00
Natalie
87099fd99b feat(pull): multi-host enumeration via rclaude --tsv
Replace local-only _claude-projects --sessions path with
'rclaude list sessions --tsv' (full uuids, separate cwd/mtime
columns) and add 'rclaude triage --tsv' ingestion emitting
TriageRecorded events. Diff against the sessions projection
to skip no-op events for unchanged (host, cwd, mtime) and
(priority, status, summary) tuples.
2026-05-18 03:23:55 -07:00
Natalie
5f316cde24 feat(sync): HMAC-SHA256 auth on /api/v1/sync/*
Adds shared-secret HMAC-SHA256 authentication to peer sync endpoints.
Sync requests now include X-Clare-Timestamp + X-Clare-Signature headers
covering ts/method/path/body. Server validates against local sync_secret
and rejects with 401 on mismatch, missing headers, or >300s skew.

- config.py: new sync_secret field (auto-generated on first run) and
  PeerConfig list (back-compat: plain-string peers still parse)
- sync.py: signs outbound peer + loopback requests; sync_peer takes
  PeerConfig and local_secret
- web/api.py: require_sync_auth dependency on /sync/* routes; /health
  remains unauthenticated; when sync_secret is unset, sync stays open
  for back-compat with fresh installs
- tests: 10 new auth tests cover valid/tampered/expired/missing/no-secret
  paths plus full two-Clare convergence with matched secrets
2026-05-18 03:04:42 -07:00
Natalie
dd3268d8f5 feat(sync): per-source HLC cursor — delta-only sync
Adds /api/v1/sync/cursor returning {machine_id: max_hlc} and
extends /api/v1/sync/events to accept since_per_source={...}.

sync_peer now asks each side for its per-source cursor, then ships
only the delta. In steady state both directions return 0 events.

Why: a single global HLC cursor was wrong for multi-master writes —
A's events with hlc < B's max would be missed. Per-source cursor
asks 'what do I have from each origin' which is precise.

Server still dedupes by event uuid in ingest_remote so over-shipping
remains safe.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 02:29:24 -07:00
Natalie
c1e6f7dbe5 feat: initial Clare scaffold — project manager for the Claude agent fleet
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>
2026-05-18 02:20:23 -07:00