Artifact ebbdd53404586f74def124a42569c685ec22cd90824ae4d5f061515ad14230fc:
- File
MEMORY.md
— part of check-in
[eda7960b81]
at
2026-04-23 19:23:42
on branch trunk
— rename module to github.com/danmestas/EdgeSync
Fix the case-sensitive module path to match the actual GitHub repo URL (danmestas/EdgeSync). Remove tracked leaf/leaf binary and ignore .claude/skills/ scratchpad dirs. (user: [email protected], size: 4840) [annotate] [blame] [check-ins using] [more...]
# EdgeSync Memory ## Project Structure - Go workspace (`go.work`) with 5 modules: root, `libfossil/`, `leaf/`, `bridge/`, `dst/` - `sim/` is a package in the root module (not its own module) - Dual VCS: git + fossil checkout — use `-buildvcs=false` for all builds - Git repo: github.com/danmestas/EdgeSync (private) - `fossil/` and `libfossil/` are gitignored (local-only reference, purged from history) - `.agents/`, `.claude/skills/`, `skills-lock.json` are gitignored (tool-local) ## Entry Points - `cmd/edgesync/` — Unified CLI (50 subcommands via kong, including `repo clone`) - `leaf/cmd/leaf/` — Standalone leaf agent daemon - `bridge/cmd/bridge/` — Standalone bridge daemon - `sim/cmd/soak/` — Continuous soak test runner ## Server Handler (2026-03-18, PR#8) - **HandleSync** in `sync/handler.go` — server-side xfer card handler. Stateless per-round. - **HandleSyncWithOpts** — same but accepts `HandleOpts{Buggify}` for DST fault injection - **HandleFunc** type — `func(ctx, *repo.Repo, *xfer.Message) (*xfer.Message, error)` - Cards handled: pull→igot, push→accept files, igot→gimme, gimme→file, file→store, clone→paginated files, clone_seqno, reqconfig→config - **ServeHTTP** in `sync/serve_http.go` — HTTP /xfer listener. `fossil clone`/`fossil sync` compatible. - **ServeNATS** in `leaf/agent/serve_nats.go` — NATS request/reply listener - **ServeP2P** in `leaf/agent/serve_p2p.go` — stub for libp2p - Agent config: `ServeHTTPAddr string`, `ServeNATSEnabled bool` - Agent.Start() launches pollLoop + server listeners concurrently - 4 BUGGIFY sites: handleGimme.skip(5%), handleFile.reject(3%), emitIGots.truncate(10%), emitCloneBatch.smallBatch(10%) - TigerStyle: preconditions on all handler methods, sql.ErrNoRows distinction, MaxBytesReader(50MB), decompressBounded(50MB) - **xfer.Decode**: tries raw zlib → 4-byte prefix+zlib → uncompressed (3-way fallback) - **parsePush/parsePull**: accept 1-arg form (Fossil omits project-code on known remotes) - Spec: `docs/dev/specs/2026-03-18-server-handler-design.md` - Plan: `docs/dev/plans/2026-03-18-server-handler.md` - Obsidian note: `~/notes/Projects/EdgeSync Server Handler.md` ## DST Updates (2026-03-18) - **MockFossil replaced with HandleSync** — `MockFossil.Exchange` delegates to `HandleSyncWithOpts`. All 37 existing DST tests pass. - **PeerNetwork** in `dst/peer_network.go` — leaf-to-leaf DST without bridge/master. Routes Exchange→HandleSync on peer repo. - **TestScenarioPeerSync** — 2 leaves, 10 blobs converge via PeerNetwork - **TestScenarioClone** — fresh repo clones 250 blobs through HandleSync pagination - DST total: 39 tests (37 existing + 2 new) ## Two Simulation Layers - `dst/` — Deterministic single-threaded sim (NewFromParts, SimNetwork/PeerNetwork, HandleSync-backed MockFossil, event queue) - `sim/` — Integration sim (real NATS + TCP fault proxy + real Fossil server + ServeHTTP/ServeNATS tests) - Both share `simio/` abstractions (Clock, Rand, Env) and `sync.BuggifyChecker` interface - sim serve tests: fossil clone, fossil sync, leaf-to-leaf NATS, leaf-to-leaf HTTP — all verified by Fossil 2.28 ## Clone Implementation (2026-03-18, PR#7 merged) - `sync.Clone()` — full repo clone via Fossil protocol v3 - `storeReceivedFile()` shared between Sync and Clone - `ErrDeltaSourceMissing` sentinel: clone creates phantoms, sync returns error - CLI: `edgesync repo clone <url> <path>` ## Config Locations - agent.Config in `leaf/agent/config.go` — includes ServeHTTPAddr, ServeNATSEnabled - bridge.Config in `bridge/bridge/config.go` - SyncOpts in `libfossil/sync/session.go` — has BuggifyChecker field - HandleOpts in `libfossil/sync/handler.go` — has BuggifyChecker field ## Key Patterns - `simio.CryptoRand{}` for production callsites of `repo.Create` and `db.SeedConfig` - `NewFromParts()` on agent/bridge bypasses NATS for testing; `New()` is production path - `HandleSync` for simple use, `HandleSyncWithOpts` when BUGGIFY is needed (DST) ## CI & Testing - `.github/workflows/test.yml` — unit tests + sim serve tests - `.githooks/pre-commit` — ~8s (unit + DST 1 seed + sim unit + sim serve) - Makefile: `make test` (CI), `make dst`/`dst-full`/`dst-hostile`/`dst-drivers`, `make sim`/`sim-full`, `make drivers` - DST: 8 seeds normal pass, 16 seeds x hostile ~40s - `backup/pre-filter` branch on remote — old history before fossil file purge ## Follow-ons (documented, not implemented) - UV cards (uvfile/uvigot/uvgimme) for forum/wiki/chat - Cookie sessions for igot optimization - In-memory TTL sessions for libp2p connection identity - Private branch cards - Full config sync (tickets, skins, backoffice) - Login verification beyond accept-all - libp2p transport (ServeP2P stub exists) - DST fault schedule for peer-to-peer topology - Clone under DST event model