Skip to content
edgesync Artifact [6e6874b0dc]
Login

Artifact [6e6874b0dc]

Artifact 6e6874b0dc6cf4c7bec1cab75511e8855fc6a704b304fe502199d5498e91ed9d:


EdgeSync

Fossil sync engine — replace Fossil's HTTP sync with NATS messaging or direct peer-to-peer. Leaf agents act as both sync clients and servers.

See MEMORY.md for detailed project history, patterns, and decisions across sessions.

See docs/architecture/ for condensed architectural decision records (ARDs):

Architecture

Local-Only Directories

fossil/ and libfossil/ are upstream C reference checkouts, gitignored (local-only). They exist on disk for porting reference but are NOT tracked in git.

Build & Test

make build              # Build edgesync, leaf, bridge binaries into bin/
make test               # Run CI-level tests + sim serve tests (~15s)
make setup-hooks        # Install pre-commit hook (~8s before each commit)
go build -buildvcs=false ./cmd/edgesync/   # Dual VCS needs -buildvcs=false

CI: GitHub Actions (.github/workflows/ci.yml) runs on push to main and PRs. Steps: go vet, unit tests (leaf + bridge in parallel), CLI build, CLI tests. Uses GOWORK=off. All Go deps are public — no private-module auth needed.

Go Modules (go.work)

Four modules in a workspace:

For local libfossil development, copy go.work.example to go.work and clone libfossil at ../libfossil.

Important: libfossil hides all implementation packages under internal/. EdgeSync imports only the root package handle API (libfossil.Repo, libfossil.Transport, etc.), plus db/, simio/, and testutil/ which remain public.

Project Structure

Entry Points

Core Library: libfossil (external: github.com/danmestas/libfossil v0.1.x)

libfossil exposes an opaque Repo handle — all operations are methods on it. Implementation packages (blob, content, manifest, sync, xfer, etc.) are under internal/ and not importable.

Public API surface:

Symbol Purpose
libfossil.Create(), Open(), Clone() Repo constructors
r.Commit(), r.Timeline(), r.ListFiles() Checkout operations
r.Sync(), r.HandleSync(), r.XferHandler() Client + server sync
r.CreateCheckout(), r.OpenCheckout() Working directory management
r.Tag(), r.UVWrite/Read/List() Tags, unversioned files
r.CreateUser(), r.ListUsers(), r.Config() Admin
libfossil.Transport Interface — RoundTrip(ctx, []byte) ([]byte, error)
libfossil.SyncObserver, CheckoutObserver Telemetry hooks
libfossil.NewHTTPTransport() Built-in HTTP transport
libfossil.NopSyncObserver(), StdoutSyncObserver() Built-in observers

Public packages (still importable):

EdgeSync-specific commands (not in libfossil):

Agent/Bridge

Notify Messaging

Simulation Testing

Observability (OpenTelemetry)

The leaf agent and sim tests emit traces, metrics, and logs via OpenTelemetry. Telemetry is optional — everything builds and runs without it. When OTEL_EXPORTER_OTLP_ENDPOINT is unset, the OTel observer is nil and the nopObserver (zero-cost) is used.

Secrets via Doppler

OTel export secrets (Honeycomb API key) are managed by Doppler. No .env files in the repo.

# First time per device:
brew install doppler
doppler login
doppler setup          # links this directory to edgesync/dev

# Run with telemetry:
doppler run -- go test ./sim/ -run TestSimulation -v
doppler run -- make sim-full

# Run WITHOUT telemetry (no Doppler needed):
go test ./sim/ -run TestSimulation -v     # works fine, just no OTel export
make test                                  # CI tests never need Doppler

Observer Pattern

libfossil.SyncObserver and libfossil.CheckoutObserver interfaces — lifecycle hooks for sync sessions, rounds, errors, server-side handling, and checkout operations. leaf/telemetry/observer.go implements them with OTel spans and metrics. libfossil's root package has no OTel dependency — the optional observer/otel/ sub-module provides an OTel implementation with its own go.mod.

Honeycomb Dashboard

Deployment (Hetzner VPS)

Docker Compose stack in deploy/. Two containers: NATS + leaf agent.

# On VPS (203.0.113.1):
cd ~/EdgeSync/deploy && sudo docker compose up -d --build

# Update:
cd ~/EdgeSync && git pull && cd deploy && sudo docker compose up -d --build
Endpoint URL Access
Public HTTPS https://sync.example.com Cloudflare Tunnel
Tailscale HTTP http://100.64.0.1:9000 Tailnet only
Tailscale NATS nats://100.64.0.1:4222 Tailnet only

Key Conventions

Fossil Sync Protocol

Fossil Repo Schema (core tables)

Agent skills

Issue tracker

Issues live as GitHub issues on danmestas/EdgeSync (use the gh CLI). See docs/agents/issue-tracker.md.

Triage labels

Canonical label vocabulary — needs-triage, needs-info, ready-for-agent, ready-for-human, wontfix — plus bug/enhancement. See docs/agents/triage-labels.md.

Domain docs

Single-context layout. ADRs live in docs/architecture/ (not docs/adr/); no CONTEXT.md — fall back to CLAUDE.md + MEMORY.md. See docs/agents/domain.md.

<!-- gitnexus:start -->

GitNexus — Code Intelligence

This project is indexed by GitNexus. Tools (query, context, impact, rename, detect_changes, cypher) are available via MCP. A PreToolUse hook on git commit automatically runs blast-radius analysis on staged changes — no manual steps needed. <!-- gitnexus:end -->