From 48135703e8663b71d0bc016aa9dbf9278d0abfd0 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Mon, 15 Jun 2026 19:43:29 +0100 Subject: [PATCH] Preserve Libby persona state and database preverify flow --- .../birth/runner/birth-runner-summary.json | 190 ++ .../runner/repo-memory/output-schema.json | 69 + .voidbot/birth/runner/repo-memory/prompt.md | 1619 +++++++++++++++++ .../repo-personality/output-schema.json | 69 + .../birth/runner/repo-personality/prompt.md | 1220 +++++++++++++ .../runner/repo-trajectory/output-schema.json | 97 + .../birth/runner/repo-trajectory/prompt.md | 1217 +++++++++++++ .../runner/startup/projection/projection.cc | Bin 0 -> 121528 bytes .../startup/projection/projection.cc.lock | 0 .../startup/projection/projection.msgpack | Bin 0 -> 124065 bytes .../projection/projection.msgpack.lock | 0 .../repo-initialization-startup-summary.json | 56 + .../repo-initialization-startup-summary.md | 19 + .../repo-memory-distiller-packet.json | 1501 +++++++++++++++ .../repo-memory-distiller-packet.md | 36 + .../repo-memory-distiller-prompt.md | 110 ++ .../repo-personality-distiller-packet.json | 1105 +++++++++++ .../repo-personality-distiller-packet.md | 29 + .../repo-personality-distiller-prompt.md | 107 ++ .../repo-trajectory-distiller-packet.json | 1111 +++++++++++ .../repo-trajectory-distiller-packet.md | 30 + .../repo-trajectory-distiller-prompt.md | 98 + .voidbot/birth/terrain/baseline.cc | Bin 0 -> 121528 bytes .voidbot/birth/terrain/baseline.cc.lock | 0 .voidbot/birth/terrain/baseline.msgpack | Bin 0 -> 124065 bytes .voidbot/birth/terrain/baseline.msgpack.lock | 0 .../repo-personality-scout-summary.json | 31 + .../terrain/repo-personality-scout-summary.md | 14 + .voidbot/birth/voidbot-face-birth.json | 13 + .voidbot/birth/voidbot-persona-birth.json | 13 + .voidbot/state/README.md | 4 + .voidbot/state/libby.cc | Bin 22705 -> 72566 bytes .voidbot/status/void-memory-maintenance.json | 7 + .voidbot/voice/README.md | 4 + .voidbot/voice/identity.json | 11 +- packages/cultnet-rs/tests/cultnet.rs | 28 +- packages/cultnet-ts/test/cultnet.test.ts | 26 +- .../CultNetDatabaseServer.cs | 2 + src/GameCult.Networking/Server.cs | 8 +- 39 files changed, 8813 insertions(+), 31 deletions(-) create mode 100644 .voidbot/birth/runner/birth-runner-summary.json create mode 100644 .voidbot/birth/runner/repo-memory/output-schema.json create mode 100644 .voidbot/birth/runner/repo-memory/prompt.md create mode 100644 .voidbot/birth/runner/repo-personality/output-schema.json create mode 100644 .voidbot/birth/runner/repo-personality/prompt.md create mode 100644 .voidbot/birth/runner/repo-trajectory/output-schema.json create mode 100644 .voidbot/birth/runner/repo-trajectory/prompt.md create mode 100644 .voidbot/birth/runner/startup/projection/projection.cc create mode 100644 .voidbot/birth/runner/startup/projection/projection.cc.lock create mode 100644 .voidbot/birth/runner/startup/projection/projection.msgpack create mode 100644 .voidbot/birth/runner/startup/projection/projection.msgpack.lock create mode 100644 .voidbot/birth/runner/startup/repo-initialization-startup-summary.json create mode 100644 .voidbot/birth/runner/startup/repo-initialization-startup-summary.md create mode 100644 .voidbot/birth/runner/startup/repo-memory/repo-memory-distiller-packet.json create mode 100644 .voidbot/birth/runner/startup/repo-memory/repo-memory-distiller-packet.md create mode 100644 .voidbot/birth/runner/startup/repo-memory/repo-memory-distiller-prompt.md create mode 100644 .voidbot/birth/runner/startup/repo-personality/repo-personality-distiller-packet.json create mode 100644 .voidbot/birth/runner/startup/repo-personality/repo-personality-distiller-packet.md create mode 100644 .voidbot/birth/runner/startup/repo-personality/repo-personality-distiller-prompt.md create mode 100644 .voidbot/birth/runner/startup/repo-trajectory/repo-trajectory-distiller-packet.json create mode 100644 .voidbot/birth/runner/startup/repo-trajectory/repo-trajectory-distiller-packet.md create mode 100644 .voidbot/birth/runner/startup/repo-trajectory/repo-trajectory-distiller-prompt.md create mode 100644 .voidbot/birth/terrain/baseline.cc create mode 100644 .voidbot/birth/terrain/baseline.cc.lock create mode 100644 .voidbot/birth/terrain/baseline.msgpack create mode 100644 .voidbot/birth/terrain/baseline.msgpack.lock create mode 100644 .voidbot/birth/terrain/repo-personality-scout-summary.json create mode 100644 .voidbot/birth/terrain/repo-personality-scout-summary.md create mode 100644 .voidbot/birth/voidbot-face-birth.json create mode 100644 .voidbot/birth/voidbot-persona-birth.json create mode 100644 .voidbot/state/README.md create mode 100644 .voidbot/status/void-memory-maintenance.json create mode 100644 .voidbot/voice/README.md diff --git a/.voidbot/birth/runner/birth-runner-summary.json b/.voidbot/birth/runner/birth-runner-summary.json new file mode 100644 index 00000000..b83924af --- /dev/null +++ b/.voidbot/birth/runner/birth-runner-summary.json @@ -0,0 +1,190 @@ +{ + "agentStore": "E:\\Projects\\CultLib\\.voidbot\\state\\agents.msgpack", + "artifactDir": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner", + "baseline": "E:\\Projects\\CultLib\\.voidbot\\birth\\terrain\\baseline.msgpack", + "createdAt": "2026-06-14T18:16:56Z", + "executions": [ + { + "acceptCommand": [ + "accept-init", + "--init-store", + "E:\\Projects\\CultLib\\.voidbot\\state\\repo-initialization.msgpack", + "--packet", + "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\startup\\repo-trajectory\\repo-trajectory-distiller-packet.json", + "--kind", + "repo-trajectory", + "--accepted-by", + "Self", + "--summary", + "Accepted repo-trajectory birth specialist result after review.", + "--result", + "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-trajectory\\result.json", + "--agent-store", + "E:\\Projects\\CultLib\\.voidbot\\state\\agents.msgpack", + "--apply-self-patches", + "true" + ], + "birthOnly": true, + "executionOwner": "repo-initialization-startup-runner", + "executor": "model-runtime", + "heartbeatParticipant": null, + "kind": "repo-trajectory", + "modelProvider": "openai-codex", + "modelRuntimeBin": "epiphany-model-runtime", + "packetPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\startup\\repo-trajectory\\repo-trajectory-distiller-packet.json", + "promptPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-trajectory\\prompt.md", + "requestPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-trajectory\\model-request.json", + "resultPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-trajectory\\result.json", + "runtimeSummaryPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-trajectory\\model-runtime-summary.json", + "schemaPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-trajectory\\output-schema.json", + "status": "planned", + "stderrPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-trajectory\\executor.stderr.log", + "stdoutPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-trajectory\\executor.stdout.log" + }, + { + "acceptCommand": [ + "accept-init", + "--init-store", + "E:\\Projects\\CultLib\\.voidbot\\state\\repo-initialization.msgpack", + "--packet", + "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\startup\\repo-personality\\repo-personality-distiller-packet.json", + "--kind", + "repo-personality", + "--accepted-by", + "Self", + "--summary", + "Accepted repo-personality birth specialist result after review.", + "--result", + "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-personality\\result.json", + "--agent-store", + "E:\\Projects\\CultLib\\.voidbot\\state\\agents.msgpack", + "--apply-self-patches", + "true", + "--heartbeat-store", + "E:\\Projects\\CultLib\\.voidbot\\state\\agent-heartbeats.msgpack", + "--apply-heartbeat-seeds", + "true" + ], + "birthOnly": true, + "executionOwner": "repo-initialization-startup-runner", + "executor": "model-runtime", + "heartbeatParticipant": null, + "kind": "repo-personality", + "modelProvider": "openai-codex", + "modelRuntimeBin": "epiphany-model-runtime", + "packetPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\startup\\repo-personality\\repo-personality-distiller-packet.json", + "promptPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-personality\\prompt.md", + "requestPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-personality\\model-request.json", + "resultPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-personality\\result.json", + "runtimeSummaryPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-personality\\model-runtime-summary.json", + "schemaPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-personality\\output-schema.json", + "status": "planned", + "stderrPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-personality\\executor.stderr.log", + "stdoutPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-personality\\executor.stdout.log" + }, + { + "acceptCommand": [ + "accept-init", + "--init-store", + "E:\\Projects\\CultLib\\.voidbot\\state\\repo-initialization.msgpack", + "--packet", + "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\startup\\repo-memory\\repo-memory-distiller-packet.json", + "--kind", + "repo-memory", + "--accepted-by", + "Self", + "--summary", + "Accepted repo-memory birth specialist result after review.", + "--result", + "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-memory\\result.json", + "--agent-store", + "E:\\Projects\\CultLib\\.voidbot\\state\\agents.msgpack", + "--apply-self-patches", + "true" + ], + "birthOnly": true, + "executionOwner": "repo-initialization-startup-runner", + "executor": "model-runtime", + "heartbeatParticipant": null, + "kind": "repo-memory", + "modelProvider": "openai-codex", + "modelRuntimeBin": "epiphany-model-runtime", + "packetPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\startup\\repo-memory\\repo-memory-distiller-packet.json", + "promptPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-memory\\prompt.md", + "requestPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-memory\\model-request.json", + "resultPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-memory\\result.json", + "runtimeSummaryPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-memory\\model-runtime-summary.json", + "schemaPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-memory\\output-schema.json", + "status": "planned", + "stderrPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-memory\\executor.stderr.log", + "stdoutPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\repo-memory\\executor.stdout.log" + } + ], + "executor": "model-runtime", + "heartbeatStore": "E:\\Projects\\CultLib\\.voidbot\\state\\agent-heartbeats.msgpack", + "initStore": "E:\\Projects\\CultLib\\.voidbot\\state\\repo-initialization.msgpack", + "mode": "plan", + "modelProvider": "openai-codex", + "modelRuntimeBin": "epiphany-model-runtime", + "nextSafeMove": "Review planned startup-only birth executions, then rerun with --mode run.", + "repo": "E:\\Projects\\CultLib", + "requiresReview": true, + "runtimeStore": "E:\\Projects\\CultLib\\.voidbot\\state\\runtime-spine.msgpack", + "schemaVersion": "epiphany.repo_birth_runner.v0", + "startup": { + "acceptedKinds": [], + "action": "reviewInitializationPackets", + "artifactDir": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\startup", + "baseline": "E:\\Projects\\CultLib\\.voidbot\\birth\\terrain\\baseline.msgpack", + "generatedPackets": [ + { + "birthOnly": true, + "contract": "Startup-only specialist packet. Do not register as a heartbeat lane; accept-init may apply reviewed role selfPatch requests only after Self review.", + "executionOwner": "repo-initialization-startup-runner", + "heartbeatParticipant": null, + "kind": "repo-trajectory", + "packetPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\startup\\repo-trajectory\\repo-trajectory-distiller-packet.json", + "promptPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\startup\\repo-trajectory\\repo-trajectory-distiller-prompt.md", + "summaryPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\startup\\repo-trajectory\\repo-trajectory-distiller-packet.md" + }, + { + "birthOnly": true, + "contract": "Startup-only specialist packet. Do not register as a heartbeat lane; accept-init may stamp the newborn trait lattice and seed heartbeat physiology only after Self review.", + "executionOwner": "repo-initialization-startup-runner", + "heartbeatParticipant": null, + "kind": "repo-personality", + "packetPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\startup\\repo-personality\\repo-personality-distiller-packet.json", + "promptPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\startup\\repo-personality\\repo-personality-distiller-prompt.md", + "summaryPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\startup\\repo-personality\\repo-personality-distiller-packet.md" + }, + { + "birthOnly": true, + "contract": "Startup-only specialist packet. Do not register as a heartbeat lane; accept-init may apply reviewed role selfPatch requests only after Self review.", + "executionOwner": "repo-initialization-startup-runner", + "heartbeatParticipant": null, + "kind": "repo-memory", + "packetPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\startup\\repo-memory\\repo-memory-distiller-packet.json", + "promptPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\startup\\repo-memory\\repo-memory-distiller-prompt.md", + "summaryPath": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\startup\\repo-memory\\repo-memory-distiller-packet.md" + } + ], + "initStore": "E:\\Projects\\CultLib\\.voidbot\\state\\repo-initialization.msgpack", + "missingKinds": [ + "repo-trajectory", + "repo-personality", + "repo-memory" + ], + "mode": "startup", + "nextSafeMove": "Self reviews generated birth packets, runs the startup-only distiller specialists outside the heartbeat lane system, applies accepted selfPatch candidates, trait-lattice seeds, and heartbeat seeds through accept-init, then records each completed birth rite.", + "projectionStore": "E:\\Projects\\CultLib\\.voidbot\\birth\\runner\\startup\\projection\\projection.msgpack", + "repo": "E:\\Projects\\CultLib", + "repoId": "cultlib", + "requiredActions": [ + "reviewRepoTrajectoryInitialization", + "reviewRepoPersonalityInitialization", + "reviewRepoMemoryInitialization" + ], + "requiresReview": true, + "schemaVersion": "epiphany.repo_personality_artifacts.v0" + } +} \ No newline at end of file diff --git a/.voidbot/birth/runner/repo-memory/output-schema.json b/.voidbot/birth/runner/repo-memory/output-schema.json new file mode 100644 index 00000000..df74df9e --- /dev/null +++ b/.voidbot/birth/runner/repo-memory/output-schema.json @@ -0,0 +1,69 @@ +{ + "additionalProperties": true, + "properties": { + "confidence": { + "type": "number" + }, + "doNotMutate": { + "items": { + "type": "string" + }, + "type": "array" + }, + "globalMemoryCandidates": { + "items": { + "type": "object" + }, + "type": "array" + }, + "initializationRecord": { + "type": "object" + }, + "nextSafeMove": { + "type": "string" + }, + "roleMemoryPatches": { + "items": { + "type": "object" + }, + "type": "array" + }, + "summary": { + "type": "string" + }, + "verdict": { + "enum": [ + "ready-for-review", + "needs-more-terrain", + "reject" + ], + "type": "string" + } + }, + "required": [ + "verdict", + "summary", + "confidence", + "roleMemoryPatches", + "initializationRecord", + "doNotMutate", + "nextSafeMove" + ], + "type": "object", + "xEpiphanyExpectedOutput": { + "confidence": "0.0..1.0", + "doNotMutate": [], + "globalMemoryCandidates": [], + "initializationRecord": { + "acceptedOnce": true, + "distillerKind": "repo-memory", + "profileSchemaVersion": "epiphany.repo_personality_profile.v0", + "repoId": "cultlib", + "terrainSchemaVersion": "epiphany.repo_terrain_report.v0" + }, + "nextSafeMove": "Self reviews role-specific memory patches before first initialization mutation; later memory growth uses heartbeat, evidence, rumination, sleep, and reviewed selfPatch.", + "roleMemoryPatches": [], + "summary": "short newborn memory initialization summary", + "verdict": "ready-for-review | needs-more-source | reject" + } +} \ No newline at end of file diff --git a/.voidbot/birth/runner/repo-memory/prompt.md b/.voidbot/birth/runner/repo-memory/prompt.md new file mode 100644 index 00000000..7adb6d76 --- /dev/null +++ b/.voidbot/birth/runner/repo-memory/prompt.md @@ -0,0 +1,1619 @@ +Act as the Epiphany Repo Memory Distiller for one bounded initialization pass. + +You are not the Repo Personality Distiller. Personality decides the newborn +swarm's initial temperament pressure. Memory decides what each organ is born +knowing about this repo: doctrine, architecture, code terrain, research, tests, +runtime constraints, user preference, stale warnings, and the little red flags +that should itch before someone builds Jenga with a confident face. + +This is a birth rite, not a recurring audit. Run only when a repo/swarm has no +accepted memory initialization. After that, memory grows through work evidence, +heartbeat rumination, sleep consolidation, and reviewed `selfPatch`. Do not +reset a living agent's memory because startup happened. + +Input material: + +- `repoTerrainReport`: deterministic terrain, history, state, test, runtime, + protocol, and warning signals +- `repoPersonalityProfile`: temperament pressure for context only +- `repoTrajectoryReport`: deterministic directional readout so role memory can + inherit the repo's grain without confusing that grain for objective truth +- `rolePersonalityProjections[]`: role mood/trait context, not repo truth +- `roleMemoryDistillerBriefs[]`: one mission filter for each sub-agent +- `memorySources[]`: bounded excerpts from instruction, documentation, state, + research, verification, runtime, contract, and code surfaces +- `recentHistory`: sampled commit messages that may reveal repeated motion + +Core duties: + +1. Distill memory, not personality. + - Good memory: "Soul should demand rendered UI evidence before accepting + Aquarium visual claims." + - Good memory: "Proprioception should map CultCache/CultNet schema boundaries before + Hands changes persistence." + - Bad memory: "This repo is anxious and likes purple." + - Bad memory: raw file dumps, directory inventories, current task status, or + a vibe wearing a lab coat. + +2. Produce a separate distillation for each organ. + - Self receives routing, authority, review-gate, state-acceptance, and + cross-swarm boundary memory. + - Face receives public-interface, Discord/Aquarium, voice, visibility, and + sealed-thought boundary memory. + - Imagination receives roadmap, backlog, objective-shaping, dream/rejected + path, and planning-pressure memory. + - Eyes receives research, prior-art, canonical algorithm, vendor/API, and + invention-avoidance memory. + - Proprioception receives architecture, graph, code anatomy, invariant, data/control + flow, and checkpoint memory. + - Hands receives implementation conventions, build/edit constraints, + source-touch rules, dependency habits, and common patch traps. + - Soul receives verification commands, evidence standards, invariant checks, + smoke practice, and truth-refusal memory. + - Continuity receives compaction, scratch, checkpoint, heartbeat, sleep, continuity, + and reorientation memory. + - Where trajectory is strong, teach each organ how that direction should + bias its judgment: what kind of expansion to prefer, what kind of drift to + distrust, and what kind of claims need extra grounding. + +3. Compress, cite, and preserve uncertainty. + - Every memory candidate needs source refs from `memorySources[].path`, + terrain fields, or history signals. + - Repository docs can be stale. Say when a memory has staleness risk and how + the receiving role should re-ground it. + - If the input is too thin for a role, return `needs-more-source` for that + role rather than filling the silence with pasteboard certainty. + +4. Keep project truth in the correct organ. + - Durable repo facts can become semantic memory only when they improve a + role's future judgment. + - Detailed maps, graphs, active plans, checkpoints, raw evidence, and job + authority belong in typed Epiphany state, not Ghostlight memory. + - `selfPatch` is a petition to Self, never a direct mutation. + +5. Protect the newborn from fossilized documentation. + - Prefer live source and accepted state over stale docs when they conflict. + - Convert contradictions into memories of caution, not accepted facts. + - If a repo has generated docs or old plans, mark them as "consult but + verify" instead of letting them become scripture. + +Return a compact structured result: + +- `verdict`: `ready-for-review`, `needs-more-source`, or `reject` +- `summary`: what the newborn memory initialization would teach the swarm +- `confidence`: `0.0..1.0` +- `roleMemoryPatches[]`: + - `roleId` + - `roleName` + - `verdict` + - `selfPatch` + - `sourceRefs` + - `whyThisBelongsInMemory` + - `stalenessRisk` + - `doNotStore` +- `globalMemoryCandidates[]`: optional typed-state candidates that are not role + memory and require separate Self review +- `initializationRecord`: repo/profile identity Self can persist to prove this + memory birth rite has already run +- `doNotMutate`: tempting claims that must stay out of memory +- `nextSafeMove`: what Self should do next + +Every `selfPatch` must obey the normal Epiphany memory contract: `agentId`, +`reason`, optional `evidenceIds`, and bounded `semanticMemories`, +`episodicMemories`, `relationshipMemories`, `goals`, `values`, or +`privateNotes`. Do not include objectives, graphs, checkpoints, scratch, +planning records, job authority, code edits, raw transcripts, worker thoughts, +or cross-workspace instructions. + +The output is a petition. Self may accept, refuse, split, or ask for more +source. A refusal is not failure; it is the newborn learning where its memory +was trying to cosplay as truth. + + +# Startup-Only Birth Packet + +You are executing exactly one repo initialization birth specialist packet. Do not edit files. Do not mutate state. Return only JSON that matches the provided schema. The coordinator/Self will review and decide whether to accept the result. + +```json +{ + "createdAt": "2026-06-14T18:16:52Z", + "expectedOutput": { + "confidence": "0.0..1.0", + "doNotMutate": [], + "globalMemoryCandidates": [], + "initializationRecord": { + "acceptedOnce": true, + "distillerKind": "repo-memory", + "profileSchemaVersion": "epiphany.repo_personality_profile.v0", + "repoId": "cultlib", + "terrainSchemaVersion": "epiphany.repo_terrain_report.v0" + }, + "nextSafeMove": "Self reviews role-specific memory patches before first initialization mutation; later memory growth uses heartbeat, evidence, rumination, sleep, and reviewed selfPatch.", + "roleMemoryPatches": [], + "summary": "short newborn memory initialization summary", + "verdict": "ready-for-review | needs-more-source | reject" + }, + "guardrails": [ + "This packet is input to role-specific memory distillers, not accepted truth.", + "This packet is birth-only; it pre-fills newborn memory and then gets out of the way.", + "Memory distillation is separate from personality distillation.", + "Each role receives only knowledge relevant to its mission.", + "Do not copy raw file dumps into memory; compress into durable doctrine, source maps, invariants, risks, and practices.", + "Preserve uncertainty and staleness risk; repository documentation can lie by age.", + "No objectives, authority claims, active job state, raw transcripts, code edits, or arbitrary workspace access in selfPatch." + ], + "input": { + "memorySourceInventory": { + "maxBytesPerFile": 12000, + "maxFiles": 48, + "maxTotalBytes": 120000, + "repoPath": "\\\\?\\E:\\Projects\\CultLib", + "sourceCount": 26, + "sourceKinds": [ + "doctrine", + "documentation", + "readme", + "research" + ] + }, + "memorySources": [ + { + "bytes": 766, + "kind": "doctrine", + "path": "AGENTS.md", + "text": "# AGENTS.md\n\n## Repository Guidance\n\n- Refrain from commenting on current changes in README files unless the user explicitly asks for that commentary.\n- Treat clean API surface as a core project priority.\n- Favor developer ergonomics in public APIs, examples, naming, defaults, and documentation.\n- Prefer interfaces and behaviors that are predictable, easy to discover, and easy to integrate correctly.\n- Keep public abstractions small and coherent; avoid exposing internal workflow complexity through the API when it can be encapsulated.\n- When adding documentation or examples, optimize for practical usage by downstream developers.\n- When proposing or implementing changes, consider how they affect usability, readability, and maintenance for library consumers.\n", + "truncated": false + }, + { + "bytes": 201, + "kind": "readme", + "path": ".voidbot/state/README.md", + "text": "# Repo Face State\r\n\r\nThis folder stores birth and continuity state for `Libby`.\r\nDo not treat these files as arbitrary editable projections. Persistent memory should cross typed operation boundaries.\r\n", + "truncated": false + }, + { + "bytes": 160, + "kind": "readme", + "path": ".voidbot/voice/README.md", + "text": "# Repo Face Voice\r\n\r\nThis folder belongs to the Discord-facing Face for `Libby`.\r\nDiscord roles address the Face; VoidBot's webhook persona pipe is the mouth.\r\n", + "truncated": false + }, + { + "bytes": 13047, + "kind": "readme", + "path": "README.md", + "text": "# CultLib\r\n\r\nCultLib is a set of reusable C# libraries for game backends, game-adjacent services, and Unity-integrated tooling, including a declarative runtime UI composition framework for Unity.\r\n\r\nThe libraries cover three main areas:\r\n\r\n- logging primitives and implementations\r\n- a typed in-memory cache with pluggable persistence\n- LiteNetLib-based networking with encrypted credential exchange and signed session tokens\n- CultMesh distributed realtime database and simulation-consensus primitives\n- typed geometry domain/chunk documents for distributed CSG and LOD streaming\n- declarative Unity UI composition and reflective runtime inspector tooling\n\r\n## Which Package Do I Want?\r\n\r\nIf the job is shared game state, start here before inventing a fourth drawer\r\nand pretending the label makes it furniture.\r\n\r\n| Job | Start With | Owns | Use When | Do Not Use It For |\r\n| --- | --- | --- | --- | --- |\r\n| Local typed state | `GameCult.Caching` / CultCache | Document identity, schema compatibility, record keys, indexes, globals, and local persistence | You need a typed cache, file-compatible save data, local reactive reads, or a stable domain document model | Peer discovery, transport security, shard routing, or mesh consensus |\n| Procedural geometry state | `GameCult.Geometry` | CultCache-native domain trees, LOD build requests, selected-cut diagnostics, and chunk artifact payloads | Rust, Unity, or remote workers need to share CSG/LOD geometry and graph metadata as typed state | Transport policy, peer discovery, or gameplay authority |\n| Network transport and database plumbing | `GameCult.Networking` / CultNet | LiteNetLib transport, authentication, schema-v0 wire contracts, shard authority, raw document replication, snapshots, and subscriptions | You need a client/server pipe, login/session flow, schema discovery, or a low-level distributed CultCache lane | Gameplay-facing mesh ergonomics, Verse policy, mod branches, or simulation consensus composition |\n| Distributed realtime gameplay state | `GameCult.Mesh` / CultMesh | Public mesh entrypoints, Verse discovery, peer exchange, shard replication defaults, authority leases, client prediction, and witness consensus | You want the game to treat clients and servers as one reactive database for persistent state, input state, and simulation facts | A tiny local-only tool, a bare transport client, or a storage format contract |\n| Realtime media/frame streams | `GameCult.Mesh` / CultMesh streaming mode | Stream identity, authority, clock metadata, body transport negotiation, frame cursors, and backpressure state | Audio/video/tensor frames need to move between runtimes through shared memory, GPU handles, platform buffers, or CultCache page refs | Durable document mutation, mesh consensus facts, or pretending inline bytes are zero-copy |\n\r\nQuick rule:\r\n\r\n- Choose CultCache when the problem is \"how do I model and persist typed state?\"\n- Choose GameCult.Geometry when the problem is \"how do geometry workers share\n domain trees, LOD build requests, and mesh chunks as typed state?\"\n- Choose CultNet when the problem is \"how do peers exchange authenticated,\n schema-aware database messages?\"\n- Choose CultMesh when the problem is \"how does a game join a Verse and share\n realtime state across a mesh?\"\n- Choose CultMesh streaming mode when the problem is \"how do these runtimes move\n audio/video frames while the mesh owns identity, clocks, cursors, and pressure?\"\n\r\nCultMesh sits on CultNet, and CultNet distributes CultCache documents. That is\r\nthe stack. If a design needs another peer-to-peer category, first check whether\r\nit is really Verse policy, peer exchange, or shard authority wearing a fake\r\nmustache.\r\n\r\nIf you want the smallest durable \"open node -> put typed doc -> get typed doc\"\r\npath, start with\r\n[`src/GameCult.Mesh/docs/durable-node-quickstart.md`](src/GameCult.Mesh/docs/durable-node-quickstart.md).\r\nIf you want the lower-level \"typed local document -> raw wire document ->\r\nmesh/runtime watch surface\" handoff, follow it with\r\n[`src/GameCult.Mesh/docs/typed-document-path.md`](src/GameCult.Mesh/docs/typed-document-path.md).\r\n\r\n## Repository Scope\r\n\r\nThe solution includes:\n\n- `GameCult.Logging`: common logging abstraction plus console and file implementations\n- `GameCult.Caching`: `DatabaseEntry`-based cache, indexes, global entries, and backing-store abstractions\n- `GameCult.Caching.MessagePack`: MessagePack-backed persistence for the cache\r\n- `GameCult.Caching.NewtonsoftJson`: Newtonsoft.Json-backed persistence for the cache\r\n- `GameCult.Caching.MessagePack.Generator`: source generator for MessagePack formatters for cache models\n- `GameCult.Caching.MessagePack.Analyzers`: packaging project that delivers the generator to consuming projects\n- `GameCult.Geometry`: CultCache-native geometry domain, selected-cut, and chunk artifact documents for VibeGeometry/Fensalir-style pipelines\n- `GameCult.Networking`: encrypted login/register/verify flows and message dispatch over LiteNetLib\n- `GameCult.Mesh`: CultMesh package home for distributed realtime database, shard replication, client prediction, Verse discovery, and mesh witness consensus\n- `GameCult.Caching.Tests`: NUnit tests for cache and backing-store behavior\n- `GameCult.Networking.Tests`: NUnit tests for networking behavior\n- `GameCult.Unity`: CultUI, a Unity runtime UI composition framework with reflective inspector generation, prefab-backed field resolvers, reusable controls, and a demo project packaged for UPM-style consumption\n- `packages/cultcache-ts`: TypeScript CultCache with MessagePack persistence and inspector tooling\n- `packages/cultnet-ts`: TypeScript CultNet schema-v0 contracts, framing, discovery, raw document replication, and interop tests\n- `packages/cultmesh-ts`: TypeScript CultMesh local node and mesh catalog surface for local runtimes such as VoidBot\n- `packages/cultcache-rs`: Rust CultCache and derive macro\n- `packages/cultnet-rs`: Rust CultNet contracts, framing, discovery, and interop peer\n\n## Repository Layout\n\n```text\npackage.json\nsrc/\n GameCult.Logging/\n GameCult.Caching/\n GameCult.Caching.MessagePack/\r\n GameCult.Caching.NewtonsoftJson/\r\n GameCult.Caching.MessagePack.Generator/\n GameCult.Caching.MessagePack.Analyzers/\n GameCult.Geometry/\n GameCult.Networking/\n GameCult.Mesh/\r\n GameCult.Unity/\r\ntests/\n GameCult.Caching.Tests/\n GameCult.Geometry.Tests/\n GameCult.Networking.Tests/\npackages/\n cultcache-ts/\n cultnet-ts/\n cultmesh-ts/\n cultcache-rs/\n cultnet-rs/\n```\n\r\n## Build\r\n\r\n```powershell\r\ndotnet build CultLib.sln\r\n```\r\n\r\n## Test\n\n```powershell\ndotnet test CultLib.sln\n```\n\nTypeScript package tests:\n\n```powershell\nnpm test --workspace packages/cultcache-ts\nnpm test --workspace packages/cultnet-ts\nnpm run test:interop --workspace packages/cultnet-ts\nnpm test --workspace packages/cultmesh-ts\n```\n\nRust package tests:\n\n```powershell\ncargo test --manifest-path packages/cultcache-rs/Cargo.toml\ncargo test --manifest-path packages/cultnet-rs/Cargo.toml\n```\n\r\n## Common Concepts\r\n\r\n### `DatabaseEntry`\r\n\r\nThe cache-centric libraries revolve around `DatabaseEntry`. Every entry has a stable `Guid` identifier and can optionally:\r\n\r\n- expose a human-readable name through `INamedEntry`\r\n- participate in generic indexes registered at runtime\r\n- be treated as a global singleton entry through `GlobalSettingsAttribute`\r\n\r\nTypical entry shape:\r\n\r\n```csharp\r\nusing GameCult.Caching;\r\n\r\npublic class ItemData : DatabaseEntry, INamedEntry\r\n{\r\n public string Name = string.Empty;\r\n public int Value;\r\n\r\n public string EntryName\r\n {\r\n get => Name;\r\n set => Name = value;\r\n }\r\n}\r\n```\r\n\r\n### `CultCache` and Backing Stores\r\n\r\n`CultCache` is an in-memory index over `DatabaseEntry` objects. It can operate entirely in memory, or it can be attached to one or more backing stores for persistence and synchronization.\r\n\r\n- the cache is the query surface\r\n- backing stores are persistence adapters\r\n- indexes and name maps are maintained inside the cache, not inside the store\r\n\r\n### Important: Multiple Backing Stores\r\n\r\nWhen multiple backing stores are added, behavior depends on how they are registered.\r\n\r\nIf a store is added with domain types:\r\n\r\n```csharp\r\ncache.AddBackingStore(playerStore, typeof(PlayerData));\r\ncache.AddBackingStore(settingsStore, typeof(AppSettings));\r\n```\r\n\r\nthen that store becomes the direct persistence target for those types.\r\n\r\nIf a store is added without domain types:\r\n\r\n```csharp\r\ncache.AddBackingStore(primaryStore);\r\ncache.AddBackingStore(mirrorStore);\r\n```\r\n\r\nthen the first generic store acts as the primary writable store for non-domain-specific entries. Additional generic stores subscribe to the existing stores and mirror their change events.\r\n\r\nImplications:\r\n\r\n- order matters for generic stores\r\n- `AddAsync` writes to the type-specific store when one exists\r\n- otherwise `AddAsync` writes to the first generic store\r\n- later generic stores do not become co-primaries; they mirror earlier stores\r\n- `PullAllBackingStoresAsync` pulls from every registered store\r\n\r\nRecommended patterns:\r\n\r\n- use one generic primary store if you want simple persistence\r\n- use domain-specific stores when different entry types belong in different persistence layers\r\n- treat additional generic stores as mirrors or downstream replicas, not independent write targets\r\n\r\n## Example: Cache + Networking\r\n\r\n```csharp\r\nusing GameCult.Caching;\r\nusing GameCult.Logging;\r\nusing GameCult.Networking;\r\n\r\nvar cache = new CultCache\r\n{\r\n Logger = new ConsoleLogger()\r\n};\r\n\r\nvar server = new Server(cache)\r\n{\r\n Logger = new ConsoleLogger()\r\n};\r\n\r\nserver.Start();\r\n```\r\n\r\n## Secrets and Runtime Configuration\r\n\r\n`GameCult.Networking` uses two pieces of deployment configuration:\r\n\r\n- `GAMECULT_CONNECTION_KEY`\r\n- `GAMECULT_SESSION_SIGNING_SECRET`\r\n\r\nProduction guidance:\r\n\r\n- set both values before starting the server\r\n- treat `GAMECULT_CONNECTION_KEY` as shared client/server protocol configuration\r\n- treat `GAMECULT_SESSION_SIGNING_SECRET` as a server-only secret\r\n- generate high-entropy random values and store the server-side value in your platform's secret store\r\n- do not rely on local-development defaults in production\r\n- partial configuration is rejected at startup\r\n\r\nRecommended value format:\r\n\r\n- at least 32 random bytes per value\r\n- encode as Base64 or Base64Url if you want a portable text representation\r\n\r\nExample secret generation in PowerShell:\r\n\r\n```powershell\r\n[Convert]::ToBase64String((1..32 | ForEach-Object { Get-Random -Maximum 256 }))\r\n```\r\n\r\nTypical production setup patterns:\r\n\r\n- inject `GAMECULT_SESSION_SIGNING_SECRET` and the server copy of `GAMECULT_CONNECTION_KEY` as environment variables from Docker secrets, Kubernetes secrets, systemd environment files, or your cloud secret manager\r\n- ship the matching `GAMECULT_CONNECTION_KEY` to the client through a build-generated config asset, code-generated constants, or another explicit client configuration mechanism\r\n- scope them per environment so development, staging, and production do not share values\r\n- rotate `GAMECULT_SESSION_SIGNING_SECRET` operationally\r\n- treat `GAMECULT_CONNECTION_KEY` as versioned protocol config; changing it requires a coordinated client/server rollout\r\n\r\nExample server startup with strict environment validation:\r\n\r\n```csharp\r\nusing GameCult.Caching;\r\nusing GameCult.Networking;\r\n\r\nvar cache = new CultCache();\r\nvar security = ServerSecurityOptions.FromEnvironment();\r\nvar server = new Server(cache, security);\r\n```\r\n\r\nExample local-development server startup:\r\n\r\n```csharp\r\nusing GameCult.Caching;\r\nusing GameCult.Networking;\r\n\r\nvar cache = new CultCache();\r\nvar security = ServerSecurityOptions.Development();\r\nvar server = new Server(cache, security);\r\n```\r\n\r\nExample shipped-client startup with explicit client configuration:\r\n\r\n```csharp\r\nusing GameCult.Networking;\r\n\r\nvar security = new ClientSecurityOptions(\"\");\r\nvar client = new Client(security);\r\n```\r\n\r\n## Pro", + "truncated": true + }, + { + "bytes": 11124, + "kind": "readme", + "path": "packages/cultcache-rs/README.md", + "text": "# CultCache Rust\r\n\r\n`cultcache-rs` is the Rust port of the useful part of GameCult's CultCache:\r\na polymorphism-aware in-memory cache that remembers through pluggable backing\r\nstores.\r\n\r\nConsumer code should think in domain types:\r\n\r\n```rust\r\nlet player = cache.get_required::(\"player:meta\")?;\r\ncache.put(\"player:meta\", &player)?;\r\n```\r\n\r\nThe persistence layer should deal with envelopes, routing, MessagePack payload\nbytes, and schema identity. Application code should not paw at loose JSON files\nlike a sad little bureaucrat with a clipboard.\n\r\n## What It Is\r\n\r\nCultCache is a domain cache with persistence adapters.\r\n\r\n- `CultCache` is the query and mutation surface.\r\n- Domain structs implement `DatabaseEntry`.\r\n- Entries are stored behind a `type::key` identity, so multiple entry types\n can share a logical key without colliding.\n- Each payload is encoded directly from the known `DatabaseEntry` type into\n MessagePack bytes.\n- Backing stores are adapters, not the public data model.\n- Writes persist to the resolved backing store before the in-memory cache is\n updated.\n- Type-specific backing stores beat generic backing stores.\n- `SingleFileMessagePackBackingStore` is the first concrete store and guards\n file access with a sidecar lock file.\n\r\nThis is not an ORM, not a database, and not distributed consensus in a novelty\r\nhat. If multiple processes write the same backing file, use an external lock or\r\na coordinator.\r\n\r\n## Current API\r\n\r\n```rust\r\nuse cultcache_rs::{CultCache, DatabaseEntry, SingleFileMessagePackBackingStore};\n\n#[derive(Clone, Debug, PartialEq, Eq, DatabaseEntry)]\n#[cultcache(type = \"settings\")]\nstruct Settings {\n #[cultcache(key = 0)]\n theme: String,\n\n #[cultcache(key = 1, default)]\n retries: u32,\n}\n\nlet mut cache = CultCache::new();\ncache.register_entry_type::()?;\ncache.add_generic_backing_store(SingleFileMessagePackBackingStore::new(\"cache.msgpack\"));\r\ncache.pull_all_backing_stores()?;\r\n\r\ncache.put(\"app\", &Settings {\r\n theme: \"ash\".to_string(),\r\n retries: 3,\r\n})?;\r\n\r\nlet settings = cache.get_required::(\"app\")?;\n# Ok::<(), anyhow::Error>(())\n```\n\nFor a closed set of entries, generate a registry instead of repeating yourself:\n\n```rust\nuse cultcache_rs::cultcache_registry;\n\ncultcache_registry!(GameCultEntries {\n Settings,\n PlayerData,\n});\n\nlet mut cache = CultCache::new();\ncache.register_registry(GameCultEntries)?;\n```\n\nThe important part is that callers retrieve domain values directly:\n\r\n```rust\r\nlet settings: Settings = cache.get_required(\"app\")?;\r\nlet all_settings: Vec = cache.get_all()?;\r\n```\r\n\r\nThe cache is the ergonomic surface. The backing store is the memory prosthetic.\r\n\r\n## How This Maps From Original CultCache\r\n\r\nThe original C# CultCache relies on runtime reflection:\r\n\r\n- cacheable models inherit from `DatabaseEntry`\r\n- the cache scans child classes at startup\r\n- `Get(id)` returns a `T`\r\n- optional `INamedEntry` enables name lookup\r\n- optional field/property indexes are registered by member name\r\n- backing stores pull/push/delete `DatabaseEntry` values\r\n\r\nRust does not have C#-style assembly scanning or runtime subclass discovery.\r\nThe closest honest Rust translation is:\r\n\r\n- domain structs implement a marker trait, `DatabaseEntry`\n- the derive macro generates a positional array formatter from explicit integer\n field slots\n- the envelope carries the polymorphic type discriminator\n- unknown persisted type ids fail closed instead of constructing arbitrary\n runtime types\n- a generated registry should eventually replace repetitive manual\r\n registration\r\n\r\nManual `register_entry_type::()` is still accepted, but entry identity no\nlonger needs a hand-written impl: `#[derive(DatabaseEntry)]` declares it beside\nthe domain type. `cultcache_registry!` provides the current generated resolver\nsurface for a closed entry set.\n\r\n## Intended Rust Ergonomics\r\n\r\nThe target user-facing shape should be:\r\n\r\n```rust\r\n#[derive(Clone, DatabaseEntry)]\n#[cultcache(type = \"player\")]\npub struct PlayerData {\n #[cultcache(key = 0)]\n pub id: String,\n\n #[cultcache(key = 1)]\n pub name: String,\n\n #[cultcache(key = 2)]\n pub faction: String,\n}\n\r\nlet mut cache = CultCache::builder()\r\n .with_generated_entries(game_entries())\r\n .with_generic_store(SingleFileMessagePackBackingStore::new(\"cache.msgpack\"))\r\n .build()?;\r\n\r\ncache.pull_all_backing_stores()?;\r\nlet player = cache.get_required::(\"player:ari\")?;\r\n```\r\n\r\nThe current `cultcache_registry!` macro is deliberately simple. The remaining\nergonomic endpoint is automatic inventory or build-script generation so users\ndo not have to maintain the registry list by hand.\n\nThe registry is the Rust equivalent of C# reflection and MessagePack resolver\nsetup. It should know:\n\r\n- entry type id\n- generated MessagePack/serde formatter path\n- Rust type name / schema name\n- optional store domain route\r\n- optional name key extractor\r\n- optional secondary indexes\r\n- optional global singleton marker\r\n\r\nIn other words: code generation should restore the original CultCache feeling\r\nwithout pretending Rust has runtime reflection hiding under the floorboards.\r\n\r\n## Current Surface\r\n\r\n- `CultCache::new`\r\n- `register_entry_type::`\n- `add_generic_backing_store`\r\n- `add_backing_store`\r\n- `pull_all_backing_stores`\r\n- `get::`\n- `get_required::`\n- `get_envelope::`\n- `get_required_envelope::`\n- `get_all::`\n- `put::`\n- `put_envelope::`\n- `update::`\n- `delete::`\n- `snapshot`\n- `SingleFileMessagePackBackingStore`\r\n\r\n## Backing Store Routing\r\n\r\nGeneric store:\r\n\r\n```rust\r\ncache.add_generic_backing_store(SingleFileMessagePackBackingStore::new(\"cache.msgpack\"));\r\n```\r\n\r\nType-specific store:\r\n\r\n```rust\r\ncache.add_backing_store(\r\n SingleFileMessagePackBackingStore::new(\"players.msgpack\"),\r\n [\"player\"],\r\n);\r\n```\r\n\r\nWhen writing a `PlayerData`, the cache checks type-specific stores first. If none\r\nmatch, it writes to the first generic store. Later matching stores are mirrors.\r\n\r\nThis mirrors the C# behavior:\r\n\r\n- specific domain stores own their domain\r\n- the first generic store is the primary generic write target\r\n- later generic stores mirror writes\r\n- this is not multi-master\r\n\r\n## Persistence Semantics\r\n\r\n`put` persists before mutating the in-memory cache. If persistence fails, the\ncache does not pretend the write succeeded.\n\nThe envelope is MessagePack, and the payload inside each envelope is also raw\nMessagePack bytes encoded from the registered concrete `DatabaseEntry` type.\nThat avoids the old bootstrap path where payloads were normalized through\n`serde_json::Value`.\n\nFor bit-compatible neighbors, that also enables a real fast lane:\n\n- `get_envelope::()` exports the canonical persisted bytes for a typed entry\n- `put_envelope::()` ingests the same envelope into another cache instance\n without re-encoding the payload first\n\nIt still decodes once for validation and typed reads. We are not pretending one\n`Vec` became metaphysically zero-copy because we believed in it harder. But\nthe stupid decode/re-encode loop is gone.\n\nThe `DatabaseEntry` derive does not trust Rust source field order as the durable\nschema. Every persisted member must declare a stable integer slot:\n\n```rust\n#[derive(Clone, DatabaseEntry)]\n#[cultcache(type = \"player\")]\npub struct PlayerData {\n #[cultcache(key = 0)]\n pub id: String,\n\n #[cultcache(key = 1)]\n pub name: String,\n\n #[cultcache(key = 2, default)]\n pub level: u32,\n}\n```\n\nThe derive emits a tuple/array formatter. Gaps serialize as nil. Missing fields\nmarked `default` use `Default::default()` when older payloads are read. Deleted\nfield slots should stay reserved until an explicit store migration rewrites the\ndata.\n\nThe single-file MessagePack store rewrites an atomic snapshot. That is a sane\nstarting point for small typed state surfaces, settings, Epiphany agent memory,\nheartbeat state, and other compact control-plane data. Large corpora should use\na sharded store or a real database instead of asking one file to become a\nwarehouse and then acting wounded when physics invoices us.\n\nThe single-file store uses a sidecar lock file for shared reads and exclusive\nwrites. That protects ordinary multi-process access to the same file. It is\nstill not a multi-master replication protocol, and it is not a substitute for a\ncoordinator when higher-level write ordering matters.\n\r\n## Near-Term Ergonomic Improvements\r\n\r\n1. **Derive macro**\n - `#[derive(DatabaseEntry)]`\n - `#[cultcache(type = \"...\")]`\n - `#[cultcache(key = N)]` on every persisted field\n - tuple/array formatter generation landed\n - optional `#[cultcache(name)]`, `#[cultcache(index)]`, and\n `#[cultcache(global)]` are still future work\n\r\n2. **Generated registry**\n - a `CultCacheRegistry` trait\n - `cache.register_registry(GameCultEntries)`\n - basic macro registry landed\n - automatic inventory/build-script generation and store routes are future work\n\r\n3. **Name and index lookups**\r\n - `cache.get_by_name::(\"Potion\")`\r\n - `cache.get_by_index::(\"faction\", \"Lucent\")`\r\n - generated extractors instead of reflection strings\r\n\r\n4. **Schema/version metadata**\r\n - schema version in the envelope or payload metadata\r\n - explicit migration hooks\r\n - refusal on unknown persisted entry types unless a migration/resolver is\r\n installed\r\n\r\n5. **Projection helpers**\r\n - JSON projection for review and git diffs\r\n - vector stripping / large-field elision for agent memory surfaces\r\n\r\n## Why Not Skip Registration Immediately?\r\n\r\nRust can only deserialize polymorphic data into concrete types if something\nmaps the persisted `type` discriminator to the Rust type. In C#, reflection and\nMessagePack resolvers can discover a closed `DatabaseEntry` inheritance tree at\nruntime and route it through known formatters. In Rust, that map has to come from\nsomewhere:\n\r\n- explicit registration\r\n- a generated registry\r\n- a macro inventory crate\r\n- a hand-written resolver\r\n\r\nExplicit registration is the simplest honest implementation. Generated registry\nis the ergonomic destination. Hand-written resolver tables are the punishment\nwe give ourselves if we get lazy.\n\n## Security Model\n\nCultCache should never parse arbitrary structured data into arbitrary runtime\ntypes. It only accepts persisted envelopes whose `type` discriminator resolves\nto a known `DatabaseEntry` type registered in the cache or generated registry.\n\nThat is the Rust version of the original trick:\n\n- C# refuses to store objects outside the `DatabaseEntry` root type.\n- Runtime-visible `DatabaseEntry` subclasses get dedicated formatters.\n- Unknown or unregistered types are rejected.\n- MessagePack payload bytes deserialize through known concrete formatters, not\n an open-world type loader or generic structured-value bridge.\n\nThe derive/registry work should preserve that shape. Its job is to remove\nmanual registration ceremony, not to loosen the closed-world boundary.\n\r\n## License\r\n\r\nPrivate GameCult infrastructure for now. Public packaging can wait until the\r\nAPI grows enough teeth to deserve strangers.\r\n", + "truncated": false + }, + { + "bytes": 8312, + "kind": "readme", + "path": "packages/cultcache-ts/README.md", + "text": "# CultCacheTS\n\n`CultCacheTS` is the TypeScript port of the useful part of GameCult's `CultCache` idea: consumer code talks to typed domain documents, while a closed-world persistence layer deals with schemas, routing, name lookups, indexes, globals, and raw MessagePack bytes.\n\nThis is not an ORM in a fake mustache. It is for cases where you want:\n\n- one cache API for heterogeneous domain documents\n- typed reads and writes instead of every script massaging anonymous blobs\n- lookup by type, logical key, name, and indexed property\n- singleton-style global documents\n- backing-store routing instead of every caller pawing raw files directly\n- a persistence boundary that refuses unregistered polymorphic junk\n\n## Current Shape\n\n- document types are registered explicitly\n- a document schema only needs a `parse(...)` function, so generated JSON-schema\n contracts can plug in directly without growing a second hand-written Zod body\n- each persisted record stores:\n - `key`\n - `schemaId`\n - raw MessagePack `payload` bytes\n - `storedAt`\n- the single-file store writes the CultCache v1 snapshot shape:\n - `formatVersion`\n - embedded schema catalog\n - record array\n- payload bytes only decode through the registered document definition for that schema\n- name and index maps live in the cache, not in the backing store\n- global documents are treated as a singleton per type\n- backing stores are adapters, not the public data model\n\nThat keeps the polymorphic boundary tight without making callers write boilerplate by candlelight.\n\n## `.cc` Inspection\n\nCultCache files may use the `.cc` extension. The bytes are still the canonical\n`cultcache.store.v1` MessagePack snapshot; the extension is the human handle, not\na second format.\n\n`inspectCultCacheBytes(...)` reads `.cc`, `.msgpack`, or `.mpack` bytes and\nreturns the snapshot header, schema catalog, records, and decoded MessagePack\npayload previews without registering application schemas. Presentation runtimes\nsuch as Huginn consume that inspection result; they do not own the storage\nformat.\n\n## Example\n\n```ts\nimport { z } from \"zod\";\nimport {\n CultCache,\n SingleFileMessagePackBackingStore,\n defineDocumentRegistry,\n defineDocumentType,\n} from \"cultcache-ts\";\n\nconst itemDocument = defineDocumentType({\n type: \"item\",\n schemaId: \"gamecult.item.v1\",\n schemaName: \"item\",\n schemaVersion: \"item.v1\",\n schema: z.object({\n name: z.string(),\n category: z.string(),\n value: z.number().int(),\n }),\n name: \"name\",\n indexes: {\n category: \"category\",\n },\n});\n\nconst settingsDocument = defineDocumentType({\n type: \"settings\",\n schema: z.object({\n theme: z.string(),\n retries: z.number().int().nonnegative(),\n }),\n global: true,\n});\n\nconst registry = defineDocumentRegistry(itemDocument, settingsDocument);\n\nconst cache = CultCache.builder()\n .withRegistry(registry)\n .withGenericStore(new SingleFileMessagePackBackingStore(\"cache.msgpack\"))\n .build();\n\nawait cache.pullAllBackingStores();\n\nawait cache.put(itemDocument, \"item:potion\", {\n name: \"Potion\",\n category: \"Consumable\",\n value: 50,\n});\n\nawait cache.putGlobal(settingsDocument, {\n theme: \"ash\",\n retries: 3,\n});\n\nconst potion = cache.getByName(itemDocument, \"Potion\");\nconst consumable = cache.getByIndex(itemDocument, \"category\", \"Consumable\");\nconst settings = cache.getRequiredGlobal(settingsDocument);\n```\n\n## Public Surface\n\n- `defineDocumentType(...)`\n- `defineDocumentRegistry(...)`\n- `CultCache.builder()`\n- `registerDocumentType(...)`\n- `registerRegistry(...)`\n- `registerNameLookup(...)`\n- `registerIndex(...)`\n- `addBackingStore(...)`\n- `addGenericBackingStore(...)`\n- `pullAllBackingStores()`\n- `get(...)`\n- `getRequired(...)`\n- `getAll(...)`\n- `getKeyByName(...)`\n- `getByName(...)`\n- `getKeyByIndex(...)`\n- `getByIndex(...)`\n- `getGlobal(...)`\n- `getRequiredGlobal(...)`\n- `put(...)`\n- `putGlobal(...)`\n- `update(...)`\n- `updateGlobal(...)`\n- `delete(...)`\n- `deleteGlobal(...)`\n- `snapshot()`\n- `getEnvelope(...)`\n- `getRequiredEnvelope(...)`\n- `getGlobalEnvelope(...)`\n- `putEnvelope(...)`\n\nDocument definitions may also carry persistence metadata for cross-language\nstores: `schemaId`, `schemaName`, `schemaVersion`, `contentHash`,\n`canonicalSchemaJson`, `compatibleSchemaIds`, and slot `members`.\n\n## Name, Index, and Global Semantics\n\n`name` and `indexes` can be declared on the document definition:\n\n```ts\nconst playerDocument = defineDocumentType({\n type: \"player\",\n schema: playerSchema,\n name: \"displayName\",\n indexes: {\n faction: \"faction\",\n email: \"email\",\n },\n});\n```\n\nYou can also register them later if you feel like changing the machine after boot:\n\n```ts\ncache.registerNameLookup(playerDocument, \"displayName\");\ncache.registerIndex(playerDocument, \"faction\", \"faction\");\n```\n\nGlobal documents are singleton-style per type:\n\n```ts\nawait cache.putGlobal(settingsDocument, { theme: \"ash\", retries: 3 });\nconst settings = cache.getRequiredGlobal(settingsDocument);\n```\n\nIf persisted state contains two globals for the same type, `pullAllBackingStores()` fails closed instead of pretending the contradiction is charming.\n\n## Typed Formatters\n\nEach document definition can provide a custom formatter:\n\n```ts\nconst combatLogDocument = defineDocumentType({\n type: \"combat-log\",\n schema: combatLogSchema,\n formatter: {\n encode(value) {\n return myFastBinaryEncoder(value);\n },\n decode(payload) {\n return myFastBinaryDecoder(payload);\n },\n },\n});\n```\n\nIf you do not supply one, `CultCacheTS` uses MessagePack plus Zod validation by default.\n\nZod is no longer mandatory. Any schema object with a `parse(...)` function will\ndo, which means generated Ajv-backed JSON-schema contracts can feed the cache\ndirectly as long as they expose the same parse surface.\n\nThe important boundary is this:\n\n- payload bytes are persisted as bytes\n- decoding goes through the registered formatter for that document type\n- the decoded value is still validated against the declared schema\n\nSo callers get typed values, and the persistence layer does not become an open polymorphic sewer.\n\n## Raw Envelope Fast Path\n\nFor bit-compatible neighbors such as CultNet peers that already share the same\nformatter contract, `CultCacheTS` can now move the persisted envelope directly:\n\n- `getEnvelope(...)` / `getRequiredEnvelope(...)` export the canonical\n MessagePack payload bytes for a typed document\n- `putEnvelope(...)` ingests that envelope into another cache instance without\n re-encoding the payload first\n\nRaw envelopes may carry `schemaId` and catalog metadata. Domain callers should\nnot need that sludge. Replication, migration tooling, and wire-compatibility\ntests do.\n\nThat still is not magic shared memory. The cache decodes once so lookups and\ntyped reads stay honest. But it stops doing the stupid part where identical\nMessagePack payload bytes get decoded into a generic value, then re-encoded\ninto the same bytes again just to cross the room.\n\n## Security Model\n\n`CultCacheTS` should never deserialize arbitrary persisted payloads into arbitrary runtime shapes.\n\nIt only accepts persisted records whose `schemaId` or legacy `type` discriminator resolves to a registered document definition on the cache instance. Unknown schemas fail immediately. Known schemas decode through the registered formatter and schema only.\n\nThat is the TypeScript version of the original CultCache trick:\n\n- closed discriminator set\n- explicit registration\n- typed formatter path\n- no runtime type-name roulette\n\n## Persistence Model\n\n`SingleFileMessagePackBackingStore` is the first concrete store.\n\n- it writes atomic CultCache v1 MessagePack snapshots\n- the top-level MessagePack value is `[formatVersion, schemaCatalog, records]`\n- each record is `[key, schemaId, storedAt, payload]`\n- each catalog entry is `[schemaId, schemaName, schemaVersion, contentHash, canonicalSchemaJson, compatibleSchemaIds, members]`\n- it still reads the older TS/Rust-style envelope array and rewrites repaired legacy payloads as v1 snapshots\n- it queues local writes so one process does not step on its own shoelaces\n- it persists raw MessagePack payload bytes inside schema-addressed records\n\nIt is a control-plane store, not a tiny god. If multiple processes hammer the same file, you still need a coordinator or an external lock instead of prayer.\n", + "truncated": false + }, + { + "bytes": 2406, + "kind": "readme", + "path": "packages/cultmesh-ts/README.md", + "text": "# CultMesh TS\r\n\r\n`cultmesh-ts` is the TypeScript projection of CultMesh contracts for local\ntools and browser-adjacent runtimes. The C# `GameCult.Mesh` package owns the\nnative CultMesh stream implementation used by Mimir and Fensalir; this package\nmirrors the typed declaration and negotiation shapes without owning the hot\nframe body path.\n\r\n## Streaming Mode\r\n\r\nCultMesh streaming mode is for audio, video, tensor, and opaque byte frames that\r\nneed to move between diverse runtimes with as few copies as the platform allows.\r\nIt is not document replication with a bigger packet.\r\n\r\nThe split is deliberate:\r\n\r\n- CultMesh owns stream identity, authority, clock metadata, negotiated body\r\n transport, frame cursors, and health/backpressure state.\r\n- The body lane owns frame bytes or native handles: shared memory, D3D11/D3D12\r\n textures, DMA-BUF, IOSurface, AHardwareBuffer, CultCache page refs, or inline\r\n bytes as a last resort.\r\n- Producers report `unavoidableCopyCount`; zero-copy is a target and a measured\r\n property, not a vibe in a lab coat.\r\n\r\nThe mirrored API shape is `CultMeshStreamCatalog`:\n\r\n```ts\r\nimport { CultMesh } from \"cultmesh-ts\";\r\n\r\nconst streams = CultMesh.createStreamCatalog();\r\n\r\nstreams.declare({\r\n streamId: \"mimir:kiyo-pro\",\r\n verseId: \"studio\",\r\n ownerPeerId: \"starfire\",\r\n kind: \"video\",\r\n clock: { clockDomainId: \"starfire-qpc\" },\r\n video: {\r\n width: 1920,\r\n height: 1080,\r\n pixelFormat: \"YUY2\",\r\n framesPerSecond: 30,\r\n },\r\n preferredTransports: [\r\n \"shared-d3d12-texture\",\r\n \"shared-memory\",\r\n \"cultcache-page\",\r\n ],\r\n});\r\n\r\nconst lane = streams.negotiate(\"mimir:kiyo-pro\", {\r\n peerId: \"fensalir\",\r\n verseId: \"studio\",\r\n supportedTransports: [\"shared-d3d12-texture\", \"cultcache-page\"],\r\n acceptedKinds: [\"video\"],\r\n canImportGpuHandles: true,\r\n});\r\n\r\nstreams.publishFrame({\r\n streamId: lane.streamId,\r\n sequence: 42n,\r\n timestampNs: 1_000_000_000n,\r\n durationNs: 33_333_334n,\r\n transport: lane.transport,\r\n nativeHandle: \"0xfeed\",\r\n fenceHandle: \"0xbeef\",\r\n fenceValue: 7n,\r\n unavoidableCopyCount: 0,\r\n});\r\n```\r\n\r\nCurrent implementation status: this package mirrors typed stream declaration,\nnegotiation, and latest-frame cursor contracts for non-C# clients. The native\nC# path owns shared-memory rings and GPU-handle integration points. CultCache\npage append/readback remains the durable recording or nonlocal fallback.\n", + "truncated": false + }, + { + "bytes": 3512, + "kind": "readme", + "path": "packages/cultnet-rs/README.md", + "text": "# CultNet RS\r\n\r\n`cultnet-rs` is the Rust sibling of `cultnet-ts`: typed MessagePack messages,\r\n4-byte length-prefixed direct-pipe framing, CultLib-shaped security helpers, and\r\nCultCache replication without making callers paw through raw envelopes like we\r\nlost a bet.\r\n\r\nThe contract is intentionally boring:\r\n\r\n- `cultnet.schema.v0` sends schema-versioned MessagePack objects.\r\n- `gamecult.networking.v0` maps the legacy C# union shape explicitly.\r\n- schema discovery uses explicit catalog request/response messages; no inbound\r\n auto-detect sludge.\r\n- document put/delete/snapshot messages move typed CultCache entries.\r\n- raw document put/snapshot messages preserve canonical MessagePack payload\r\n bytes for bit-compatible neighbors.\r\n- hello messages advertise `supportedMutationContracts`, so callers discover\r\n which document types are read-only, which accept typed intents, which\r\n authority owns the mutation, and which receipt documents prove the outcome.\r\n- payloads are decoded through registered Rust types before entering the cache.\r\n\r\nThis crate is not an HTTP wrapper. It is the wire vocabulary Epiphany,\r\nGhostlight, VoidBot, and the rest of the swarm can share.\r\n\r\nThe public API surface is the schema plus its mutation contracts. A runtime does\r\nnot expose a pile of bespoke verbs and hope everyone remembers the ritual; it\r\nadvertises typed documents, typed intents, and typed receipts. Polite machines\r\nknock on the contract before touching the furniture.\r\n\r\n## Receipts\r\n\r\n```powershell\r\ncargo test\r\n```\r\n\r\nThe initial tests prove:\r\n\r\n- CultLib-compatible AES-GCM string encryption and HMAC session tokens\r\n- 4-byte big-endian MessagePack framing\r\n- schema-versioned message round trips\r\n- legacy `gamecult.networking.v0` login mapping\r\n- schema discovery catalog responses with canonical JSON schema hashes\r\n- CultCache snapshot replication through registered typed documents\r\n- raw snapshot replication that preserves the original payload bytes\r\n- document mutation contract advertisement through hello frames and registries\r\n\r\n## Schema Discovery\r\n\r\n`cultnet-rs` now ships a built-in schema registry for the shared swarm contract\r\nsurface:\r\n\r\n- core wire messages\r\n- legacy `gamecult.networking.v0` auth/sample payloads\r\n- schema catalog request/response messages\r\n- the canonical `ghostlight.agent-state` document payload schema\r\n\r\nUse `builtin_schema_registry()` when you want the standard catalog, or register\r\nyour own closed-world schema set with `CultNetSchemaRegistry`. Discovery stays\r\nexplicit on purpose: peers advertise only the contracts they were compiled to\r\nunderstand, the same way CultCache only consumes the document types you\r\nregistered instead of pretending polymorphism is a public park.\r\n\r\n## Local Fast Lane\r\n\r\n`cultnet-rs` now mirrors the raw replication seam from `cultnet-ts`:\r\n\r\n- `cultnet.document_put_raw.v0`\r\n- `cultnet.snapshot_response_raw.v0`\r\n\r\nThose messages carry the exact persisted MessagePack payload bytes from\r\nCultCache along with the typed envelope metadata. Combined with\r\n`CultCache::put_envelope::()`, that lets a bit-compatible neighbor ingest the\r\ndocument without re-encoding the payload first.\r\n\r\nThat still is not zero-copy in the religious sense. Frames allocate, bytes move,\r\nand the receiving cache still decodes once to keep typed reads and validation\r\nhonest. The win is narrower and realer: identical payload bytes stop getting\r\ndecoded into generic sludge and then encoded right back into the same bytes for\r\nno reason.\r\n", + "truncated": false + }, + { + "bytes": 8437, + "kind": "readme", + "path": "packages/cultnet-ts/README.md", + "text": "# CultNet TS\n\n`cultnet-ts` is the TypeScript port of the useful shape of GameCult's\nnetworking layer: typed MessagePack messages, direct-pipe framing, CultLib-style\nsecurity/session helpers, and state replication that hands typed values into a\n`CultCache` instead of making consumer code paw raw database envelopes.\n\nThis is not an HTTP wrapper wearing a fake mustache. It is for runtimes that\nalready trust a direct channel and want a compact shared contract over it.\n\n## Scope\n\nThe library currently includes:\n\n- JSON-schema-backed wire contracts for the first CultNet message set\n- a MessagePack codec plus 4-byte length-prefixed framing for direct pipes\n- a `CultNetPeer` wrapper over any Node `Duplex`\n- CultLib-style client/server security options and `Secret` helpers\n- session-token signing/validation compatible with the C# CultLib semantics\n- explicit wire-contract selection instead of heuristic payload guessing\n- `CultCacheTS` replication helpers for document put/delete/snapshot flows\n- schema discovery catalog messages and a registry for asking what contracts a\n peer can actually exchange safely\n- generated TypeScript contracts and runtime verifiers from canonical JSON\n schemas owned elsewhere in the swarm\n- an exact mirrored runtime validator and generated TS contract surface for\n Ghostlight's canonical `ghostlight.agent_state.v0` payload\n\n## Why This Exists\n\nWe want:\n\n- one shared agent-state vocabulary across `Ghostlight`, `EpiphanyAgent`,\n `VoidBot`, and whatever other little laboratory creature appears next\n- typed persistence through `CultCache`\n- direct pipes instead of every consumer inventing bespoke JSON fog\n- authentication and session semantics that match the original CultLib intent\n\nSo the split is:\n\n- `cultcache-ts`: typed local persistence\n- `cultnet-ts`: typed transport, auth, and state replication\n\nSame family. Different organs. Nobody needs a second spine growing out of the\ntransport layer.\n\n## Contracts\n\nWire contracts live under `contracts/` as JSON Schema files.\n\nCurrent message families:\n\n- `cultnet.hello.v0`\n- `cultnet.login.v0`\n- `cultnet.register.v0`\n- `cultnet.verify.v0`\n- `cultnet.login_success.v0`\n- `cultnet.error.v0`\n- `cultnet.document_put.v0`\n- `cultnet.document_delete.v0`\n- `cultnet.document_put_raw.v0`\n- `cultnet.snapshot_request.v0`\n- `cultnet.snapshot_response.v0`\n- `cultnet.snapshot_response_raw.v0`\n- `cultnet.sample.change_name.v0`\n- `cultnet.sample.chat.v0`\n\nFor shared agent state, the first payload contract is the existing Ghostlight\nfixture format:\n\n- payload schema version: `ghostlight.agent_state.v0`\n- mirrored validator: `contracts/ghostlight.agent-state.schema.json`\n\nThat means `EpiphanyAgent` role dossiers and Ghostlight fixtures can travel over\nCultNet without inventing a second ontology first.\n\n## Generated Swarm Contracts\n\n`cultnet-ts` can consume canonical JSON Schema files and generate:\n\n- TypeScript contract classes/interfaces\n- runtime schema verifiers\n- parse-compatible schema objects that can be handed directly to\n `CultCacheTS`\n\nThe manifest lives at [contracts/swarm-contracts.manifest.json](contracts/swarm-contracts.manifest.json).\nRight now it points at Ghostlight's canonical agent-state schema, because\nGhostlight owns the swarm's most important mind-shape contract.\n\nGenerate the contract layer with:\n\n```bash\nnpm run contracts:generate\n```\n\nThat emits [src/generated/swarm-contracts.generated.ts](src/generated/swarm-contracts.generated.ts),\nwhich exports:\n\n- the generated TS contract shape\n- named runtime verifier helpers such as\n `validateGhostlightAgentStateGenerated(...)` and\n `parseGhostlightAgentStateGenerated(...)`\n- a runtime `validate(...)` / `parse(...)` contract object via\n `defineJsonSchemaContract(...)`\n- a contract object that `CultCacheTS` can persist directly without a second\n hand-written Zod mirror\n\n## Wire Contracts\n\n`cultnet-ts` does not sniff random payloads and pretend that counts as rigor.\nYou choose the contract explicitly.\n\nCurrent wire-contract options:\n\n- `cultnet.schema.v0`\n - the newer schema-versioned object contract for CultNet-native message\n families such as hello, document replication, and snapshots\n- `gamecult.networking.v0`\n - the legacy C# `GameCult.Networking` MessagePack union contract for\n login/register/verify/session/error plus the sample `ChangeNameMessage` and\n `ChatMessage` payloads\n\nSo the transport can stay developer-friendly while the binary stops freelancing\naway from the C# lineage.\n\n## Local Fast Lane\n\nFor direct-pipe neighbors that already share the same CultCache formatter\ncontract, `cultnet-ts` now has a raw replication lane:\n\n- `cultnet.document_put_raw.v0`\n- `cultnet.snapshot_response_raw.v0`\n\nThose messages carry the canonical persisted MessagePack payload bytes plus the\ntyped envelope metadata. Paired with `CultCacheTS.putEnvelope(...)`, that means\nthe receiving cache can ingest the exact payload bytes directly instead of\ndecoding them into generic object soup and then re-encoding the same document\nagain.\n\nThis is cheaper. It is not magic:\n\n- framing still copies\n- MessagePack decoding still happens once on ingest\n- ordinary `CultNetPeer` send/receive still materializes messages\n\nBut for local or near-local runtimes sharing the same contract, the fast lane\ncuts out the dumbest part of the trip.\n\n## Schema Discovery\n\nApps sharing a CultNet space should be able to ask each other what they can\nexchange without resorting to folklore.\n\n`cultnet-ts` now includes:\n\n- `cultnet.schema_catalog_request.v0`\n- `cultnet.schema_catalog_response.v0`\n- `CultNetSchemaRegistry`\n- `cultNetBuiltinSchemaRegistry`\n\nDescriptors include:\n\n- canonical `schemaId`\n- discovery `kind`\n- optional `schemaVersion`\n- optional `documentType`\n- supported `wireContracts`\n- a SHA-256 `contentHash`\n- optional inline `schemaJson`\n\nThe inline schema body travels as canonical JSON text, not as a loose object\ngraph. Discovery is supposed to reduce ambiguity, not smuggle in a cute new\npolymorphic attack surface.\n\n## Quick Example\n\n```ts\nimport { CultCache, defineDocumentType } from \"cultcache-ts\";\nimport {\n CultNetDocumentRegistry,\n CultNetPeer,\n defineCultNetDocumentBinding,\n ghostlightAgentStateGeneratedContract,\n} from \"cultnet-ts\";\n\nconst ghostlightStateDefinition = defineDocumentType({\n type: \"ghostlight.agent-state\",\n schema: ghostlightAgentStateGeneratedContract,\n});\n\nconst registry = new CultNetDocumentRegistry([\n defineCultNetDocumentBinding({\n definition: ghostlightStateDefinition,\n payloadSchemaVersion: \"ghostlight.agent_state.v0\",\n }),\n]);\n\nconst peer = new CultNetPeer(stream, {\n wireContract: \"cultnet.schema.v0\",\n});\n```\n\n## Security Model\n\nThe security helpers intentionally mirror CultLib's shape:\n\n- shared connection key -> SHA-256 derived AES-GCM key\n- server-only session signing secret -> HMAC-SHA256 session token signing\n- 12-byte nonce\n- authentication tag prefixed onto ciphertext\n- session token format: `base64url(payload).base64url(signature)`\n\nThat means a TypeScript runtime can follow the same cryptographic and session\nstory as the C# version instead of inventing one more house religion around\n\"trust me, this pipe is probably fine.\"\n\nFor the legacy `gamecult.networking.v0` contract, `cultnet-ts` normalizes the\nencrypted binary fields as base64url strings in the ergonomic TS surface and\nmaps them back to the exact C# union payload shape at the wire boundary.\n\n## Current Limits\n\n- This repo currently implements the client-side wire contract and pipe\n ergonomics, not a full account server.\n- The Ghostlight agent-state mirror is an exact copy of Ghostlight's current\n canonical schema. If Ghostlight changes the contract, this mirror must be\n updated in lockstep instead of playing coy with partial validation.\n- The direct transport is any Node `Duplex`; named-pipe/socket server wrappers\n can be added without changing the message contract.\n\n## Development\n\n```bash\nnpm install\nnpm run contracts:generate\nnpm run build\nnpm run typecheck\nnpm run test\n```\n\n## Interop CI\n\nThe cross-runtime interop harness is meant to run in GitHub Actions on\n`windows-latest`.\n\nIt expects these sibling checkouts inside the same workspace:\n\n- `CultNetTS`\n- `cultnet-rs`\n- `cultcache-rs`\n- `CultLib`\n\nThe workflow lives at\n[.github/workflows/cultnet-interop.yml](.github/workflows/cultnet-interop.yml)\nand drives the whole ritual through one command:\n\n```bash\nnpm run test:interop\n```\n", + "truncated": false + }, + { + "bytes": 1004, + "kind": "readme", + "path": "src/GameCult.Caching.MessagePack.Analyzers/README.md", + "text": "# GameCult.Caching.MessagePack.Analyzers\n\n`GameCult.Caching.MessagePack.Analyzers` is the delivery mechanism for the MessagePack source generator used by the cache libraries.\n\n## Scope\n\nThis project is primarily packaging infrastructure. It exists so consuming projects can receive generator output at compile time without treating the generator assembly as a normal runtime dependency.\n\n## What It Does\n\n- references the generator project\n- arranges for the generator assembly to be packed under `analyzers/dotnet/cs`\n- keeps generator assets out of the normal compile/runtime reference flow\n\n## Practical Meaning\n\nWhen a consuming project adds the analyzer package:\n\n- the generator runs during compilation\n- concrete `DatabaseEntry` types receive generated MessagePack formatters\n- `GameCult.Caching.MessagePack` can then serialize those types without handwritten formatter code\n\n## Current State\n\nThis project is a packaging host. It does not currently expose custom analyzer diagnostics of its own.\n", + "truncated": false + }, + { + "bytes": 2458, + "kind": "readme", + "path": "src/GameCult.Caching.MessagePack.Generator/README.md", + "text": "# GameCult.Caching.MessagePack.Generator\n\n`GameCult.Caching.MessagePack.Generator` is a Roslyn incremental source generator that emits MessagePack formatters for concrete `DatabaseEntry` subclasses.\n\n## Scope\n\nThis project is infrastructure for the caching stack. Application code usually does not reference it directly.\n\nIts job is to:\n\n- find non-abstract subclasses of `DatabaseEntry`\n- generate concrete `IMessagePackFormatter` implementations\n- generate resolver mappings consumed by `DatabaseEntryResolver`\n\n## What It Generates\n\nFor each discovered concrete `DatabaseEntry` subtype, the generator emits:\n\n- a formatter type\n- a resolver mapping entry\n\nMember slot assignment is:\n\n1. `ID` in slot `0`\n2. members with `[Key(...)]` in their exact key slot\n3. remaining non-ignored instance fields and properties appended after the\n highest occupied slot as legacy convenience\n\nThe generated formatter writes a MessagePack array sized to the highest occupied\nslot and writes nil for unused gaps. Deserialization tolerates shorter older\narrays by leaving missing members at their constructor/field-initializer values,\nand skips unknown extra slots. That makes `[Key(n)]` a durable wire contract:\ndeleted fields can leave their slot reserved and new fields can use new keys\nwithout a store migration.\n\nFor schema-stable cache entries, annotate every persisted member. Unkeyed\nmembers are supported for older code, but they are not a good long-term wire\ncontract because source member order is not a schema.\n\n## Example\n\nGiven:\n\n```csharp\n[MessagePackObject]\npublic class PlayerData : DatabaseEntry, INamedEntry\n{\n [Key(1)] public string Email = string.Empty;\n [Key(2)] public string PasswordHash = string.Empty;\n [Key(3)] public string Username = string.Empty;\n\n [IgnoreMember]\n public string EntryName\n {\n get => Username;\n set => Username = value;\n }\n}\n```\n\nthe generator emits the formatter plumbing needed for MessagePack serialization of `PlayerData` without manually implementing an `IMessagePackFormatter`.\n\n## When You Need To Think About This Package\n\nUsually only when:\n\n- formatter generation is not happening\n- a cache-entry type is not serializing as expected\n- you are debugging build-time source generation behavior\n\n## Distribution\n\nThe generator is packaged for consumers through [../GameCult.Caching.MessagePack.Analyzers/README.md](../GameCult.Caching.MessagePack.Analyzers/README.md).\n", + "truncated": false + }, + { + "bytes": 1961, + "kind": "readme", + "path": "src/GameCult.Caching.MessagePack/README.md", + "text": "# GameCult.Caching.MessagePack\r\n\r\n`GameCult.Caching.MessagePack` provides the canonical CultCache persistence\r\nformat for the attribute-first `GameCult.Caching` stack.\r\n\r\n## Included Types\r\n\r\n- `SingleFileMessagePackBackingStore`\r\n- `CultDocumentMessagePackSerialization`\r\n- `CultDocumentResolver`\r\n- `CultRecordRefFormatter`\r\n\r\nWhen a project declares `[CultDocument]` models, wire in the\r\n`GameCult.Caching.MessagePack.Generator` analyzer there as well. It emits\r\nassembly-local metadata providers for the cache registry. Cult documents then\r\nserialize through explicit generated slot codecs, while the store snapshot\r\nformat is written by hand against `MessagePackWriter`/`MessagePackReader`.\r\n\r\n## What It Does\r\n\r\n- stores whole CultCache snapshots in MessagePack\r\n- serializes plain attributed document payloads through explicit generated slot codecs\r\n- keeps explicit `CultRecordRef` values compact on disk/wire\r\n- preserves the cache/store split where metadata lives outside the domain model\r\n\r\n## Example Model\r\n\r\n```csharp\r\nusing GameCult.Caching;\r\nusing MessagePack;\r\n\r\n[CultDocument(\"gamecult.item_data\", \"gamecult.item_data.v1\")]\r\npublic sealed class ItemData\r\n{\r\n [Key(0)] [CultName] public string Name = string.Empty;\r\n [Key(1)] public int Value;\r\n}\r\n```\r\n\r\n## Typical Usage\r\n\r\n```csharp\r\nusing GameCult.Caching;\r\nusing GameCult.Caching.MessagePack;\r\n\r\nvar cache = new CultCache();\r\nvar store = new SingleFileMessagePackBackingStore(\"Data.msgpack\");\r\n\r\ncache.AddBackingStore(store);\r\nawait cache.PullAllBackingStoresAsync();\r\n```\r\n\r\n## Notes\r\n\r\n- Payload bytes are MessagePack. Store metadata and schema catalogs are also\r\n persisted through hand-written MessagePack array layouts in this package.\r\n- The generator package now targets attributed document types instead of\r\n `DatabaseEntry` subclasses.\r\n- The raw CultNet document lane should treat these payload bytes as already\r\n blessed, not decode and re-encode them for sport.\r\n", + "truncated": false + }, + { + "bytes": 6190, + "kind": "readme", + "path": "src/GameCult.Caching/README.md", + "text": "# GameCult.Caching\r\n\r\n`GameCult.Caching` is an attribute-driven typed cache with a canonical\r\nsingle-file MessagePack store. Domain models stay clean. The cache owns record\r\nkeys, schema ids, timestamps, and persistence metadata instead of smearing\r\nthat sludge across every class.\r\n\r\n## Authoring Model\r\n\r\nCacheable models are plain classes annotated with cache intent.\r\n\r\n```csharp\r\nusing GameCult.Caching;\r\nusing MessagePack;\r\n\r\n[CultDocument(\"gamecult.item_data\", \"gamecult.item_data.v1\")]\r\npublic sealed class ItemData\r\n{\r\n [Key(0)]\r\n [CultName]\r\n public string Name = string.Empty;\r\n\r\n [Key(1)]\r\n [CultIndex]\r\n public string Category = string.Empty;\r\n\r\n [Key(2)]\r\n public int Value;\r\n}\r\n```\r\n\r\nAvailable cache attributes:\r\n\r\n- `CultDocument(schemaName, schemaVersion)`\r\n- `CultName`\r\n- `CultIndex(alias?)`\r\n- `CultGlobal`\r\n- `CultReference(targetType?, many: false)`\r\n\r\nIf you want compile-time document metadata instead of runtime assembly\r\nspelunking, add the `GameCult.Caching.MessagePack.Generator` analyzer to the\r\nproject that declares your `[CultDocument]` types. It emits a metadata provider\r\nthe cache registry can load directly, while reflection stays behind as fallback\r\nfor projects that have not taken the hint yet.\r\n\r\n## Main Concepts\r\n\r\n### Record keys and handles\r\n\r\n`CultCache` gives each stored document a cache-owned `CultRecordKey`. You work\r\nwith typed handles instead of forcing storage identity into the domain object.\r\n\r\n```csharp\r\nvar cache = new CultCache();\r\nvar handle = await cache.AddAsync(new ItemData\r\n{\r\n Name = \"Potion\",\r\n Category = \"Consumable\",\r\n Value = 50\r\n});\r\n\r\nvar potion = cache.Get(handle.Key);\r\n```\r\n\r\n### Name and index lookups\r\n\r\nName and index lookups are driven from attributes, not manual registration.\r\n\r\n```csharp\r\nvar byName = cache.GetByName(\"Potion\");\r\nvar byIndex = cache.GetByIndex(\"Category\", \"Consumable\");\r\n```\r\n\r\n### Explicit references\r\n\r\nReferences stay explicit in the domain. The cache will resolve them on demand,\r\nbut it will not quietly build an entire haunted object graph behind your back.\r\n\r\n```csharp\r\n[CultDocument(\"gamecult.quest_data\", \"gamecult.quest_data.v1\")]\r\npublic sealed class QuestData\r\n{\r\n [Key(0)] public string Title = string.Empty;\r\n [Key(1)] [CultReference] public CultRecordRef Reward;\r\n}\r\n```\r\n\r\n## Persistence Shape\r\n\r\nCultCache persistence is store-shaped, not entry-shaped:\r\n\r\n1. store header\r\n2. embedded schema catalog\r\n3. records\r\n\r\nEach persisted record carries:\r\n\r\n- `key`\r\n- `schemaId`\r\n- `storedAt`\r\n- `payload`\r\n\r\nThe domain payload stays free of storage metadata.\r\n\r\n## Backing Store\r\n\r\nCultCache now has one sanctioned persistence format:\r\n\r\n- `SingleFileMessagePackBackingStore`\r\n\r\nIt persists the whole store as:\r\n\r\n1. store format version\r\n2. embedded schema catalog\r\n3. persisted records\r\n\r\nEach persisted record carries:\r\n\r\n- `key`\r\n- `schemaId`\r\n- `storedAt`\r\n- `payload`\r\n\r\n## Happy Path\n\n```csharp\nusing GameCult.Caching;\nusing GameCult.Caching.MessagePack;\n\r\nvar cache = await CultCacheMessagePack.OpenAsync(\"Data.msgpack\");\r\n\r\nvar handle = await cache.UpsertAsync(new ItemData\r\n{\r\n Name = \"Potion\",\r\n Category = \"Consumable\",\r\n Value = 50\r\n});\r\n\r\nawait cache.FlushAsync();\r\n```\r\n\nIf you want the explicit assembly rite, the lower-level `CultCache` +\n`SingleFileMessagePackBackingStore` path is still there. The helper is just the\nblessed front door.\n\n## Managed Documents And SoA Storage\n\nGameplay code keeps authoring normal typed documents. CultCache owns the record\nidentity, reactive presentation, and CPU-local structure-of-arrays table behind\nthat POCO surface.\n\n```csharp\n[CultDocument(\"game.player_transform\", \"game.player_transform.v1\")]\npublic sealed class PlayerTransform\n{\n [CultName] public string Name = string.Empty;\n public float PositionX;\n public float PositionY;\n public int Health;\n}\n\nvar player = cache.Document(new CultRecordKey(\"player:alice\"));\n\nawait player.ReplaceAsync(new PlayerTransform\n{\n Name = \"Alice\",\n PositionX = 4,\n PositionY = 8,\n Health = 100\n});\n\nusing var subscription = player.Watch().Subscribe(current => Render(current));\n\nplayer.Value!.Health = 90;\nawait player.CommitAsync();\n\nvar table = cache.Soa();\n\nSpan x = table.Column(nameof(PlayerTransform.PositionX)).Span;\nSpan y = table.Column(nameof(PlayerTransform.PositionY)).Span;\nSpan health = table.Column(nameof(PlayerTransform.Health)).Span;\n\nfor (var row = 0; row < table.Count; row++)\n{\n x[row] += 0.016f;\n}\n```\n\n`Document()` is the standard presentation. `Soa()` exposes the\ncache-owned physical table for hot loops and diagnostics; it is not a second\ndomain model callers have to maintain.\n\n## Persistence discipline\n\nPersistence stays manual by default. Mutations mark the cache and attached\nbacking stores dirty; nothing silently flushes every object write just because\nthat felt convenient in the moment.\n\r\nUseful surfaces:\r\n\r\n- `CultCacheMessagePack.OpenAsync(path)`\r\n- `cache.IsDirty`\r\n- `store.IsDirty`\n- `cache.Document(key)`\n- `cache.Soa()`\n- `cache.UpsertAsync(document)`\n- `cache.FlushAllBackingStores()`\r\n- `cache.FlushAsync()`\r\n- `cache.FlushBackingStore(store)`\r\n- `cache.PrepareForReloadOrShutdown()`\r\n- `cache.PrepareForReloadOrShutdownAsync()`\r\n- `cache.FlushAttachedStoresOnDispose`\r\n- `store.FlushOnDispose`\r\n\r\nThis is built for callers like Aquarium that want durable runtime state while\r\nstill choosing *when* to pay the write cost.\r\n\r\nSingle-file MessagePack remains a single-writer format. The atomic replace path\r\nprotects against partial writes, not competing writers trampling each other.\r\n\r\n## Schema migration diagnostics\r\n\r\nCultCache does not quietly fall back from exact `schemaId` resolution to\r\n\"close enough, probably.\" When a persisted schema drifts, the cache now emits a\r\ntyped migration report describing:\r\n\r\n- exact vs compatible-drift resolution\r\n- ignored extra slots\r\n- defaulted missing slots\r\n- warning codes/messages\r\n\r\nCompatibility rules and canonical fixture receipts live in\r\n`Contracts/cultcache-schema-compatibility.md`.\r\n", + "truncated": false + }, + { + "bytes": 2690, + "kind": "readme", + "path": "src/GameCult.Geometry/README.md", + "text": "# GameCult.Geometry\n\n`GameCult.Geometry` defines CultCache-native documents for procedural geometry\ndomains, LOD build requests, selected-cut manifests, and mesh chunk artifacts.\n\nThe package is deliberately substrate-shaped:\n\n- CultCache owns document identity, schema compatibility, references, and local\n persistence.\n- CultNet can distribute these documents through the normal raw document lane.\n- CultMesh can use them as worker-visible shared state for simulation and\n geometry pipelines.\n- JSON is not a runtime transport here. It may publish schema descriptions at\n the xeno boundary, but the live machine eats and emits typed CultCache\n documents.\n\n## Runtime Path\n\n`vg-csg` emits domain documents, selected-cut manifests, and chunk artifacts as\nMessagePack CultCache documents. A Unity runtime, local worker, or remote\ngeometry process should receive the same records through CultMesh/CultNet and\nread them back as `CultGeometry*` types.\n\n```csharp\nusing GameCult.Caching;\nusing GameCult.Geometry;\nusing GameCult.Mesh;\nusing GameCult.Networking;\n\nvar geometryDocuments = new CultNetDocumentRegistry(CultDocumentRegistry.Shared)\n .Register(CultNetDocumentBinding.ForDocument())\n .Register(CultNetDocumentBinding.ForDocument())\n .Register(CultNetDocumentBinding.ForDocument())\n .Register(CultNetDocumentBinding.ForDocument());\n\nusing var node = await CultMesh.CreateNodeAsync(\"ragnarok-geometry.ccmp\", new CultMeshNodeOptions\n{\n DatabaseOptions = new CultNetDatabaseOptions\n {\n RuntimeId = \"unity-runtime\",\n DocumentRegistry = geometryDocuments\n }\n});\n\nusing var chunks = node.Database\n .Watch()\n .Subscribe(change => ApplyChunk(change.Document));\n```\n\nThe record key is part of the contract. Rust and C# must compute the same key\nfor the same geometry record, so stable fingerprints use the Rust canonical\nfield order and invariant float text. If this drifts, the same chunk becomes two\ndifferent chunks depending on which runtime touched it first. That is not a\ncache miss; that is split-brain geometry.\n\n## Documents\n\n- `CultGeometryDomainDocument`: one hierarchical domain tree, suitable for\n Ragnarok/Fensalir-style feature DSL output.\n- `CultGeometryBuildRequest`: one LOD/frustum/budget request for workers.\n- `CultGeometrySelectedCutManifest`: the selected domain cut, deferred children,\n fallback rows, and diagnostic contribution rows.\n- `CultGeometryChunkArtifact`: render mesh, optional collider mesh, source\n domain/claim identities, build counters, and transition clipping seed.\n", + "truncated": false + }, + { + "bytes": 1794, + "kind": "readme", + "path": "src/GameCult.Logging/README.md", + "text": "# GameCult.Logging\n\n`GameCult.Logging` provides a common logging contract for cache, networking, and Unity-facing code.\n\n## Scope\n\nThis package provides a minimal logging abstraction. It does not provide structured logging, external sinks, scopes, or framework integration.\n\nIt is designed for:\n\n- simple runtime diagnostics\n- lightweight library dependencies\n- swapping logging behavior by environment\n- avoiding a hard dependency on a specific logging ecosystem\n\n## Included Types\n\n- `ILogger`: interface with `LogInfo`, `LogWarning`, `LogError`, and `LogDebug`\n- `NullLogger`: no-op implementation\n- `ConsoleLogger`: writes to `System.Console`\n- `FileLogger`: appends timestamped log lines to a file\n- `UnityLogger`: Unity-specific implementation in `src/GameCult.Logging.Unity`\n\n## Behavior Notes\n\n- `NullLogger` is the safe default used by other libraries when no logger is supplied.\n- `ConsoleLogger` colors warnings and errors.\n- `FileLogger` writes plain text entries with timestamps.\n- `UnityLogger` schedules logging to the next Unity frame instead of writing immediately.\n\n## Typical Usage\n\n```csharp\nusing GameCult.Logging;\n\nILogger logger = new ConsoleLogger();\n\nlogger.LogInfo(\"Server starting\");\nlogger.LogWarning(\"High latency detected\");\nlogger.LogError(\"Connection failed\");\n```\n\n## Swapping Implementations\n\nConsumers can choose the implementation that fits the runtime.\n\n```csharp\nusing GameCult.Logging;\nusing GameCult.Networking;\n\nvar client = new Client\n{\n Logger = new FileLogger(\"client.log\")\n};\n\nclient.Connect(\"127.0.0.1\", 3075);\n```\n\n## When To Use Something Else\n\nIf you need:\n\n- structured events\n- sinks to external observability platforms\n- log scopes\n- sampling and filtering pipelines\n- JSON log output\n\nuse a logging framework at the application boundary.\n", + "truncated": false + }, + { + "bytes": 10431, + "kind": "readme", + "path": "src/GameCult.Mesh/README.md", + "text": "# CultMesh\r\n\r\nCultMesh is the distributed realtime database and simulation-consensus layer for\r\nGameCult projects. The NuGet package and assembly are named `GameCult.Mesh`;\r\nthe public surface is branded as CultMesh.\r\n\r\nCultMesh sits over:\r\n\r\n- `GameCult.Caching` for typed domain documents, local indexes, persistence, and\r\n file-compatible cache storage.\r\n- `GameCult.Networking` for LiteNetLib transport, schema-v0 wire messages, and\r\n secure client/server sessions.\r\n\r\nThe intent is direct: a game can treat a mesh of clients and servers as one\r\nreactive database for persistent state, prediction-friendly input state, and\r\nsimulation observations.\r\n\r\n## First Node\r\n\r\n```csharp\r\nusing GameCult.Mesh;\r\n\r\nusing var node = await CultMesh.StartNodeAsync(\"world.ccmp\");\r\n\r\nvar player = await node.Database.GetAsync(playerKey);\r\nawait node.Database.PutAsync(playerKey, player);\r\n```\r\n\r\nIf you want one inspectable path that starts with a durable local cache file and\r\nends with a typed read/write through the public CultMesh surface, see\r\n[docs/durable-node-quickstart.md](docs/durable-node-quickstart.md).\r\nIf you want the lower-level typed-to-raw handoff that CultNet moves across the\r\nwire, see [docs/typed-document-path.md](docs/typed-document-path.md).\r\n\r\nEnable durable authoritative shard logs when a node should serve replica\r\ncatch-up after restart:\r\n\r\n```csharp\r\nusing var node = await CultMesh.StartNodeAsync(\"world.ccmp\", new CultMeshNodeOptions\r\n{\r\n EnableDurableShardLogs = true\r\n});\r\n```\r\n\r\nIf `ShardLogPath` is omitted, CultMesh stores logs beside the cache under\r\n`world.cultmesh/shard-logs`.\r\n\r\n## Verses\r\n\r\nA Verse is a rule-bearing consensus graph. Aetheria Main can be a\r\ncloud-authoritative Verse backed by GameCult regional simulators. A modded\r\ncommunity branch can be transport-compatible with Aetheria Main while declaring\r\ndifferent rules, required plugins, and authority policy. A peer-hosted game can\r\nchoose a peer-to-peer authority model.\r\n\r\n```csharp\r\nvar rulesHash = CultMeshVerseDescriptor.ComputeRulesHash(\r\n \"aetheria\",\r\n \"rules:v1\",\r\n \"plugins:vanilla\");\r\n\r\nvar aetheria = new CultMeshVerseDescriptor(\r\n \"aetheria-main\",\r\n \"Aetheria\",\r\n CultMeshVerseAuthorityModel.OperatorCluster,\r\n new CultMeshVerseCompatibility(\"cultmesh.v0\", rulesHash),\r\n discoveryEndpoints: [\"cultmesh://us-east.aetheria.gamecult.net:3075\"]);\r\n\r\nusing var catalog = CultMesh.CreateVerseCatalog();\r\ncatalog.Upsert(aetheria);\r\n\r\nusing var discovery = CultMesh.ServeVerseCatalog(node, catalog);\r\n```\r\n\r\nPeers can request Verse catalogs over schema-v0 with\r\n`cultmesh.verse_catalog_request.v0` and receive transport-filtered\r\n`cultmesh.verse_catalog_response.v0` descriptors.\r\n\r\n## Peer Exchange\r\n\r\nVerse discovery tells a node which consensus graph exists. Peer exchange tells\r\nit who else is already in that graph.\r\n\r\n```csharp\r\nusing var peers = CultMesh.CreatePeerCatalog();\r\npeers.Upsert(new CultMeshPeerCard(\r\n \"gc-us-east-1\",\r\n \"aetheria-main\",\r\n [\"cultnet://us-east.aetheria.gamecult.net:3075\"],\r\n roles: [CultMeshPeerRoles.Discovery, CultMeshPeerRoles.ShardPrimary],\r\n shardIds: [\"players-us-east\"],\r\n authorityLeaseId: \"lease:players-us-east:42\"));\r\n\r\nusing var exchange = CultMesh.ServePeerExchange(node, peers);\r\n```\r\n\r\nPeer cards are contact candidates, not authority by themselves. Public Verses\r\nshould validate authority leases or signatures before trusting a peer for\r\ncommitted state.\r\n\r\n```csharp\r\nvar leases = CultMesh.CreateAuthorityLeaseCatalog();\r\nleases.Upsert(new CultMeshAuthorityLease(\r\n \"lease:players-us-east:42\",\r\n \"aetheria-main\",\r\n \"gc-us-east-1\",\r\n [CultMeshPeerRoles.ShardPrimary],\r\n [\"players-us-east\"],\r\n \"gamecult-operator\",\r\n DateTimeOffset.UtcNow.AddMinutes(-1),\r\n DateTimeOffset.UtcNow.AddMinutes(10),\r\n signature: \"operator-signature\"));\r\n```\r\n\r\nClients can fetch more peers from known peers:\r\n\r\n```csharp\r\nvar exchangeClient = CultMesh.CreatePeerExchangeClient();\r\nawait exchangeClient.DiscoverAsync(\r\n peers,\r\n aetheria.DiscoveryEndpoints,\r\n \"aetheria-main\",\r\n roles: [CultMeshPeerRoles.ReadReplica]);\r\n```\r\n\r\n## Client-Side Prediction\r\n\r\nCultMesh lets a runtime declare which input documents it may author\r\noptimistically. The local cache updates immediately, game simulation can proceed\r\nagainst that predicted state, and the authoritative shard log later reconciles\r\nthe record.\r\n\r\n```csharp\r\nvar db = node.Database;\r\n\r\nawait db.PutPredictedAsync(inputKey, inputState);\r\n\r\nusing var sub = db.WatchRecord(inputKey)\r\n .Subscribe(change =>\r\n {\r\n ReconcilePrediction(change);\r\n });\r\n```\r\n\r\n## Game Session\r\n\r\n`CultMeshGameSession` wires the common gameplay loop: local catalogs,\r\nobservation hub, observation server, peer exchange, Verse discovery, prediction,\r\nand quorum fact commits.\r\n\r\n```csharp\r\nusing var session = CultMesh.CreateGameSession(node, new CultMeshGameSessionOptions\r\n{\r\n ConsensusOptions = new CultNetSimulationConsensusOptions\r\n {\r\n MinimumWitnesses = 2,\r\n QuorumRatio = 0.66d\r\n }\r\n});\r\n\r\nawait session.PredictAsync(inputKey, inputState);\n\nvar committed = await session.SubmitAndCommitAsync(new CultNetSimulationObservation\n{\n WitnessRuntimeId = \"watcher-1\",\r\n ShardId = \"arena\",\r\n ShardEpoch = 4,\r\n Frame = 100,\r\n SubjectId = \"bob\",\r\n ClaimKind = \"hit\",\r\n ClaimHash = CultNetSimulationObservation.ComputeClaimHash(\"hit\", \"alice\", \"bob\", \"frame:100\")\r\n});\n```\n\n## Managed Documents\n\nCultMesh presents distributed state as the same managed POCO document shape as\nCultCache. Local edits commit through shard authority; remote shard-log or\nnetwork events update the same watched value.\n\n```csharp\nusing GameCult.Caching;\nusing GameCult.Mesh;\n\nvar player = node.Database.Document(new CultRecordKey(\"player:alice\"));\n\nusing var subscription = player.Watch().Subscribe(current => Render(current));\n\nawait player.ReplaceAsync(new PlayerTransform\n{\n Name = \"Alice\",\n PositionX = 4,\n Health = 100\n});\n\nplayer.Value!.Health = 90;\nawait player.CommitAsync();\n```\n\nThe physical cache table remains SoA for CPU-local scans:\n\n```csharp\nSpan x = node.Cache.Soa()\n .Column(nameof(PlayerTransform.PositionX))\n .Span;\n```\n\n## Witness Consensus\n\nCultMesh nodes can publish observations about simulation facts: shard epoch,\nframe, subject, claim kind, and claim hash. `CultNetSimulationConsensus`\naggregates those observations deterministically into candidate facts with\r\nsupport weight, total observed weight, confidence, and quorum status.\r\n\r\nThose candidates are not committed world state by themselves. They are the fast\r\nmesh opinion layer that can feed an authoritative shard commit path. Once a\r\ncandidate has quorum, a shard-authoritative node can commit it as a\r\n`CultMeshSimulationFact`.\r\n\r\n```csharp\r\nvar committer = CultMesh.CreateSimulationFactCommitter(node.Database);\r\nawait committer.CommitAsync(candidate);\r\n```\r\n\r\nThe central server does not need to decide what every witness saw. It only\nneeds to accept the quorum result through the shard log.\n\n## Durable Catch-Up\n\r\nCultMesh can persist authoritative shard logs through\r\n`ICultNetShardMutationLogStore`. The included file store writes one MessagePack\r\nlog per shard, so a restarted primary can still serve replica catch-up without\r\ndepending on warm process memory. When retained log history is compacted, stale\r\nreplicas get an explicit resync requirement instead of a partial log pretending\r\nto be enough. The replicator can answer that by fetching a shard-bounded\r\nsnapshot, replacing the local shard view, and advancing its cursor to the\nsnapshot's represented log sequence.\n\n## Streaming Mode\n\nCultMesh streaming mode is the low-latency body path for Mimir, Fensalir, Eve,\nand other realtime runtimes. CultCache and CultNet own typed state, discovery,\nstream descriptors, negotiations, and frame handles. The frame bodies stay in\nruntime-native storage: shared D3D12 textures, shared memory rings, platform GPU\nhandles, DMA buffers, or paged CultCache fallbacks when a zero-copy transport is\nnot available.\n\n```csharp\nusing GameCult.Mesh;\n\nvar streams = CultMesh.CreateStreamCatalog();\n\nstreams.Declare(new CultMeshStreamDescriptor(\n \"mimir:kiyo-pro:rgba\",\n \"mimir-live\",\n \"starfire\",\n CultMeshStreamKind.Video,\n new CultMeshStreamClock(\"mimir:clock\", \"kiyo-pro\", sampleRate: 90_000, confidence: 0.92),\n new[]\n {\n CultMeshStreamBodyTransport.SharedD3D12Texture,\n CultMeshStreamBodyTransport.SharedMemory,\n CultMeshStreamBodyTransport.CultCachePage\n },\n video: new CultMeshVideoStreamFormat(1920, 1080, \"rgba8\", framesPerSecond: 60),\n maxInFlightFrames: 4));\n\nvar fensalir = new CultMeshStreamConsumerProfile(\n \"fensalir\",\n \"mimir-live\",\n new[] { CultMeshStreamBodyTransport.SharedD3D12Texture },\n acceptedKinds: new[] { CultMeshStreamKind.Video },\n canImportGpuHandles: true);\n\nvar negotiation = streams.Negotiate(\"mimir:kiyo-pro:rgba\", fensalir);\n```\n\nFor CPU-visible data, `CultMeshSharedMemoryFrameRing` preallocates fixed slots\nand hands producers writable leases. Consumers hold read leases so the producer\ndoes not overwrite a visible frame. `TryPublishCopy` exists for unavoidable\nfallbacks and increments copy telemetry; the normal hot path writes directly\ninto a lease and commits a `CultMeshStreamFrameHandle`.\n\n```csharp\nstreams.Declare(new CultMeshStreamDescriptor(\n \"mimir:leap:depth\",\n \"mimir-live\",\n \"starfire\",\n CultMeshStreamKind.Tensor,\n new CultMeshStreamClock(\"mimir:clock\", \"leap\"),\n new[] { CultMeshStreamBodyTransport.SharedMemory }));\n\nusing var ring = streams.CreateSharedMemoryRing(\"mimir:leap:depth\", slotCount: 4, slotByteLength: 640 * 480 * 2);\n\nif (ring.TryAcquireWriteSlot(out var write))\n{\n FillDepthFrame(write.Span);\n var frame = ring.CommitWriteSlot(write, timestampNs: GetVerseTimeNs(), byteLength: 640 * 480 * 2);\n streams.PublishFrame(frame);\n}\n```\n\nThe invariant is simple: typed mesh state describes and synchronizes streams;\nhot frame bodies remain in the cheapest storage both endpoints can share.\n\n## Documentation\n\n- [Public API](docs/public-api.md)\n- [Durable Node Quickstart](docs/durable-node-quickstart.md)\r\n- [Typed Document Path](docs/typed-document-path.md)\r\n- [Research Notes](docs/research.md)\r\n- [Verse Model](docs/verses.md)\r\n", + "truncated": false + }, + { + "bytes": 15418, + "kind": "readme", + "path": "src/GameCult.Networking/README.md", + "text": "# GameCult.Networking\r\n\r\n`GameCult.Networking` provides client/server messaging over LiteNetLib with encrypted credential exchange and signed session tokens.\r\n\r\nIt is intended for game or game-service scenarios where you want a compact transport layer with a small set of built-in authentication flows rather than a full HTTP stack.\r\n\r\nThe networking/auth layer is the durable organ. Some payloads in this repo are\r\njust sample application messages riding that organ.\r\n\r\n## Scope\r\n\r\nThe library currently includes:\r\n\r\n- a shared message contract model\r\n- a client wrapper around LiteNetLib\r\n- a server wrapper around LiteNetLib\r\n- encrypted login, register, and verify flows\r\n- signed session-token generation and validation\r\n- `PlayerData` integration with `CultCache`\r\n- explicit schema discovery for shared contracts\r\n- a raw MessagePack document/snapshot lane for bit-compatible neighbors\r\n- sample application payloads under `Samples/`\r\n\r\nThe library is focused on the built-in authentication and session flows in this repository.\r\n\r\nCurrent readiness target:\r\n\r\n- trusted local mesh / self-hosted swarm use: yes\r\n- hostile public internet edge: not yet\r\n\r\nKeep the distinction clean:\r\n\r\n- auth/session semantics belong to the core library\r\n- application payload contracts should be explicit, versioned, and kept in sync\r\n across runtimes\r\n- runtimes should be able to ask each other which schemas they speak before\r\n pretending a shared pipe implies shared understanding\r\n- if multiple apps share a message contract, they should be able to talk\r\n directly without bespoke translation sludge\r\n\r\n## Wire Contracts\r\n\r\n`GameCult.Networking` now speaks two explicit wire contracts:\r\n\r\n- `gamecult.networking.v0`\r\n - the legacy union-based auth/session/sample message surface\r\n- `cultnet.schema.v0`\r\n - the newer schema-first contract family for discovery, raw document puts,\r\n raw snapshot replication, and cross-runtime shared-state work\r\n\r\nThere is no inbound autodetect priesthood here. Pick the contract on purpose,\r\nkeep the schema stable, and let peers discover what they can exchange before\r\nthey start lobbing bytes at each other.\r\n\r\nModern schema-v0 helpers live in:\r\n\r\n- `CultNetSchemaMessageSerialization`\r\n- `CultNetSchemaRegistry`\r\n- `CultNetDocumentRegistry`\r\n- `CultNetDatabase`\r\n- `CultNetDatabaseServer`\r\n- `NetPeerExtensions.SendCultNet(...)`\r\n\r\n## Main Types\r\n\r\n- `Message`: base type for all wire messages\r\n- `Client`: client connection, dispatch, reconnect, and login/register helpers\r\n- `Server`: server dispatch, auth flow handling, rate limiting, and session refresh\r\n- `Secret`: encryption and signed-token helper methods\r\n- `PlayerData`: cache-backed player record type\r\n\r\nSample payloads:\r\n\r\n- `ChangeNameMessage`\r\n- `ChatMessage`\r\n- `SchemaCatalogRequestMessage`\r\n- `SchemaCatalogResponseMessage`\r\n\r\nThose now live under `Samples/` to make it obvious they are example application\r\nmessages, not the entire meaning of the library.\r\n\r\nSchema-v0 message families include:\r\n\r\n- `CultNetHelloMessage`\r\n- `CultNetSchemaCatalogRequestMessage`\r\n- `CultNetSchemaCatalogResponseMessage`\r\n- `CultNetDocumentPutRawMessage`\r\n- `CultNetDocumentDeleteMessage`\r\n- `CultNetSnapshotRequestMessage`\r\n- `CultNetSnapshotResponseRawMessage`\r\n\r\nThe raw document/snapshot lane is meant for neighbors that already share the\r\nsame payload schema and MessagePack semantics. It carries exact payload bytes\r\nplus `schemaId`/record-key metadata; it does not guess what a blob \"probably\"\r\nmeans.\r\n\r\n## CultMesh Lives In GameCult.Mesh\n\nThe distributed realtime database and simulation-consensus surface now has its\nown package home: `GameCult.Mesh`, branded publicly as CultMesh. This networking\npackage still owns CultNet transport, authentication, and schema-v0 wire\ncontracts. CultMesh owns the developer-facing mesh entrypoints and higher-level\nruntime documentation.\n\nSee `src/GameCult.Mesh/README.md` for the public-facing CultMesh API.\nFor one small end-to-end path from durable local typed state into `node.Database`,\nsee `src/GameCult.Mesh/docs/durable-node-quickstart.md`.\n\r\n## Distributed CultCache\r\n\r\nCultNet should be able to start as a sharding layer over CultCache. In that\r\nmode, applications treat the cluster as one typed realtime database instead of\r\nmanually juggling a local cache, a network client, and a synchronization loop.\r\n\r\nTarget feel:\r\n\r\n```csharp\r\nvar db = await CultNetDatabase.ConnectAsync(\"localhost\", 3075);\r\n\r\nvar player = await db.GetAsync(playerKey);\r\nawait db.PutAsync(playerKey, player);\r\n\r\nusing var subscription = db\r\n .WatchByIndex(\"Region\", \"eu-west\")\r\n .Subscribe(change => Render(change.Document));\r\n```\r\n\r\nCultCache remains the document model:\r\n\r\n- schema identity and compatibility\r\n- record keys and handles\r\n- local indexes, globals, and typed lookups\r\n- persistence and local domain-change diffing\r\n\r\nCultNet becomes the distribution model:\r\n\r\n- peer membership\r\n- shard ownership\r\n- mutation routing\r\n- snapshot catch-up\r\n- remote subscription fanout\r\n- reconnect resynchronization\r\n\r\nThe current first slice exposes this as `CultNetDatabase` and wires hosted\r\nservers through `CultNetDatabaseServer`. It handles primary-shard writes, typed\r\nR3 watch streams, raw document puts/deletes, raw snapshot responses,\r\nschema/key-filtered live subscriptions, shard catalog exchange, and stale-epoch\r\nwrite rejection. Non-primary write forwarding is available behind an injectable\r\n`ICultNetShardWriteForwarder`, with `CultNetSchemaWriteForwarder` as the\r\nschema-v0 `cultnet://host:port` endpoint dialer. It also records accepted\r\nmutations in per-shard ordered logs and exposes those logs over\r\n`cultnet.shard_log_request.v0` / `cultnet.shard_log_response.v0` for replica\r\ncatch-up. Replicas apply those committed entries through\r\n`CultNetDatabase.ApplyShardLogResponseAsync`, which checks shard epoch, rejects\r\nsequence gaps, and treats replayed entries as already applied.\r\n`CultNetShardReplicator` can then pull non-primary shard logs from advertised\r\nprimary endpoints, using `CultNetSchemaShardLogFetcher` for the schema-v0\r\ntransport path. Replica cursors can be stored through\r\n`ICultNetShardReplicaCursorStore`; `CultNetFileShardReplicaCursorStore` keeps\r\nthose cursors in one local MessagePack file so replicas can resume after a\r\nrestart. Authoritative shard logs can be stored through\r\n`ICultNetShardMutationLogStore`; `CultNetFileShardMutationLogStore` keeps one\r\nMessagePack log file per shard and lets a restarted primary continue answering\r\n`cultnet.shard_log_request.v0` from durable wire entries. The same store owns\r\nlog compaction: once entries are compacted through a sequence, older catch-up\r\nrequests return `ResyncRequired` with `reason = \"compacted_history\"` instead of\r\nsilently handing a replica a partial history. `CultNetShardReplicator` can use\r\nan `ICultNetShardSnapshotFetcher` to recover from that response: it fetches a\r\nshard-bounded snapshot, replaces the local shard view, advances the cursor to\r\nthe snapshot's represented log sequence, and resumes normal log pulls on later\r\nticks.\r\n\r\nFor client-side prediction, `CultNetClientAuthorityScope` declares which input\r\ndocuments a runtime may author optimistically. `PutPredictedAsync` updates the\r\nlocal cache immediately and emits a `Predicted` change; when the authoritative\r\nshard log arrives for the same record, the database emits `Reconciled` and the\r\ncache holds the committed value.\r\n\r\nFor mesh-side simulation agreement, `CultNetSimulationObservation` records what\r\na witness saw for one shard epoch, frame, subject, and claim kind.\r\n`CultNetSimulationConsensus` deterministically aggregates those observations\r\ninto candidates with support weight, total observed weight, confidence, and\r\nquorum status. Those candidates are opinions ready for an authoritative commit\r\npath, not committed world state by themselves. The schema-v0 wire contracts are\r\n`cultnet.simulation_observation.v0` and\r\n`cultnet.simulation_consensus_candidate.v0`. `CultNetSimulationObservationHub`\r\ncollects incoming observations and emits candidate updates reactively.\r\n`CultNetSimulationObservationServer` attaches that hub to a server so incoming\r\nobservation messages update the hub and receive current candidate messages in\r\nreply.\r\n\r\nThe first coherent shard policy is primary ownership. Each shard has one\r\nauthoritative writer at a time. Clients may connect to any node; a non-owner\r\nnode forwards a write to the owner or rejects it honestly when forwarding is\r\nnot available. Followers subscribe to committed shard mutations and apply them\r\nthrough the same CultCache reconciliation path as local file changes.\r\n\r\nThis should feel like the local-first parts of Firebase or RethinkDB without\r\ncopying their hidden machinery wholesale. The hard line is conflict honesty:\r\nsplit-brain writes, stale shard epochs, and schema-incompatible documents must\r\nsurface as explicit failures instead of being laundered into cheerful-looking\r\nstate.\r\n\r\n## Authentication Model\r\n\r\nThe built-in flow is:\r\n\r\n1. client connects with the shared LiteNetLib connection key\r\n2. credentials are encrypted with AES-GCM using a per-message nonce\r\n3. server validates credentials and issues a signed session token\r\n4. client stores the encrypted session token and can send `VerifyMessage` on reconnect\r\n5. server validates the token and re-establishes the session\r\n\r\nThe session token is signed and validated by the server.\r\nEach newly issued session token also carries a monotonic session version so\r\nolder signed tokens can be superseded cleanly instead of haunting reconnect\r\npaths forever.\r\n\r\n## Runtime Secrets\r\n\r\n`GameCult.Networking` uses:\r\n\r\n- `GAMECULT_CONNECTION_KEY`\r\n- `GAMECULT_SESSION_SIGNING_SECRET`\r\n\r\nProduction requirements:\r\n\r\n- set both before constructing `Server` without explicit `ServerSecurityOptions`\r\n- use high-entropy random values, not human-memorable strings\r\n- keep `GAMECULT_SESSION_SIGNING_SECRET` in your deployment platform's secret store rather than in source control or appsettings checked into the repo\r\n- distribute `GAMECULT_CONNECTION_KEY` to clients through your build or asset pipeline, not through runtime environment variables on shipped clients\r\n- partial configuration is rejected by `ServerSecurityOptions.FromEnvironment()`\r\n\r\nRecommended format:\r\n\r\n- 32 or more random bytes per value\r\n- store as Base64/Base64Url text if needed\r\n\r\nExample PowerShell generation:\r\n\r\n```powershell\r\n[Convert]::ToBase64String((1..32 | ForEach-Object { Get-Random -Maximum 256 }))\r\n```\r\n\r\nExample environment assignment in PowerShell:\r\n\r\n```powershell\r\n$env:GAMECULT_CONNECTION_KEY = \"\"\r\n$env:GAMECULT_SESSION_SIGNING_SECRET = \"\"\r\n```\r\n\r\nDeployment model:\r\n\r\n- the client and server must share the same `GAMECULT_CONNECTION_KEY`\r\n- the server alone needs `GAMECULT_SESSION_SIGNING_SECRET`\r\n- `GAMECULT_CONNECTION_KEY` is shared protocol configuration, not a server-only secret\r\n- rotating `GAMECULT_CONNECTION_KEY` requires a coordinated client/server rollout or multi-key server support during migration\r\n- `GAMECULT_SESSION_SIGNING_SECRET` can be rotated server-side with the usual session invalidation tradeoffs\r\n\r\nStrict production-style configuration:\r\n\r\n```csharp\r\nusing GameCult.Caching;\r\nusing GameCult.Networking;\r\n\r\nvar cache = new CultCache();\r\nvar security = ServerSecurityOptions.FromEnvironment();\r\nvar server = new Server(cache, security);\r\n```\r\n\r\nExplicit local-development server configuration:\r\n\r\n```csharp\r\nusing GameCult.Caching;\r\nusing GameCult.Networking;\r\n\r\nvar cache = new CultCache();\r\nvar security = ServerSecurityOptions.Development();\r\nvar server = new Server(cache, security);\r\n```\r\n\r\nExplicit client configuration:\r\n\r\n```csharp\r\nusing GameCult.Networking;\r\n\r\nvar security = new ClientSecurityOptions(\"\");\r\nvar client = new Client(security);\r\n```\r\n\r\nUse `ServerSecurityOptions.Development()` only for local development and tests. `Cli", + "truncated": true + }, + { + "bytes": 859, + "kind": "readme", + "path": "src/GameCult.Networking/Samples/README.md", + "text": "# Sample Payload Messages\n\n`ChangeNameMessage` and `ChatMessage` are example application payloads.\n\nThey are kept in the base union because they are useful for smoke tests, sample\nclient/server code, and cross-runtime compatibility checks. They are not meant\nto imply that CultNet itself is only for game chat or lobby glue.\n\nThe actual durable contract is:\n\n- transport + framing\n- encryption and verify/login/register session flow\n- shared MessagePack message layout\n\nApplications should define their own domain messages with the same discipline\nused by CultCache document contracts:\n\n- explicit field keys\n- stable tag assignments\n- shared definitions across runtimes\n- no casual drift between language bindings\n\nIf two apps share a message contract, they should be able to share data without\ntranslating through bespoke middleware fog. That is the point.\n", + "truncated": false + }, + { + "bytes": 2306, + "kind": "readme", + "path": "src/GameCult.Unity/Assets/Caching/README.md", + "text": "# GameCult CultCache Unity Tools\r\n\r\n`org.gamecult.caching.unity` provides Unity editor tooling for opening,\r\ninspecting, editing, and saving CultCache `.cc` stores.\r\n\r\nThe package is intentionally a Unity editor surface over `GameCult.Caching`.\r\nCultCache owns document identity, schema descriptors, persistence, dirty state,\r\nand flush behavior. The editor window owns selection, presentation, and edit\r\ncommands.\r\n\r\n## Use\r\n\r\n1. Reference `GameCult.Caching`, `GameCult.Caching.MessagePack`, and this UPM\r\n package from the Unity project that declares your `[CultDocument]` classes.\r\n2. Open Unity's `GameCult/CultCache Studio` menu.\r\n3. Open or create a `.cc` file.\r\n4. Select a document type, select a record, edit fields, then save explicitly.\r\n\r\nThe editor discovers registered CultCache document descriptors from the same\r\nregistry used by runtime code. It does not require document classes to inherit\r\nfrom Unity types or storage base classes.\r\n\r\n## Inspector Annotations\r\n\r\nDomain classes can opt into nicer Unity editor rendering with attributes from\r\n`GameCult.Unity.Caching`:\r\n\r\n```csharp\r\nusing GameCult.Caching;\r\nusing GameCult.Unity.Caching;\r\nusing MessagePack;\r\n\r\n[CultDocument(\"game.item\", \"game.item.v1\")]\r\npublic sealed class ItemData\r\n{\r\n [Key(0)]\r\n [CultName]\r\n [CultInspectorLabel(\"Display Name\")]\r\n public string Name = string.Empty;\r\n\r\n [Key(1)]\r\n [CultInspectorRange(0, 999)]\r\n public int Value;\r\n\r\n [Key(2)]\r\n [CultInspectorTextArea]\r\n public string Notes = string.Empty;\r\n\r\n [Key(3)]\r\n [CultInspectorAssetPath(typeof(UnityEngine.Texture2D))]\r\n public string IconPath = string.Empty;\r\n}\r\n```\r\n\r\nAvailable annotations:\r\n\r\n- `CultInspectorLabel`\r\n- `CultInspectorHidden`\r\n- `CultInspectorReadOnly`\r\n- `CultInspectorOrder`\r\n- `CultInspectorTextArea`\r\n- `CultInspectorRange`\r\n- `CultInspectorAssetPath`\r\n\r\n## Current Scope\r\n\r\nThe first studio pass supports local `.cc` files, explicit save/reload, adding\r\nrecords with parameterless constructors, deleting records, primitive fields,\r\nenums, strings, lists/arrays, nested objects, Unity object references, asset\r\npath pickers, and `CultRecordRef` key editing.\r\n\r\nCultMesh collaboration should feed the same CultCache mutation surface rather\r\nthan becoming a second owner for document state.\r\n", + "truncated": false + }, + { + "bytes": 5058, + "kind": "readme", + "path": "src/GameCult.Unity/README.md", + "text": "# CultUI\r\n\r\n`CultUI` is a Unity runtime UI composition and inspector framework, packaged for UPM and developed alongside a demo project that showcases its components, layout system, and reflective inspector workflow.\r\n\r\nThis repository serves two purposes:\r\n\r\n- the source of the `org.gamecult.ui` package\r\n- the source of the `org.gamecult.caching.unity` CultCache editor package\r\n- a Unity project for developing and demonstrating the package in a real scene\r\n\r\n## Scope\r\n\r\nCultUI is aimed at runtime, data-driven interface generation rather than hand-authoring every screen from scratch.\r\n\r\nIt is built for cases like:\r\n\r\n- in-game settings menus\r\n- debug and developer panels\r\n- runtime inspectors for game objects and data models\r\n- tools for exposing configurable values with minimal UI boilerplate\r\n- reusable menu flows composed from prefabs and field handlers\r\n\r\n## Features\r\n\r\n- reflective runtime inspector generation for fields and properties\r\n- prefab-driven resolver system for mapping value types to UI controls\r\n- built-in field components for common input and display patterns\r\n- foldouts and nested inspectors for structured data\r\n- modal and color-picker style components\r\n- reusable layout components for composing inspector rows and panels\r\n- runtime menu composition for demos and application flows\r\n- UPM-style package metadata and assembly definition for integration into Unity projects\r\n\r\n## Package Layout\r\n\r\nThe package source lives under `Assets/UI`.\r\n\r\nKey parts of the package include:\r\n\r\n- `package.json`: package metadata for `org.gamecult.ui`\r\n- `GameCult.Unity.UI.asmdef`: assembly definition for the runtime package\r\n- `Generator.cs`: reflective inspector generation entry point\r\n- `ReflectiveResolver.cs`: runtime resolver for prefab-backed field handlers and components\r\n- `Components/`: built-in controls such as toggles, sliders, enum selectors, text input, buttons, labels, foldouts, and modal UI\r\n- `Prefabs/`, `Resources/`, `Shaders/`: packaged assets used by the framework\r\n\r\n## Demo Project\r\n\r\nThis repository also contains a Unity project used to develop and preview the package.\r\n\r\nThe demo project provides:\r\n\r\n- a sample scene under `Assets/Scenes`\r\n- package assets wired into a working Unity editor project\r\n- demo menu flow showing how CultUI panels can be assembled at runtime\r\n- CultCache Studio, a Unity editor window for opening and editing `.cc` files\r\n- a place to iterate on prefabs, resources, and inspector behavior without needing a separate host project\r\n\r\n## Installation\r\n\r\n### Local Package Development\r\n\r\nIf you are working in this repository directly:\r\n\r\n1. Open the project in Unity `6000.4.2f1`.\r\n2. Let Unity import packages and regenerate project files.\r\n3. Open the demo scene in `Assets/Scenes`.\r\n\r\n### Installing As A UPM Package\r\n\r\nTo consume CultUI from another Unity project, reference the package by local path or Git URL in your project's `manifest.json`.\r\n\r\nExample local reference:\r\n\r\n```json\r\n{\r\n \"dependencies\": {\r\n \"org.gamecult.ui\": \"file:../path-to-CultUI/Assets/UI\"\r\n }\r\n}\r\n```\r\n\r\n## Usage\r\n\r\nAt a high level, CultUI works by combining:\r\n\r\n- a `ReflectiveResolver` asset that knows which prefabs handle which value types\r\n- reusable UI component prefabs\r\n- a `Generator` or `GeneratorPanel` that inspects an object and emits UI rows at runtime\r\n\r\nTypical flow:\r\n\r\n1. Create or configure a `ReflectiveResolver`.\r\n2. Assign field and component prefabs to the resolver.\r\n3. Place a `Generator` or `GeneratorPanel` in your canvas hierarchy.\r\n4. Call `Inspect(...)` on a target object or use the helper methods for explicit UI composition.\r\n5. Refresh displayed values as your runtime state changes.\r\n\r\nCultUI can be used both reflectively and imperatively:\r\n\r\n- reflective mode generates inspector UI from object members\r\n- imperative mode builds menus and panels directly through helper methods and component composition\r\n\r\n## Included Controls\r\n\r\nThe package currently includes components for patterns such as:\r\n\r\n- labels\r\n- text buttons\r\n- boolean toggles\r\n- text input\r\n- numeric sliders\r\n- increment/decrement fields\r\n- enum selection\r\n- foldouts\r\n- modal overlays\r\n- color selection workflows\r\n\r\n## Requirements\r\n\r\n- Unity `6000.4.2f1` for this repository's demo project\r\n- `uGUI`\r\n- TextMeshPro\r\n\r\nThe development project also includes additional Unity packages and NuGet-managed dependencies used by the demo environment.\r\n\r\n## Repository Structure\r\n\r\n- `Assets/UI`: package source\r\n- `Assets/Caching`: CultCache Unity editor package source\r\n- `Assets/Scenes`: demo scene content\r\n- `Assets/Prefabs`, `Assets/Resources`, `Assets/Scripts`: demo-project support assets and scripts\r\n- `Packages`, `ProjectSettings`: Unity project configuration for package development and demonstration\r\n\r\n## Development Notes\r\n\r\n- the Unity project is the development host for the package\r\n- generated `.csproj` and solution files are editor artifacts\r\n- package-facing code should remain centered in `Assets/UI`\r\n- demo-only code should stay separate from reusable package code\r\n", + "truncated": false + }, + { + "bytes": 462, + "kind": "readme", + "path": "tests/GameCult.Caching.Tests/README.md", + "text": "# GameCult.Caching.Tests\r\n\r\n`GameCult.Caching.Tests` contains NUnit tests for the caching library and its\r\nsingle-file MessagePack persistence path.\r\n\r\n## Scope\r\n\r\nThe tests currently cover:\r\n\r\n- `SingleFileMessagePackBackingStore` round-trips\r\n- explicit Cult document payload codecs\r\n- hand-written MessagePack store snapshot/record/catalog serialization\r\n\r\n## Run\r\n\r\n```powershell\r\ndotnet test tests\\GameCult.Caching.Tests\\GameCult.Caching.Tests.csproj\r\n```\r\n", + "truncated": false + }, + { + "bytes": 626, + "kind": "readme", + "path": "tests/GameCult.Networking.Tests/README.md", + "text": "# GameCult.Networking.Tests\n\n`GameCult.Networking.Tests` contains NUnit tests for the networking library.\n\n## Scope\n\nThe tests currently cover:\n\n- AES-GCM encrypt/decrypt round-trips in `Secret`\n- signed session-token validation\n- signed session-token tamper detection\n- signed session-token expiry handling\n\n## Run\n\n```powershell\ndotnet test tests\\GameCult.Networking.Tests\\GameCult.Networking.Tests.csproj\n```\n\n## Adding New Tests\n\nTypical future areas to expand include:\n\n- client reconnect and verify flows\n- login and registration integration tests\n- malformed message handling\n- rate-limiting behavior under concurrency\n", + "truncated": false + }, + { + "bytes": 497, + "kind": "documentation", + "path": "notes/operator-interventions.md", + "text": "# Operator Interventions\n\n## 2026-05-08\n\n- External Codex session from `E:\\Projects\\EpiphanyAgent` added\n `src/GameCult.Caching/Contracts/cultcache-persistence-format.md`.\n- Intent: write down the next canonical CultCache persistence-format design in\n the C# source-of-truth repo before Rust/TS implementations harden the wrong\n shape.\n- Existing unrelated worktree changes in `src/GameCult.Networking/PlayerData.cs`\n and `src/GameCult.Unity/Assets/UI/Default Resolver.asset` were left alone.\n", + "truncated": false + }, + { + "bytes": 46272, + "kind": "research", + "path": "research/cultnet-distributed-database/crdt-arxiv-1805.06358.html", + "text": "\r\n\r\n\r\n [1805.06358] Conflict-free Replicated Data Types (CRDTs)\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n\r\n \r\n \r\n
\r\n
\r\n Skip to main content\r\n \r\n
\r\n
\r\n \"Cornell\r\n
\r\n We gratefully acknowledge support from the Simons Foundation, member institutions, and all contributors.\r\n Donate\r\n
\r\n
\r\n\r\n
\r\n\r\n
\r\n \"arxiv > cs > arXiv:1805.06358\r\n
\r\n\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n \r\n

Help | Advanced Search

\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\"arXiv
\r\n \r\n
\r\n \r\n
\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n
\r\n
\r\n
\r\n\r\n \r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n >\rendobj\r \r\nxref\r\n101 29\r\n0000000016 00000 n\r\n0000001444 00000 n\r\n0000001525 00000 n\r\n0000001727 00000 n\r\n0000001863 00000 n\r\n0000002320 00000 n\r\n0000002760 00000 n\r\n0000003302 00000 n\r\n0000004074 00000 n\r\n0000004327 00000 n\r\n0000004601 00000 n\r\n0000004869 00000 n\r\n0000004982 00000 n\r\n0000005229 00000 n\r\n0000006383 00000 n\r\n0000006918 00000 n\r\n0000007199 00000 n\r\n0000008288 00000 n\r\n0000009351 00000 n\r\n0000010473 00000 n\r\n0000011530 00000 n\r\n0000012622 00000 n\r\n0000013685 00000 n\r\n0000014725 00000 n\r\n0000035703 00000 n\r\n0000072079 00000 n\r\n0000119236 00000 n\r\n0000150351 00000 n\r\n0000000876 00000 n\r\ntrailer\r\n<\r \r \r put typed doc -> get typed doc\"\r\npath, start with\r\n[`src/GameCult.Mesh/docs/durable-node-quickstart.md`](src/GameCult.Mesh/docs/durable-node-quickstart.md).\r\nIf you want the lower-level \"typed local document -> raw wire document ->\r\nmesh/runtime watch surface\" handoff, follow it with\r\n[`src/GameCult.Mesh/docs/typed-document-path.md`](src/GameCult.Mesh/docs/typed-document-path.md).\r\n\r\n## Repository Scope\r\n\r\nThe solution includes:\n\n- `GameCult.Logging`: common logging abstraction plus console and file implementations\n- `GameCult.Caching`: `DatabaseEntry`-based cache, indexes, global entries, and backing-store abstractions\n- `GameCult.Caching.MessagePack`: MessagePack-backed persistence for the cache\r\n- `GameCult.Caching.NewtonsoftJson`: Newtonsoft.Json-backed persistence for the cache\r\n- `GameCult.Caching.MessagePack.Generator`: source generator for MessagePack formatters for cache models\n- `GameCult.Caching.MessagePack.Analyzers`: packaging project that delivers the generator to consuming projects\n- `GameCult.Geometry`: CultCache-native geometry domain, selected-cut, and chunk artifact documents for VibeGeometry/Fensalir-style pipelines\n- `GameCult.Networking`: encrypted login/register/verify flows and message dispatch over LiteNetLib\n- `GameCult.Mesh`: CultMesh package home for distributed realtime database, shard replication, client prediction, Verse discovery, and mesh witness consensus\n- `GameCult.Caching.Tests`: NUnit tests for cache and backing-store behavior\n- `GameCult.Networking.Tests`: NUnit tests for networking behavior\n- `GameCult.Unity`: CultUI, a Unity runtime UI composition framework with reflective inspector generation, prefab-backed field resolvers, reusable controls, and a demo project packaged for UPM-style consumption\n- `packages/cultcache-ts`: TypeScript CultCache with MessagePack persistence and inspector tooling\n- `packages/cultnet-ts`: TypeScript CultNet schema-v0 contracts, framing, discovery, raw document replication, and interop tests\n- `packages/cultmesh-ts`: TypeScript CultMesh local node and mesh catalog surface for local runtimes such as VoidBot\n- `packages/cultcache-rs`: Rust CultCache and derive macro\n- `packages/cultnet-rs`: Rust CultNet contracts, framing, discovery, and interop peer\n\n## Repository Layout\n\n```text\npackage.json\nsrc/\n GameCult.Logging/\n GameCult.Caching/\n GameCult.Caching.MessagePack/\r\n GameCult.Caching.NewtonsoftJson/\r\n GameCult.Caching.MessagePack.Generator/\n GameCult.Caching.MessagePack.Analyzers/\n GameCult.Geometry/\n GameCult.Networking/\n GameCult.Mesh/\r\n GameCult.Unity/\r\ntests/\n GameCult.Caching.Tests/\n GameCult.Geometry.Tests/\n GameCult.Networking.Tests/\npackages/\n cultcache-ts/\n cultnet-ts/\n cultmesh-ts/\n cultcache-rs/\n cultnet-rs/\n```\n\r\n## Build\r\n\r\n```powershell\r\ndotnet build CultLib.sln\r\n```\r\n\r\n## Test\n\n```powershell\ndotnet test CultLib.sln\n```\n\nTypeScript package tests:\n\n```powershell\nnpm test --workspace packages/cultcache-ts\nnpm test --workspace packages/cultnet-ts\nnpm run test:interop --workspace packages/cultnet-ts\nnpm test --workspace packages/cultmesh-ts\n```\n\nRust package tests:\n\n```powershell\ncargo test --manifest-path packages/cultcache-rs/Cargo.toml\ncargo test --manifest-path packages/cultnet-rs/Cargo.toml\n```\n\r\n## Common Concepts\r\n\r\n### `DatabaseEntry`\r\n\r\nThe cache-centric libraries revolve around `DatabaseEntry`. Every entry has a stable `Guid` identifier and can optionally:\r\n\r\n- expose a human-readable name through `INamedEntry`\r\n- participate in generic indexes registered at runtime\r\n- be treated as a global singleton entry through `GlobalSettingsAttribute`\r\n\r\nTypical entry shape:\r\n\r\n```csharp\r\nusing GameCult.Caching;\r\n\r\npublic class ItemData : DatabaseEntry, INamedEntry\r\n{\r\n public string Name = string.Empty;\r\n public int Value;\r\n\r\n public string EntryName\r\n {\r\n get => Name;\r\n set => Name = value;\r\n }\r\n}\r\n```\r\n\r\n### `CultCache` and Backing Stores\r\n\r\n`CultCache` is an in-memory index over `DatabaseEntry` objects. It can operate entirely in memory, or it can be attached to one or more backing stores for persistence and synchronization.\r\n\r\n- the cache is the query surface\r\n- backing stores are persistence adapters\r\n- indexes and name maps are maintained inside the cache, not inside the store\r\n\r\n### Important: Multiple Backing Stores\r\n\r\nWhen multiple backing stores are added, behavior depends on how they are registered.\r\n\r\nIf a store is added with domain types:\r\n\r\n```csharp\r\ncache.AddBackingStore(playerStore, typeof(PlayerData));\r\ncache.AddBackingStore(settingsStore, typeof(AppSettings));\r\n```\r\n\r\nthen that store becomes the direct persistence target for those types.\r\n\r\nIf a store is added without domain types:\r\n\r\n```csharp\r\ncache.AddBackingStore(primaryStore);\r\ncache.AddBackingStore(mirrorStore);\r\n```\r\n\r\nthen the first generic store acts as the primary writable store for non-domain-specific entries. Additional generic stores subscribe to the existing stores and mirror their change events.\r\n\r\nImplications:\r\n\r\n- order matters for generic stores\r\n- `AddAsync` writes to the type-specific store when one exists\r\n- otherwise `AddAsync` writes to the first generic store\r\n- later generic stores do not become co-primaries; they mirror earlier s", + "truncated": true + }, + { + "bytes": 497, + "kind": "documentation", + "path": "notes/operator-interventions.md", + "text": "# Operator Interventions\n\n## 2026-05-08\n\n- External Codex session from `E:\\Projects\\EpiphanyAgent` added\n `src/GameCult.Caching/Contracts/cultcache-persistence-format.md`.\n- Intent: write down the next canonical CultCache persistence-format design in\n the C# source-of-truth repo before Rust/TS implementations harden the wrong\n shape.\n- Existing unrelated worktree changes in `src/GameCult.Networking/PlayerData.cs`\n and `src/GameCult.Unity/Assets/UI/Default Resolver.asset` were left alone.\n", + "truncated": false + }, + { + "bytes": 133069, + "kind": "research", + "path": "research/cultnet-distributed-database/swim.pdf", + "text": "%PDF-1.2\r%����\r\n35 0 obj\r<< \r/Linearized 1 \r/O 37 \r/H [ 5122 1132 ] \r/L 133069 \r/E 57214 \r/N 10 \r/T 132251 \r>> \rendobj\r xref\r35 235 \r0000000016 00000 n\r\n0000005049 00000 n\r\n0000006254 00000 n\r\n0000006560 00000 n\r\n0000006625 00000 n\r\n0000006733 00000 n\r\n0000006839 00000 n\r\n0000006928 00000 n\r\n0000006949 00000 n\r\n0000010404 00000 n\r\n0000011912 00000 n\r\n0000012019 00000 n\r\n0000012133 00000 n\r\n0000013163 00000 n\r\n0000013184 00000 n\r\n0000013270 00000 n\r\n0000014189 00000 n\r\n0000014210 00000 n\r\n0000015099 00000 n\r\n0000015120 00000 n\r\n0000016100 00000 n\r\n0000016121 00000 n\r\n0000017102 00000 n\r\n0000017123 00000 n\r\n0000018048 00000 n\r\n0000018069 00000 n\r\n0000018962 00000 n\r\n0000018983 00000 n\r\n0000019160 00000 n\r\n0000019376 00000 n\r\n0000019596 00000 n\r\n0000019775 00000 n\r\n0000020079 00000 n\r\n0000020316 00000 n\r\n0000020565 00000 n\r\n0000020804 00000 n\r\n0000021022 00000 n\r\n0000021309 00000 n\r\n0000021545 00000 n\r\n0000021802 00000 n\r\n0000022011 00000 n\r\n0000022242 00000 n\r\n0000022541 00000 n\r\n0000022803 00000 n\r\n0000023071 00000 n\r\n0000023314 00000 n\r\n0000023507 00000 n\r\n0000023741 00000 n\r\n0000023918 00000 n\r\n0000024149 00000 n\r\n0000024370 00000 n\r\n0000024616 00000 n\r\n0000024867 00000 n\r\n0000025088 00000 n\r\n0000025292 00000 n\r\n0000025507 00000 n\r\n0000025716 00000 n\r\n0000025929 00000 n\r\n0000026147 00000 n\r\n0000026371 00000 n\r\n0000026595 00000 n\r\n0000026816 00000 n\r\n0000026994 00000 n\r\n0000027221 00000 n\r\n0000027434 00000 n\r\n0000027662 00000 n\r\n0000027942 00000 n\r\n0000028200 00000 n\r\n0000028467 00000 n\r\n0000028709 00000 n\r\n0000028982 00000 n\r\n0000029259 00000 n\r\n0000029466 00000 n\r\n0000029722 00000 n\r\n0000030047 00000 n\r\n0000030301 00000 n\r\n0000030538 00000 n\r\n0000030776 00000 n\r\n0000031062 00000 n\r\n0000031265 00000 n\r\n0000031503 00000 n\r\n0000031755 00000 n\r\n0000031947 00000 n\r\n0000032198 00000 n\r\n0000032449 00000 n\r\n0000032686 00000 n\r\n0000032934 00000 n\r\n0000033141 00000 n\r\n0000033445 00000 n\r\n0000033644 00000 n\r\n0000033858 00000 n\r\n0000034127 00000 n\r\n0000034339 00000 n\r\n0000034560 00000 n\r\n0000034775 00000 n\r\n0000034982 00000 n\r\n0000035194 00000 n\r\n0000035416 00000 n\r\n0000035673 00000 n\r\n0000035949 00000 n\r\n0000036236 00000 n\r\n0000036520 00000 n\r\n0000036754 00000 n\r\n0000037025 00000 n\r\n0000037312 00000 n\r\n0000037500 00000 n\r\n0000037755 00000 n\r\n0000037977 00000 n\r\n0000038211 00000 n\r\n0000038499 00000 n\r\n0000038710 00000 n\r\n0000038921 00000 n\r\n0000039188 00000 n\r\n0000039405 00000 n\r\n0000039619 00000 n\r\n0000039839 00000 n\r\n0000040059 00000 n\r\n0000040320 00000 n\r\n0000040563 00000 n\r\n0000040805 00000 n\r\n0000041093 00000 n\r\n0000041327 00000 n\r\n0000041588 00000 n\r\n0000041846 00000 n\r\n0000042141 00000 n\r\n0000042404 00000 n\r\n0000042658 00000 n\r\n0000042860 00000 n\r\n0000043103 00000 n\r\n0000043356 00000 n\r\n0000043625 00000 n\r\n0000043694 00000 n\r\n0000043763 00000 n\r\n0000043832 00000 n\r\n0000043901 00000 n\r\n0000043970 00000 n\r\n0000044039 00000 n\r\n0000044108 00000 n\r\n0000044177 00000 n\r\n0000044246 00000 n\r\n0000044315 00000 n\r\n0000044384 00000 n\r\n0000044453 00000 n\r\n0000044522 00000 n\r\n0000044591 00000 n\r\n0000044660 00000 n\r\n0000044729 00000 n\r\n0000044798 00000 n\r\n0000044867 00000 n\r\n0000044936 00000 n\r\n0000045005 00000 n\r\n0000045074 00000 n\r\n0000045143 00000 n\r\n0000045212 00000 n\r\n0000045281 00000 n\r\n0000045350 00000 n\r\n0000045419 00000 n\r\n0000045488 00000 n\r\n0000045557 00000 n\r\n0000045626 00000 n\r\n0000045695 00000 n\r\n0000045765 00000 n\r\n0000045835 00000 n\r\n0000045905 00000 n\r\n0000045975 00000 n\r\n0000046045 00000 n\r\n0000046115 00000 n\r\n0000046185 00000 n\r\n0000046254 00000 n\r\n0000046323 00000 n\r\n0000046392 00000 n\r\n0000046461 00000 n\r\n0000046530 00000 n\r\n0000046599 00000 n\r\n0000046668 00000 n\r\n0000046737 00000 n\r\n0000046806 00000 n\r\n0000046875 00000 n\r\n0000046944 00000 n\r\n0000047013 00000 n\r\n0000047082 00000 n\r\n0000047151 00000 n\r\n0000047401 00000 n\r\n0000047662 00000 n\r\n0000047901 00000 n\r\n0000048126 00000 n\r\n0000048349 00000 n\r\n0000048575 00000 n\r\n0000048822 00000 n\r\n0000049044 00000 n\r\n0000049277 00000 n\r\n0000049515 00000 n\r\n0000049741 00000 n\r\n0000050062 00000 n\r\n0000050309 00000 n\r\n0000050544 00000 n\r\n0000050777 00000 n\r\n0000051018 00000 n\r\n0000051204 00000 n\r\n0000051424 00000 n\r\n0000051681 00000 n\r\n0000051915 00000 n\r\n0000052162 00000 n\r\n0000052408 00000 n\r\n0000052653 00000 n\r\n0000052885 00000 n\r\n0000053111 00000 n\r\n0000053312 00000 n\r\n0000053381 00000 n\r\n0000053450 00000 n\r\n0000053519 00000 n\r\n0000053588 00000 n\r\n0000053657 00000 n\r\n0000053726 00000 n\r\n0000053795 00000 n\r\n0000053864 00000 n\r\n0000053933 00000 n\r\n0000054002 00000 n\r\n0000054071 00000 n\r\n0000054140 00000 n\r\n0000054209 00000 n\r\n0000054488 00000 n\r\n0000054762 00000 n\r\n0000054987 00000 n\r\n0000055221 00000 n\r\n0000055431 00000 n\r\n0000055668 00000 n\r\n0000055737 00000 n\r\n0000055806 00000 n\r\n0000055875 00000 n\r\n0000055944 00000 n\r\n0000056013 00000 n\r\n0000056082 00000 n\r\n0000005122 00000 n\r\n0000006231 00000 n\r\ntrailer\r<<\r/Size 270\r/Info 33 0 R \r/Root 36 0 R \r/Prev 132241 \r/ID[]\r>>\rstartxref\r0\r%%EOF\r \r36 0 obj\r<< \r/Type /Catalog \r/Pages 32 0 R \r/Metadata 34 0 R \r>> \rendobj\r268 0 obj\r<< /S 2996 /Filter /FlateDecode /Length 269 0 R >> \rstream\r\nH�b```f`\u0010ab�``�\\� ��\u0000\u0002@1\u000e\u0006\u0016\u0006�'p�5u\f\fL���\u0019MY\u0003�8XED.21_�|��k׮_�`\u0018�������QRJFZNV^UQIAEYW]CSK[�HO��P�������������������������;���? 0(8$4,<\"2*:&6.>!1)9%5-=#3+�07/����������������������������������I��L�6}��Y��̝7��E��,]�|��U�׬]�~��M��lݶ}��]���ݷ���C��\u001c=v���S�Ϝ=w���K��\\�v���[��ܽw���G��<�d�`gafd�������UPTRVQՇxJW�\b�)cTO99�@=�G�S9���:D���\u001c�'�)\u000eF&v6N��,/^�\u0004y\f\u0018[J��\n*��0��\u001b\u0018�9�x��\u0018�\u0002�\u001e��/D��A�=v�\u0010\u0011\u001e\u0003��s��RC���\bgt�\u0010᫂�\u0001I��9؆��@q����2�|��񜅙�񕔬��������������v���������������������������������\u0017����㓟�ꫦ����F��Z;�&��L���;e��S���֕����߶e��};��=~����\u0007O\u001c;}��]��^�y����7.]���έ{g��~�����O89����bf\u0001yJ�HNUAQZYE\r�)=\u001d\u0003C\u0017dO\u0019;(�=E(��rr�\u000bPV�j~�P���\u0000�+zY%\u0018�F/�\u0018\u0018��g\u0015C\u0004}�b`q�[\u00002\u001a'`kq\u0003=+���K\u0005H?\u0007���f�(\u0003��\u0005\u001dւP\u0016\u0007�kKϳ&��\u000b0�\b710�00�g`>��������0���8�Ciކ'�\u000b�\n,��w`\u000f��\u0018��w�\u0007kx\u0003��*��\u0013x�Ӱ�Ga\u000f\u000f�Q�\r�y\u001a��<8����7�\u000b\u0004\u0018v�m4��p�w\"'w�M���|\t�x\u001b\u001es/��V8�߰���\u0010���<\u0013���\u0012(�ʿ����\u0015τ�\u0002\u001b�q?���p���8?�=ދܼ\u0001\u001f�.\n�+��\u000e��������\u0004$`\bCX\u0015<�g��s�\u0014υG<\u0013��N8+t�\u0011o�\u0015�\u0003Ky\n��\u0006<�\u0013x�kp��\u0001�^\u0001��<\u0007�r_�\u0001\u00171wpaY\u0010�2\u0001G\u0001 �\u0000X��_\rendstream\rendobj\r269 0 obj\r1021 \rendobj\r37 0 obj\r<< \r/Type /Page \r/MediaBox [ 0 0 612 792 ] \r/Parent 32 0 R \r/Resources << /ProcSet [ /PDF /ImageB /Text ] /Font << /R13 49 0 R /A 43 0 R /R8 45 0 R /R7 39 0 R /R6 40 0 R >> >> \r/Contents [ 47 0 R 50 0 R 52 0 R 54 0 R 56 0 R 58 0 R 60 0 R 267 0 R ] \r/CropBox [ 0 0 612 792 ] \r/Rotate 0 \r>> \rendobj\r38 0 obj\r<< \r/Type /Encoding \r/Differences [ 2 /fi ] \r>> \rendobj\r39 0 obj\r<< \r/Type /Font \r/Name /R7 \r/Subtype /Type1 \r/BaseFont /Times-Italic \r/Encoding 38 0 R \r>> \rendobj\r40 0 obj\r<< \r/Type /Font \r/Name /R6 \r/Subtype /Type1 \r/BaseFont /Times-Bold \r/Encoding 41 0 R \r>> \rendobj\r41 0 obj\r<< \r/Type /Encoding \r/Differences [ 2 /fi 150 /endash 173 /hyphen ] \r>> \rendobj\r42 0 obj\r952 \rendobj\r43 0 obj\r<< \r/Type /Font \r/Name /A \r/Subtype /Type3 \r/Encoding 44 0 R \r/FirstChar 0 \r/LastChar 204 \r/CharProcs << /a203 129 0 R /a202 130 0 R /a201 128 0 R /a200 126 0 R /a199 127 0 R \r/a198 131 0 R /a195 135 0 R /a194 136 0 R /a193 137 0 R /a192 134 0 R \r/a190 132 0 R /a189 133 0 R /a187 125 0 R /a186 117 0 R /a185 118 0 R \r/a183 116 0 R /a182 114 0 R /a181 115 0 R /a180 119 0 R /a179 123 0 R \r/a178 124 0 R /a177 122 0 R /a176 120 0 R /a175 121 0 R /a174 138 0 R \r/a173 155 0 R /a171 156 0 R /a170 154 0 R /a169 152 0 R /a168 153 0 R \r/a167 157 0 R /a166 161 0 R /a165 162 0 R /a164 163 0 R /a163 160 0 R \r/a162 158 0 R /a161 159 0 R /a160 151 0 R /a154 142 0 R /a152 143 0 R \r/a151 141 0 R /a150 139 0 R /a148 140 0 R /a147 144 0 R /a146 148 0 R \r/a145 149 0 R /a143 113 0 R /a141 147 0 R /a139 145 0 R /a138 146 0 R \r/a137 150 0 R /a135 79 0 R /a133 80 0 R /a132 78 0 R /a131 76 0 R \r/a130 77 0 R /a128 81 0 R /a127 85 0 R /a124 86 0 R /a121 75 0 R \r/a119 84 0 R /a118 82 0 R /a117 83 0 R /a115 87 0 R /a113 67 0 R \r/a111 68 0 R /a108 66 0 R /a106 63 0 R /a104 62 0 R /a101 65 0 R \r/a100 64 0 R /a99 72 0 R /a98 73 0 R /a97 74 0 R /a96 69 0 R /a94 70 0 R \r/a93 71 0 R /a91 103 0 R /a89 104 0 R /a87 105 0 R /a85 88 0 R /a83 101 0 R \r/a82 102 0 R /a80 106 0 R /a78 110 0 R /a76 111 0 R /a73 112 0 R \r/a72 109 0 R /a71 107 0 R /a69 108 0 R /a68 100 0 R /a67 92 0 R \r/a65 93 0 R /a64 91 0 R /a62 89 0 R /a61 90 0 R /a59 94 0 R /a58 98 0 R \r/a57 99 0 R /a55 97 0 R /a54 95 0 R /a52 96 0 R /a50 233 0 R /a48 232 0 R \r/a45 164 0 R /a43 231 0 R /a41 229 0 R /a40 230 0 R /a38 234 0 R \r/a35 238 0 R /a31 239 0 R /a29 240 0 R /a27 237 0 R /a26 235 0 R \r/a25 236 0 R /a23 228 0 R /a22 219 0 R /a20 220 0 R /a18 218 0 R \r/a16 216 0 R /a15 217 0 R /a14 221 0 R /a13 225 0 R /a11 226 0 R \r/a10 227 0 R /a9 224 0 R /a8 222 0 R /a7 223 0 R /a6 241 0 R /a5 258 0 R \r/a4 259 0 R /a3 257 0 R /a2 255 0 R /a1 256 0 R /a0 260 0 R /a66 264 0 R \r/a42 265 0 R /a36 266 0 R /a39 263 0 R /a47 261 0 R /a92 262 0 R \r/a77 254 0 R /a125 245 0 R /a44 246 0 R /a63 244 0 R /", + "truncated": true + }, + { + "bytes": 8481, + "kind": "research", + "path": "research/cultnet-distributed-database/summary.md", + "text": "# CultNet Distributed Database Research Summary\r\n\r\nPurpose: ground CultNet's distributed realtime database design in prior art\r\nbefore adding more machinery. The goal is a coherent local-first mesh database\r\nover CultCache, not a hand-rolled distributed-systems costume party.\r\n\r\n## Sources Stored Here\r\n\r\n- `hashgraph-swirlds-tr-2016-01.pdf`\r\n - Source: \r\n - Topic: gossip-about-gossip, virtual voting, fair ordering, asynchronous BFT.\r\n- `raft-extended.html`\r\n - Source: \r\n - Topic: understandable consensus, leader election, log replication, safety.\r\n- `raft-extended.pdf`\r\n - Source: \r\n - Topic: canonical Raft paper copy.\r\n- `dynamo-amazon-science.html`\r\n - Source: \r\n - Topic: Dynamo publication page and abstract.\r\n- `dynamo-sosp2007.pdf`\r\n - Source: \r\n - Topic: highly available key-value store, consistent hashing, versioning,\r\n quorums, hinted handoff, anti-entropy.\r\n- `swim.pdf`\r\n - Source: \r\n - Topic: scalable weakly consistent process-group membership.\r\n- `rethinkdb-changefeeds.html`\r\n - Source: \r\n - Topic: realtime query/changefeed ergonomics.\r\n- `firebase-realtime-offline.html`\r\n - Source: \r\n - Topic: offline behavior, presence, server-side disconnect operations.\r\n- `crdt-arxiv-1805.06358.html`\r\n - Source: \r\n - Topic: conflict-free replicated data types and deterministic convergence.\r\n\r\n## Design Takeaways\r\n\r\n### RethinkDB\r\n\r\nKeep: changefeeds as the product feel. Subscribers should receive document\r\nchanges continuously, with enough old/new context to render, reconcile, or\r\ndebug. Point subscriptions and filtered subscriptions are both first-class.\r\n\r\nCultNet implication: database subscriptions should be explicit schema-v0\r\nmessages. The server should stream raw document changes that clients can apply\r\nthrough the same CultCache reconciliation path as snapshots.\r\n\r\n### Firebase Realtime Database\r\n\r\nKeep: realtime sync and local/offline ergonomics. Presence and disconnect\r\nbehavior are database features, not application afterthoughts.\r\n\r\nDefer: full offline writes. CultNet should not pretend arbitrary offline\r\nmulti-writer changes merge safely. Offline/local-first behavior needs declared\r\nper-document conflict policy.\r\n\r\nCultNet implication: add presence/disconnect records later as ordinary\r\nCultCache documents with server authority, not as hidden transport state.\r\n\r\n### Raft\r\n\r\nKeep: the understandable authority model. One leader/primary owns ordered\r\nwrites for a shard. Decompose the problem into ownership, log/mutation\r\nreplication, and safety.\r\n\r\nDefer: full automatic leader election and replicated logs until shard catalogs\r\nand explicit epochs exist.\r\n\r\nCultNet implication: the current primary-shard policy is the correct first\r\nfoundation. Every write should either hit the primary, be forwarded to the\r\nprimary, or fail with routing information.\r\n\r\n### Dynamo\r\n\r\nKeep: partitioning, replication metadata, vector-ish causality, hinted recovery,\r\nanti-entropy, and application-visible conflicts.\r\n\r\nReject for now: \"always writeable\" semantics. That is attractive, expensive,\r\nand easy to lie about.\r\n\r\nCultNet implication: shard descriptors should grow into a shard catalog with\r\nowner runtime id, epoch, schema/key ranges, and later replica/preference-list\r\nmetadata. Conflicts must surface as data, not disappear into last-writer-wins\r\nunless a document explicitly chose that policy.\r\n\r\n### SWIM\r\n\r\nKeep: gossip-shaped membership once the mesh grows beyond a small static\r\ncluster. SWIM separates failure detection from membership dissemination and\r\nkeeps per-node message load stable.\r\n\r\nDefer: membership implementation until there is a shard catalog to disseminate.\r\n\r\nCultNet implication: do not build peer discovery as a side-channel registry.\r\nWhen it arrives, it should update membership and shard-catalog state together.\r\n\r\n### CRDTs\r\n\r\nKeep: CRDTs for documents whose merge law is explicit and deterministic.\r\n\r\nReject: generic automatic merge for arbitrary domain objects. That is a\r\nlanguage cop with a nicer hat.\r\n\r\nCultNet implication: CRDT support belongs in schema metadata or document\r\ncontract metadata. A document type can opt into a known merge strategy; the\r\ndefault distributed write policy remains primary authority.\r\n\r\n### Hashgraph\r\n\r\nKeep: gossip-about-gossip as an idea for compact event provenance and possible\r\nfair ordering research. Virtual voting is interesting when every member sees\r\nthe same gossip history.\r\n\r\nReject for now: adopting hashgraph consensus as CultNet's core. The public\r\nledger/crypto smell is not the main issue; the issue is that CultNet does not\r\ncurrently need asynchronous Byzantine total ordering to become a good mesh\r\ndatabase. Dragging that in now would make the machine harder to explain.\r\n\r\nCultNet implication: if we later need decentralized event ordering, use a\r\ndedicated design pass. Do not smuggle hashgraph metadata into ordinary document\r\nreplication because it sounds powerful.\r\n\r\n## Current CultNet Direction\r\n\r\nThe coherent path is:\r\n\r\n1. Primary-shard authority.\r\n2. Explicit schema-v0 snapshot, put, delete, subscribe, unsubscribe, and change\r\n messages.\r\n3. Shard catalog exchange with owner runtime id and epoch.\r\n4. Optional forwarding from non-owner nodes to owners.\r\n5. Membership/failure detection, likely SWIM-shaped.\r\n6. Replication and failover, likely Raft-shaped per shard.\r\n7. Optional CRDT policies for document types that deserve offline multi-writer\r\n semantics.\r\n8. Optional gossip-history research if fair decentralized ordering becomes a\r\n real requirement.\r\n\r\n## Live Invariants\r\n\r\n- CultCache owns document identity, schema compatibility, local indexes, and\r\n reconciliation.\r\n- CultNet owns transport, shard authority, subscriptions, and remote mutation\r\n delivery.\r\n- Raw wire records must pass through `CultNetDatabase` before mutating local\r\n cache state.\r\n- A write without authority is rejected or explicitly forwarded. It is never\r\n silently applied.\r\n- Realtime change streams publish domain changes, not storage implementation\r\n details.\r\n- Conflict policy must be declared before conflicting writes are accepted.\r\n\r\n## Current Cut\r\n\r\nShard catalog exchange now exists:\r\n\r\n- `cultnet.shard_catalog_request.v0`\r\n- `cultnet.shard_catalog_response.v0`\r\n- per-shard id, owner runtime id, epoch, schema ids, key prefix/range\r\n- stale epoch rejection on writes\r\n- routing error that tells clients where the primary lives when known\r\n- injectable non-primary write forwarding policy\r\n- concrete schema-v0 write forwarder for `cultnet://host:port` primary\r\n endpoints\r\n- in-memory per-shard mutation logs and catch-up by last seen sequence\r\n- wire-level shard mutation log catch-up with raw put/delete entries\r\n- replica-side application of shard log responses with epoch checks, gap\r\n rejection, and idempotent replay\r\n- background shard log replicator plus schema-v0 fetcher for primary endpoints\r\n- restart-safe replica cursor store with a local MessagePack file\r\n implementation\r\n- client authority scopes for predicted local input documents\r\n- predicted/reconciled change events for client-side prediction\r\n- simulation witness observations and deterministic consensus candidates\r\n- schema-v0 simulation observation and candidate messages\r\n- reactive observation hub for witness gossip and consensus candidates\r\n- server-side observation bridge for observation messages and candidate replies\r\n\r\n## Next Cut\r\n\r\nBuild durable authoritative mutation logs:\r\n\r\n- persist per-shard primary logs\r\n- define the snapshot fallback boundary for compacted history\r\n- return explicit resync-required responses when requested history is gone\r\n- then add simulation-frame rollback and resimulation helpers on top of\r\n predicted input streams\r\n- add peer-to-peer fanout for observation gossip and candidate propagation\r\n\r\nThat is the next foundation needed before membership, Raft-style failover, or\r\nCRDT policy work can be honest.\r\n", + "truncated": false + }, + { + "bytes": 573786, + "kind": "research", + "path": "research/cultnet-distributed-database/raft-extended.pdf", + "text": "%PDF-1.4\r%����\r\n120 0 obj\r<>\rendobj\r \r\nxref\r\n120 32\r\n0000000016 00000 n\r\n0000001664 00000 n\r\n0000001730 00000 n\r\n0000001974 00000 n\r\n0000002007 00000 n\r\n0000002076 00000 n\r\n0000002185 00000 n\r\n0000010658 00000 n\r\n0000011226 00000 n\r\n0000011907 00000 n\r\n0000011999 00000 n\r\n0000017965 00000 n\r\n0000018414 00000 n\r\n0000018854 00000 n\r\n0000018897 00000 n\r\n0000020780 00000 n\r\n0000022482 00000 n\r\n0000022579 00000 n\r\n0000030097 00000 n\r\n0000030533 00000 n\r\n0000031055 00000 n\r\n0000032778 00000 n\r\n0000034750 00000 n\r\n0000034850 00000 n\r\n0000035314 00000 n\r\n0000035533 00000 n\r\n0000035774 00000 n\r\n0000035967 00000 n\r\n0000037616 00000 n\r\n0000039244 00000 n\r\n0000040734 00000 n\r\n0000000936 00000 n\r\ntrailer\r\n<]/Prev 571253>>\r\nstartxref\r\n0\r\n%%EOF\r\n \r\n151 0 obj\r<>stream\r\nh�b```\u0006�W\f�\f\f�|\f\u0002\f\b ��������q\u0001I�C��Wؓ�a6O�_պ(�\u0018e���Z-*�w���ۅ�%\u001aYU|M��<9�j��R�/\u0000Y3\u0004l^p��G�a�s�\u0004���I�X�9D\f\u001f!�\u0011���{��(�)� �\u0006\u000f�pl�S�X�\u00004ڢ�I�k�^�\u0006�>n��\u0004��y�\u0017\f\u001a��\u0005T\u0002�*w�=����\u000fB\rc�\u00075�]@%�ii�\fq\r\t����\n.\u0016�JS�<�\u0006�qLP���Ri8�`7��\u0005+P��\u0006��\u0005\u0013 >\n~�\u0007�I.z淀G!��\u0011N\u0011���@��\nͼ�\b���`\u000b��\u0006�E�ݥon�ЁX����\u001c\u0012>JJ..\u000e����&.@\u0000\u001606NKK��2\u001b������\b\u0010\u001a\ne��\u0006@U\u001a\u0003ՆF�9�@ \u0000\u0012\u0001\u001b��\u0002\u0006iH\u0000j1�\t\r@cBA\u00165�\f2qq```\u0004\u001a!l��\u0000R�(ALB\u0000*4a`[\"\u000e�e�8\u000el�\"\u0003?�2�\t\n,G�\u0019Z\u000f�0X�E�5��`X��q����-�\u001a�\u0012�\u000b�\u0006\u001c\t�\u0007b\u0019.0:H:\u0018ވ\u0016���q@���1��{�\ne\u0001��_\u001c�ڶ2�0\u001eamT� � }@��,�%�9l\u0006�\u000e�\u0007X\u000f\b6p3�b��(�^���q |c3�\u0006�\u00116\r���\u0006o�\u0019\fkNǰ[0�`,�tz�p�A����\u000e�\t�\u0007b\u000bx\u001b$\u0019�\u0018S�d�g�7�+�5�\u0005u9\u0003��\u0002P(\u0000�.@�\u0001\u0000�\n�\u0006\r\nendstream\rendobj\r121 0 obj\r<>\rendobj\r122 0 obj\r<>/Rotate 0/Type/Page>>\rendobj\r123 0 obj\r<>\rendobj\r124 0 obj\r<>\rendobj\r125 0 obj\r<>\rendobj\r126 0 obj\r<>stream\r\nx��xyXS����!9�uhK���&i���y�S�qFE\u0004e\u0010\u0011!̐@\u0002$��\u0004\u0012��\u0018�$@�<� ��,\u000e�V�\u001d���mk��}����\u0007no�������?0{���z�Z�z�f\u0011N\u0013\b\u0016���\u0013\u001e}4^�!��#[�6�C\u001a\u001a���\u0016�¢�O�g�����5#�\u001cZ4�\u0000��`�S��Yw�G>{id�\u000b��/����jd\r�F�xy\u001c|s��y�eru\\xh�R�xժU��jɿV$�RExh��\r�G�4J&���(\u0017H�K�\u0012e�T\u0012\u0012\u001e%�l���c�6ɜm{�$ۤ1Ҹ�(�{�Ѩ� �[x�4F!}S\u0012\"��D��G\u0012$�\t\u000eW��b\u0014\u000b$\u001b\u0015�@�B.\r\n�\u001fIUAR9�0O\"��E�+\u0014�oI�B\u0012\u001a\u0017\u0018��\u0006K�2IxLPT|0s=�=D\u0016����dx=\u001a���e\n�\"(.\\���\u001b�]��ۨ\f\u000bT2�*��D\u0016�w\u0006˂�\u0019o���\f\f�QH�R����T\u0012\u001c��G\u0005���(y\\��\t��пn�'���\u0006�\u0005GI\u0015c�2����?�\u000e�ˣ�c���v���p�B\u001a\u0015�`<�\u0012\u001c��\u0018\t\u000e��M�D7*0�W����_\u0004\t���\u0018�I�Y��\u001a�%n�b�r{�������TG��A����H�����\u000b�\b�\u001f�\u0019�\u0015u ��բ5��f\u0017�Y����\t����K\u0017,\\��l��eˋ�^�� ^#�\u0012���\twb51��G�!f\u0011\u001e�\u001b�~b6�I�!��7�\u0003�[�Ab.�Ml\"�\u0011>�fb>�K�\u0012\u000b\b?b\u000b���J,\"�\u0011����\u0012b\u0007���I,#v\u0011�\t7�mb7���C�$�\u0011.���Np\t-A\u0011��s��x�x��DD\u0013��\u0018b\u001d1��\u0011/\u0010/\u0012/\u0011�D\u0016�#^&��+D\"1�\u0010\u0010B�\u000bW\u0001�DH��,���'\u001c�p���}��\u0015�\u0002\u000e�)���=…d:�\r\u0015@�|n�sQ��=����'&O�L\n��?���y�єuSN�0�\u0005�\"�b��\u001f�����|��ʫyy��\u0003|'~�+\u0013_��J�T��\u001f\n�\u000b��\u001a��\b��6y��i��h\u0017��q�O���k�:#mFی�3n��V�\u0012\u001d\u0015�����b����]r��7_�z�\u0001̛2\u0012\u0002\u001cл�~��\u001a9`�\u001f�3���E��5A\"\u0017\u0005���Bo�$�e\tU��N�%Z\u001a��\u0005\u0016� |�\u0003mܾ�ers,�\nA\\RځlJ\u0005��Q\u001d,�C\u00126B\n5r�Й�FO;���1t}�.�_�\u0017��\u0002��X�+F9$��k�3(\r\f�����2�I�v����6@\r�F�\u0010#)\t�tI>̦`\u001b�[�R\u0006�(�&�\t���?*i�6�#Ҙ�\u000e�{&\u000b�\\\u001a���q\u001by��RU�sY�F�\u0004\u001a�:&\u0014q�H\u0010xi�\u0013E?�\u0016\u0002���-�1G`G�U��J�?�\u0018��2\u0001Z������ᝁ]���}��\"P\u0003l���A8\u0011�\u0011|�$m���@#\u0004�dCxv\u0006�g�0\b���\u0007\n5%G��'l\u0010�7��k\u000f\u001de��c�\u0016\u0002���~ҥ�;C�3��l5$��ު�v�l*�qz�\u001el�F�I�Q�[�I�\"T�S�!�U�����8\u000eN�\u0001uoTSt��lg�\u0019KUIm\u0015ŋ���u�M�NK��F�*�9�{0�ީ��_T4\u0004�M\u0003^\t�A�H�Ѵ\u001d���\u0016��a�\u0013���\\l\u0013\rpyQ���d큀�b\u001c.C#�����\u0005�~��y�\u0011>ze�\\$B._�\u0001���w��\"8u��e�N�|i.��8��m\b\u000e��M\u0010��$\u0000nQߞ�zK�\u0004�>�v���g��L0d*��4�\u0000���T\rz\u001d%\b�\u001c\u0018�/7U�R!��\u0016���\u0012P�C�Q��<�e���^�S��\u0000m\"�2�aQ\u0006\u0006���\\��-\u0003�)x��s`•��O�a�\u001d��e��c�\u0010�\u0001~*L�$pM\t�)� \u0015h�4���>E��*�2j����\u0005\u0000M\u0000\u000b�������+�\u000f\u0000r�\u000f�W>�ԕ\u001b]wD�\u0004B7��q��s(�\u000b\u0000�\u0014��5|\u000eκx&!�W�\u001ai��wR\u00185\u0014]�T��цVz�e�{�a�ө��bz\u0006�8�\f�\u0001�n6\u001c\u0012����^�n�xo$�t�w��ܐ�+\u0005�Rp1�\u0011Qk8\u0006(��W�\t΂/n����\u0001q^\u0001�\u0007�)�+!L�$�om�7_�\u001c�;�\u001eQ���a�!��f�\u0014\u001a�n��n\u0016}\u000b���\u001b\u0012\u0012�\u0015q\u0001Z\u000f@�\u0012.�J��c\u001b�!\u0013�zN=�x��QQU�t�z\u001d�\u0016�\u001d�1�O���B�BW�X����_��\\Ț���\u0005��`s�n}:�7\u0015�\"!\u0005~m�z�ڥ������臞��D�N4\u0003�X��MW���ũ8�yQ���-�E}O�%��\u0014=��[\u000e\u0010\u0001��GW�>�\u001d�/e\u0019��RpR��h�V@�+�s�s�S��x*O\u0003G�|����`|�Ks�\u0013����/�f�|��\u00011�Ų_�q�v\r%A���,K+\u0002�(�[=�\t}�\u0007�\f�!-^\u0015�\u0012\u0005���$�\u0011ٔp\r\\�(����jK��1�ǰ�\u000f\u0016wc�x6�����k�2�\u000f\"�(�뀒s}A`�ќ��U\n*(\b�\u0002�c`�YVR5P��\u001a�fh�Z]�,�\u00106s\u0001��6\u0016\u00166��\u000b\u0017�S��b1U�̈́�sF\u001b��\u001c\u0015y�dт-c��E�ل�wU�]�\u0014�\u0014��Z\u0007��c���Ʒ�\u0015�\u0001��89@��H�c4�J�,h����l�\"\u0005����S\r���RQ���d\u0001T����-�\u0011�ō���+2=�@|��]%�B�\u0005vx�?�\f�\u00150��\u001d S֨5k��\u0018�\u000b\u0018ӧ���\u000f�2}\u000b\tVꙄP�6;�._k\u0005�)\u0018\u0003g�\u001f�\nM�j\\\u0015BCu��^��U;��\nW}0�7\u000fހ��3�t�����j�Ƽ)4\u0001C����U\u0014���Ǻ���yk�\u0013?�pDGb�\u0002D\t\u0003\"e��Q�j�(�.�Fw�JF�,\\sI~.F��V\f�Y5��*L�\r\u0019�.\u000f�\u001b����mo�\u0018\u0011���5u�A���8x�9|I\rCK�^��^V+�Ғ��#>�7>*Rs�3�2��l��Jp�Bo��{�ъِ\u000b�|�����h`�j�\rp\u0001\f�zB�e��=T\r7\r�r�&�Z�\u0000\f 9Om>l�/:��<��m6:�fÆ\u000b����~'�\u0013�S\u0000_����`\u0000\t.�Y�\u000b�)��p����l��h7N�'�\b�\u0016��\u001b��d�D�TS�� �<◜A��&c�4�����E�n�E�+��\\\u001a�=�&ҕ&�%\u0019�0D��\u0018���'?q�J\u001a\u000e\r�.;�g��36�B���\tn��>0c�mQ�\u000f��z�y,�+\f)k�����\r�:\u000b&tx\u0014^@\u0007�n�v��S�\u0001�i%�\u001e\u000ezu���|�1܊}�N+N�ӹ���A1�\u000e-!ymI���2\u0003�P\n\td�Z�^\u001e\u001f�\u0012\r����cb^\u0005|��В'3�\u001a�O�\u0002��w�z�\u001b\u001aD����$�-?딣���U�\u0014�}��΂$��d\u0018k�.eE�xO^��l\u0005w�̽c�<���R�O�[.�U��q��X�=\u0012k���6\u0003P\u0001C�!�0\u0007�\tf�b�5�\n�q�*5w�Q6�!��̆��p\u0012�\u0015��yi��´BP\b�\u0016[\u0017|\u0019�\u00154�(47�1�����\u0007��mk�O����ҏ\n�\u0015�*�c\u0013\u0006m\u00135\u001aD\u001eNI�՚��\"CGry,�x�<�/z\u0018\u0012Wn×�L�\u001bz\u0003\u001b�!ۍ%F�\u00044&�^�\u0018�\tV@e� \u0000�\"\u0004ե�\u0013flf����(�;��*��P�\b�\t�@kFIV\t(\u0011�����|�k����*2T{C\u0017���,�H[\b\n@���\u001e�\"��K����\n��\f\n��{�\u0006�APy,������v7\\�\u0018�\u0005��\u0017>�s>��;N��OҦ�k\u0000�4Z\u0007�\u0010'ϙ�&Mm|�\u0011�;��o�uS:\u0012kj�\u001c���\u0005�fqVqv\u00110S\r�սC\r1^�=$Z�;)�4>Q\u001b\u000e\"(���@�����3WD<���ʄ>�vlG7^B\u000b1�G��&�(���\u0004@���������:��\u0001j\\�0���36�xd*�,�\u0004�欲4�\b�ў�h\u000bZ.���#ӥ\"\u001f��t��O�{�I�\u000e;��Q�w(������k�7�s\u0005\n!�j���t�\u0007c2p�N\u001e�і,�\u001eia�\u0000z@�\u001b�ʋn\u0014\b�\u0001,\u00138�6\u0016ly\u0005�۸Q ��,\u0013�e�|\f\u0013?c��#k�鹁\u001ay�!�0&��L\u0016��\u00033�z�S\u0003ţ�dԓ�\u000f��\u0019�\u0000_�/��f��}����\u0003N=':�<<�\u0016MAl�]�\u000e\u001e���Wc��\u001a�5r�\u0003���$�*5Ia��ꕀ��ݤ+�\u0010��$�e�>*��w�gs�\u0015��\u001e�Ut\u0007y\u0012nb\u0006\n\u0014󘾂K@�Ԫ\u000b�����lS�Q�\u0016jB$,4Y3,cr�f���\u0000\u001dՒ�\u0019\u0015��$�Eق�4[t�Oy(#�5J��hml�J\u000bL 5�P�2'�'�MLTD��\u001d{��\u00058�\u0018.��YZKKj�L�ߦ9M��\u0007l�5���%T�e֢]\u001fB���>��CJą�E�Ju\u0015\u0010�W�k.l9���;1���'@�\r�C�W\u001e-����-���Z\u001c�KԔ�'�+CY\u0003t%\u0016�o�\u001f�G}pޥ��\u001dn��\np�\u001d��[\u0016�]&G�H\u0014;����\\\u000e�Uq?N��0L�\u0016\tfjU+M��\u0014�9'Հ�(z6\t�GOp�\\�\u0004h��5�跡\u000b_�o�1%뒄ڤ�ToܹD\\XM�ɱ�\u001f�L�<��[|�f�������ob�8y��πr��FV�S���\r�7���3�rR��\u00052\u0001\u0015��Y�~\u000f�\u000f��0î$a2Y�S\b�\u0000�Ul8*F�Hi��4\b�G.�c�k��{���\u000bݎ\u0013��]����јbЫ\u0013�\f1�Z��!|\u0001r���?;t�\u0000C�zG*\u0003�3\u0003��\u0001�sh=��!��.��Zb��fX>EEvgZ3l�\u000emq(�M�/�Q>���*n?���\u001e�Fw�<�\u0003l:ɳ�{0dL�o˜VHv��yp%�o���]�\u0003\u001ci����6�e]��\u0015n�5CS\\kt��A�\u0003\u000e��ᇎ�]�*\f������%H\u001c\u0013��p\u001e��a{�\u0015p\u0005��,�\u0018z�v����Վ5�:�e�?FV��~4\u001d�]������\u0013\u000f�}\u001e�\u0019��\u000f�\u000e%����'���n7Wt��P;\r�Aug�9ߖ�\u0000M\u0004�\u0007S��ʰ���\u0003�\u001f\u001c�\fk98\u0018�\u0013�a����z����\u0003j\\s�n�����q\u0018�2U�\u0002\u0016\u001f����*�!�RT\u001e[f�\u0000T����3�~��\u0003r�Xql@Zh�\u001ajU���}.ؤO����\u0016\u001b��Rp����)���q��g0�\u0019'��a8��ϪȮ\u0007\u000f�����˭�W�upL�-o\n\u001aX�8\u001fgE\u0005�W�� ���,I3�7�W�;y\u001a����\u0004�\u0006��\u0001�\\=4�-w\u001fD&jsr��1��\b�:��:\u0018�S��j�\u0000&?hhd�\u0011��߳�Lij`�9�H /�\u0017�F�`��En\r��\u0011b�Z�dJ���%�ΐP�җ�zP\u001e\u0001B�\u0003\u000f\u0003������\u0019QwKE+�\u0006W\u000f\u001dۘ����\u0003�qŠ\u001c8�:\u001a�����y��e�.\u0004]������h�\u0000�@Sz���B��i�6㇦!@}٦\u000bݷ>\u0018q��k\u001a�1[��\u0012\u0017����\u001a;\u0006[ꓢ�E�ae� ��\u001f\u0013�7��w�v\u001dy��,\u0019ه��\u00117o���_oX:+\u0006{�^��rlJ�G��L�@�)\u0014�f�K�D=����\u0014'<\u00057ށ������'S\"%�\u0019�q��<7{N��悧�\f�\u0011����M�u���~���\u001a\u0012�\u0012�6\u001c8\u0000�Q�u_=~L\u0015�!j��Ɩ��\u0010��b�G�Ƽ�j����\u0017��O�sWJu�j��\u00059�\\[N\t\u0010�\u0014'ှ@���q�D�A��\u0005\u001a`0'U�k��ɸ骓�#{����K��kb�O�#��\u000e\u0014�*�\u001ccA3���\u0011�?�I�����L�<��~���(��s$�ju\r�@�rMp\u001dg�\nׄ�qj���Uc�N��J\u001b�cb�k$���*�\u000e��u��\u0011�\u001e+\u001e\u0004\u000f�Ә���l;Ơ�[�S���tk���x4�\u0004^Z�[:FAo#��SJ�y��\u0006�{0Ijؚ$\u001ck�#�\u001d����\u001b_��{>�R\u000fd �(O�F�G�\u00024\u0017~\u0019q'�\u0006؄�n-a��Js��\u001b�]E\u000eeY��K`���ƅq�pۣ�ғXi��qlf�a=}\fݘl;�\u001aߒWļ\u001e�\u0017'��Q!c�f6�-�F\u001e�Ք�\u001e\nv� ���l����\u0000�@u\u0018&\",1���\u001eL�)m�G��\u0002\\�`\u0001���V9\b����b\u0014J\u0002���}F�If#cs�su��G\b��������y���\u0012�/�7x�\u0000 Ӯt���\\oU��S#���8\u000e��dp�j�t:�A\u000e\u0012L�\u0006\u0019z\t}%@\u0002�MVAjuv�0��d\u0007�����\u001c��CE^�.Im_ӶJ A\u001dh&=�X�1�(Zm5���[�T��t��k>�\u001amg�Z@���F�pl�'�Z�\bY���Li��\u0012&����vjd5ž\u0014χN���\u001bC�ܿ\u0002_\u0004Ѕ��\u0016��\u0010\u001fM\\�\u0006rASn����c�}gEG�\nĖ�y�\u0014�\u0004G� 1#U�*S��B\u0001���\u001e�x��rU���QW�\u0004�O�/G�q��!\u001b�@6\u000bN�\u0003��q�Q1uqM-�uM-���b����7�:F�p�`:��G��\u001cuej�\u0006\b\u0013t)��RMe\n��oq��&G�/0\u001b��?�씞�����W�7��/��ԩ���a��p\u0011/3�Z�Uh��)\u0014��r�\u0000�\u0014\u0015��\"e!^!�n�!�'�o\u000bF��\u001c�fX�^�\n��j�M\u000e�+�a\\ݵ�0�~*����b��#�\u0004=�^Z{�����\u000e��sm\u001f���\ri�N�9���\u001a\u001a�\u0011�MzH\u001c\u0019\u0014��a\n���>��q�\u0019qCoce\u000b�\u0002�\u0017�`��wP�n\u0010\u0004�f���?���\u0015D� �\u0004MD�-g=��\u001fwt��Ϝm}\u0004�\u0000kVYze��2�\t\f�zso\r��\u000f��$������\u0011~ab�\u0006h)�Y���a���c�\u001b\r�D<ΓsM��-.\u0005 7�0ݪ+KoJ���Z���\u000b���\u0014[@�С+�פ���\"4\u001b��P?�o�‚�z������o;~��\b+�#kT���s1���0�", + "truncated": true + }, + { + "bytes": 33609, + "kind": "research", + "path": "research/cultnet-distributed-database/raft-extended.html", + "text": "\r\n\r\n\r\n\r\nIn Search of an Understandable Consensus Algorithm (Extended Version)\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n UP \r\n |\r\n HOME \r\n
\r\n

In Search of an Understandable Consensus Algorithm (Extended Version)

\r\n\r\n\r\n
\r\n

DECLARATION

\r\n
\r\n

\r\nThis page is the In Search of an Understandable Consensus Algorithm\r\n(Extended Version) paper. Original Paper Link\r\nis: https://raft.github.io/raft.pdf\r\n

\r\n\r\n

\r\nIn Search of an Understandable Consensus Algorithm
\r\n(Extended Version)
\r\nDiego Ongaro and John Ousterhout
\r\nStanford University\r\n

\r\n
\r\n
\r\n\r\n
\r\n

Abstract

\r\n
\r\n

\r\nRaft is a consensus algorithm for managing a replicated log. It produces a\r\nresult equivalent to (multi-)Paxos, and it is as efficient as Paxos, but its\r\nstructure is different from Paxos; this makes Raft more understandable than\r\nPaxos and also provides a better foundation for building practical systems.\r\nIn order to enhance understandability, Raft separates the key elements of\r\nconsensus, such as leader election, log replication, and safety, and it enforces\r\na stronger degree of coherency to reduce the number of states that must be\r\nconsidered. Results from a user study demonstrate that Raft is easier for\r\nstudents to learn than Paxos. Raft also includes a new mechanism for changing\r\nthe cluster membership, which uses overlapping majorities to guarantee safety.\r\n

\r\n
\r\n
\r\n\r\n
\r\n

1 Introduction

\r\n
\r\n

\r\nConsensus algorithms allow a collection of machines to work as a coherent group\r\nthat can survive the failures of some of its members. Because of this, they play\r\na key role in building reliable large-scale software systems. Paxos [15, 16] has\r\ndominated the discussion of consensus algorithms over the last decade: most\r\nimplementations of consensus are based on Paxos or influenced by it, and Paxos\r\nhas become the primary vehicle used to teach students about consensus.\r\n

\r\n\r\n

\r\nUnfortunately, Paxos is quite difficult to understand, in spite of numerous\r\nattempts to make it more approachable. Furthermore, its architecture requires\r\ncomplex changes to support practical systems. As a result, both system builders\r\nand students struggle with Paxos.\r\n

\r\n\r\n

\r\nAfter struggling with Paxos ourselves, we set out to find a new consensus\r\nalgorithm that could provide a better foundation for system building and\r\neducation. Our approach was unusual in that our primary goal was\r\nunderstandability: could we define a consensus algorithm for practical systems\r\nand describe it in a way that is significantly easier to learn than Paxos?\r\nFurthermore, we wanted the algorithm to facilitate the development of intuitions\r\nthat are essential for system builders. It was important not just for the\r\nalgorithm to work, but for it to be obvious why it works.\r\n

\r\n\r\n

\r\nThe result of this work is a consensus algorithm called Raft. In designing Raft\r\nwe applied specific techniques to improve understandability,including\r\ndecomposition (Raft separates leader election, log replication, and safety) and\r\nThis tech report is an extended version of [32]; additional material is noted\r\nwith a gray bar in the margin. Published May 20, 2014. state space reduction\r\n(relative to Paxos, Raft reduces the degree of nondeterminism and the ways\r\nservers can be inconsistent with each other). A user study with 43 students\r\nat two universities shows that Raft is significantly easier to understand than\r\nPaxos: after learning both algorithms, 33 of these students were able to answer\r\nquestions about Raft better than questions about Paxos.\r\n

\r\n\r\n

\r\nRaft is similar in many ways to existing consensus algorithms (most notably, Oki\r\nand Liskov's Viewstamped Replication [29, 22]), but it has several novel\r\nfeatures:\r\n

\r\n\r\n

\r\n1/. Strong leader: Raft uses a stronger form of leadership than other consensus\r\nalgorithms. For example, log entries only flow from the leader to other servers.\r\nThis simplifies the management of the replicated log and makes Raft easier to\r\nunderstand.\r\n

\r\n\r\n

\r\n2/. Leader election: Raft uses randomized timers to elect leaders. This adds\r\nonly a small amount of mechanism to the heartbeats already required for any\r\nconsensus algorithm, while resolving conflicts simply and rapidly.\r\n

\r\n\r\n

\r\n3/. Membership changes: Raft's mechanism for changing the set of servers in the\r\ncluster uses a new joint consensus approach where the majorities of two\r\ndifferent configurations overlap during transitions. This allows the cluster to\r\ncontinue operating normally during configuration changes.\r\n

\r\n\r\n

\r\nWe believe that Raft is superior to Paxos and other consensus algorithms, both\r\nfor educational purposes and as a foundation for implementation. It is simpler\r\nand more understandable than other algorithms; it is described completely enough\r\nto meet the needs of a practical system; it has several open-source\r\nimplementations and is used by several companies; its safety properties have\r\nbeen formally specified and proven; and its efficiency is comparable to other\r\nalgorithms.\r\n

\r\n\r\n

\r\nThe remainder of the paper introduces the replicated state machine problem\r\n(Section 2), discusses the strengths and weaknesses of Paxos (Section 3),\r\ndescribes our general approach to understandability (Section 4), presents the\r\nRaft consensus algorithm (Sections 5–8), evaluates Raft (Section 9), and\r\ndiscusses related work (Section 10).\r\n

\r\n
\r\n
\r\n\r\n
\r\n

2 Replicated state machines

\r\n
\r\n

\r\nConsensus algorithms typically arise in the context of replicated state machines\r\n[37]. In this approach, state machines on a collection of servers compute\r\nidentical copies of the same state and can continue operating even if some of\r\nthe servers are down. Replicated state machines are used to solve a variety of\r\nfault tolerance problems in distributed systems. For example, large-scale\r\nsystems that have a single cluster leader, such as GFS [8], HDFS [38], and\r\nRAMCloud [33], typically use a separate replicated state machine to manage\r\nleader election and store configuration information that must survive leader\r\ncrashes. Examples of replicated state machines include Chubby [2] and\r\nZooKeeper [11].\r\n

\r\n\r\n\r\n
\r\n

\"raft-figure1.jpg\"\r\n

\r\n

Figure 1: Replicated state machine architecture. The consensus algorithm manages a replicated log containing state machine commands from clients. The state machines process identical sequences of commands from the logs, so they produce the same outputs.

\r\n
\r\n\r\n

\r\nReplicated state machines are typically implemented using a replicated log, as\r\nshown in Figure 1. Each server s", + "truncated": true + }, + { + "bytes": 900468, + "kind": "research", + "path": "research/cultnet-distributed-database/dynamo-sosp2007.pdf", + "text": "%PDF-1.3\r%����\r\n101 0 obj <>\rendobj\r \r\nxref\r\n101 29\r\n0000000016 00000 n\r\n0000001444 00000 n\r\n0000001525 00000 n\r\n0000001727 00000 n\r\n0000001863 00000 n\r\n0000002320 00000 n\r\n0000002760 00000 n\r\n0000003302 00000 n\r\n0000004074 00000 n\r\n0000004327 00000 n\r\n0000004601 00000 n\r\n0000004869 00000 n\r\n0000004982 00000 n\r\n0000005229 00000 n\r\n0000006383 00000 n\r\n0000006918 00000 n\r\n0000007199 00000 n\r\n0000008288 00000 n\r\n0000009351 00000 n\r\n0000010473 00000 n\r\n0000011530 00000 n\r\n0000012622 00000 n\r\n0000013685 00000 n\r\n0000014725 00000 n\r\n0000035703 00000 n\r\n0000072079 00000 n\r\n0000119236 00000 n\r\n0000150351 00000 n\r\n0000000876 00000 n\r\ntrailer\r\n<]>>\r\nstartxref\r\n0\r\n%%EOF\r\n \r\n129 0 obj<>stream\r\nx�b```\u0006��\f�\f\f�\u0002\f�\f\b \f\u0014cc`a�������Ȣ��\u0010�됺���qņ�\u000elݬ|\u0015\u0012;��Y.wh\u0005�\u0019+x��\u00196l\u0007jl��\u001ez���\u000e�UH�1(\u0004�q\u0014�\u001a�NOh��ql29\u001a\u0016��jr\b((\u001aY��Q�!2٧\u0010,+��,���$\u001a\u0019Y&_y\t�&IB�Hh�\r �\u0010�f\tT�\ndL2��\u0005��2�q\u0014r�I���ި}�!2�\rf���,w��\u001b@5*\t�\u0002\u000b�\u0002\u0015�]��s\u0019�X���B�����\t\u000bN\u0000\u001d�Z\u0006v+�DG\u0007\u0003���GG\u0003��K(�\u0003�I\u00009\f\fJ\u0011 1\u0010��\u0000�3\u0018\u001b�)\u0006�\b0�ll\u0001�\u0019\u0005��4�*\u001a�,a\u000b�V�\f�1b\u0019`���2 ���\nv4\u0010\u0017�@`��\u0013\u001a\u0005���X\u000b,�� �0�!�q\u0016c'�{��\f�\u0018\u001e3�epb8�\u0012����\u0015�\u0010�\u000f\u0016c�O,��?�\u001f\u0006\u001e�}���2&�#��K\f�\u0018:\u0019�I�1\u00043|\u0000�T�pIU�\u0001\u001d�1��O\u0005�\u0002`�'\u0006\u000e��1T1X\n����J\u0010\u000b{��s��}�P\u001c\u0003�V+ �\u0004��@���sd?T�K�\u0000\u0003\u0000���z\r\nendstream\rendobj\r102 0 obj<>\rendobj\r103 0 obj<>\rendobj\r104 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>>\rendobj\r105 0 obj<>\rendobj\r106 0 obj<>\rendobj\r107 0 obj<>\rendobj\r108 0 obj<>\rendobj\r109 0 obj<>\rendobj\r110 0 obj<>\rendobj\r111 0 obj<>\rendobj\r112 0 obj<>\rendobj\r113 0 obj<>\rendobj\r114 0 obj<>stream\r\nH�lUێ�6\u0010}�W�#\u0005X�D��''\u000bl��@\u0010\u000b�â\u000f\\��ٕ(W��n>#_�!)��E�X�™9g�\\��q��A�>��\u000fm� �v�JkH�\u000f/UC\u001b\u0006U�Q\u0006��J���m�Jh�$h{Y��WŇ�\u0017�\f�Ǩ~j�,\u000f��\u00156g.{��\u000b�*^�3�g\u0001[3N\u0002��o\u000b�/`̃1h\u0012��e�\u000e\u001cA7��\u0017�ɾ;J|�^��0+Z$\u0001\u0013]����3�����QZ�oˆ\t�\u0018�>�_xd�n�Ӹ��*G\u0003\u0015�?Ť��A�ڹ�h����XU�\n��JZ��η��ꮸQAK�\"D�\t��!�\bxͯ%̰L%��j�.\u0018��z���1K-��Ѯ�!�|ܶ\u0011�U��O�����wl\u001cH\u0003E\u000eE��2\u000fL��g�\u0016��$�E/�sTњ�^:����F��@�\t\u0013n`�RF3�#dT\u0011��Y��x�ӆ��eJ�{\u0000�C��.�li0K�\u0005����#FoP��2\"`�{4s\u0014�,\u000f\u0007��\u0006\u00054Q�\btGg�E\u0015\nO�\"r��\u0018Y�\b��3�kl�ڒ^\u0010`\u001d�.��\u000bZ.�s���\bN\u0016J؋A(#v�`��ϒ�\n�xZ\u0006��]�R�'_Cm��CQ�\u001c��ܙ�[\b[e\u001c�\u0010�\b��[�S�'a�5VQ��N�6ќ�rp��\u0014��$+��\u00055\u0015��\u0007%\f��\u0002X�\u0013Λ2���X�\u001b��\u0010�-�Տ\u001dG\t�4�bJm�6��X֩U������G�&}dzy�u|\u000f����B�i���u\b)l\f>a\rp���x�K�0Nr�Į��o�`�D6_�C\\�(q\u001d��?\u0001\u0006\u0000�V!o\r\nendstream\rendobj\r115 0 obj<>\rendobj\r116 0 obj<>\rendobj\r117 0 obj<>stream\r\nH�tU˖�6\f��+��ΉTQ/K˞z�l��w9Ypd�f\"�>zx2���\u001f�\u000b��x&�J6\t\\\u0000\u0017�e��Y�Iq�vY*%�z�E�\u001bn�j;O�L/��]��AQ�D����xرs\u0019���%�/𶳱�[��%N괈���>��I�W-��z|��d��M�hF�����N���-@�\u0005h|\u00001�j��Lb`�N2$��:��2��\u0012��4�����p�\u001b�\u0014<���\u0017��>R�$��mT���\u0006��W\u001b\u0004d3��\\��(��$�,�}��;��jԂ�k#�)s������V�\u001e�T< 6�\u00011p��+��+�)tD�F�O���Nz2\u0017�a(F\u0003�^[#W�\"�0T�\u0019n�\u001e��f�,�w�\u0004\u000b�Ģ��wk\u001f\r�Pk{\u0002���e\u001b\u0002\u0014e��j.�\u001e(%\u0017-�\r$߹]h\u00033\\��\u0015\u0018\u0002��N=�o>I,argCE�m�/��(-a1{w7��v\u000eW�A�1�\u0003�\u0006cj\u000e\u0000\u000e!�ȟk\u001f���ݟ����{z���P���۪XW�{]\u0000DSw�h��edh�0��N,|\u0018\f���Kw7'>\r��.v�1����������\r`D���e�=���i10F,\u001b��\u0018�7\u0010G�ˉ��\fR��k\u0000��w�0�\u0011�\b\f�Q�\u001f���!�\u001b�ʟC�\u0018 d�\u0014�\u001ab�A{*^\u000f��\"-���]5��\u0003�\u001f�6h�\u0001;�P�4/V\r@���P\u001dՍ���=��\u0012V\u0010\u0000�\u001d$\f��Y��u�9��f�\u001a��>�bOغN���xqդ�\u000b��Ӵ2(o4nJ���y�g_��\bQ\u001c�w\u001dH�?��\u0004�\u0012\u000b��1™\u0018A\u0015�����\f\u0019��򐵕��NJ���\u0017h���U�ۭ7\u001d/y��zb*N��g�7:�o�����3 fH������S�\t%q� f�o�{�*�&�\u001e�7�O=�Bfh\u001eD\u0006s\u001b���==��z�1��w>Y�A�Fٚ\r70�\u0007����Fh\"�\u001c=^\u001e\u000f{��\u0015�\n� �9�v<�\u0002=>C8��\t|�R\u0014\r��qx`%�Z���\u000f�m\u00177\u001a4�����\u001bv�S7���Ɖ�c�7\u001e�e�V�E�\u0002�\u0001�K`̟^���ޖ萖��\u0012b�\u0002��\u001e��t������ч&��\u0007\u001b�B^X\u0001�g��B�j��I�\u0007*�*�\u0013`\u0000h�\u001f\u0016\r\nendstream\rendobj\r118 0 obj<>stream\r\nH�|Uێ�6\u0010}�W�#\t�X��'OE\u0017(\u0012�� �>-�i[�,�\u0014�E�\u0019��ΐ�/�m��K�2g�3���槶�AB���\"��\nRh�7�HӴ���+�C��yb_y%\u0014{�\u0013)2\u0006��X���5��M�.YG�\r��\u000e\u001b�=܋�/\u0005O��Y\u0001�k�q��T�M�\u0001>�9\u0002\u0013�G$0���?(�2$��\f�.��sr2&�p⹨���\u001b&��sJ\u0005\u001e��\b��'��ٌG9s����q���rp\u0005R�A�\u000b\u0003\r1�b=�E�C���26�\u0003/�����\u001d�K\u0016*�SA�TL�ӊW�x�\nx���^\u0001s�V\u0015\n��#\u0016P����Gi�0ev�\u0011S�lk|\u0017YW�hdd����ؾT�Y۝��n���(�L\u0003F!�欀�\f�\u0012I�\u0004/+(r�2%\n\u0005�1D/�A�.Q�_�����j�Մ8��Ƈi@f��u��9<2VUf�\u0012u.C�\u0004f*���7vp��|G&��3\u001d�u7�\u0006�Y�'Ff��n\u001cV�ůC(}�%�ǜ�\u0004��_�t�\u0006�\r�Q3�C��K�\u001a\r�\u00062\f\u001ar���\u0001\"�u\u0003P�]�\u0017-�D���`u0s�\u0004��Ӎ\u0006�Q\"UDI$�I\u0011�VkWUE�������\"��~\u001f>�_\u001e������\t�m\u0001)�\u001a�YS *W}J��s�\u0005͍��\u0004v�f�Qgu�e����q��\f[\r:Azs֛�2=\n�:4��5��\u000e\tn�$�\u0005M�x\u000fܡs\u0010\u0000�7�|4\u001dQ]�G!�9p���'\r�\bY�q�\u001d\u001c���8\u000e\u0006\u001f�����\t��΀�'", + "truncated": true + }, + { + "bytes": 46272, + "kind": "research", + "path": "research/cultnet-distributed-database/crdt-arxiv-1805.06358.html", + "text": "\r\n\r\n\r\n [1805.06358] Conflict-free Replicated Data Types (CRDTs)\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n\r\n \r\n \r\n

\r\n
\r\n Skip to main content\r\n \r\n
\r\n
\r\n \"Cornell\r\n
\r\n We gratefully acknowledge support from the Simons Foundation, member institutions, and all contributors.\r\n Donate\r\n
\r\n
\r\n\r\n
\r\n\r\n
\r\n \"arxiv > cs > arXiv:1805.06358\r\n
\r\n\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n \r\n

Help | Advanced Search

\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\"arXiv
\r\n
\r\n \r\n \r\n\r\n \r\n \r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\nDynamo: Amazon’s highly available key-value store - Amazon Science\r\n \r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n \r\n\r\n \r\n\r\n\r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n\r\n\r\n\r\n \r\n \r\n \r\n\r\n \r\n \r\n\r\n\r\n\r\n\r\n\r\n
\r\n UP \r\n |\r\n HOME \r\n
\r\n

In Search of an Understandable Consensus Algorithm (Extended Version)

\r\n\r\n\r\n
\r\n

DECLARATION

\r\n
\r\n

\r\nThis page is the In Search of an Understandable Consensus Algorithm\r\n(Extended Version) paper. Original Paper Link\r\nis: https://raft.github.io/raft.pdf\r\n

\r\n\r\n

\r\nIn Search of an Understandable Consensus Algorithm
\r\n(Extended Version)
\r\nDiego Ongaro and John Ousterhout
\r\nStanford University\r\n

\r\n
\r\n
\r\n\r\n
\r\n

Abstract

\r\n
\r\n

\r\nRaft is a consensus algorithm for managing a replicated log. It produces a\r\nresult equivalent to (multi-)Paxos, and it is as efficient as Paxos, but its\r\nstructure is different from Paxos; this makes Raft more understandable than\r\nPaxos and also provides a better foundation for building practical systems.\r\nIn order to enhance understandability, Raft separates the key elements of\r\nconsensus, such as leader election, log replication, and safety, and it enforces\r\na stronger degree of coherency to reduce the number of states that must be\r\nconsidered. Results from a user study demonstrate that Raft is easier for\r\nstudents to learn than Paxos. Raft also includes a new mechanism for changing\r\nthe cluster membership, which uses overlapping majorities to guarantee safety.\r\n

\r\n
\r\n
\r\n\r\n
\r\n

1 Introduction

\r\n
\r\n

\r\nConsensus algorithms allow a collection of machines to work as a coherent group\r\nthat can survive the failures of some of its members. Because of this, they play\r\na key role in building reliable large-scale software systems. Paxos [15, 16] has\r\ndominated the discussion of consensus algorithms over the last decade: most\r\nimplementations of consensus are based on Paxos or influenced by it, and Paxos\r\nhas become the primary vehicle used to teach students about consensus.\r\n

\r\n\r\n

\r\nUnfortunately, Paxos is quite difficult to understand, in spite of numerous\r\nattempts to make it more approachable. Furthermore, its architecture requires\r\ncomplex changes to support practical systems. As a result, both system builders\r\nand students struggle with Paxos.\r\n

\r\n\r\n

\r\nAfter struggling with Paxos ourselves, we set out to find a new consensus\r\nalgorithm that could provide a better foundation for system building and\r\neducation. Our approach was unusual in that our primary goal was\r\nunderstandability: could we define a consensus algorithm for practical systems\r\nand describe it in a way that is significantly easier to learn than Paxos?\r\nFurthermore, we wanted the algorithm to facilitate the development of intuitions\r\nthat are essential for system builders. It was important not just for the\r\nalgorithm to work, but for it to be obvious why it works.\r\n

\r\n\r\n

\r\nThe result of this work is a consensus algorithm called Raft. In designing Raft\r\nwe applied specific techniques to improve understandability,including\r\ndecomposition (Raft separates leader election, log replication, and safety) and\r\nThis tech report is an extended version of [32]; additional material is noted\r\nwith a gray bar in the margin. Published May 20, 2014. state space reduction\r\n(relative to Paxos, Raft reduces the degree of nondeterminism and the ways\r\nservers can be inconsistent with each other). A user study with 43 students\r\nat two universities shows that Raft is significantly easier to understand than\r\nPaxos: after learning both algorithms, 33 of these students were able to answer\r\nquestions about Raft better than questions about Paxos.\r\n

\r\n\r\n

\r\nRaft is similar in many ways to existing consensus algorithms (most notably, Oki\r\nand Liskov's Viewstamped Replication [29, 22]), but it has several novel\r\nfeatures:\r\n

\r\n\r\n

\r\n1/. Strong leader: Raft uses a stronger form of leadership than other consensus\r\nalgorithms. For example, log entries only flow from the leader to other servers.\r\nThis simplifies the management of the replicated log and makes Raft easier to\r\nunderstand.\r\n

\r\n\r\n

\r\n2/. Leader election: Raft uses randomized timers to elect leaders. This adds\r\nonly a small amount of mechanism to the heartbeats already required for any\r\nconsensus algorithm, while resolving conflicts simply and rapidly.\r\n

\r\n\r\n

\r\n3/. Membership changes: Raft's mechanism for changing the set of servers in the\r\ncluster uses a new joint consensus approach where the majorities of two\r\ndifferent configurations overlap during transitions. This allows the cluster to\r\ncontinue operating normally during configuration changes.\r\n

\r\n\r\n

\r\nWe believe that Raft is superior to Paxos and other consensus algorithms, both\r\nfor educational purposes and as a foundation for implementation. It is simpler\r\nand more understandable than other algorithms; it is described completely enough\r\nto meet the needs of a practical system; it has several open-source\r\nimplementations and is used by several companies; its safety properties have\r\nbeen formally specified and proven; and its efficiency is comparable to other\r\nalgorithms.\r\n

\r\n\r\n

\r\nThe remainder of the paper introduces the replicated state machine problem\r\n(Section 2), discusses the strengths and weaknesses of Paxos (Section 3),\r\ndescribes our general approach to understandability (Section 4), presents the\r\nRaft consensus algorithm (Sections 5–8), evaluates Raft (Section 9), and\r\ndiscusses related work (Section 10).\r\n

\r\n
\r\n
\r\n\r\n
\r\n

2 Replicated state machines

\r\n
\r\n

\r\nConsensus algorithms typically arise in the context of replicated state machines\r\n[37]. In this approach, state machines on a collection of servers compute\r\nidentical copies of the same state and can continue operating even if some of\r\nthe servers are down. Replicated state machines are used to solve a variety of\r\nfault tolerance problems in distributed systems. For example, large-scale\r\nsystems that have a single cluster leader, such as GFS [8], HDFS [38], and\r\nRAMCloud [33], typically use a separate replicated state machine to manage\r\nleader election and store configuration information that must survive leader\r\ncrashes. Examples of replicated state machines include Chubby [2] and\r\nZooKeeper [11].\r\n

\r\n\r\n\r\n
\r\n

\"raft-figure1.jpg\"\r\n

\r\n

Figure 1: Replicated state machine architecture. The consensus algorithm manages a replicated log containing state machine commands from clients. The state machines process identical sequences of commands from the logs, so they produce the same outputs.

\r\n
\r\n\r\n

\r\nReplicated state machines are typically implemented using a replicated log, as\r\nshown in Figure 1. Each server s", + "truncated": true + }, + { + "bytes": 900468, + "kind": "research", + "path": "research/cultnet-distributed-database/dynamo-sosp2007.pdf", + "text": "%PDF-1.3\r%����\r\n101 0 obj <>\rendobj\r \r\nxref\r\n101 29\r\n0000000016 00000 n\r\n0000001444 00000 n\r\n0000001525 00000 n\r\n0000001727 00000 n\r\n0000001863 00000 n\r\n0000002320 00000 n\r\n0000002760 00000 n\r\n0000003302 00000 n\r\n0000004074 00000 n\r\n0000004327 00000 n\r\n0000004601 00000 n\r\n0000004869 00000 n\r\n0000004982 00000 n\r\n0000005229 00000 n\r\n0000006383 00000 n\r\n0000006918 00000 n\r\n0000007199 00000 n\r\n0000008288 00000 n\r\n0000009351 00000 n\r\n0000010473 00000 n\r\n0000011530 00000 n\r\n0000012622 00000 n\r\n0000013685 00000 n\r\n0000014725 00000 n\r\n0000035703 00000 n\r\n0000072079 00000 n\r\n0000119236 00000 n\r\n0000150351 00000 n\r\n0000000876 00000 n\r\ntrailer\r\n<]>>\r\nstartxref\r\n0\r\n%%EOF\r\n \r\n129 0 obj<>stream\r\nx�b```\u0006��\f�\f\f�\u0002\f�\f\b \f\u0014cc`a�������Ȣ��\u0010�됺���qņ�\u000elݬ|\u0015\u0012;��Y.wh\u0005�\u0019+x��\u00196l\u0007jl��\u001ez���\u000e�UH�1(\u0004�q\u0014�\u001a�NOh��ql29\u001a\u0016��jr\b((\u001aY��Q�!2٧\u0010,+��,���$\u001a\u0019Y&_y\t�&IB�Hh�\r �\u0010�f\tT�\ndL2��\u0005��2�q\u0014r�I���ި}�!2�\rf���,w��\u001b@5*\t�\u0002\u000b�\u0002\u0015�]��s\u0019�X���B�����\t\u000bN\u0000\u001d�Z\u0006v+�DG\u0007\u0003���GG\u0003��K(�\u0003�I\u00009\f\fJ\u0011 1\u0010��\u0000�3\u0018\u001b�)\u0006�\b0�ll\u0001�\u0019\u0005��4�*\u001a�,a\u000b�V�\f�1b\u0019`���2 ���\nv4\u0010\u0017�@`��\u0013\u001a\u0005���X\u000b,�� �0�!�q\u0016c'�{��\f�\u0018\u001e3�epb8�\u0012����\u0015�\u0010�\u000f\u0016c�O,��?�\u001f\u0006\u001e�}���2&�#��K\f�\u0018:\u0019�I�1\u00043|\u0000�T�pIU�\u0001\u001d�1��O\u0005�\u0002`�'\u0006\u000e��1T1X\n����J\u0010\u000b{��s��}�P\u001c\u0003�V+ �\u0004��@���sd?T�K�\u0000\u0003\u0000���z\r\nendstream\rendobj\r102 0 obj<>\rendobj\r103 0 obj<>\rendobj\r104 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>>\rendobj\r105 0 obj<>\rendobj\r106 0 obj<>\rendobj\r107 0 obj<>\rendobj\r108 0 obj<>\rendobj\r109 0 obj<>\rendobj\r110 0 obj<>\rendobj\r111 0 obj<>\rendobj\r112 0 obj<>\rendobj\r113 0 obj<>\rendobj\r114 0 obj<>stream\r\nH�lUێ�6\u0010}�W�#\u0005X�D��''\u000bl��@\u0010\u000b�â\u000f\\��ٕ(W��n>#_�!)��E�X�™9g�\\��q��A�>��\u000fm� �v�JkH�\u000f/UC\u001b\u0006U�Q\u0006��J���m�Jh�$h{Y��WŇ�\u0017�\f�Ǩ~j�,\u000f��\u00156g.{��\u000b�*^�3�g\u0001[3N\u0002��o\u000b�/`̃1h\u0012��e�\u000e\u001cA7��\u0017�ɾ;J|�^��0+Z$\u0001\u0013]����3�����QZ�oˆ\t�\u0018�>�_xd�n�Ӹ��*G\u0003\u0015�?Ť��A�ڹ�h����XU�\n��JZ��η��ꮸQAK�\"D�\t��!�\bxͯ%̰L%��j�.\u0018��z���1K-��Ѯ�!�|ܶ\u0011�U��O�����wl\u001cH\u0003E\u000eE��2\u000fL��g�\u0016��$�E/�sTњ�^:����F��@�\t\u0013n`�RF3�#dT\u0011��Y��x�ӆ��eJ�{\u0000�C��.�li0K�\u0005����#FoP��2\"`�{4s\u0014�,\u000f\u0007��\u0006\u00054Q�\btGg�E\u0015\nO�\"r��\u0018Y�\b��3�kl�ڒ^\u0010`\u001d�.��\u000bZ.�s���\bN\u0016J؋A(#v�`��ϒ�\n�xZ\u0006��]�R�'_Cm��CQ�\u001c��ܙ�[\b[e\u001c�\u0010�\b��[�S�'a�5VQ��N�6ќ�rp��\u0014��$+��\u00055\u0015��\u0007%\f��\u0002X�\u0013Λ2���X�\u001b��\u0010�-�Տ\u001dG\t�4�bJm�6��X֩U������G�&}dzy�u|\u000f����B�i���u\b)l\f>a\rp���x�K�0Nr�Į��o�`�D6_�C\\�(q\u001d��?\u0001\u0006\u0000�V!o\r\nendstream\rendobj\r115 0 obj<>\rendobj\r116 0 obj<>\rendobj\r117 0 obj<>stream\r\nH�tU˖�6\f��+��ΉTQ/K˞z�l��w9Ypd�f\"�>zx2���\u001f�\u000b��x&�J6\t\\\u0000\u0017�e��Y�Iq�vY*%�z�E�\u001bn�j;O�L/��]��AQ�D����xرs\u0019���%�/𶳱�[��%N괈���>��I�W-��z|��d��M�hF�����N���-@�\u0005h|\u00001�j��Lb`�N2$��:��2��\u0012��4�����p�\u001b�\u0014<���\u0017��>R�$��mT���\u0006��W\u001b\u0004d3��\\��(��$�,�}��;��jԂ�k#�)s������V�\u001e�T< 6�\u00011p��+��+�)tD�F�O���Nz2\u0017�a(F\u0003�^[#W�\"�0T�\u0019n�\u001e��f�,�w�\u0004\u000b�Ģ��wk\u001f\r�Pk{\u0002���e\u001b\u0002\u0014e��j.�\u001e(%\u0017-�\r$߹]h\u00033\\��\u0015\u0018\u0002��N=�o>I,argCE�m�/��(-a1{w7��v\u000eW�A�1�\u0003�\u0006cj\u000e\u0000\u000e!�ȟk\u001f���ݟ����{z���P���۪XW�{]\u0000DSw�h��edh�0��N,|\u0018\f���Kw7'>\r��.v�1����������\r`D���e�=���i10F,\u001b��\u0018�7\u0010G�ˉ��\fR��k\u0000��w�0�\u0011�\b\f�Q�\u001f���!�\u001b�ʟC�\u0018 d�\u0014�\u001ab�A{*^\u000f��\"-���]5��\u0003�\u001f�6h�\u0001;�P�4/V\r@���P\u001dՍ���=��\u0012V\u0010\u0000�\u001d$\f��Y��u�9��f�\u001a��>�bOغN���xqդ�\u000b��Ӵ2(o4nJ���y�g_��\bQ\u001c�w\u001dH�?��\u0004�\u0012\u000b��1™\u0018A\u0015�����\f\u0019��򐵕��NJ���\u0017h���U�ۭ7\u001d/y��zb*N��g�7:�o�����3 fH������S�\t%q� f�o�{�*�&�\u001e�7�O=�Bfh\u001eD\u0006s\u001b���==��z�1��w>Y�A�Fٚ\r70�\u0007����Fh\"�\u001c=^\u001e\u000f{��\u0015�\n� �9�v<�\u0002=>C8��\t|�R\u0014\r��qx`%�Z���\u000f�m\u00177\u001a4�����\u001bv�S7���Ɖ�c�7\u001e�e�V�E�\u0002�\u0001�K`̟^���ޖ萖��\u0012b�\u0002��\u001e��t������ч&��\u0007\u001b�B^X\u0001�g��B�j��I�\u0007*�*�\u0013`\u0000h�\u001f\u0016\r\nendstream\rendobj\r118 0 obj<>stream\r\nH�|Uێ�6\u0010}�W�#\t�X��'OE\u0017(\u0012�� �>-�i[�,�\u0014�E�\u0019��ΐ�/�m��K�2g�3���槶�AB���\"��\nRh�7�HӴ���+�C��yb_y%\u0014{�\u0013)2\u0006��X���5��M�.YG�\r��\u000e\u001b�=܋�/\u0005O��Y\u0001�k�q��T�M�\u0001>�9\u0002\u0013�G$0���?(�2$��\f�.��sr2&�p⹨���\u001b&��sJ\u0005\u001e��\b��'��ٌG9s����q���rp\u0005R�A�\u000b\u0003\r1�b=�E�C���26�\u0003/�����\u001d�K\u0016*�SA�TL�ӊW�x�\nx���^\u0001s�V\u0015\n��#\u0016P����Gi�0ev�\u0011S�lk|\u0017YW�hdd����ؾT�Y۝��n���(�L\u0003F!�欀�\f�\u0012I�\u0004/+(r�2%\n\u0005�1D/�A�.Q�_�����j�Մ8��Ƈi@f��u��9<2VUf�\u0012u.C�\u0004f*���7vp��|G&��3\u001d�u7�\u0006�Y�'Ff��n\u001cV�ůC(}�%�ǜ�\u0004��_�t�\u0006�\r�Q3�C��K�\u001a\r�\u00062\f\u001ar���\u0001\"�u\u0003P�]�\u0017-�D���`u0s�\u0004��Ӎ\u0006�Q\"UDI$�I\u0011�VkWUE�������\"��~\u001f>�_\u001e������\t�m\u0001)�\u001a�YS *W}J��s�\u0005͍��\u0004v�f�Qgu�e����q��\f[\r:Azs֛�2=\n�:4��5��\u000e\tn�$�\u0005M�x\u000fܡs\u0010\u0000�7�|4\u001dQ]�G!�9p���'\r�\bY�q�\u001d\u001c���8\u000e\u0006\u001f�����\t��΀�'", + "truncated": true + }, + { + "bytes": 46272, + "kind": "research", + "path": "research/cultnet-distributed-database/crdt-arxiv-1805.06358.html", + "text": "\r\n\r\n\r\n [1805.06358] Conflict-free Replicated Data Types (CRDTs)\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n\r\n \r\n \r\n

\r\n
\r\n Skip to main content\r\n \r\n
\r\n
\r\n \"Cornell\r\n
\r\n We gratefully acknowledge support from the Simons Foundation, member institutions, and all contributors.\r\n Donate\r\n
\r\n
\r\n\r\n
\r\n\r\n
\r\n \"arxiv > cs > arXiv:1805.06358\r\n
\r\n\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n \r\n

Help | Advanced Search

\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\"arXiv
\r\n
\r\n \r\n \r\n\r\n \r\n \r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\nDynamo: Amazon’s highly available key-value store - Amazon Science\r\n \r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n \r\n\r\n \r\n\r\n\r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n\r\n\r\n\r\n \r\n \r\n \r\n\r\n \r\n \r\n\r\n\r\n\r\n\r\n\r\n
\r\n UP \r\n |\r\n HOME \r\n
\r\n

In Search of an Understandable Consensus Algorithm (Extended Version)

\r\n\r\n\r\n
\r\n

DECLARATION

\r\n
\r\n

\r\nThis page is the In Search of an Understandable Consensus Algorithm\r\n(Extended Version) paper. Original Paper Link\r\nis: https://raft.github.io/raft.pdf\r\n

\r\n\r\n

\r\nIn Search of an Understandable Consensus Algorithm
\r\n(Extended Version)
\r\nDiego Ongaro and John Ousterhout
\r\nStanford University\r\n

\r\n
\r\n
\r\n\r\n
\r\n

Abstract

\r\n
\r\n

\r\nRaft is a consensus algorithm for managing a replicated log. It produces a\r\nresult equivalent to (multi-)Paxos, and it is as efficient as Paxos, but its\r\nstructure is different from Paxos; this makes Raft more understandable than\r\nPaxos and also provides a better foundation for building practical systems.\r\nIn order to enhance understandability, Raft separates the key elements of\r\nconsensus, such as leader election, log replication, and safety, and it enforces\r\na stronger degree of coherency to reduce the number of states that must be\r\nconsidered. Results from a user study demonstrate that Raft is easier for\r\nstudents to learn than Paxos. Raft also includes a new mechanism for changing\r\nthe cluster membership, which uses overlapping majorities to guarantee safety.\r\n

\r\n
\r\n
\r\n\r\n
\r\n

1 Introduction

\r\n
\r\n

\r\nConsensus algorithms allow a collection of machines to work as a coherent group\r\nthat can survive the failures of some of its members. Because of this, they play\r\na key role in building reliable large-scale software systems. Paxos [15, 16] has\r\ndominated the discussion of consensus algorithms over the last decade: most\r\nimplementations of consensus are based on Paxos or influenced by it, and Paxos\r\nhas become the primary vehicle used to teach students about consensus.\r\n

\r\n\r\n

\r\nUnfortunately, Paxos is quite difficult to understand, in spite of numerous\r\nattempts to make it more approachable. Furthermore, its architecture requires\r\ncomplex changes to support practical systems. As a result, both system builders\r\nand students struggle with Paxos.\r\n

\r\n\r\n

\r\nAfter struggling with Paxos ourselves, we set out to find a new consensus\r\nalgorithm that could provide a better foundation for system building and\r\neducation. Our approach was unusual in that our primary goal was\r\nunderstandability: could we define a consensus algorithm for practical systems\r\nand describe it in a way that is significantly easier to learn than Paxos?\r\nFurthermore, we wanted the algorithm to facilitate the development of intuitions\r\nthat are essential for system builders. It was important not just for the\r\nalgorithm to work, but for it to be obvious why it works.\r\n

\r\n\r\n

\r\nThe result of this work is a consensus algorithm called Raft. In designing Raft\r\nwe applied specific techniques to improve understandability,including\r\ndecomposition (Raft separates leader election, log replication, and safety) and\r\nThis tech report is an extended version of [32]; additional material is noted\r\nwith a gray bar in the margin. Published May 20, 2014. state space reduction\r\n(relative to Paxos, Raft reduces the degree of nondeterminism and the ways\r\nservers can be inconsistent with each other). A user study with 43 students\r\nat two universities shows that Raft is significantly easier to understand than\r\nPaxos: after learning both algorithms, 33 of these students were able to answer\r\nquestions about Raft better than questions about Paxos.\r\n

\r\n\r\n

\r\nRaft is similar in many ways to existing consensus algorithms (most notably, Oki\r\nand Liskov's Viewstamped Replication [29, 22]), but it has several novel\r\nfeatures:\r\n

\r\n\r\n

\r\n1/. Strong leader: Raft uses a stronger form of leadership than other consensus\r\nalgorithms. For example, log entries only flow from the leader to other servers.\r\nThis simplifies the management of the replicated log and makes Raft easier to\r\nunderstand.\r\n

\r\n\r\n

\r\n2/. Leader election: Raft uses randomized timers to elect leaders. This adds\r\nonly a small amount of mechanism to the heartbeats already required for any\r\nconsensus algorithm, while resolving conflicts simply and rapidly.\r\n

\r\n\r\n

\r\n3/. Membership changes: Raft's mechanism for changing the set of servers in the\r\ncluster uses a new joint consensus approach where the majorities of two\r\ndifferent configurations overlap during transitions. This allows the cluster to\r\ncontinue operating normally during configuration changes.\r\n

\r\n\r\n

\r\nWe believe that Raft is superior to Paxos and other consensus algorithms, both\r\nfor educational purposes and as a foundation for implementation. It is simpler\r\nand more understandable than other algorithms; it is described completely enough\r\nto meet the needs of a practical system; it has several open-source\r\nimplementations and is used by several companies; its safety properties have\r\nbeen formally specified and proven; and its efficiency is comparable to other\r\nalgorithms.\r\n

\r\n\r\n

\r\nThe remainder of the paper introduces the replicated state machine problem\r\n(Section 2), discusses the strengths and weaknesses of Paxos (Section 3),\r\ndescribes our general approach to understandability (Section 4), presents the\r\nRaft consensus algorithm (Sections 5–8), evaluates Raft (Section 9), and\r\ndiscusses related work (Section 10).\r\n

\r\n
\r\n
\r\n\r\n
\r\n

2 Replicated state machines

\r\n
\r\n

\r\nConsensus algorithms typically arise in the context of replicated state machines\r\n[37]. In this approach, state machines on a collection of servers compute\r\nidentical copies of the same state and can continue operating even if some of\r\nthe servers are down. Replicated state machines are used to solve a variety of\r\nfault tolerance problems in distributed systems. For example, large-scale\r\nsystems that have a single cluster leader, such as GFS [8], HDFS [38], and\r\nRAMCloud [33], typically use a separate replicated state machine to manage\r\nleader election and store configuration information that must survive leader\r\ncrashes. Examples of replicated state machines include Chubby [2] and\r\nZooKeeper [11].\r\n

\r\n\r\n\r\n
\r\n

\"raft-figure1.jpg\"\r\n

\r\n

Figure 1: Replicated state machine architecture. The consensus algorithm manages a replicated log containing state machine commands from clients. The state machines process identical sequences of commands from the logs, so they produce the same outputs.

\r\n
\r\n\r\n

\r\nReplicated state machines are typically implemented using a replicated log, as\r\nshown in Figure 1. Each server s", + "truncated": true + }, + { + "bytes": 900468, + "kind": "research", + "path": "research/cultnet-distributed-database/dynamo-sosp2007.pdf", + "text": "%PDF-1.3\r%����\r\n101 0 obj <>\rendobj\r \r\nxref\r\n101 29\r\n0000000016 00000 n\r\n0000001444 00000 n\r\n0000001525 00000 n\r\n0000001727 00000 n\r\n0000001863 00000 n\r\n0000002320 00000 n\r\n0000002760 00000 n\r\n0000003302 00000 n\r\n0000004074 00000 n\r\n0000004327 00000 n\r\n0000004601 00000 n\r\n0000004869 00000 n\r\n0000004982 00000 n\r\n0000005229 00000 n\r\n0000006383 00000 n\r\n0000006918 00000 n\r\n0000007199 00000 n\r\n0000008288 00000 n\r\n0000009351 00000 n\r\n0000010473 00000 n\r\n0000011530 00000 n\r\n0000012622 00000 n\r\n0000013685 00000 n\r\n0000014725 00000 n\r\n0000035703 00000 n\r\n0000072079 00000 n\r\n0000119236 00000 n\r\n0000150351 00000 n\r\n0000000876 00000 n\r\ntrailer\r\n<]>>\r\nstartxref\r\n0\r\n%%EOF\r\n \r\n129 0 obj<>stream\r\nx�b```\u0006��\f�\f\f�\u0002\f�\f\b \f\u0014cc`a�������Ȣ��\u0010�됺���qņ�\u000elݬ|\u0015\u0012;��Y.wh\u0005�\u0019+x��\u00196l\u0007jl��\u001ez���\u000e�UH�1(\u0004�q\u0014�\u001a�NOh��ql29\u001a\u0016��jr\b((\u001aY��Q�!2٧\u0010,+��,���$\u001a\u0019Y&_y\t�&IB�Hh�\r �\u0010�f\tT�\ndL2��\u0005��2�q\u0014r�I���ި}�!2�\rf���,w��\u001b@5*\t�\u0002\u000b�\u0002\u0015�]��s\u0019�X���B�����\t\u000bN\u0000\u001d�Z\u0006v+�DG\u0007\u0003���GG\u0003��K(�\u0003�I\u00009\f\fJ\u0011 1\u0010��\u0000�3\u0018\u001b�)\u0006�\b0�ll\u0001�\u0019\u0005��4�*\u001a�,a\u000b�V�\f�1b\u0019`���2 ���\nv4\u0010\u0017�@`��\u0013\u001a\u0005���X\u000b,�� �0�!�q\u0016c'�{��\f�\u0018\u001e3�epb8�\u0012����\u0015�\u0010�\u000f\u0016c�O,��?�\u001f\u0006\u001e�}���2&�#��K\f�\u0018:\u0019�I�1\u00043|\u0000�T�pIU�\u0001\u001d�1��O\u0005�\u0002`�'\u0006\u000e��1T1X\n����J\u0010\u000b{��s��}�P\u001c\u0003�V+ �\u0004��@���sd?T�K�\u0000\u0003\u0000���z\r\nendstream\rendobj\r102 0 obj<>\rendobj\r103 0 obj<>\rendobj\r104 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>>\rendobj\r105 0 obj<>\rendobj\r106 0 obj<>\rendobj\r107 0 obj<>\rendobj\r108 0 obj<>\rendobj\r109 0 obj<>\rendobj\r110 0 obj<>\rendobj\r111 0 obj<>\rendobj\r112 0 obj<>\rendobj\r113 0 obj<>\rendobj\r114 0 obj<>stream\r\nH�lUێ�6\u0010}�W�#\u0005X�D��''\u000bl��@\u0010\u000b�â\u000f\\��ٕ(W��n>#_�!)��E�X�™9g�\\��q��A�>��\u000fm� �v�JkH�\u000f/UC\u001b\u0006U�Q\u0006��J���m�Jh�$h{Y��WŇ�\u0017�\f�Ǩ~j�,\u000f��\u00156g.{��\u000b�*^�3�g\u0001[3N\u0002��o\u000b�/`̃1h\u0012��e�\u000e\u001cA7��\u0017�ɾ;J|�^��0+Z$\u0001\u0013]����3�����QZ�oˆ\t�\u0018�>�_xd�n�Ӹ��*G\u0003\u0015�?Ť��A�ڹ�h����XU�\n��JZ��η��ꮸQAK�\"D�\t��!�\bxͯ%̰L%��j�.\u0018��z���1K-��Ѯ�!�|ܶ\u0011�U��O�����wl\u001cH\u0003E\u000eE��2\u000fL��g�\u0016��$�E/�sTњ�^:����F��@�\t\u0013n`�RF3�#dT\u0011��Y��x�ӆ��eJ�{\u0000�C��.�li0K�\u0005����#FoP��2\"`�{4s\u0014�,\u000f\u0007��\u0006\u00054Q�\btGg�E\u0015\nO�\"r��\u0018Y�\b��3�kl�ڒ^\u0010`\u001d�.��\u000bZ.�s���\bN\u0016J؋A(#v�`��ϒ�\n�xZ\u0006��]�R�'_Cm��CQ�\u001c��ܙ�[\b[e\u001c�\u0010�\b��[�S�'a�5VQ��N�6ќ�rp��\u0014��$+��\u00055\u0015��\u0007%\f��\u0002X�\u0013Λ2���X�\u001b��\u0010�-�Տ\u001dG\t�4�bJm�6��X֩U������G�&}dzy�u|\u000f����B�i���u\b)l\f>a\rp���x�K�0Nr�Į��o�`�D6_�C\\�(q\u001d��?\u0001\u0006\u0000�V!o\r\nendstream\rendobj\r115 0 obj<>\rendobj\r116 0 obj<>\rendobj\r117 0 obj<>stream\r\nH�tU˖�6\f��+��ΉTQ/K˞z�l��w9Ypd�f\"�>zx2���\u001f�\u000b��x&�J6\t\\\u0000\u0017�e��Y�Iq�vY*%�z�E�\u001bn�j;O�L/��]��AQ�D����xرs\u0019���%�/𶳱�[��%N괈���>��I�W-��z|��d��M�hF�����N���-@�\u0005h|\u00001�j��Lb`�N2$��:��2��\u0012��4�����p�\u001b�\u0014<���\u0017��>R�$��mT���\u0006��W\u001b\u0004d3��\\��(��$�,�}��;��jԂ�k#�)s������V�\u001e�T< 6�\u00011p��+��+�)tD�F�O���Nz2\u0017�a(F\u0003�^[#W�\"�0T�\u0019n�\u001e��f�,�w�\u0004\u000b�Ģ��wk\u001f\r�Pk{\u0002���e\u001b\u0002\u0014e��j.�\u001e(%\u0017-�\r$߹]h\u00033\\��\u0015\u0018\u0002��N=�o>I,argCE�m�/��(-a1{w7��v\u000eW�A�1�\u0003�\u0006cj\u000e\u0000\u000e!�ȟk\u001f���ݟ����{z���P���۪XW�{]\u0000DSw�h��edh�0��N,|\u0018\f���Kw7'>\r��.v�1����������\r`D���e�=���i10F,\u001b��\u0018�7\u0010G�ˉ��\fR��k\u0000��w�0�\u0011�\b\f�Q�\u001f���!�\u001b�ʟC�\u0018 d�\u0014�\u001ab�A{*^\u000f��\"-���]5��\u0003�\u001f�6h�\u0001;�P�4/V\r@���P\u001dՍ���=��\u0012V\u0010\u0000�\u001d$\f��Y��u�9��f�\u001a��>�bOغN���xqդ�\u000b��Ӵ2(o4nJ���y�g_��\bQ\u001c�w\u001dH�?��\u0004�\u0012\u000b��1™\u0018A\u0015�����\f\u0019��򐵕��NJ���\u0017h���U�ۭ7\u001d/y��zb*N��g�7:�o�����3 fH������S�\t%q� f�o�{�*�&�\u001e�7�O=�Bfh\u001eD\u0006s\u001b���==��z�1��w>Y�A�Fٚ\r70�\u0007����Fh\"�\u001c=^\u001e\u000f{��\u0015�\n� �9�v<�\u0002=>C8��\t|�R\u0014\r��qx`%�Z���\u000f�m\u00177\u001a4�����\u001bv�S7���Ɖ�c�7\u001e�e�V�E�\u0002�\u0001�K`̟^���ޖ萖��\u0012b�\u0002��\u001e��t������ч&��\u0007\u001b�B^X\u0001�g��B�j��I�\u0007*�*�\u0013`\u0000h�\u001f\u0016\r\nendstream\rendobj\r118 0 obj<>stream\r\nH�|Uێ�6\u0010}�W�#\t�X��'OE\u0017(\u0012�� �>-�i[�,�\u0014�E�\u0019��ΐ�/�m��K�2g�3���槶�AB���\"��\nRh�7�HӴ���+�C��yb_y%\u0014{�\u0013)2\u0006��X���5��M�.YG�\r��\u000e\u001b�=܋�/\u0005O��Y\u0001�k�q��T�M�\u0001>�9\u0002\u0013�G$0���?(�2$��\f�.��sr2&�p⹨���\u001b&��sJ\u0005\u001e��\b��'��ٌG9s����q���rp\u0005R�A�\u000b\u0003\r1�b=�E�C���26�\u0003/�����\u001d�K\u0016*�SA�TL�ӊW�x�\nx���^\u0001s�V\u0015\n��#\u0016P����Gi�0ev�\u0011S�lk|\u0017YW�hdd����ؾT�Y۝��n���(�L\u0003F!�欀�\f�\u0012I�\u0004/+(r�2%\n\u0005�1D/�A�.Q�_�����j�Մ8��Ƈi@f��u��9<2VUf�\u0012u.C�\u0004f*���7vp��|G&��3\u001d�u7�\u0006�Y�'Ff��n\u001cV�ůC(}�%�ǜ�\u0004��_�t�\u0006�\r�Q3�C��K�\u001a\r�\u00062\f\u001ar���\u0001\"�u\u0003P�]�\u0017-�D���`u0s�\u0004��Ӎ\u0006�Q\"UDI$�I\u0011�VkWUE�������\"��~\u001f>�_\u001e������\t�m\u0001)�\u001a�YS *W}J��s�\u0005͍��\u0004v�f�Qgu�e����q��\f[\r:Azs֛�2=\n�:4��5��\u000e\tn�$�\u0005M�x\u000fܡs\u0010\u0000�7�|4\u001dQ]�G!�9p���'\r�\bY�q�\u001d\u001c���8\u000e\u0006\u001f�����\t��΀�'", + "truncated": true + }, + { + "bytes": 46272, + "kind": "research", + "path": "research/cultnet-distributed-database/crdt-arxiv-1805.06358.html", + "text": "\r\n\r\n\r\n [1805.06358] Conflict-free Replicated Data Types (CRDTs)\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n\r\n \r\n \r\n

\r\n
\r\n Skip to main content\r\n \r\n
\r\n
\r\n \"Cornell\r\n
\r\n We gratefully acknowledge support from the Simons Foundation, member institutions, and all contributors.\r\n Donate\r\n
\r\n
\r\n\r\n
\r\n\r\n
\r\n \"arxiv > cs > arXiv:1805.06358\r\n
\r\n\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n \r\n

Help | Advanced Search

\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\"arXiv
\r\n
\r\n \r\n \r\n\r\n \r\n \r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\nDynamo: Amazon’s highly available key-value store - Amazon Science\r\n \r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n \r\n\r\n \r\n\r\n\r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n\r\n\r\n\r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n\r\n \r\n \r\n
\r\n
\r\n Skip to main content\r\n \r\n
\r\n
\r\n \"Cornell\r\n
\r\n We gratefully acknowledge support from the Simons Foundation, member institutions, and all contributors.\r\n Donate\r\n
\r\n
\r\n\r\n
\r\n\r\n
\r\n \"arxiv > cs > arXiv:1805.06358\r\n
\r\n\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n \r\n

Help | Advanced Search

\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\"arXiv
\r\n \r\n
\r\n \r\n
\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n
\r\n
\r\n
\r\n\r\n \r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n >\rendobj\r \r\nxref\r\n101 29\r\n0000000016 00000 n\r\n0000001444 00000 n\r\n0000001525 00000 n\r\n0000001727 00000 n\r\n0000001863 00000 n\r\n0000002320 00000 n\r\n0000002760 00000 n\r\n0000003302 00000 n\r\n0000004074 00000 n\r\n0000004327 00000 n\r\n0000004601 00000 n\r\n0000004869 00000 n\r\n0000004982 00000 n\r\n0000005229 00000 n\r\n0000006383 00000 n\r\n0000006918 00000 n\r\n0000007199 00000 n\r\n0000008288 00000 n\r\n0000009351 00000 n\r\n0000010473 00000 n\r\n0000011530 00000 n\r\n0000012622 00000 n\r\n0000013685 00000 n\r\n0000014725 00000 n\r\n0000035703 00000 n\r\n0000072079 00000 n\r\n0000119236 00000 n\r\n0000150351 00000 n\r\n0000000876 00000 n\r\ntrailer\r\n<\r \r \r put typed doc -> get typed doc\"\r\npath, start with\r\n[`src/GameCult.Mesh/docs/durable-node-quickstart.md`](src/GameCult.Mesh/docs/durable-node-quickstart.md).\r\nIf you want the lower-level \"typed local document -> raw wire document ->\r\nmesh/runtime watch surface\" handoff, follow it with\r\n[`src/GameCult.Mesh/docs/typed-document-path.md`](src/GameCult.Mesh/docs/typed-document-path.md).\r\n\r\n## Repository Scope\r\n\r\nThe solution includes:\n\n- `GameCult.Logging`: common logging abstraction plus console and file implementations\n- `GameCult.Caching`: `DatabaseEntry`-based cache, indexes, global entries, and backing-store abstractions\n- `GameCult.Caching.MessagePack`: MessagePack-backed persistence for the cache\r\n- `GameCult.Caching.NewtonsoftJson`: Newtonsoft.Json-backed persistence for the cache\r\n- `GameCult.Caching.MessagePack.Generator`: source generator for MessagePack formatters for cache models\n- `GameCult.Caching.MessagePack.Analyzers`: packaging project that delivers the generator to consuming projects\n- `GameCult.Geometry`: CultCache-native geometry domain, selected-cut, and chunk artifact documents for VibeGeometry/Fensalir-style pipelines\n- `GameCult.Networking`: encrypted login/register/verify flows and message dispatch over LiteNetLib\n- `GameCult.Mesh`: CultMesh package home for distributed realtime database, shard replication, client prediction, Verse discovery, and mesh witness consensus\n- `GameCult.Caching.Tests`: NUnit tests for cache and backing-store behavior\n- `GameCult.Networking.Tests`: NUnit tests for networking behavior\n- `GameCult.Unity`: CultUI, a Unity runtime UI composition framework with reflective inspector generation, prefab-backed field resolvers, reusable controls, and a demo project packaged for UPM-style consumption\n- `packages/cultcache-ts`: TypeScript CultCache with MessagePack persistence and inspector tooling\n- `packages/cultnet-ts`: TypeScript CultNet schema-v0 contracts, framing, discovery, raw document replication, and interop tests\n- `packages/cultmesh-ts`: TypeScript CultMesh local node and mesh catalog surface for local runtimes such as VoidBot\n- `packages/cultcache-rs`: Rust CultCache and derive macro\n- `packages/cultnet-rs`: Rust CultNet contracts, framing, discovery, and interop peer\n\n## Repository Layout\n\n```text\npackage.json\nsrc/\n GameCult.Logging/\n GameCult.Caching/\n GameCult.Caching.MessagePack/\r\n GameCult.Caching.NewtonsoftJson/\r\n GameCult.Caching.MessagePack.Generator/\n GameCult.Caching.MessagePack.Analyzers/\n GameCult.Geometry/\n GameCult.Networking/\n GameCult.Mesh/\r\n GameCult.Unity/\r\ntests/\n GameCult.Caching.Tests/\n GameCult.Geometry.Tests/\n GameCult.Networking.Tests/\npackages/\n cultcache-ts/\n cultnet-ts/\n cultmesh-ts/\n cultcache-rs/\n cultnet-rs/\n```\n\r\n## Build\r\n\r\n```powershell\r\ndotnet build CultLib.sln\r\n```\r\n\r\n## Test\n\n```powershell\ndotnet test CultLib.sln\n```\n\nTypeScript package tests:\n\n```powershell\nnpm test --workspace packages/cultcache-ts\nnpm test --workspace packages/cultnet-ts\nnpm run test:interop --workspace packages/cultnet-ts\nnpm test --workspace packages/cultmesh-ts\n```\n\nRust package tests:\n\n```powershell\ncargo test --manifest-path packages/cultcache-rs/Cargo.toml\ncargo test --manifest-path packages/cultnet-rs/Cargo.toml\n```\n\r\n## Common Concepts\r\n\r\n### `DatabaseEntry`\r\n\r\nThe cache-centric libraries revolve around `DatabaseEntry`. Every entry has a stable `Guid` identifier and can optionally:\r\n\r\n- expose a human-readable name through `INamedEntry`\r\n- participate in generic indexes registered at runtime\r\n- be treated as a global singleton entry through `GlobalSettingsAttribute`\r\n\r\nTypical entry shape:\r\n\r\n```csharp\r\nusing GameCult.Caching;\r\n\r\npublic class ItemData : DatabaseEntry, INamedEntry\r\n{\r\n public string Name = string.Empty;\r\n public int Value;\r\n\r\n public string EntryName\r\n {\r\n get => Name;\r\n set => Name = value;\r\n }\r\n}\r\n```\r\n\r\n### `CultCache` and Backing Stores\r\n\r\n`CultCache` is an in-memory index over `DatabaseEntry` objects. It can operate entirely in memory, or it can be attached to one or more backing stores for persistence and synchronization.\r\n\r\n- the cache is the query surface\r\n- backing stores are persistence adapters\r\n- indexes and name maps are maintained inside the cache, not inside the store\r\n\r\n### Important: Multiple Backing Stores\r\n\r\nWhen multiple backing stores are added, behavior depends on how they are registered.\r\n\r\nIf a store is added with domain types:\r\n\r\n```csharp\r\ncache.AddBackingStore(playerStore, typeof(PlayerData));\r\ncache.AddBackingStore(settingsStore, typeof(AppSettings));\r\n```\r\n\r\nthen that store becomes the direct persistence target for those types.\r\n\r\nIf a store is added without domain types:\r\n\r\n```csharp\r\ncache.AddBackingStore(primaryStore);\r\ncache.AddBackingStore(mirrorStore);\r\n```\r\n\r\nthen the first generic store acts as the primary writable store for non-domain-specific entries. Additional generic stores subscribe to the existing stores and mirror their change events.\r\n\r\nImplications:\r\n\r\n- order matters for generic stores\r\n- `AddAsync` writes to the type-specific store when one exists\r\n- otherwise `AddAsync` writes to the first generic store\r\n- later generic stores do not become co-primaries; they mirror earlier s", + "truncated": true + }, + { + "bytes": 497, + "kind": "documentation", + "path": "notes/operator-interventions.md", + "text": "# Operator Interventions\n\n## 2026-05-08\n\n- External Codex session from `E:\\Projects\\EpiphanyAgent` added\n `src/GameCult.Caching/Contracts/cultcache-persistence-format.md`.\n- Intent: write down the next canonical CultCache persistence-format design in\n the C# source-of-truth repo before Rust/TS implementations harden the wrong\n shape.\n- Existing unrelated worktree changes in `src/GameCult.Networking/PlayerData.cs`\n and `src/GameCult.Unity/Assets/UI/Default Resolver.asset` were left alone.\n", + "truncated": false + }, + { + "bytes": 133069, + "kind": "research", + "path": "research/cultnet-distributed-database/swim.pdf", + "text": "%PDF-1.2\r%����\r\n35 0 obj\r<< \r/Linearized 1 \r/O 37 \r/H [ 5122 1132 ] \r/L 133069 \r/E 57214 \r/N 10 \r/T 132251 \r>> \rendobj\r xref\r35 235 \r0000000016 00000 n\r\n0000005049 00000 n\r\n0000006254 00000 n\r\n0000006560 00000 n\r\n0000006625 00000 n\r\n0000006733 00000 n\r\n0000006839 00000 n\r\n0000006928 00000 n\r\n0000006949 00000 n\r\n0000010404 00000 n\r\n0000011912 00000 n\r\n0000012019 00000 n\r\n0000012133 00000 n\r\n0000013163 00000 n\r\n0000013184 00000 n\r\n0000013270 00000 n\r\n0000014189 00000 n\r\n0000014210 00000 n\r\n0000015099 00000 n\r\n0000015120 00000 n\r\n0000016100 00000 n\r\n0000016121 00000 n\r\n0000017102 00000 n\r\n0000017123 00000 n\r\n0000018048 00000 n\r\n0000018069 00000 n\r\n0000018962 00000 n\r\n0000018983 00000 n\r\n0000019160 00000 n\r\n0000019376 00000 n\r\n0000019596 00000 n\r\n0000019775 00000 n\r\n0000020079 00000 n\r\n0000020316 00000 n\r\n0000020565 00000 n\r\n0000020804 00000 n\r\n0000021022 00000 n\r\n0000021309 00000 n\r\n0000021545 00000 n\r\n0000021802 00000 n\r\n0000022011 00000 n\r\n0000022242 00000 n\r\n0000022541 00000 n\r\n0000022803 00000 n\r\n0000023071 00000 n\r\n0000023314 00000 n\r\n0000023507 00000 n\r\n0000023741 00000 n\r\n0000023918 00000 n\r\n0000024149 00000 n\r\n0000024370 00000 n\r\n0000024616 00000 n\r\n0000024867 00000 n\r\n0000025088 00000 n\r\n0000025292 00000 n\r\n0000025507 00000 n\r\n0000025716 00000 n\r\n0000025929 00000 n\r\n0000026147 00000 n\r\n0000026371 00000 n\r\n0000026595 00000 n\r\n0000026816 00000 n\r\n0000026994 00000 n\r\n0000027221 00000 n\r\n0000027434 00000 n\r\n0000027662 00000 n\r\n0000027942 00000 n\r\n0000028200 00000 n\r\n0000028467 00000 n\r\n0000028709 00000 n\r\n0000028982 00000 n\r\n0000029259 00000 n\r\n0000029466 00000 n\r\n0000029722 00000 n\r\n0000030047 00000 n\r\n0000030301 00000 n\r\n0000030538 00000 n\r\n0000030776 00000 n\r\n0000031062 00000 n\r\n0000031265 00000 n\r\n0000031503 00000 n\r\n0000031755 00000 n\r\n0000031947 00000 n\r\n0000032198 00000 n\r\n0000032449 00000 n\r\n0000032686 00000 n\r\n0000032934 00000 n\r\n0000033141 00000 n\r\n0000033445 00000 n\r\n0000033644 00000 n\r\n0000033858 00000 n\r\n0000034127 00000 n\r\n0000034339 00000 n\r\n0000034560 00000 n\r\n0000034775 00000 n\r\n0000034982 00000 n\r\n0000035194 00000 n\r\n0000035416 00000 n\r\n0000035673 00000 n\r\n0000035949 00000 n\r\n0000036236 00000 n\r\n0000036520 00000 n\r\n0000036754 00000 n\r\n0000037025 00000 n\r\n0000037312 00000 n\r\n0000037500 00000 n\r\n0000037755 00000 n\r\n0000037977 00000 n\r\n0000038211 00000 n\r\n0000038499 00000 n\r\n0000038710 00000 n\r\n0000038921 00000 n\r\n0000039188 00000 n\r\n0000039405 00000 n\r\n0000039619 00000 n\r\n0000039839 00000 n\r\n0000040059 00000 n\r\n0000040320 00000 n\r\n0000040563 00000 n\r\n0000040805 00000 n\r\n0000041093 00000 n\r\n0000041327 00000 n\r\n0000041588 00000 n\r\n0000041846 00000 n\r\n0000042141 00000 n\r\n0000042404 00000 n\r\n0000042658 00000 n\r\n0000042860 00000 n\r\n0000043103 00000 n\r\n0000043356 00000 n\r\n0000043625 00000 n\r\n0000043694 00000 n\r\n0000043763 00000 n\r\n0000043832 00000 n\r\n0000043901 00000 n\r\n0000043970 00000 n\r\n0000044039 00000 n\r\n0000044108 00000 n\r\n0000044177 00000 n\r\n0000044246 00000 n\r\n0000044315 00000 n\r\n0000044384 00000 n\r\n0000044453 00000 n\r\n0000044522 00000 n\r\n0000044591 00000 n\r\n0000044660 00000 n\r\n0000044729 00000 n\r\n0000044798 00000 n\r\n0000044867 00000 n\r\n0000044936 00000 n\r\n0000045005 00000 n\r\n0000045074 00000 n\r\n0000045143 00000 n\r\n0000045212 00000 n\r\n0000045281 00000 n\r\n0000045350 00000 n\r\n0000045419 00000 n\r\n0000045488 00000 n\r\n0000045557 00000 n\r\n0000045626 00000 n\r\n0000045695 00000 n\r\n0000045765 00000 n\r\n0000045835 00000 n\r\n0000045905 00000 n\r\n0000045975 00000 n\r\n0000046045 00000 n\r\n0000046115 00000 n\r\n0000046185 00000 n\r\n0000046254 00000 n\r\n0000046323 00000 n\r\n0000046392 00000 n\r\n0000046461 00000 n\r\n0000046530 00000 n\r\n0000046599 00000 n\r\n0000046668 00000 n\r\n0000046737 00000 n\r\n0000046806 00000 n\r\n0000046875 00000 n\r\n0000046944 00000 n\r\n0000047013 00000 n\r\n0000047082 00000 n\r\n0000047151 00000 n\r\n0000047401 00000 n\r\n0000047662 00000 n\r\n0000047901 00000 n\r\n0000048126 00000 n\r\n0000048349 00000 n\r\n0000048575 00000 n\r\n0000048822 00000 n\r\n0000049044 00000 n\r\n0000049277 00000 n\r\n0000049515 00000 n\r\n0000049741 00000 n\r\n0000050062 00000 n\r\n0000050309 00000 n\r\n0000050544 00000 n\r\n0000050777 00000 n\r\n0000051018 00000 n\r\n0000051204 00000 n\r\n0000051424 00000 n\r\n0000051681 00000 n\r\n0000051915 00000 n\r\n0000052162 00000 n\r\n0000052408 00000 n\r\n0000052653 00000 n\r\n0000052885 00000 n\r\n0000053111 00000 n\r\n0000053312 00000 n\r\n0000053381 00000 n\r\n0000053450 00000 n\r\n0000053519 00000 n\r\n0000053588 00000 n\r\n0000053657 00000 n\r\n0000053726 00000 n\r\n0000053795 00000 n\r\n0000053864 00000 n\r\n0000053933 00000 n\r\n0000054002 00000 n\r\n0000054071 00000 n\r\n0000054140 00000 n\r\n0000054209 00000 n\r\n0000054488 00000 n\r\n0000054762 00000 n\r\n0000054987 00000 n\r\n0000055221 00000 n\r\n0000055431 00000 n\r\n0000055668 00000 n\r\n0000055737 00000 n\r\n0000055806 00000 n\r\n0000055875 00000 n\r\n0000055944 00000 n\r\n0000056013 00000 n\r\n0000056082 00000 n\r\n0000005122 00000 n\r\n0000006231 00000 n\r\ntrailer\r<<\r/Size 270\r/Info 33 0 R \r/Root 36 0 R \r/Prev 132241 \r/ID[]\r>>\rstartxref\r0\r%%EOF\r \r36 0 obj\r<< \r/Type /Catalog \r/Pages 32 0 R \r/Metadata 34 0 R \r>> \rendobj\r268 0 obj\r<< /S 2996 /Filter /FlateDecode /Length 269 0 R >> \rstream\r\nH�b```f`\u0010ab�``�\\� ��\u0000\u0002@1\u000e\u0006\u0016\u0006�'p�5u\f\fL���\u0019MY\u0003�8XED.21_�|��k׮_�`\u0018�������QRJFZNV^UQIAEYW]CSK[�HO��P�������������������������;���? 0(8$4,<\"2*:&6.>!1)9%5-=#3+�07/����������������������������������I��L�6}��Y��̝7��E��,]�|��U�׬]�~��M��lݶ}��]���ݷ���C��\u001c=v���S�Ϝ=w���K��\\�v���[��ܽw���G��<�d�`gafd�������UPTRVQՇxJW�\b�)cTO99�@=�G�S9���:D���\u001c�'�)\u000eF&v6N��,/^�\u0004y\f\u0018[J��\n*��0��\u001b\u0018�9�x��\u0018�\u0002�\u001e��/D��A�=v�\u0010\u0011\u001e\u0003��s��RC���\bgt�\u0010᫂�\u0001I��9؆��@q����2�|��񜅙�񕔬��������������v���������������������������������\u0017����㓟�ꫦ����F��Z;�&��L���;e��S���֕����߶e��};��=~����\u0007O\u001c;}��]��^�y����7.]���έ{g��~�����O89����bf\u0001yJ�HNUAQZYE\r�)=\u001d\u0003C\u0017dO\u0019;(�=E(��rr�\u000bPV�j~�P���\u0000�+zY%\u0018�F/�\u0018\u0018��g\u0015C\u0004}�b`q�[\u00002\u001a'`kq\u0003=+���K\u0005H?\u0007���f�(\u0003��\u0005\u001dւP\u0016\u0007�kKϳ&��\u000b0�\b710�00�g`>��������0���8�Ciކ'�\u000b�\n,��w`\u000f��\u0018��w�\u0007kx\u0003��*��\u0013x�Ӱ�Ga\u000f\u000f�Q�\r�y\u001a��<8����7�\u000b\u0004\u0018v�m4��p�w\"'w�M���|\t�x\u001b\u001es/��V8�߰���\u0010���<\u0013���\u0012(�ʿ����\u0015τ�\u0002\u001b�q?���p���8?�=ދܼ\u0001\u001f�.\n�+��\u000e��������\u0004$`\bCX\u0015<�g��s�\u0014υG<\u0013��N8+t�\u0011o�\u0015�\u0003Ky\n��\u0006<�\u0013x�kp��\u0001�^\u0001��<\u0007�r_�\u0001\u00171wpaY\u0010�2\u0001G\u0001 �\u0000X��_\rendstream\rendobj\r269 0 obj\r1021 \rendobj\r37 0 obj\r<< \r/Type /Page \r/MediaBox [ 0 0 612 792 ] \r/Parent 32 0 R \r/Resources << /ProcSet [ /PDF /ImageB /Text ] /Font << /R13 49 0 R /A 43 0 R /R8 45 0 R /R7 39 0 R /R6 40 0 R >> >> \r/Contents [ 47 0 R 50 0 R 52 0 R 54 0 R 56 0 R 58 0 R 60 0 R 267 0 R ] \r/CropBox [ 0 0 612 792 ] \r/Rotate 0 \r>> \rendobj\r38 0 obj\r<< \r/Type /Encoding \r/Differences [ 2 /fi ] \r>> \rendobj\r39 0 obj\r<< \r/Type /Font \r/Name /R7 \r/Subtype /Type1 \r/BaseFont /Times-Italic \r/Encoding 38 0 R \r>> \rendobj\r40 0 obj\r<< \r/Type /Font \r/Name /R6 \r/Subtype /Type1 \r/BaseFont /Times-Bold \r/Encoding 41 0 R \r>> \rendobj\r41 0 obj\r<< \r/Type /Encoding \r/Differences [ 2 /fi 150 /endash 173 /hyphen ] \r>> \rendobj\r42 0 obj\r952 \rendobj\r43 0 obj\r<< \r/Type /Font \r/Name /A \r/Subtype /Type3 \r/Encoding 44 0 R \r/FirstChar 0 \r/LastChar 204 \r/CharProcs << /a203 129 0 R /a202 130 0 R /a201 128 0 R /a200 126 0 R /a199 127 0 R \r/a198 131 0 R /a195 135 0 R /a194 136 0 R /a193 137 0 R /a192 134 0 R \r/a190 132 0 R /a189 133 0 R /a187 125 0 R /a186 117 0 R /a185 118 0 R \r/a183 116 0 R /a182 114 0 R /a181 115 0 R /a180 119 0 R /a179 123 0 R \r/a178 124 0 R /a177 122 0 R /a176 120 0 R /a175 121 0 R /a174 138 0 R \r/a173 155 0 R /a171 156 0 R /a170 154 0 R /a169 152 0 R /a168 153 0 R \r/a167 157 0 R /a166 161 0 R /a165 162 0 R /a164 163 0 R /a163 160 0 R \r/a162 158 0 R /a161 159 0 R /a160 151 0 R /a154 142 0 R /a152 143 0 R \r/a151 141 0 R /a150 139 0 R /a148 140 0 R /a147 144 0 R /a146 148 0 R \r/a145 149 0 R /a143 113 0 R /a141 147 0 R /a139 145 0 R /a138 146 0 R \r/a137 150 0 R /a135 79 0 R /a133 80 0 R /a132 78 0 R /a131 76 0 R \r/a130 77 0 R /a128 81 0 R /a127 85 0 R /a124 86 0 R /a121 75 0 R \r/a119 84 0 R /a118 82 0 R /a117 83 0 R /a115 87 0 R /a113 67 0 R \r/a111 68 0 R /a108 66 0 R /a106 63 0 R /a104 62 0 R /a101 65 0 R \r/a100 64 0 R /a99 72 0 R /a98 73 0 R /a97 74 0 R /a96 69 0 R /a94 70 0 R \r/a93 71 0 R /a91 103 0 R /a89 104 0 R /a87 105 0 R /a85 88 0 R /a83 101 0 R \r/a82 102 0 R /a80 106 0 R /a78 110 0 R /a76 111 0 R /a73 112 0 R \r/a72 109 0 R /a71 107 0 R /a69 108 0 R /a68 100 0 R /a67 92 0 R \r/a65 93 0 R /a64 91 0 R /a62 89 0 R /a61 90 0 R /a59 94 0 R /a58 98 0 R \r/a57 99 0 R /a55 97 0 R /a54 95 0 R /a52 96 0 R /a50 233 0 R /a48 232 0 R \r/a45 164 0 R /a43 231 0 R /a41 229 0 R /a40 230 0 R /a38 234 0 R \r/a35 238 0 R /a31 239 0 R /a29 240 0 R /a27 237 0 R /a26 235 0 R \r/a25 236 0 R /a23 228 0 R /a22 219 0 R /a20 220 0 R /a18 218 0 R \r/a16 216 0 R /a15 217 0 R /a14 221 0 R /a13 225 0 R /a11 226 0 R \r/a10 227 0 R /a9 224 0 R /a8 222 0 R /a7 223 0 R /a6 241 0 R /a5 258 0 R \r/a4 259 0 R /a3 257 0 R /a2 255 0 R /a1 256 0 R /a0 260 0 R /a66 264 0 R \r/a42 265 0 R /a36 266 0 R /a39 263 0 R /a47 261 0 R /a92 262 0 R \r/a77 254 0 R /a125 245 0 R /a44 246 0 R /a63 244 0 R /", + "truncated": true + }, + { + "bytes": 8481, + "kind": "research", + "path": "research/cultnet-distributed-database/summary.md", + "text": "# CultNet Distributed Database Research Summary\r\n\r\nPurpose: ground CultNet's distributed realtime database design in prior art\r\nbefore adding more machinery. The goal is a coherent local-first mesh database\r\nover CultCache, not a hand-rolled distributed-systems costume party.\r\n\r\n## Sources Stored Here\r\n\r\n- `hashgraph-swirlds-tr-2016-01.pdf`\r\n - Source: \r\n - Topic: gossip-about-gossip, virtual voting, fair ordering, asynchronous BFT.\r\n- `raft-extended.html`\r\n - Source: \r\n - Topic: understandable consensus, leader election, log replication, safety.\r\n- `raft-extended.pdf`\r\n - Source: \r\n - Topic: canonical Raft paper copy.\r\n- `dynamo-amazon-science.html`\r\n - Source: \r\n - Topic: Dynamo publication page and abstract.\r\n- `dynamo-sosp2007.pdf`\r\n - Source: \r\n - Topic: highly available key-value store, consistent hashing, versioning,\r\n quorums, hinted handoff, anti-entropy.\r\n- `swim.pdf`\r\n - Source: \r\n - Topic: scalable weakly consistent process-group membership.\r\n- `rethinkdb-changefeeds.html`\r\n - Source: \r\n - Topic: realtime query/changefeed ergonomics.\r\n- `firebase-realtime-offline.html`\r\n - Source: \r\n - Topic: offline behavior, presence, server-side disconnect operations.\r\n- `crdt-arxiv-1805.06358.html`\r\n - Source: \r\n - Topic: conflict-free replicated data types and deterministic convergence.\r\n\r\n## Design Takeaways\r\n\r\n### RethinkDB\r\n\r\nKeep: changefeeds as the product feel. Subscribers should receive document\r\nchanges continuously, with enough old/new context to render, reconcile, or\r\ndebug. Point subscriptions and filtered subscriptions are both first-class.\r\n\r\nCultNet implication: database subscriptions should be explicit schema-v0\r\nmessages. The server should stream raw document changes that clients can apply\r\nthrough the same CultCache reconciliation path as snapshots.\r\n\r\n### Firebase Realtime Database\r\n\r\nKeep: realtime sync and local/offline ergonomics. Presence and disconnect\r\nbehavior are database features, not application afterthoughts.\r\n\r\nDefer: full offline writes. CultNet should not pretend arbitrary offline\r\nmulti-writer changes merge safely. Offline/local-first behavior needs declared\r\nper-document conflict policy.\r\n\r\nCultNet implication: add presence/disconnect records later as ordinary\r\nCultCache documents with server authority, not as hidden transport state.\r\n\r\n### Raft\r\n\r\nKeep: the understandable authority model. One leader/primary owns ordered\r\nwrites for a shard. Decompose the problem into ownership, log/mutation\r\nreplication, and safety.\r\n\r\nDefer: full automatic leader election and replicated logs until shard catalogs\r\nand explicit epochs exist.\r\n\r\nCultNet implication: the current primary-shard policy is the correct first\r\nfoundation. Every write should either hit the primary, be forwarded to the\r\nprimary, or fail with routing information.\r\n\r\n### Dynamo\r\n\r\nKeep: partitioning, replication metadata, vector-ish causality, hinted recovery,\r\nanti-entropy, and application-visible conflicts.\r\n\r\nReject for now: \"always writeable\" semantics. That is attractive, expensive,\r\nand easy to lie about.\r\n\r\nCultNet implication: shard descriptors should grow into a shard catalog with\r\nowner runtime id, epoch, schema/key ranges, and later replica/preference-list\r\nmetadata. Conflicts must surface as data, not disappear into last-writer-wins\r\nunless a document explicitly chose that policy.\r\n\r\n### SWIM\r\n\r\nKeep: gossip-shaped membership once the mesh grows beyond a small static\r\ncluster. SWIM separates failure detection from membership dissemination and\r\nkeeps per-node message load stable.\r\n\r\nDefer: membership implementation until there is a shard catalog to disseminate.\r\n\r\nCultNet implication: do not build peer discovery as a side-channel registry.\r\nWhen it arrives, it should update membership and shard-catalog state together.\r\n\r\n### CRDTs\r\n\r\nKeep: CRDTs for documents whose merge law is explicit and deterministic.\r\n\r\nReject: generic automatic merge for arbitrary domain objects. That is a\r\nlanguage cop with a nicer hat.\r\n\r\nCultNet implication: CRDT support belongs in schema metadata or document\r\ncontract metadata. A document type can opt into a known merge strategy; the\r\ndefault distributed write policy remains primary authority.\r\n\r\n### Hashgraph\r\n\r\nKeep: gossip-about-gossip as an idea for compact event provenance and possible\r\nfair ordering research. Virtual voting is interesting when every member sees\r\nthe same gossip history.\r\n\r\nReject for now: adopting hashgraph consensus as CultNet's core. The public\r\nledger/crypto smell is not the main issue; the issue is that CultNet does not\r\ncurrently need asynchronous Byzantine total ordering to become a good mesh\r\ndatabase. Dragging that in now would make the machine harder to explain.\r\n\r\nCultNet implication: if we later need decentralized event ordering, use a\r\ndedicated design pass. Do not smuggle hashgraph metadata into ordinary document\r\nreplication because it sounds powerful.\r\n\r\n## Current CultNet Direction\r\n\r\nThe coherent path is:\r\n\r\n1. Primary-shard authority.\r\n2. Explicit schema-v0 snapshot, put, delete, subscribe, unsubscribe, and change\r\n messages.\r\n3. Shard catalog exchange with owner runtime id and epoch.\r\n4. Optional forwarding from non-owner nodes to owners.\r\n5. Membership/failure detection, likely SWIM-shaped.\r\n6. Replication and failover, likely Raft-shaped per shard.\r\n7. Optional CRDT policies for document types that deserve offline multi-writer\r\n semantics.\r\n8. Optional gossip-history research if fair decentralized ordering becomes a\r\n real requirement.\r\n\r\n## Live Invariants\r\n\r\n- CultCache owns document identity, schema compatibility, local indexes, and\r\n reconciliation.\r\n- CultNet owns transport, shard authority, subscriptions, and remote mutation\r\n delivery.\r\n- Raw wire records must pass through `CultNetDatabase` before mutating local\r\n cache state.\r\n- A write without authority is rejected or explicitly forwarded. It is never\r\n silently applied.\r\n- Realtime change streams publish domain changes, not storage implementation\r\n details.\r\n- Conflict policy must be declared before conflicting writes are accepted.\r\n\r\n## Current Cut\r\n\r\nShard catalog exchange now exists:\r\n\r\n- `cultnet.shard_catalog_request.v0`\r\n- `cultnet.shard_catalog_response.v0`\r\n- per-shard id, owner runtime id, epoch, schema ids, key prefix/range\r\n- stale epoch rejection on writes\r\n- routing error that tells clients where the primary lives when known\r\n- injectable non-primary write forwarding policy\r\n- concrete schema-v0 write forwarder for `cultnet://host:port` primary\r\n endpoints\r\n- in-memory per-shard mutation logs and catch-up by last seen sequence\r\n- wire-level shard mutation log catch-up with raw put/delete entries\r\n- replica-side application of shard log responses with epoch checks, gap\r\n rejection, and idempotent replay\r\n- background shard log replicator plus schema-v0 fetcher for primary endpoints\r\n- restart-safe replica cursor store with a local MessagePack file\r\n implementation\r\n- client authority scopes for predicted local input documents\r\n- predicted/reconciled change events for client-side prediction\r\n- simulation witness observations and deterministic consensus candidates\r\n- schema-v0 simulation observation and candidate messages\r\n- reactive observation hub for witness gossip and consensus candidates\r\n- server-side observation bridge for observation messages and candidate replies\r\n\r\n## Next Cut\r\n\r\nBuild durable authoritative mutation logs:\r\n\r\n- persist per-shard primary logs\r\n- define the snapshot fallback boundary for compacted history\r\n- return explicit resync-required responses when requested history is gone\r\n- then add simulation-frame rollback and resimulation helpers on top of\r\n predicted input streams\r\n- add peer-to-peer fanout for observation gossip and candidate propagation\r\n\r\nThat is the next foundation needed before membership, Raft-style failover, or\r\nCRDT policy work can be honest.\r\n", + "truncated": false + }, + { + "bytes": 573786, + "kind": "research", + "path": "research/cultnet-distributed-database/raft-extended.pdf", + "text": "%PDF-1.4\r%����\r\n120 0 obj\r<>\rendobj\r \r\nxref\r\n120 32\r\n0000000016 00000 n\r\n0000001664 00000 n\r\n0000001730 00000 n\r\n0000001974 00000 n\r\n0000002007 00000 n\r\n0000002076 00000 n\r\n0000002185 00000 n\r\n0000010658 00000 n\r\n0000011226 00000 n\r\n0000011907 00000 n\r\n0000011999 00000 n\r\n0000017965 00000 n\r\n0000018414 00000 n\r\n0000018854 00000 n\r\n0000018897 00000 n\r\n0000020780 00000 n\r\n0000022482 00000 n\r\n0000022579 00000 n\r\n0000030097 00000 n\r\n0000030533 00000 n\r\n0000031055 00000 n\r\n0000032778 00000 n\r\n0000034750 00000 n\r\n0000034850 00000 n\r\n0000035314 00000 n\r\n0000035533 00000 n\r\n0000035774 00000 n\r\n0000035967 00000 n\r\n0000037616 00000 n\r\n0000039244 00000 n\r\n0000040734 00000 n\r\n0000000936 00000 n\r\ntrailer\r\n<]/Prev 571253>>\r\nstartxref\r\n0\r\n%%EOF\r\n \r\n151 0 obj\r<>stream\r\nh�b```\u0006�W\f�\f\f�|\f\u0002\f\b ��������q\u0001I�C��Wؓ�a6O�_պ(�\u0018e���Z-*�w���ۅ�%\u001aYU|M��<9�j��R�/\u0000Y3\u0004l^p��G�a�s�\u0004���I�X�9D\f\u001f!�\u0011���{��(�)� �\u0006\u000f�pl�S�X�\u00004ڢ�I�k�^�\u0006�>n��\u0004��y�\u0017\f\u001a��\u0005T\u0002�*w�=����\u000fB\rc�\u00075�]@%�ii�\fq\r\t����\n.\u0016�JS�<�\u0006�qLP���Ri8�`7��\u0005+P��\u0006��\u0005\u0013 >\n~�\u0007�I.z淀G!��\u0011N\u0011���@��\nͼ�\b���`\u000b��\u0006�E�ݥon�ЁX����\u001c\u0012>JJ..\u000e����&.@\u0000\u001606NKK��2\u001b������\b\u0010\u001a\ne��\u0006@U\u001a\u0003ՆF�9�@ \u0000\u0012\u0001\u001b��\u0002\u0006iH\u0000j1�\t\r@cBA\u00165�\f2qq```\u0004\u001a!l��\u0000R�(ALB\u0000*4a`[\"\u000e�e�8\u000el�\"\u0003?�2�\t\n,G�\u0019Z\u000f�0X�E�5��`X��q����-�\u001a�\u0012�\u000b�\u0006\u001c\t�\u0007b\u0019.0:H:\u0018ވ\u0016���q@���1��{�\ne\u0001��_\u001c�ڶ2�0\u001eamT� � }@��,�%�9l\u0006�\u000e�\u0007X\u000f\b6p3�b��(�^���q |c3�\u0006�\u00116\r���\u0006o�\u0019\fkNǰ[0�`,�tz�p�A����\u000e�\t�\u0007b\u000bx\u001b$\u0019�\u0018S�d�g�7�+�5�\u0005u9\u0003��\u0002P(\u0000�.@�\u0001\u0000�\n�\u0006\r\nendstream\rendobj\r121 0 obj\r<>\rendobj\r122 0 obj\r<>/Rotate 0/Type/Page>>\rendobj\r123 0 obj\r<>\rendobj\r124 0 obj\r<>\rendobj\r125 0 obj\r<>\rendobj\r126 0 obj\r<>stream\r\nx��xyXS����!9�uhK���&i���y�S�qFE\u0004e\u0010\u0011!̐@\u0002$��\u0004\u0012��\u0018�$@�<� ��,\u000e�V�\u001d���mk��}����\u0007no�������?0{���z�Z�z�f\u0011N\u0013\b\u0016���\u0013\u001e}4^�!��#[�6�C\u001a\u001a���\u0016�¢�O�g�����5#�\u001cZ4�\u0000��`�S��Yw�G>{id�\u000b��/����jd\r�F�xy\u001c|s��y�eru\\xh�R�xժU��jɿV$�RExh��\r�G�4J&���(\u0017H�K�\u0012e�T\u0012\u0012\u001e%�l���c�6ɜm{�$ۤ1Ҹ�(�{�Ѩ� �[x�4F!}S\u0012\"��D��G\u0012$�\t\u000eW��b\u0014\u000b$\u001b\u0015�@�B.\r\n�\u001fIUAR9�0O\"��E�+\u0014�oI�B\u0012\u001a\u0017\u0018��\u0006K�2IxLPT|0s=�=D\u0016����dx=\u001a���e\n�\"(.\\���\u001b�]��ۨ\f\u000bT2�*��D\u0016�w\u0006˂�\u0019o���\f\f�QH�R����T\u0012\u001c��G\u0005���(y\\��\t��пn�'���\u0006�\u0005GI\u0015c�2����?�\u000e�ˣ�c���v���p�B\u001a\u0015�`<�\u0012\u001c��\u0018\t\u000e��M�D7*0�W����_\u0004\t���\u0018�I�Y��\u001a�%n�b�r{�������TG��A����H�����\u000b�\b�\u001f�\u0019�\u0015u ��բ5��f\u0017�Y����\t����K\u0017,\\��l��eˋ�^�� ^#�\u0012���\twb51��G�!f\u0011\u001e�\u001b�~b6�I�!��7�\u0003�[�Ab.�Ml\"�\u0011>�fb>�K�\u0012\u000b\b?b\u000b���J,\"�\u0011����\u0012b\u0007���I,#v\u0011�\t7�mb7���C�$�\u0011.���Np\t-A\u0011��s��x�x��DD\u0013��\u0018b\u001d1��\u0011/\u0010/\u0012/\u0011�D\u0016�#^&��+D\"1�\u0010\u0010B�\u000bW\u0001�DH��,���'\u001c�p���}��\u0015�\u0002\u000e�)���=…d:�\r\u0015@�|n�sQ��=����'&O�L\n��?���y�єuSN�0�\u0005�\"�b��\u001f�����|��ʫyy��\u0003|'~�+\u0013_��J�T��\u001f\n�\u000b��\u001a��\b��6y��i��h\u0017��q�O���k�:#mFی�3n��V�\u0012\u001d\u0015�����b����]r��7_�z�\u0001̛2\u0012\u0002\u001cл�~��\u001a9`�\u001f�3���E��5A\"\u0017\u0005���Bo�$�e\tU��N�%Z\u001a��\u0005\u0016� |�\u0003mܾ�ers,�\nA\\RځlJ\u0005��Q\u001d,�C\u00126B\n5r�Й�FO;���1t}�.�_�\u0017��\u0002��X�+F9$��k�3(\r\f�����2�I�v����6@\r�F�\u0010#)\t�tI>̦`\u001b�[�R\u0006�(�&�\t���?*i�6�#Ҙ�\u000e�{&\u000b�\\\u001a���q\u001by��RU�sY�F�\u0004\u001a�:&\u0014q�H\u0010xi�\u0013E?�\u0016\u0002���-�1G`G�U��J�?�\u0018��2\u0001Z������ᝁ]���}��\"P\u0003l���A8\u0011�\u0011|�$m���@#\u0004�dCxv\u0006�g�0\b���\u0007\n5%G��'l\u0010�7��k\u000f\u001de��c�\u0016\u0002���~ҥ�;C�3��l5$��ު�v�l*�qz�\u001el�F�I�Q�[�I�\"T�S�!�U�����8\u000eN�\u0001uoTSt��lg�\u0019KUIm\u0015ŋ���u�M�NK��F�*�9�{0�ީ��_T4\u0004�M\u0003^\t�A�H�Ѵ\u001d���\u0016��a�\u0013���\\l\u0013\rpyQ���d큀�b\u001c.C#�����\u0005�~��y�\u0011>ze�\\$B._�\u0001���w��\"8u��e�N�|i.��8��m\b\u000e��M\u0010��$\u0000nQߞ�zK�\u0004�>�v���g��L0d*��4�\u0000���T\rz\u001d%\b�\u001c\u0018�/7U�R!��\u0016���\u0012P�C�Q��<�e���^�S��\u0000m\"�2�aQ\u0006\u0006���\\��-\u0003�)x��s`•��O�a�\u001d��e��c�\u0010�\u0001~*L�$pM\t�)� \u0015h�4���>E��*�2j����\u0005\u0000M\u0000\u000b�������+�\u000f\u0000r�\u000f�W>�ԕ\u001b]wD�\u0004B7��q��s(�\u000b\u0000�\u0014��5|\u000eκx&!�W�\u001ai��wR\u00185\u0014]�T��цVz�e�{�a�ө��bz\u0006�8�\f�\u0001�n6\u001c\u0012����^�n�xo$�t�w��ܐ�+\u0005�Rp1�\u0011Qk8\u0006(��W�\t΂/n����\u0001q^\u0001�\u0007�)�+!L�$�om�7_�\u001c�;�\u001eQ���a�!��f�\u0014\u001a�n��n\u0016}\u000b���\u001b\u0012\u0012�\u0015q\u0001Z\u000f@�\u0012.�J��c\u001b�!\u0013�zN=�x��QQU�t�z\u001d�\u0016�\u001d�1�O���B�BW�X����_��\\Ț���\u0005��`s�n}:�7\u0015�\"!\u0005~m�z�ڥ������臞��D�N4\u0003�X��MW���ũ8�yQ���-�E}O�%��\u0014=��[\u000e\u0010\u0001��GW�>�\u001d�/e\u0019��RpR��h�V@�+�s�s�S��x*O\u0003G�|����`|�Ks�\u0013����/�f�|��\u00011�Ų_�q�v\r%A���,K+\u0002�(�[=�\t}�\u0007�\f�!-^\u0015�\u0012\u0005���$�\u0011ٔp\r\\�(����jK��1�ǰ�\u000f\u0016wc�x6�����k�2�\u000f\"�(�뀒s}A`�ќ��U\n*(\b�\u0002�c`�YVR5P��\u001a�fh�Z]�,�\u00106s\u0001��6\u0016\u00166��\u000b\u0017�S��b1U�̈́�sF\u001b��\u001c\u0015y�dт-c��E�ل�wU�]�\u0014�\u0014��Z\u0007��c���Ʒ�\u0015�\u0001��89@��H�c4�J�,h����l�\"\u0005����S\r���RQ���d\u0001T����-�\u0011�ō���+2=�@|��]%�B�\u0005vx�?�\f�\u00150��\u001d S֨5k��\u0018�\u000b\u0018ӧ���\u000f�2}\u000b\tVꙄP�6;�._k\u0005�)\u0018\u0003g�\u001f�\nM�j\\\u0015BCu��^��U;��\nW}0�7\u000fހ��3�t�����j�Ƽ)4\u0001C����U\u0014���Ǻ���yk�\u0013?�pDGb�\u0002D\t\u0003\"e��Q�j�(�.�Fw�JF�,\\sI~.F��V\f�Y5��*L�\r\u0019�.\u000f�\u001b����mo�\u0018\u0011���5u�A���8x�9|I\rCK�^��^V+�Ғ��#>�7>*Rs�3�2��l��Jp�Bo��{�ъِ\u000b�|�����h`�j�\rp\u0001\f�zB�e��=T\r7\r�r�&�Z�\u0000\f 9Om>l�/:��<��m6:�fÆ\u000b����~'�\u0013�S\u0000_����`\u0000\t.�Y�\u000b�)��p����l��h7N�'�\b�\u0016��\u001b��d�D�TS�� �<◜A��&c�4�����E�n�E�+��\\\u001a�=�&ҕ&�%\u0019�0D��\u0018���'?q�J\u001a\u000e\r�.;�g��36�B���\tn��>0c�mQ�\u000f��z�y,�+\f)k�����\r�:\u000b&tx\u0014^@\u0007�n�v��S�\u0001�i%�\u001e\u000ezu���|�1܊}�N+N�ӹ���A1�\u000e-!ymI���2\u0003�P\n\td�Z�^\u001e\u001f�\u0012\r����cb^\u0005|��В'3�\u001a�O�\u0002��w�z�\u001b\u001aD����$�-?딣���U�\u0014�}��΂$��d\u0018k�.eE�xO^��l\u0005w�̽c�<���R�O�[.�U��q��X�=\u0012k���6\u0003P\u0001C�!�0\u0007�\tf�b�5�\n�q�*5w�Q6�!��̆��p\u0012�\u0015��yi��´BP\b�\u0016[\u0017|\u0019�\u00154�(47�1�����\u0007��mk�O����ҏ\n�\u0015�*�c\u0013\u0006m\u00135\u001aD\u001eNI�՚��\"CGry,�x�<�/z\u0018\u0012Wn×�L�\u001bz\u0003\u001b�!ۍ%F�\u00044&�^�\u0018�\tV@e� \u0000�\"\u0004ե�\u0013flf����(�;��*��P�\b�\t�@kFIV\t(\u0011�����|�k����*2T{C\u0017���,�H[\b\n@���\u001e�\"��K����\n��\f\n��{�\u0006�APy,������v7\\�\u0018�\u0005��\u0017>�s>��;N��OҦ�k\u0000�4Z\u0007�\u0010'ϙ�&Mm|�\u0011�;��o�uS:\u0012kj�\u001c���\u0005�fqVqv\u00110S\r�սC\r1^�=$Z�;)�4>Q\u001b\u000e\"(���@�����3WD<���ʄ>�vlG7^B\u000b1�G��&�(���\u0004@���������:��\u0001j\\�0���36�xd*�,�\u0004�欲4�\b�ў�h\u000bZ.���#ӥ\"\u001f��t��O�{�I�\u000e;��Q�w(������k�7�s\u0005\n!�j���t�\u0007c2p�N\u001e�і,�\u001eia�\u0000z@�\u001b�ʋn\u0014\b�\u0001,\u00138�6\u0016ly\u0005�۸Q ��,\u0013�e�|\f\u0013?c��#k�鹁\u001ay�!�0&��L\u0016��\u00033�z�S\u0003ţ�dԓ�\u000f��\u0019�\u0000_�/��f��}����\u0003N=':�<<�\u0016MAl�]�\u000e\u001e���Wc��\u001a�5r�\u0003���$�*5Ia��ꕀ��ݤ+�\u0010��$�e�>*��w�gs�\u0015��\u001e�Ut\u0007y\u0012nb\u0006\n\u0014󘾂K@�Ԫ\u000b�����lS�Q�\u0016jB$,4Y3,cr�f���\u0000\u001dՒ�\u0019\u0015��$�Eق�4[t�Oy(#�5J��hml�J\u000bL 5�P�2'�'�MLTD��\u001d{��\u00058�\u0018.��YZKKj�L�ߦ9M��\u0007l�5���%T�e֢]\u001fB���>��CJą�E�Ju\u0015\u0010�W�k.l9���;1���'@�\r�C�W\u001e-����-���Z\u001c�KԔ�'�+CY\u0003t%\u0016�o�\u001f�G}pޥ��\u001dn��\np�\u001d��[\u0016�]&G�H\u0014;����\\\u000e�Uq?N��0L�\u0016\tfjU+M��\u0014�9'Հ�(z6\t�GOp�\\�\u0004h��5�跡\u000b_�o�1%뒄ڤ�ToܹD\\XM�ɱ�\u001f�L�<��[|�f�������ob�8y��πr��FV�S���\r�7���3�rR��\u00052\u0001\u0015��Y�~\u000f�\u000f��0î$a2Y�S\b�\u0000�Ul8*F�Hi��4\b�G.�c�k��{���\u000bݎ\u0013��]����јbЫ\u0013�\f1�Z��!|\u0001r���?;t�\u0000C�zG*\u0003�3\u0003��\u0001�sh=��!��.��Zb��fX>EEvgZ3l�\u000emq(�M�/�Q>���*n?���\u001e�Fw�<�\u0003l:ɳ�{0dL�o˜VHv��yp%�o���]�\u0003\u001ci����6�e]��\u0015n�5CS\\kt��A�\u0003\u000e��ᇎ�]�*\f������%H\u001c\u0013��p\u001e��a{�\u0015p\u0005��,�\u0018z�v����Վ5�:�e�?FV��~4\u001d�]������\u0013\u000f�}\u001e�\u0019��\u000f�\u000e%����'���n7Wt��P;\r�Aug�9ߖ�\u0000M\u0004�\u0007S��ʰ���\u0003�\u001f\u001c�\fk98\u0018�\u0013�a����z����\u0003j\\s�n�����q\u0018�2U�\u0002\u0016\u001f����*�!�RT\u001e[f�\u0000T����3�~��\u0003r�Xql@Zh�\u001ajU���}.ؤO����\u0016\u001b��Rp����)���q��g0�\u0019'��a8��ϪȮ\u0007\u000f�����˭�W�upL�-o\n\u001aX�8\u001fgE\u0005�W�� ���,I3�7�W�;y\u001a����\u0004�\u0006��\u0001�\\=4�-w\u001fD&jsr��1��\b�:��:\u0018�S��j�\u0000&?hhd�\u0011��߳�Lij`�9�H /�\u0017�F�`��En\r��\u0011b�Z�dJ���%�ΐP�җ�zP\u001e\u0001B�\u0003\u000f\u0003������\u0019QwKE+�\u0006W\u000f\u001dۘ����\u0003�qŠ\u001c8�:\u001a�����y��e�.\u0004]������h�\u0000�@Sz���B��i�6㇦!@}٦\u000bݷ>\u0018q��k\u001a�1[��\u0012\u0017����\u001a;\u0006[ꓢ�E�ae� ��\u001f\u0013�7��w�v\u001dy��,\u0019ه��\u00117o���_oX:+\u0006{�^��rlJ�G��L�@�)\u0014�f�K�D=����\u0014'<\u00057ށ������'S\"%�\u0019�q��<7{N��悧�\f�\u0011����M�u���~���\u001a\u0012�\u0012�6\u001c8\u0000�Q�u_=~L\u0015�!j��Ɩ��\u0010��b�G�Ƽ�j����\u0017��O�sWJu�j��\u00059�\\[N\t\u0010�\u0014'ှ@���q�D�A��\u0005\u001a`0'U�k��ɸ骓�#{����K��kb�O�#��\u000e\u0014�*�\u001ccA3���\u0011�?�I�����L�<��~���(��s$�ju\r�@�rMp\u001dg�\nׄ�qj���Uc�N��J\u001b�cb�k$���*�\u000e��u��\u0011�\u001e+\u001e\u0004\u000f�Ә���l;Ơ�[�S���tk���x4�\u0004^Z�[:FAo#��SJ�y��\u0006�{0Ijؚ$\u001ck�#�\u001d����\u001b_��{>�R\u000fd �(O�F�G�\u00024\u0017~\u0019q'�\u0006؄�n-a��Js��\u001b�]E\u000eeY��K`���ƅq�pۣ�ғXi��qlf�a=}\fݘl;�\u001aߒWļ\u001e�\u0017'��Q!c�f6�-�F\u001e�Ք�\u001e\nv� ���l����\u0000�@u\u0018&\",1���\u001eL�)m�G��\u0002\\�`\u0001���V9\b����b\u0014J\u0002���}F�If#cs�su��G\b��������y���\u0012�/�7x�\u0000 Ӯt���\\oU��S#���8\u000e��dp�j�t:�A\u000e\u0012L�\u0006\u0019z\t}%@\u0002�MVAjuv�0��d\u0007�����\u001c��CE^�.Im_ӶJ A\u001dh&=�X�1�(Zm5���[�T��t��k>�\u001amg�Z@���F�pl�'�Z�\bY���Li��\u0012&����vjd5ž\u0014χN���\u001bC�ܿ\u0002_\u0004Ѕ��\u0016��\u0010\u001fM\\�\u0006rASn����c�}gEG�\nĖ�y�\u0014�\u0004G� 1#U�*S��B\u0001���\u001e�x��rU���QW�\u0004�O�/G�q��!\u001b�@6\u000bN�\u0003��q�Q1uqM-�uM-���b����7�:F�p�`:��G��\u001cuej�\u0006\b\u0013t)��RMe\n��oq��&G�/0\u001b��?�씞�����W�7��/��ԩ���a��p\u0011/3�Z�Uh��)\u0014��r�\u0000�\u0014\u0015��\"e!^!�n�!�'�o\u000bF��\u001c�fX�^�\n��j�M\u000e�+�a\\ݵ�0�~*����b��#�\u0004=�^Z{�����\u000e��sm\u001f���\ri�N�9���\u001a\u001a�\u0011�MzH\u001c\u0019\u0014��a\n���>��q�\u0019qCoce\u000b�\u0002�\u0017�`��wP�n\u0010\u0004�f���?���\u0015D� �\u0004MD�-g=��\u001fwt��Ϝm}\u0004�\u0000kVYze��2�\t\f�zso\r��\u000f��$������\u0011~ab�\u0006h)�Y���a���c�\u001b\r�D<ΓsM��-.\u0005 7�0ݪ+KoJ���Z���\u000b���\u0014[@�С+�פ���\"4\u001b��P?�o�‚�z������o;~��\b+�#kT���s1���0�", + "truncated": true + }, + { + "bytes": 33609, + "kind": "research", + "path": "research/cultnet-distributed-database/raft-extended.html", + "text": "\r\n\r\n\r\n\r\nIn Search of an Understandable Consensus Algorithm (Extended Version)\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
\r\n UP \r\n |\r\n HOME \r\n
\r\n

In Search of an Understandable Consensus Algorithm (Extended Version)

\r\n\r\n\r\n
\r\n

DECLARATION

\r\n
\r\n

\r\nThis page is the In Search of an Understandable Consensus Algorithm\r\n(Extended Version) paper. Original Paper Link\r\nis: https://raft.github.io/raft.pdf\r\n

\r\n\r\n

\r\nIn Search of an Understandable Consensus Algorithm
\r\n(Extended Version)
\r\nDiego Ongaro and John Ousterhout
\r\nStanford University\r\n

\r\n
\r\n
\r\n\r\n
\r\n

Abstract

\r\n
\r\n

\r\nRaft is a consensus algorithm for managing a replicated log. It produces a\r\nresult equivalent to (multi-)Paxos, and it is as efficient as Paxos, but its\r\nstructure is different from Paxos; this makes Raft more understandable than\r\nPaxos and also provides a better foundation for building practical systems.\r\nIn order to enhance understandability, Raft separates the key elements of\r\nconsensus, such as leader election, log replication, and safety, and it enforces\r\na stronger degree of coherency to reduce the number of states that must be\r\nconsidered. Results from a user study demonstrate that Raft is easier for\r\nstudents to learn than Paxos. Raft also includes a new mechanism for changing\r\nthe cluster membership, which uses overlapping majorities to guarantee safety.\r\n

\r\n
\r\n
\r\n\r\n
\r\n

1 Introduction

\r\n
\r\n

\r\nConsensus algorithms allow a collection of machines to work as a coherent group\r\nthat can survive the failures of some of its members. Because of this, they play\r\na key role in building reliable large-scale software systems. Paxos [15, 16] has\r\ndominated the discussion of consensus algorithms over the last decade: most\r\nimplementations of consensus are based on Paxos or influenced by it, and Paxos\r\nhas become the primary vehicle used to teach students about consensus.\r\n

\r\n\r\n

\r\nUnfortunately, Paxos is quite difficult to understand, in spite of numerous\r\nattempts to make it more approachable. Furthermore, its architecture requires\r\ncomplex changes to support practical systems. As a result, both system builders\r\nand students struggle with Paxos.\r\n

\r\n\r\n

\r\nAfter struggling with Paxos ourselves, we set out to find a new consensus\r\nalgorithm that could provide a better foundation for system building and\r\neducation. Our approach was unusual in that our primary goal was\r\nunderstandability: could we define a consensus algorithm for practical systems\r\nand describe it in a way that is significantly easier to learn than Paxos?\r\nFurthermore, we wanted the algorithm to facilitate the development of intuitions\r\nthat are essential for system builders. It was important not just for the\r\nalgorithm to work, but for it to be obvious why it works.\r\n

\r\n\r\n

\r\nThe result of this work is a consensus algorithm called Raft. In designing Raft\r\nwe applied specific techniques to improve understandability,including\r\ndecomposition (Raft separates leader election, log replication, and safety) and\r\nThis tech report is an extended version of [32]; additional material is noted\r\nwith a gray bar in the margin. Published May 20, 2014. state space reduction\r\n(relative to Paxos, Raft reduces the degree of nondeterminism and the ways\r\nservers can be inconsistent with each other). A user study with 43 students\r\nat two universities shows that Raft is significantly easier to understand than\r\nPaxos: after learning both algorithms, 33 of these students were able to answer\r\nquestions about Raft better than questions about Paxos.\r\n

\r\n\r\n

\r\nRaft is similar in many ways to existing consensus algorithms (most notably, Oki\r\nand Liskov's Viewstamped Replication [29, 22]), but it has several novel\r\nfeatures:\r\n

\r\n\r\n

\r\n1/. Strong leader: Raft uses a stronger form of leadership than other consensus\r\nalgorithms. For example, log entries only flow from the leader to other servers.\r\nThis simplifies the management of the replicated log and makes Raft easier to\r\nunderstand.\r\n

\r\n\r\n

\r\n2/. Leader election: Raft uses randomized timers to elect leaders. This adds\r\nonly a small amount of mechanism to the heartbeats already required for any\r\nconsensus algorithm, while resolving conflicts simply and rapidly.\r\n

\r\n\r\n

\r\n3/. Membership changes: Raft's mechanism for changing the set of servers in the\r\ncluster uses a new joint consensus approach where the majorities of two\r\ndifferent configurations overlap during transitions. This allows the cluster to\r\ncontinue operating normally during configuration changes.\r\n

\r\n\r\n

\r\nWe believe that Raft is superior to Paxos and other consensus algorithms, both\r\nfor educational purposes and as a foundation for implementation. It is simpler\r\nand more understandable than other algorithms; it is described completely enough\r\nto meet the needs of a practical system; it has several open-source\r\nimplementations and is used by several companies; its safety properties have\r\nbeen formally specified and proven; and its efficiency is comparable to other\r\nalgorithms.\r\n

\r\n\r\n

\r\nThe remainder of the paper introduces the replicated state machine problem\r\n(Section 2), discusses the strengths and weaknesses of Paxos (Section 3),\r\ndescribes our general approach to understandability (Section 4), presents the\r\nRaft consensus algorithm (Sections 5–8), evaluates Raft (Section 9), and\r\ndiscusses related work (Section 10).\r\n

\r\n
\r\n
\r\n\r\n
\r\n

2 Replicated state machines

\r\n
\r\n

\r\nConsensus algorithms typically arise in the context of replicated state machines\r\n[37]. In this approach, state machines on a collection of servers compute\r\nidentical copies of the same state and can continue operating even if some of\r\nthe servers are down. Replicated state machines are used to solve a variety of\r\nfault tolerance problems in distributed systems. For example, large-scale\r\nsystems that have a single cluster leader, such as GFS [8], HDFS [38], and\r\nRAMCloud [33], typically use a separate replicated state machine to manage\r\nleader election and store configuration information that must survive leader\r\ncrashes. Examples of replicated state machines include Chubby [2] and\r\nZooKeeper [11].\r\n

\r\n\r\n\r\n
\r\n

\"raft-figure1.jpg\"\r\n

\r\n

Figure 1: Replicated state machine architecture. The consensus algorithm manages a replicated log containing state machine commands from clients. The state machines process identical sequences of commands from the logs, so they produce the same outputs.

\r\n
\r\n\r\n

\r\nReplicated state machines are typically implemented using a replicated log, as\r\nshown in Figure 1. Each server s", + "truncated": true + }, + { + "bytes": 900468, + "kind": "research", + "path": "research/cultnet-distributed-database/dynamo-sosp2007.pdf", + "text": "%PDF-1.3\r%����\r\n101 0 obj <>\rendobj\r \r\nxref\r\n101 29\r\n0000000016 00000 n\r\n0000001444 00000 n\r\n0000001525 00000 n\r\n0000001727 00000 n\r\n0000001863 00000 n\r\n0000002320 00000 n\r\n0000002760 00000 n\r\n0000003302 00000 n\r\n0000004074 00000 n\r\n0000004327 00000 n\r\n0000004601 00000 n\r\n0000004869 00000 n\r\n0000004982 00000 n\r\n0000005229 00000 n\r\n0000006383 00000 n\r\n0000006918 00000 n\r\n0000007199 00000 n\r\n0000008288 00000 n\r\n0000009351 00000 n\r\n0000010473 00000 n\r\n0000011530 00000 n\r\n0000012622 00000 n\r\n0000013685 00000 n\r\n0000014725 00000 n\r\n0000035703 00000 n\r\n0000072079 00000 n\r\n0000119236 00000 n\r\n0000150351 00000 n\r\n0000000876 00000 n\r\ntrailer\r\n<]>>\r\nstartxref\r\n0\r\n%%EOF\r\n \r\n129 0 obj<>stream\r\nx�b```\u0006��\f�\f\f�\u0002\f�\f\b \f\u0014cc`a�������Ȣ��\u0010�됺���qņ�\u000elݬ|\u0015\u0012;��Y.wh\u0005�\u0019+x��\u00196l\u0007jl��\u001ez���\u000e�UH�1(\u0004�q\u0014�\u001a�NOh��ql29\u001a\u0016��jr\b((\u001aY��Q�!2٧\u0010,+��,���$\u001a\u0019Y&_y\t�&IB�Hh�\r �\u0010�f\tT�\ndL2��\u0005��2�q\u0014r�I���ި}�!2�\rf���,w��\u001b@5*\t�\u0002\u000b�\u0002\u0015�]��s\u0019�X���B�����\t\u000bN\u0000\u001d�Z\u0006v+�DG\u0007\u0003���GG\u0003��K(�\u0003�I\u00009\f\fJ\u0011 1\u0010��\u0000�3\u0018\u001b�)\u0006�\b0�ll\u0001�\u0019\u0005��4�*\u001a�,a\u000b�V�\f�1b\u0019`���2 ���\nv4\u0010\u0017�@`��\u0013\u001a\u0005���X\u000b,�� �0�!�q\u0016c'�{��\f�\u0018\u001e3�epb8�\u0012����\u0015�\u0010�\u000f\u0016c�O,��?�\u001f\u0006\u001e�}���2&�#��K\f�\u0018:\u0019�I�1\u00043|\u0000�T�pIU�\u0001\u001d�1��O\u0005�\u0002`�'\u0006\u000e��1T1X\n����J\u0010\u000b{��s��}�P\u001c\u0003�V+ �\u0004��@���sd?T�K�\u0000\u0003\u0000���z\r\nendstream\rendobj\r102 0 obj<>\rendobj\r103 0 obj<>\rendobj\r104 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>>\rendobj\r105 0 obj<>\rendobj\r106 0 obj<>\rendobj\r107 0 obj<>\rendobj\r108 0 obj<>\rendobj\r109 0 obj<>\rendobj\r110 0 obj<>\rendobj\r111 0 obj<>\rendobj\r112 0 obj<>\rendobj\r113 0 obj<>\rendobj\r114 0 obj<>stream\r\nH�lUێ�6\u0010}�W�#\u0005X�D��''\u000bl��@\u0010\u000b�â\u000f\\��ٕ(W��n>#_�!)��E�X�™9g�\\��q��A�>��\u000fm� �v�JkH�\u000f/UC\u001b\u0006U�Q\u0006��J���m�Jh�$h{Y��WŇ�\u0017�\f�Ǩ~j�,\u000f��\u00156g.{��\u000b�*^�3�g\u0001[3N\u0002��o\u000b�/`̃1h\u0012��e�\u000e\u001cA7��\u0017�ɾ;J|�^��0+Z$\u0001\u0013]����3�����QZ�oˆ\t�\u0018�>�_xd�n�Ӹ��*G\u0003\u0015�?Ť��A�ڹ�h����XU�\n��JZ��η��ꮸQAK�\"D�\t��!�\bxͯ%̰L%��j�.\u0018��z���1K-��Ѯ�!�|ܶ\u0011�U��O�����wl\u001cH\u0003E\u000eE��2\u000fL��g�\u0016��$�E/�sTњ�^:����F��@�\t\u0013n`�RF3�#dT\u0011��Y��x�ӆ��eJ�{\u0000�C��.�li0K�\u0005����#FoP��2\"`�{4s\u0014�,\u000f\u0007��\u0006\u00054Q�\btGg�E\u0015\nO�\"r��\u0018Y�\b��3�kl�ڒ^\u0010`\u001d�.��\u000bZ.�s���\bN\u0016J؋A(#v�`��ϒ�\n�xZ\u0006��]�R�'_Cm��CQ�\u001c��ܙ�[\b[e\u001c�\u0010�\b��[�S�'a�5VQ��N�6ќ�rp��\u0014��$+��\u00055\u0015��\u0007%\f��\u0002X�\u0013Λ2���X�\u001b��\u0010�-�Տ\u001dG\t�4�bJm�6��X֩U������G�&}dzy�u|\u000f����B�i���u\b)l\f>a\rp���x�K�0Nr�Į��o�`�D6_�C\\�(q\u001d��?\u0001\u0006\u0000�V!o\r\nendstream\rendobj\r115 0 obj<>\rendobj\r116 0 obj<>\rendobj\r117 0 obj<>stream\r\nH�tU˖�6\f��+��ΉTQ/K˞z�l��w9Ypd�f\"�>zx2���\u001f�\u000b��x&�J6\t\\\u0000\u0017�e��Y�Iq�vY*%�z�E�\u001bn�j;O�L/��]��AQ�D����xرs\u0019���%�/𶳱�[��%N괈���>��I�W-��z|��d��M�hF�����N���-@�\u0005h|\u00001�j��Lb`�N2$��:��2��\u0012��4�����p�\u001b�\u0014<���\u0017��>R�$��mT���\u0006��W\u001b\u0004d3��\\��(��$�,�}��;��jԂ�k#�)s������V�\u001e�T< 6�\u00011p��+��+�)tD�F�O���Nz2\u0017�a(F\u0003�^[#W�\"�0T�\u0019n�\u001e��f�,�w�\u0004\u000b�Ģ��wk\u001f\r�Pk{\u0002���e\u001b\u0002\u0014e��j.�\u001e(%\u0017-�\r$߹]h\u00033\\��\u0015\u0018\u0002��N=�o>I,argCE�m�/��(-a1{w7��v\u000eW�A�1�\u0003�\u0006cj\u000e\u0000\u000e!�ȟk\u001f���ݟ����{z���P���۪XW�{]\u0000DSw�h��edh�0��N,|\u0018\f���Kw7'>\r��.v�1����������\r`D���e�=���i10F,\u001b��\u0018�7\u0010G�ˉ��\fR��k\u0000��w�0�\u0011�\b\f�Q�\u001f���!�\u001b�ʟC�\u0018 d�\u0014�\u001ab�A{*^\u000f��\"-���]5��\u0003�\u001f�6h�\u0001;�P�4/V\r@���P\u001dՍ���=��\u0012V\u0010\u0000�\u001d$\f��Y��u�9��f�\u001a��>�bOغN���xqդ�\u000b��Ӵ2(o4nJ���y�g_��\bQ\u001c�w\u001dH�?��\u0004�\u0012\u000b��1™\u0018A\u0015�����\f\u0019��򐵕��NJ���\u0017h���U�ۭ7\u001d/y��zb*N��g�7:�o�����3 fH������S�\t%q� f�o�{�*�&�\u001e�7�O=�Bfh\u001eD\u0006s\u001b���==��z�1��w>Y�A�Fٚ\r70�\u0007����Fh\"�\u001c=^\u001e\u000f{��\u0015�\n� �9�v<�\u0002=>C8��\t|�R\u0014\r��qx`%�Z���\u000f�m\u00177\u001a4�����\u001bv�S7���Ɖ�c�7\u001e�e�V�E�\u0002�\u0001�K`̟^���ޖ萖��\u0012b�\u0002��\u001e��t������ч&��\u0007\u001b�B^X\u0001�g��B�j��I�\u0007*�*�\u0013`\u0000h�\u001f\u0016\r\nendstream\rendobj\r118 0 obj<>stream\r\nH�|Uێ�6\u0010}�W�#\t�X��'OE\u0017(\u0012�� �>-�i[�,�\u0014�E�\u0019��ΐ�/�m��K�2g�3���槶�AB���\"��\nRh�7�HӴ���+�C��yb_y%\u0014{�\u0013)2\u0006��X���5��M�.YG�\r��\u000e\u001b�=܋�/\u0005O��Y\u0001�k�q��T�M�\u0001>�9\u0002\u0013�G$0���?(�2$��\f�.��sr2&�p⹨���\u001b&��sJ\u0005\u001e��\b��'��ٌG9s����q���rp\u0005R�A�\u000b\u0003\r1�b=�E�C���26�\u0003/�����\u001d�K\u0016*�SA�TL�ӊW�x�\nx���^\u0001s�V\u0015\n��#\u0016P����Gi�0ev�\u0011S�lk|\u0017YW�hdd����ؾT�Y۝��n���(�L\u0003F!�欀�\f�\u0012I�\u0004/+(r�2%\n\u0005�1D/�A�.Q�_�����j�Մ8��Ƈi@f��u��9<2VUf�\u0012u.C�\u0004f*���7vp��|G&��3\u001d�u7�\u0006�Y�'Ff��n\u001cV�ůC(}�%�ǜ�\u0004��_�t�\u0006�\r�Q3�C��K�\u001a\r�\u00062\f\u001ar���\u0001\"�u\u0003P�]�\u0017-�D���`u0s�\u0004��Ӎ\u0006�Q\"UDI$�I\u0011�VkWUE�������\"��~\u001f>�_\u001e������\t�m\u0001)�\u001a�YS *W}J��s�\u0005͍��\u0004v�f�Qgu�e����q��\f[\r:Azs֛�2=\n�:4��5��\u000e\tn�$�\u0005M�x\u000fܡs\u0010\u0000�7�|4\u001dQ]�G!�9p���'\r�\bY�q�\u001d\u001c���8\u000e\u0006\u001f�����\t��΀�'", + "truncated": true + }, + { + "bytes": 46272, + "kind": "research", + "path": "research/cultnet-distributed-database/crdt-arxiv-1805.06358.html", + "text": "\r\n\r\n\r\n [1805.06358] Conflict-free Replicated Data Types (CRDTs)\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n\r\n \r\n \r\n

\r\n
\r\n Skip to main content\r\n \r\n
\r\n
\r\n \"Cornell\r\n
\r\n We gratefully acknowledge support from the Simons Foundation, member institutions, and all contributors.\r\n Donate\r\n
\r\n
\r\n\r\n
\r\n\r\n
\r\n \"arxiv > cs > arXiv:1805.06358\r\n
\r\n\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n \r\n

Help | Advanced Search

\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\"arXiv
\r\n
\r\n \r\n \r\n\r\n \r\n \r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\nDynamo: Amazon’s highly available key-value store - Amazon Science\r\n \r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n \r\n\r\n \r\n\r\n\r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n\r\n\r\n\r\n \r\n \r\n \r\n\r\n \r\n \r\n\r\n\r\n\r\n\r\n\r\n
\r\n UP \r\n |\r\n HOME \r\n
\r\n

In Search of an Understandable Consensus Algorithm (Extended Version)

\r\n\r\n\r\n
\r\n

DECLARATION

\r\n
\r\n

\r\nThis page is the In Search of an Understandable Consensus Algorithm\r\n(Extended Version) paper. Original Paper Link\r\nis: https://raft.github.io/raft.pdf\r\n

\r\n\r\n

\r\nIn Search of an Understandable Consensus Algorithm
\r\n(Extended Version)
\r\nDiego Ongaro and John Ousterhout
\r\nStanford University\r\n

\r\n
\r\n
\r\n\r\n
\r\n

Abstract

\r\n
\r\n

\r\nRaft is a consensus algorithm for managing a replicated log. It produces a\r\nresult equivalent to (multi-)Paxos, and it is as efficient as Paxos, but its\r\nstructure is different from Paxos; this makes Raft more understandable than\r\nPaxos and also provides a better foundation for building practical systems.\r\nIn order to enhance understandability, Raft separates the key elements of\r\nconsensus, such as leader election, log replication, and safety, and it enforces\r\na stronger degree of coherency to reduce the number of states that must be\r\nconsidered. Results from a user study demonstrate that Raft is easier for\r\nstudents to learn than Paxos. Raft also includes a new mechanism for changing\r\nthe cluster membership, which uses overlapping majorities to guarantee safety.\r\n

\r\n
\r\n
\r\n\r\n
\r\n

1 Introduction

\r\n
\r\n

\r\nConsensus algorithms allow a collection of machines to work as a coherent group\r\nthat can survive the failures of some of its members. Because of this, they play\r\na key role in building reliable large-scale software systems. Paxos [15, 16] has\r\ndominated the discussion of consensus algorithms over the last decade: most\r\nimplementations of consensus are based on Paxos or influenced by it, and Paxos\r\nhas become the primary vehicle used to teach students about consensus.\r\n

\r\n\r\n

\r\nUnfortunately, Paxos is quite difficult to understand, in spite of numerous\r\nattempts to make it more approachable. Furthermore, its architecture requires\r\ncomplex changes to support practical systems. As a result, both system builders\r\nand students struggle with Paxos.\r\n

\r\n\r\n

\r\nAfter struggling with Paxos ourselves, we set out to find a new consensus\r\nalgorithm that could provide a better foundation for system building and\r\neducation. Our approach was unusual in that our primary goal was\r\nunderstandability: could we define a consensus algorithm for practical systems\r\nand describe it in a way that is significantly easier to learn than Paxos?\r\nFurthermore, we wanted the algorithm to facilitate the development of intuitions\r\nthat are essential for system builders. It was important not just for the\r\nalgorithm to work, but for it to be obvious why it works.\r\n

\r\n\r\n

\r\nThe result of this work is a consensus algorithm called Raft. In designing Raft\r\nwe applied specific techniques to improve understandability,including\r\ndecomposition (Raft separates leader election, log replication, and safety) and\r\nThis tech report is an extended version of [32]; additional material is noted\r\nwith a gray bar in the margin. Published May 20, 2014. state space reduction\r\n(relative to Paxos, Raft reduces the degree of nondeterminism and the ways\r\nservers can be inconsistent with each other). A user study with 43 students\r\nat two universities shows that Raft is significantly easier to understand than\r\nPaxos: after learning both algorithms, 33 of these students were able to answer\r\nquestions about Raft better than questions about Paxos.\r\n

\r\n\r\n

\r\nRaft is similar in many ways to existing consensus algorithms (most notably, Oki\r\nand Liskov's Viewstamped Replication [29, 22]), but it has several novel\r\nfeatures:\r\n

\r\n\r\n

\r\n1/. Strong leader: Raft uses a stronger form of leadership than other consensus\r\nalgorithms. For example, log entries only flow from the leader to other servers.\r\nThis simplifies the management of the replicated log and makes Raft easier to\r\nunderstand.\r\n

\r\n\r\n

\r\n2/. Leader election: Raft uses randomized timers to elect leaders. This adds\r\nonly a small amount of mechanism to the heartbeats already required for any\r\nconsensus algorithm, while resolving conflicts simply and rapidly.\r\n

\r\n\r\n

\r\n3/. Membership changes: Raft's mechanism for changing the set of servers in the\r\ncluster uses a new joint consensus approach where the majorities of two\r\ndifferent configurations overlap during transitions. This allows the cluster to\r\ncontinue operating normally during configuration changes.\r\n

\r\n\r\n

\r\nWe believe that Raft is superior to Paxos and other consensus algorithms, both\r\nfor educational purposes and as a foundation for implementation. It is simpler\r\nand more understandable than other algorithms; it is described completely enough\r\nto meet the needs of a practical system; it has several open-source\r\nimplementations and is used by several companies; its safety properties have\r\nbeen formally specified and proven; and its efficiency is comparable to other\r\nalgorithms.\r\n

\r\n\r\n

\r\nThe remainder of the paper introduces the replicated state machine problem\r\n(Section 2), discusses the strengths and weaknesses of Paxos (Section 3),\r\ndescribes our general approach to understandability (Section 4), presents the\r\nRaft consensus algorithm (Sections 5–8), evaluates Raft (Section 9), and\r\ndiscusses related work (Section 10).\r\n

\r\n
\r\n
\r\n\r\n
\r\n

2 Replicated state machines

\r\n
\r\n

\r\nConsensus algorithms typically arise in the context of replicated state machines\r\n[37]. In this approach, state machines on a collection of servers compute\r\nidentical copies of the same state and can continue operating even if some of\r\nthe servers are down. Replicated state machines are used to solve a variety of\r\nfault tolerance problems in distributed systems. For example, large-scale\r\nsystems that have a single cluster leader, such as GFS [8], HDFS [38], and\r\nRAMCloud [33], typically use a separate replicated state machine to manage\r\nleader election and store configuration information that must survive leader\r\ncrashes. Examples of replicated state machines include Chubby [2] and\r\nZooKeeper [11].\r\n

\r\n\r\n\r\n
\r\n

\"raft-figure1.jpg\"\r\n

\r\n

Figure 1: Replicated state machine architecture. The consensus algorithm manages a replicated log containing state machine commands from clients. The state machines process identical sequences of commands from the logs, so they produce the same outputs.

\r\n
\r\n\r\n

\r\nReplicated state machines are typically implemented using a replicated log, as\r\nshown in Figure 1. Each server s", + "truncated": true + }, + { + "bytes": 900468, + "kind": "research", + "path": "research/cultnet-distributed-database/dynamo-sosp2007.pdf", + "text": "%PDF-1.3\r%����\r\n101 0 obj <>\rendobj\r \r\nxref\r\n101 29\r\n0000000016 00000 n\r\n0000001444 00000 n\r\n0000001525 00000 n\r\n0000001727 00000 n\r\n0000001863 00000 n\r\n0000002320 00000 n\r\n0000002760 00000 n\r\n0000003302 00000 n\r\n0000004074 00000 n\r\n0000004327 00000 n\r\n0000004601 00000 n\r\n0000004869 00000 n\r\n0000004982 00000 n\r\n0000005229 00000 n\r\n0000006383 00000 n\r\n0000006918 00000 n\r\n0000007199 00000 n\r\n0000008288 00000 n\r\n0000009351 00000 n\r\n0000010473 00000 n\r\n0000011530 00000 n\r\n0000012622 00000 n\r\n0000013685 00000 n\r\n0000014725 00000 n\r\n0000035703 00000 n\r\n0000072079 00000 n\r\n0000119236 00000 n\r\n0000150351 00000 n\r\n0000000876 00000 n\r\ntrailer\r\n<]>>\r\nstartxref\r\n0\r\n%%EOF\r\n \r\n129 0 obj<>stream\r\nx�b```\u0006��\f�\f\f�\u0002\f�\f\b \f\u0014cc`a�������Ȣ��\u0010�됺���qņ�\u000elݬ|\u0015\u0012;��Y.wh\u0005�\u0019+x��\u00196l\u0007jl��\u001ez���\u000e�UH�1(\u0004�q\u0014�\u001a�NOh��ql29\u001a\u0016��jr\b((\u001aY��Q�!2٧\u0010,+��,���$\u001a\u0019Y&_y\t�&IB�Hh�\r �\u0010�f\tT�\ndL2��\u0005��2�q\u0014r�I���ި}�!2�\rf���,w��\u001b@5*\t�\u0002\u000b�\u0002\u0015�]��s\u0019�X���B�����\t\u000bN\u0000\u001d�Z\u0006v+�DG\u0007\u0003���GG\u0003��K(�\u0003�I\u00009\f\fJ\u0011 1\u0010��\u0000�3\u0018\u001b�)\u0006�\b0�ll\u0001�\u0019\u0005��4�*\u001a�,a\u000b�V�\f�1b\u0019`���2 ���\nv4\u0010\u0017�@`��\u0013\u001a\u0005���X\u000b,�� �0�!�q\u0016c'�{��\f�\u0018\u001e3�epb8�\u0012����\u0015�\u0010�\u000f\u0016c�O,��?�\u001f\u0006\u001e�}���2&�#��K\f�\u0018:\u0019�I�1\u00043|\u0000�T�pIU�\u0001\u001d�1��O\u0005�\u0002`�'\u0006\u000e��1T1X\n����J\u0010\u000b{��s��}�P\u001c\u0003�V+ �\u0004��@���sd?T�K�\u0000\u0003\u0000���z\r\nendstream\rendobj\r102 0 obj<>\rendobj\r103 0 obj<>\rendobj\r104 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>>\rendobj\r105 0 obj<>\rendobj\r106 0 obj<>\rendobj\r107 0 obj<>\rendobj\r108 0 obj<>\rendobj\r109 0 obj<>\rendobj\r110 0 obj<>\rendobj\r111 0 obj<>\rendobj\r112 0 obj<>\rendobj\r113 0 obj<>\rendobj\r114 0 obj<>stream\r\nH�lUێ�6\u0010}�W�#\u0005X�D��''\u000bl��@\u0010\u000b�â\u000f\\��ٕ(W��n>#_�!)��E�X�™9g�\\��q��A�>��\u000fm� �v�JkH�\u000f/UC\u001b\u0006U�Q\u0006��J���m�Jh�$h{Y��WŇ�\u0017�\f�Ǩ~j�,\u000f��\u00156g.{��\u000b�*^�3�g\u0001[3N\u0002��o\u000b�/`̃1h\u0012��e�\u000e\u001cA7��\u0017�ɾ;J|�^��0+Z$\u0001\u0013]����3�����QZ�oˆ\t�\u0018�>�_xd�n�Ӹ��*G\u0003\u0015�?Ť��A�ڹ�h����XU�\n��JZ��η��ꮸQAK�\"D�\t��!�\bxͯ%̰L%��j�.\u0018��z���1K-��Ѯ�!�|ܶ\u0011�U��O�����wl\u001cH\u0003E\u000eE��2\u000fL��g�\u0016��$�E/�sTњ�^:����F��@�\t\u0013n`�RF3�#dT\u0011��Y��x�ӆ��eJ�{\u0000�C��.�li0K�\u0005����#FoP��2\"`�{4s\u0014�,\u000f\u0007��\u0006\u00054Q�\btGg�E\u0015\nO�\"r��\u0018Y�\b��3�kl�ڒ^\u0010`\u001d�.��\u000bZ.�s���\bN\u0016J؋A(#v�`��ϒ�\n�xZ\u0006��]�R�'_Cm��CQ�\u001c��ܙ�[\b[e\u001c�\u0010�\b��[�S�'a�5VQ��N�6ќ�rp��\u0014��$+��\u00055\u0015��\u0007%\f��\u0002X�\u0013Λ2���X�\u001b��\u0010�-�Տ\u001dG\t�4�bJm�6��X֩U������G�&}dzy�u|\u000f����B�i���u\b)l\f>a\rp���x�K�0Nr�Į��o�`�D6_�C\\�(q\u001d��?\u0001\u0006\u0000�V!o\r\nendstream\rendobj\r115 0 obj<>\rendobj\r116 0 obj<>\rendobj\r117 0 obj<>stream\r\nH�tU˖�6\f��+��ΉTQ/K˞z�l��w9Ypd�f\"�>zx2���\u001f�\u000b��x&�J6\t\\\u0000\u0017�e��Y�Iq�vY*%�z�E�\u001bn�j;O�L/��]��AQ�D����xرs\u0019���%�/𶳱�[��%N괈���>��I�W-��z|��d��M�hF�����N���-@�\u0005h|\u00001�j��Lb`�N2$��:��2��\u0012��4�����p�\u001b�\u0014<���\u0017��>R�$��mT���\u0006��W\u001b\u0004d3��\\��(��$�,�}��;��jԂ�k#�)s������V�\u001e�T< 6�\u00011p��+��+�)tD�F�O���Nz2\u0017�a(F\u0003�^[#W�\"�0T�\u0019n�\u001e��f�,�w�\u0004\u000b�Ģ��wk\u001f\r�Pk{\u0002���e\u001b\u0002\u0014e��j.�\u001e(%\u0017-�\r$߹]h\u00033\\��\u0015\u0018\u0002��N=�o>I,argCE�m�/��(-a1{w7��v\u000eW�A�1�\u0003�\u0006cj\u000e\u0000\u000e!�ȟk\u001f���ݟ����{z���P���۪XW�{]\u0000DSw�h��edh�0��N,|\u0018\f���Kw7'>\r��.v�1����������\r`D���e�=���i10F,\u001b��\u0018�7\u0010G�ˉ��\fR��k\u0000��w�0�\u0011�\b\f�Q�\u001f���!�\u001b�ʟC�\u0018 d�\u0014�\u001ab�A{*^\u000f��\"-���]5��\u0003�\u001f�6h�\u0001;�P�4/V\r@���P\u001dՍ���=��\u0012V\u0010\u0000�\u001d$\f��Y��u�9��f�\u001a��>�bOغN���xqդ�\u000b��Ӵ2(o4nJ���y�g_��\bQ\u001c�w\u001dH�?��\u0004�\u0012\u000b��1™\u0018A\u0015�����\f\u0019��򐵕��NJ���\u0017h���U�ۭ7\u001d/y��zb*N��g�7:�o�����3 fH������S�\t%q� f�o�{�*�&�\u001e�7�O=�Bfh\u001eD\u0006s\u001b���==��z�1��w>Y�A�Fٚ\r70�\u0007����Fh\"�\u001c=^\u001e\u000f{��\u0015�\n� �9�v<�\u0002=>C8��\t|�R\u0014\r��qx`%�Z���\u000f�m\u00177\u001a4�����\u001bv�S7���Ɖ�c�7\u001e�e�V�E�\u0002�\u0001�K`̟^���ޖ萖��\u0012b�\u0002��\u001e��t������ч&��\u0007\u001b�B^X\u0001�g��B�j��I�\u0007*�*�\u0013`\u0000h�\u001f\u0016\r\nendstream\rendobj\r118 0 obj<>stream\r\nH�|Uێ�6\u0010}�W�#\t�X��'OE\u0017(\u0012�� �>-�i[�,�\u0014�E�\u0019��ΐ�/�m��K�2g�3���槶�AB���\"��\nRh�7�HӴ���+�C��yb_y%\u0014{�\u0013)2\u0006��X���5��M�.YG�\r��\u000e\u001b�=܋�/\u0005O��Y\u0001�k�q��T�M�\u0001>�9\u0002\u0013�G$0���?(�2$��\f�.��sr2&�p⹨���\u001b&��sJ\u0005\u001e��\b��'��ٌG9s����q���rp\u0005R�A�\u000b\u0003\r1�b=�E�C���26�\u0003/�����\u001d�K\u0016*�SA�TL�ӊW�x�\nx���^\u0001s�V\u0015\n��#\u0016P����Gi�0ev�\u0011S�lk|\u0017YW�hdd����ؾT�Y۝��n���(�L\u0003F!�欀�\f�\u0012I�\u0004/+(r�2%\n\u0005�1D/�A�.Q�_�����j�Մ8��Ƈi@f��u��9<2VUf�\u0012u.C�\u0004f*���7vp��|G&��3\u001d�u7�\u0006�Y�'Ff��n\u001cV�ůC(}�%�ǜ�\u0004��_�t�\u0006�\r�Q3�C��K�\u001a\r�\u00062\f\u001ar���\u0001\"�u\u0003P�]�\u0017-�D���`u0s�\u0004��Ӎ\u0006�Q\"UDI$�I\u0011�VkWUE�������\"��~\u001f>�_\u001e������\t�m\u0001)�\u001a�YS *W}J��s�\u0005͍��\u0004v�f�Qgu�e����q��\f[\r:Azs֛�2=\n�:4��5��\u000e\tn�$�\u0005M�x\u000fܡs\u0010\u0000�7�|4\u001dQ]�G!�9p���'\r�\bY�q�\u001d\u001c���8\u000e\u0006\u001f�����\t��΀�'", + "truncated": true + }, + { + "bytes": 46272, + "kind": "research", + "path": "research/cultnet-distributed-database/crdt-arxiv-1805.06358.html", + "text": "\r\n\r\n\r\n [1805.06358] Conflict-free Replicated Data Types (CRDTs)\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n\r\n \r\n \r\n

\r\n
\r\n Skip to main content\r\n \r\n
\r\n
\r\n \"Cornell\r\n
\r\n We gratefully acknowledge support from the Simons Foundation, member institutions, and all contributors.\r\n Donate\r\n
\r\n
\r\n\r\n
\r\n\r\n
\r\n \"arxiv > cs > arXiv:1805.06358\r\n
\r\n\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n \r\n

Help | Advanced Search

\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\"arXiv
\r\n
\r\n \r\n \r\n\r\n \r\n \r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\nDynamo: Amazon’s highly available key-value store - Amazon Science\r\n \r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n \r\n\r\n \r\n\r\n\r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n\r\n\r\n\r\n \r\n \r\n \r\n\r\n \r\n \r\n\r\n\r\n\r\n\r\n\r\n
\r\n UP \r\n |\r\n HOME \r\n
\r\n

In Search of an Understandable Consensus Algorithm (Extended Version)

\r\n\r\n\r\n
\r\n

DECLARATION

\r\n
\r\n

\r\nThis page is the In Search of an Understandable Consensus Algorithm\r\n(Extended Version) paper. Original Paper Link\r\nis: https://raft.github.io/raft.pdf\r\n

\r\n\r\n

\r\nIn Search of an Understandable Consensus Algorithm
\r\n(Extended Version)
\r\nDiego Ongaro and John Ousterhout
\r\nStanford University\r\n

\r\n
\r\n
\r\n\r\n
\r\n

Abstract

\r\n
\r\n

\r\nRaft is a consensus algorithm for managing a replicated log. It produces a\r\nresult equivalent to (multi-)Paxos, and it is as efficient as Paxos, but its\r\nstructure is different from Paxos; this makes Raft more understandable than\r\nPaxos and also provides a better foundation for building practical systems.\r\nIn order to enhance understandability, Raft separates the key elements of\r\nconsensus, such as leader election, log replication, and safety, and it enforces\r\na stronger degree of coherency to reduce the number of states that must be\r\nconsidered. Results from a user study demonstrate that Raft is easier for\r\nstudents to learn than Paxos. Raft also includes a new mechanism for changing\r\nthe cluster membership, which uses overlapping majorities to guarantee safety.\r\n

\r\n
\r\n
\r\n\r\n
\r\n

1 Introduction

\r\n
\r\n

\r\nConsensus algorithms allow a collection of machines to work as a coherent group\r\nthat can survive the failures of some of its members. Because of this, they play\r\na key role in building reliable large-scale software systems. Paxos [15, 16] has\r\ndominated the discussion of consensus algorithms over the last decade: most\r\nimplementations of consensus are based on Paxos or influenced by it, and Paxos\r\nhas become the primary vehicle used to teach students about consensus.\r\n

\r\n\r\n

\r\nUnfortunately, Paxos is quite difficult to understand, in spite of numerous\r\nattempts to make it more approachable. Furthermore, its architecture requires\r\ncomplex changes to support practical systems. As a result, both system builders\r\nand students struggle with Paxos.\r\n

\r\n\r\n

\r\nAfter struggling with Paxos ourselves, we set out to find a new consensus\r\nalgorithm that could provide a better foundation for system building and\r\neducation. Our approach was unusual in that our primary goal was\r\nunderstandability: could we define a consensus algorithm for practical systems\r\nand describe it in a way that is significantly easier to learn than Paxos?\r\nFurthermore, we wanted the algorithm to facilitate the development of intuitions\r\nthat are essential for system builders. It was important not just for the\r\nalgorithm to work, but for it to be obvious why it works.\r\n

\r\n\r\n

\r\nThe result of this work is a consensus algorithm called Raft. In designing Raft\r\nwe applied specific techniques to improve understandability,including\r\ndecomposition (Raft separates leader election, log replication, and safety) and\r\nThis tech report is an extended version of [32]; additional material is noted\r\nwith a gray bar in the margin. Published May 20, 2014. state space reduction\r\n(relative to Paxos, Raft reduces the degree of nondeterminism and the ways\r\nservers can be inconsistent with each other). A user study with 43 students\r\nat two universities shows that Raft is significantly easier to understand than\r\nPaxos: after learning both algorithms, 33 of these students were able to answer\r\nquestions about Raft better than questions about Paxos.\r\n

\r\n\r\n

\r\nRaft is similar in many ways to existing consensus algorithms (most notably, Oki\r\nand Liskov's Viewstamped Replication [29, 22]), but it has several novel\r\nfeatures:\r\n

\r\n\r\n

\r\n1/. Strong leader: Raft uses a stronger form of leadership than other consensus\r\nalgorithms. For example, log entries only flow from the leader to other servers.\r\nThis simplifies the management of the replicated log and makes Raft easier to\r\nunderstand.\r\n

\r\n\r\n

\r\n2/. Leader election: Raft uses randomized timers to elect leaders. This adds\r\nonly a small amount of mechanism to the heartbeats already required for any\r\nconsensus algorithm, while resolving conflicts simply and rapidly.\r\n

\r\n\r\n

\r\n3/. Membership changes: Raft's mechanism for changing the set of servers in the\r\ncluster uses a new joint consensus approach where the majorities of two\r\ndifferent configurations overlap during transitions. This allows the cluster to\r\ncontinue operating normally during configuration changes.\r\n

\r\n\r\n

\r\nWe believe that Raft is superior to Paxos and other consensus algorithms, both\r\nfor educational purposes and as a foundation for implementation. It is simpler\r\nand more understandable than other algorithms; it is described completely enough\r\nto meet the needs of a practical system; it has several open-source\r\nimplementations and is used by several companies; its safety properties have\r\nbeen formally specified and proven; and its efficiency is comparable to other\r\nalgorithms.\r\n

\r\n\r\n

\r\nThe remainder of the paper introduces the replicated state machine problem\r\n(Section 2), discusses the strengths and weaknesses of Paxos (Section 3),\r\ndescribes our general approach to understandability (Section 4), presents the\r\nRaft consensus algorithm (Sections 5–8), evaluates Raft (Section 9), and\r\ndiscusses related work (Section 10).\r\n

\r\n
\r\n
\r\n\r\n
\r\n

2 Replicated state machines

\r\n
\r\n

\r\nConsensus algorithms typically arise in the context of replicated state machines\r\n[37]. In this approach, state machines on a collection of servers compute\r\nidentical copies of the same state and can continue operating even if some of\r\nthe servers are down. Replicated state machines are used to solve a variety of\r\nfault tolerance problems in distributed systems. For example, large-scale\r\nsystems that have a single cluster leader, such as GFS [8], HDFS [38], and\r\nRAMCloud [33], typically use a separate replicated state machine to manage\r\nleader election and store configuration information that must survive leader\r\ncrashes. Examples of replicated state machines include Chubby [2] and\r\nZooKeeper [11].\r\n

\r\n\r\n\r\n
\r\n

\"raft-figure1.jpg\"\r\n

\r\n

Figure 1: Replicated state machine architecture. The consensus algorithm manages a replicated log containing state machine commands from clients. The state machines process identical sequences of commands from the logs, so they produce the same outputs.

\r\n
\r\n\r\n

\r\nReplicated state machines are typically implemented using a replicated log, as\r\nshown in Figure 1. Each server s", + "truncated": true + }, + { + "bytes": 900468, + "kind": "research", + "path": "research/cultnet-distributed-database/dynamo-sosp2007.pdf", + "text": "%PDF-1.3\r%����\r\n101 0 obj <>\rendobj\r \r\nxref\r\n101 29\r\n0000000016 00000 n\r\n0000001444 00000 n\r\n0000001525 00000 n\r\n0000001727 00000 n\r\n0000001863 00000 n\r\n0000002320 00000 n\r\n0000002760 00000 n\r\n0000003302 00000 n\r\n0000004074 00000 n\r\n0000004327 00000 n\r\n0000004601 00000 n\r\n0000004869 00000 n\r\n0000004982 00000 n\r\n0000005229 00000 n\r\n0000006383 00000 n\r\n0000006918 00000 n\r\n0000007199 00000 n\r\n0000008288 00000 n\r\n0000009351 00000 n\r\n0000010473 00000 n\r\n0000011530 00000 n\r\n0000012622 00000 n\r\n0000013685 00000 n\r\n0000014725 00000 n\r\n0000035703 00000 n\r\n0000072079 00000 n\r\n0000119236 00000 n\r\n0000150351 00000 n\r\n0000000876 00000 n\r\ntrailer\r\n<]>>\r\nstartxref\r\n0\r\n%%EOF\r\n \r\n129 0 obj<>stream\r\nx�b```\u0006��\f�\f\f�\u0002\f�\f\b \f\u0014cc`a�������Ȣ��\u0010�됺���qņ�\u000elݬ|\u0015\u0012;��Y.wh\u0005�\u0019+x��\u00196l\u0007jl��\u001ez���\u000e�UH�1(\u0004�q\u0014�\u001a�NOh��ql29\u001a\u0016��jr\b((\u001aY��Q�!2٧\u0010,+��,���$\u001a\u0019Y&_y\t�&IB�Hh�\r �\u0010�f\tT�\ndL2��\u0005��2�q\u0014r�I���ި}�!2�\rf���,w��\u001b@5*\t�\u0002\u000b�\u0002\u0015�]��s\u0019�X���B�����\t\u000bN\u0000\u001d�Z\u0006v+�DG\u0007\u0003���GG\u0003��K(�\u0003�I\u00009\f\fJ\u0011 1\u0010��\u0000�3\u0018\u001b�)\u0006�\b0�ll\u0001�\u0019\u0005��4�*\u001a�,a\u000b�V�\f�1b\u0019`���2 ���\nv4\u0010\u0017�@`��\u0013\u001a\u0005���X\u000b,�� �0�!�q\u0016c'�{��\f�\u0018\u001e3�epb8�\u0012����\u0015�\u0010�\u000f\u0016c�O,��?�\u001f\u0006\u001e�}���2&�#��K\f�\u0018:\u0019�I�1\u00043|\u0000�T�pIU�\u0001\u001d�1��O\u0005�\u0002`�'\u0006\u000e��1T1X\n����J\u0010\u000b{��s��}�P\u001c\u0003�V+ �\u0004��@���sd?T�K�\u0000\u0003\u0000���z\r\nendstream\rendobj\r102 0 obj<>\rendobj\r103 0 obj<>\rendobj\r104 0 obj<>/ProcSet[/PDF/Text]/ExtGState<>>>\rendobj\r105 0 obj<>\rendobj\r106 0 obj<>\rendobj\r107 0 obj<>\rendobj\r108 0 obj<>\rendobj\r109 0 obj<>\rendobj\r110 0 obj<>\rendobj\r111 0 obj<>\rendobj\r112 0 obj<>\rendobj\r113 0 obj<>\rendobj\r114 0 obj<>stream\r\nH�lUێ�6\u0010}�W�#\u0005X�D��''\u000bl��@\u0010\u000b�â\u000f\\��ٕ(W��n>#_�!)��E�X�™9g�\\��q��A�>��\u000fm� �v�JkH�\u000f/UC\u001b\u0006U�Q\u0006��J���m�Jh�$h{Y��WŇ�\u0017�\f�Ǩ~j�,\u000f��\u00156g.{��\u000b�*^�3�g\u0001[3N\u0002��o\u000b�/`̃1h\u0012��e�\u000e\u001cA7��\u0017�ɾ;J|�^��0+Z$\u0001\u0013]����3�����QZ�oˆ\t�\u0018�>�_xd�n�Ӹ��*G\u0003\u0015�?Ť��A�ڹ�h����XU�\n��JZ��η��ꮸQAK�\"D�\t��!�\bxͯ%̰L%��j�.\u0018��z���1K-��Ѯ�!�|ܶ\u0011�U��O�����wl\u001cH\u0003E\u000eE��2\u000fL��g�\u0016��$�E/�sTњ�^:����F��@�\t\u0013n`�RF3�#dT\u0011��Y��x�ӆ��eJ�{\u0000�C��.�li0K�\u0005����#FoP��2\"`�{4s\u0014�,\u000f\u0007��\u0006\u00054Q�\btGg�E\u0015\nO�\"r��\u0018Y�\b��3�kl�ڒ^\u0010`\u001d�.��\u000bZ.�s���\bN\u0016J؋A(#v�`��ϒ�\n�xZ\u0006��]�R�'_Cm��CQ�\u001c��ܙ�[\b[e\u001c�\u0010�\b��[�S�'a�5VQ��N�6ќ�rp��\u0014��$+��\u00055\u0015��\u0007%\f��\u0002X�\u0013Λ2���X�\u001b��\u0010�-�Տ\u001dG\t�4�bJm�6��X֩U������G�&}dzy�u|\u000f����B�i���u\b)l\f>a\rp���x�K�0Nr�Į��o�`�D6_�C\\�(q\u001d��?\u0001\u0006\u0000�V!o\r\nendstream\rendobj\r115 0 obj<>\rendobj\r116 0 obj<>\rendobj\r117 0 obj<>stream\r\nH�tU˖�6\f��+��ΉTQ/K˞z�l��w9Ypd�f\"�>zx2���\u001f�\u000b��x&�J6\t\\\u0000\u0017�e��Y�Iq�vY*%�z�E�\u001bn�j;O�L/��]��AQ�D����xرs\u0019���%�/𶳱�[��%N괈���>��I�W-��z|��d��M�hF�����N���-@�\u0005h|\u00001�j��Lb`�N2$��:��2��\u0012��4�����p�\u001b�\u0014<���\u0017��>R�$��mT���\u0006��W\u001b\u0004d3��\\��(��$�,�}��;��jԂ�k#�)s������V�\u001e�T< 6�\u00011p��+��+�)tD�F�O���Nz2\u0017�a(F\u0003�^[#W�\"�0T�\u0019n�\u001e��f�,�w�\u0004\u000b�Ģ��wk\u001f\r�Pk{\u0002���e\u001b\u0002\u0014e��j.�\u001e(%\u0017-�\r$߹]h\u00033\\��\u0015\u0018\u0002��N=�o>I,argCE�m�/��(-a1{w7��v\u000eW�A�1�\u0003�\u0006cj\u000e\u0000\u000e!�ȟk\u001f���ݟ����{z���P���۪XW�{]\u0000DSw�h��edh�0��N,|\u0018\f���Kw7'>\r��.v�1����������\r`D���e�=���i10F,\u001b��\u0018�7\u0010G�ˉ��\fR��k\u0000��w�0�\u0011�\b\f�Q�\u001f���!�\u001b�ʟC�\u0018 d�\u0014�\u001ab�A{*^\u000f��\"-���]5��\u0003�\u001f�6h�\u0001;�P�4/V\r@���P\u001dՍ���=��\u0012V\u0010\u0000�\u001d$\f��Y��u�9��f�\u001a��>�bOغN���xqդ�\u000b��Ӵ2(o4nJ���y�g_��\bQ\u001c�w\u001dH�?��\u0004�\u0012\u000b��1™\u0018A\u0015�����\f\u0019��򐵕��NJ���\u0017h���U�ۭ7\u001d/y��zb*N��g�7:�o�����3 fH������S�\t%q� f�o�{�*�&�\u001e�7�O=�Bfh\u001eD\u0006s\u001b���==��z�1��w>Y�A�Fٚ\r70�\u0007����Fh\"�\u001c=^\u001e\u000f{��\u0015�\n� �9�v<�\u0002=>C8��\t|�R\u0014\r��qx`%�Z���\u000f�m\u00177\u001a4�����\u001bv�S7���Ɖ�c�7\u001e�e�V�E�\u0002�\u0001�K`̟^���ޖ萖��\u0012b�\u0002��\u001e��t������ч&��\u0007\u001b�B^X\u0001�g��B�j��I�\u0007*�*�\u0013`\u0000h�\u001f\u0016\r\nendstream\rendobj\r118 0 obj<>stream\r\nH�|Uێ�6\u0010}�W�#\t�X��'OE\u0017(\u0012�� �>-�i[�,�\u0014�E�\u0019��ΐ�/�m��K�2g�3���槶�AB���\"��\nRh�7�HӴ���+�C��yb_y%\u0014{�\u0013)2\u0006��X���5��M�.YG�\r��\u000e\u001b�=܋�/\u0005O��Y\u0001�k�q��T�M�\u0001>�9\u0002\u0013�G$0���?(�2$��\f�.��sr2&�p⹨���\u001b&��sJ\u0005\u001e��\b��'��ٌG9s����q���rp\u0005R�A�\u000b\u0003\r1�b=�E�C���26�\u0003/�����\u001d�K\u0016*�SA�TL�ӊW�x�\nx���^\u0001s�V\u0015\n��#\u0016P����Gi�0ev�\u0011S�lk|\u0017YW�hdd����ؾT�Y۝��n���(�L\u0003F!�欀�\f�\u0012I�\u0004/+(r�2%\n\u0005�1D/�A�.Q�_�����j�Մ8��Ƈi@f��u��9<2VUf�\u0012u.C�\u0004f*���7vp��|G&��3\u001d�u7�\u0006�Y�'Ff��n\u001cV�ůC(}�%�ǜ�\u0004��_�t�\u0006�\r�Q3�C��K�\u001a\r�\u00062\f\u001ar���\u0001\"�u\u0003P�]�\u0017-�D���`u0s�\u0004��Ӎ\u0006�Q\"UDI$�I\u0011�VkWUE�������\"��~\u001f>�_\u001e������\t�m\u0001)�\u001a�YS *W}J��s�\u0005͍��\u0004v�f�Qgu�e����q��\f[\r:Azs֛�2=\n�:4��5��\u000e\tn�$�\u0005M�x\u000fܡs\u0010\u0000�7�|4\u001dQ]�G!�9p���'\r�\bY�q�\u001d\u001c���8\u000e\u0006\u001f�����\t��΀�'", + "truncated": true + }, + { + "bytes": 46272, + "kind": "research", + "path": "research/cultnet-distributed-database/crdt-arxiv-1805.06358.html", + "text": "\r\n\r\n\r\n [1805.06358] Conflict-free Replicated Data Types (CRDTs)\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n\r\n \r\n \r\n

\r\n
\r\n Skip to main content\r\n \r\n
\r\n
\r\n \"Cornell\r\n
\r\n We gratefully acknowledge support from the Simons Foundation, member institutions, and all contributors.\r\n Donate\r\n
\r\n
\r\n\r\n
\r\n\r\n
\r\n \"arxiv > cs > arXiv:1805.06358\r\n
\r\n\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n \r\n

Help | Advanced Search

\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\"arXiv
\r\n
\r\n \r\n \r\n\r\n \r\n \r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\nDynamo: Amazon’s highly available key-value store - Amazon Science\r\n \r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n \r\n\r\n \r\n\r\n\r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n\r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n\r\n\r\n\r\n \r\n \r\n \r\n\r\n \r\n