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=falsefor all builds - Git repo: github.com/danmestas/EdgeSync (private)
fossil/andlibfossil/are gitignored (local-only reference, purged from history).agents/,.claude/skills/,skills-lock.jsonare gitignored (tool-local)
Entry Points
cmd/edgesync/— Unified CLI (50 subcommands via kong, includingrepo clone)leaf/cmd/leaf/— Standalone leaf agent daemonbridge/cmd/bridge/— Standalone bridge daemonsim/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 synccompatible. - 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.Exchangedelegates toHandleSyncWithOpts. 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) andsync.BuggifyCheckerinterface - 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 v3storeReceivedFile()shared between Sync and CloneErrDeltaSourceMissingsentinel: 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 ofrepo.Createanddb.SeedConfigNewFromParts()on agent/bridge bypasses NATS for testing;New()is production pathHandleSyncfor simple use,HandleSyncWithOptswhen 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-filterbranch 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