fn-docs: (docs) Beads/Dolt evaluation doc
This commit is contained in:
501
docs/beads-dolt-sync-evaluation.md
Normal file
501
docs/beads-dolt-sync-evaluation.md
Normal file
@@ -0,0 +1,501 @@
|
||||
# Beads and Dolt Evaluation for Fusion Node Sync
|
||||
|
||||
[← Docs index](./README.md)
|
||||
|
||||
## Summary
|
||||
|
||||
Recommendation: **do not switch Fusion wholesale to either Beads or Dolt for node sync right now**.
|
||||
|
||||
Use them as design references or optional experiments, but keep Fusion’s current SQLite + filesystem hybrid model and add an explicit Fusion-native sync layer.
|
||||
|
||||
| Option | Recommendation |
|
||||
|---|---|
|
||||
| Beads | Useful inspiration for local-first issue/task sync, but too domain-specific to become Fusion’s persistence or sync substrate. |
|
||||
| Dolt | Technically interesting for versioned relational data and SQL merge semantics, but too heavy and operationally different from Fusion’s embedded SQLite model. Consider only as an experimental backend or audit/export target. |
|
||||
| Best path | Keep SQLite. Add a Fusion-native sync protocol based on append-only change events, per-record revisions, deterministic conflict policies, and blob transfer for `.fusion/tasks/*`. |
|
||||
|
||||
## Fusion’s Current Sync Requirements
|
||||
|
||||
Fusion is more than a task board. Current persistence includes:
|
||||
|
||||
- Project DB: `.fusion/fusion.db`
|
||||
- Central DB: `~/.fusion/fusion-central.db`
|
||||
- Filesystem blobs: `.fusion/tasks/{ID}/PROMPT.md`, logs, attachments
|
||||
- Project tables for tasks, agents, activity logs, missions, roadmaps, workflow steps, chat, insights, audit events, and more
|
||||
- Central multi-node metadata including `nodes`, `peerNodes`, `settingsSyncState`, project routing, health, and global concurrency
|
||||
|
||||
Node sync needs to handle:
|
||||
|
||||
1. Task metadata
|
||||
2. Task lifecycle transitions
|
||||
3. Agent state and heartbeats
|
||||
4. Settings sync
|
||||
5. Mission, roadmap, and todo data
|
||||
6. Attachments and task files
|
||||
7. Conflict detection
|
||||
8. Offline edits
|
||||
9. Partial peer availability
|
||||
10. Security and authentication per node
|
||||
|
||||
The sync layer needs to be more general than an issue tracker sync model.
|
||||
|
||||
## Beads Evaluation
|
||||
|
||||
Beads is attractive because it appears philosophically aligned with Fusion:
|
||||
|
||||
- Local-first
|
||||
- CLI-friendly
|
||||
- Task/issue oriented
|
||||
- Git-friendly or file/db-backed sync model
|
||||
- Human-readable workflows
|
||||
- Good fit for small project issue tracking
|
||||
|
||||
### Potential Uses
|
||||
|
||||
Beads could be useful as inspiration for:
|
||||
|
||||
- Task IDs
|
||||
- Dependency graph semantics
|
||||
- Syncing issue-like records
|
||||
- Minimal local-first UX
|
||||
- Conflict-tolerant issue updates
|
||||
- Import/export interoperability
|
||||
|
||||
### Problems as Fusion’s Backend
|
||||
|
||||
#### Domain mismatch
|
||||
|
||||
Fusion tasks are only one part of the data model. Fusion also has:
|
||||
|
||||
- Agents
|
||||
- Agent ratings
|
||||
- Heartbeat runs
|
||||
- AI sessions/messages
|
||||
- Workflow steps
|
||||
- Missions, milestones, slices, and features
|
||||
- Roadmaps
|
||||
- Settings
|
||||
- Node registry
|
||||
- Run audit events
|
||||
- Attachments and logs
|
||||
|
||||
Beads is likely optimized around issues, not full distributed orchestration state.
|
||||
|
||||
#### Schema constraints
|
||||
|
||||
If Fusion uses Beads as the substrate, Fusion either:
|
||||
|
||||
- Adopts Beads’ issue model and loses domain expressiveness, or
|
||||
- Stores Fusion-specific JSON payloads inside Beads, turning Beads into an awkward blob store.
|
||||
|
||||
Neither is ideal.
|
||||
|
||||
#### Sync granularity mismatch
|
||||
|
||||
Fusion needs record-level and event-level sync with explicit lifecycle semantics.
|
||||
|
||||
Example:
|
||||
|
||||
- Node A moves `FN-123` from `todo` to `in-progress`
|
||||
- Node B edits title/description
|
||||
- Node C assigns `nodeId`
|
||||
- An agent heartbeat writes progress
|
||||
- A reviewer moves the task to `in-review`
|
||||
|
||||
Fusion needs deterministic merge rules per field and per event type. Beads is unlikely to provide that across Fusion’s full schema.
|
||||
|
||||
#### Runtime state should not sync like tasks
|
||||
|
||||
Some Fusion data is operational and ephemeral:
|
||||
|
||||
- Agent heartbeat timestamps
|
||||
- In-progress run state
|
||||
- Local worktree paths
|
||||
- Scheduler locks
|
||||
- Checkout leases
|
||||
|
||||
A general issue tracker sync model may accidentally replicate data that should remain node-local.
|
||||
|
||||
### Beads Verdict
|
||||
|
||||
Do not use Beads as Fusion’s storage backend.
|
||||
|
||||
Potential uses:
|
||||
|
||||
- Study its local-first task model.
|
||||
- Build an importer/exporter if useful.
|
||||
- Reuse similar concepts for task dependency syncing.
|
||||
- Do not couple Fusion core storage or node sync to it.
|
||||
|
||||
## Dolt Evaluation
|
||||
|
||||
Dolt is effectively “Git for SQL databases”: relational tables with branches, diffs, commits, remotes, merges, conflicts, and SQL access.
|
||||
|
||||
### What Dolt Is Good At
|
||||
|
||||
Dolt provides:
|
||||
|
||||
- Versioned relational data
|
||||
- SQL access
|
||||
- Branch/merge workflow
|
||||
- Diff/commit history
|
||||
- Conflict detection
|
||||
- Remote push/pull semantics
|
||||
- MySQL-compatible protocol
|
||||
- Data provenance
|
||||
|
||||
This sounds compelling because Fusion already stores structured metadata in SQLite.
|
||||
|
||||
### Why Dolt Is Tempting
|
||||
|
||||
Fusion needs distributed relational sync. Dolt provides many adjacent primitives:
|
||||
|
||||
- Nodes could have branches.
|
||||
- Sync could be pull/merge/push.
|
||||
- Conflicts could be represented explicitly.
|
||||
- Settings/task diffs could be inspected.
|
||||
- History could be queryable.
|
||||
- Multi-node sync could use Dolt remotes.
|
||||
|
||||
For structured metadata, Dolt is more relevant than Beads.
|
||||
|
||||
### Major Tradeoffs
|
||||
|
||||
#### Dolt is not an embedded SQLite replacement
|
||||
|
||||
Fusion currently uses SQLite through `node:sqlite`.
|
||||
|
||||
This is simple:
|
||||
|
||||
- No server
|
||||
- No external daemon
|
||||
- Small operational footprint
|
||||
- Works inside a published npm CLI
|
||||
- Easy local project DB
|
||||
- WAL mode concurrency
|
||||
- Files live in `.fusion/fusion.db`
|
||||
|
||||
Dolt is operationally different:
|
||||
|
||||
- Usually accessed as a Dolt database/server or CLI-managed repo
|
||||
- MySQL-compatible, not SQLite-compatible
|
||||
- Requires different drivers and query behavior
|
||||
- Adds a heavier binary dependency
|
||||
- Is harder to bundle into `@runfusion/fusion`
|
||||
|
||||
For a globally installed npm CLI, this matters.
|
||||
|
||||
#### Migration cost is high
|
||||
|
||||
Fusion’s persistence layer is deeply SQLite-oriented:
|
||||
|
||||
- `packages/core/src/db.ts`
|
||||
- `TaskStore`
|
||||
- `CentralCore`
|
||||
- migrations
|
||||
- tests using real SQLite
|
||||
- project-local DB assumptions
|
||||
- `.fusion/fusion.db` file layout
|
||||
|
||||
Switching to Dolt would likely require a storage abstraction layer or a major rewrite.
|
||||
|
||||
#### SQL merge is not domain merge
|
||||
|
||||
Dolt can tell you there is a data conflict. It does not know what Fusion should do.
|
||||
|
||||
Example conflict:
|
||||
|
||||
```text
|
||||
task.status:
|
||||
Node A: in-progress
|
||||
Node B: done
|
||||
```
|
||||
|
||||
Dolt can surface a conflict, but Fusion still needs to decide:
|
||||
|
||||
- Is `done` allowed if `in-progress` happened elsewhere?
|
||||
- Was review skipped?
|
||||
- Which transition wins?
|
||||
- Should this create a merge-resolution task?
|
||||
- Should the losing transition be preserved in activity log?
|
||||
|
||||
Fusion has domain-level lifecycle rules. SQL merge does not replace those rules.
|
||||
|
||||
#### Some tables should not be globally merged
|
||||
|
||||
Fusion has mixed data classes:
|
||||
|
||||
| Data type | Sync behavior |
|
||||
|---|---|
|
||||
| Tasks | Sync |
|
||||
| Task documents | Sync |
|
||||
| Settings | Selectively sync |
|
||||
| Missions/roadmaps | Sync |
|
||||
| Activity log | Append-only |
|
||||
| Run audit | Append-only or local-origin |
|
||||
| Agent heartbeats | Usually local-only or summarized |
|
||||
| Checkout leases | Local-only or TTL-based |
|
||||
| Local worktree paths | Local-only |
|
||||
| Auth secrets | Special encrypted sync only |
|
||||
|
||||
A generic database merge risks syncing the wrong things unless carefully partitioned.
|
||||
|
||||
#### Filesystem blobs remain unsolved
|
||||
|
||||
Fusion stores large task artifacts in `.fusion/tasks/{ID}/`.
|
||||
|
||||
Dolt can store data in tables, but putting logs, prompts, attachments, and large blobs into Dolt would be undesirable. Fusion would still need a blob sync protocol.
|
||||
|
||||
#### Operational burden
|
||||
|
||||
Dolt introduces product questions:
|
||||
|
||||
- How is Dolt installed?
|
||||
- Is it bundled with the npm package?
|
||||
- What about Windows/macOS/Linux binaries?
|
||||
- How are DB upgrades handled?
|
||||
- Does the dashboard start a Dolt SQL server?
|
||||
- What port does it use?
|
||||
- How does this work with `fn serve`?
|
||||
- How does it interact with user Git repos?
|
||||
- How are backups handled?
|
||||
- How are conflicts exposed in the dashboard?
|
||||
|
||||
That is a large product surface.
|
||||
|
||||
### Dolt Verdict
|
||||
|
||||
Dolt is technically promising, but should not become Fusion’s primary storage engine now.
|
||||
|
||||
Better uses:
|
||||
|
||||
1. **Experimental sync backend**
|
||||
- Add a prototype adapter for selected tables.
|
||||
- Try syncing `tasks`, `activityLog`, and `settingsSyncState`.
|
||||
- Measure complexity.
|
||||
2. **External export format**
|
||||
- Export Fusion state into Dolt for audit/history/diff.
|
||||
- Do not make runtime depend on it.
|
||||
3. **Admin/enterprise mode**
|
||||
- Potentially useful later for teams wanting SQL history and data provenance.
|
||||
|
||||
## Recommended Fusion-Native Sync Design
|
||||
|
||||
Keep the current SQLite architecture and add a dedicated sync layer.
|
||||
|
||||
### Core Idea
|
||||
|
||||
Use **append-only change events** plus **materialized SQLite state**.
|
||||
|
||||
Fusion already has adjacent concepts:
|
||||
|
||||
- `activityLog`
|
||||
- `runAuditEvents`
|
||||
- node registry
|
||||
- settings sync state
|
||||
- task lifecycle transitions
|
||||
- central DB node metadata
|
||||
|
||||
Build on those instead of replacing storage.
|
||||
|
||||
### Stable Node Identity
|
||||
|
||||
Each node should have:
|
||||
|
||||
```ts
|
||||
nodeId
|
||||
publicKey?
|
||||
apiKey / auth credentials
|
||||
lastSeen
|
||||
syncCursorByPeer
|
||||
```
|
||||
|
||||
This is already partially represented by `nodes` and `peerNodes`.
|
||||
|
||||
### Change Log Table
|
||||
|
||||
Add a project-level sync log:
|
||||
|
||||
```sql
|
||||
CREATE TABLE sync_events (
|
||||
id TEXT PRIMARY KEY,
|
||||
originNodeId TEXT NOT NULL,
|
||||
seq INTEGER NOT NULL,
|
||||
entityType TEXT NOT NULL,
|
||||
entityId TEXT NOT NULL,
|
||||
operation TEXT NOT NULL,
|
||||
payloadJson TEXT NOT NULL,
|
||||
baseRevision TEXT,
|
||||
resultingRevision TEXT NOT NULL,
|
||||
createdAt TEXT NOT NULL
|
||||
);
|
||||
```
|
||||
|
||||
This becomes the canonical stream nodes exchange.
|
||||
|
||||
### Per-Entity Revision Metadata
|
||||
|
||||
For synced tables:
|
||||
|
||||
```sql
|
||||
CREATE TABLE entity_revisions (
|
||||
entityType TEXT NOT NULL,
|
||||
entityId TEXT NOT NULL,
|
||||
revision TEXT NOT NULL,
|
||||
updatedAt TEXT NOT NULL,
|
||||
updatedByNodeId TEXT NOT NULL,
|
||||
PRIMARY KEY (entityType, entityId)
|
||||
);
|
||||
```
|
||||
|
||||
Revision options:
|
||||
|
||||
- Lamport timestamp
|
||||
- Hybrid logical clock
|
||||
- Compact vector clock
|
||||
- Content hash plus origin sequence
|
||||
|
||||
### Conflict Policies by Entity and Field
|
||||
|
||||
Do not rely on generic last-write-wins everywhere.
|
||||
|
||||
| Entity | Conflict policy |
|
||||
|---|---|
|
||||
| Task title/description | Last-write-wins or field-level merge |
|
||||
| Task status | Lifecycle-aware transition merge |
|
||||
| Task labels | Set union |
|
||||
| Task dependencies | Set union with cycle detection |
|
||||
| Activity log | Append-only |
|
||||
| Run audit | Append-only |
|
||||
| Checkout lease | Local-only or TTL conflict |
|
||||
| Agent heartbeat | Node-local by default |
|
||||
| Settings | Scoped, field-level, explicit push/pull |
|
||||
| Auth | Encrypted explicit sync only |
|
||||
| Attachments | Content-addressed blob transfer |
|
||||
|
||||
### Blob Sync
|
||||
|
||||
For files under `.fusion/tasks/{ID}/`, use content-addressed metadata:
|
||||
|
||||
```sql
|
||||
CREATE TABLE sync_blobs (
|
||||
digest TEXT PRIMARY KEY,
|
||||
taskId TEXT,
|
||||
relativePath TEXT NOT NULL,
|
||||
size INTEGER NOT NULL,
|
||||
mimeType TEXT,
|
||||
createdAt TEXT NOT NULL
|
||||
);
|
||||
```
|
||||
|
||||
Then transfer blobs separately:
|
||||
|
||||
```text
|
||||
GET /api/sync/blobs/:digest
|
||||
PUT /api/sync/blobs/:digest
|
||||
```
|
||||
|
||||
Avoid stuffing large logs and attachments into relational sync.
|
||||
|
||||
### Peer Protocol
|
||||
|
||||
Potential endpoints:
|
||||
|
||||
```text
|
||||
GET /api/sync/summary
|
||||
GET /api/sync/events?since=<cursor>
|
||||
POST /api/sync/events
|
||||
GET /api/sync/blobs/:digest
|
||||
POST /api/sync/blobs
|
||||
POST /api/sync/resolve-conflict
|
||||
```
|
||||
|
||||
### Conflict Visibility
|
||||
|
||||
Conflicts should become first-class Fusion objects:
|
||||
|
||||
- Shown in the dashboard
|
||||
- Resolvable by user or agent
|
||||
- Optionally converted into `FN-*` tasks
|
||||
- Include both versions and proposed resolution
|
||||
|
||||
## Dolt vs Fusion-Native Sync
|
||||
|
||||
### Dolt Advantages
|
||||
|
||||
- Existing versioned SQL system
|
||||
- Built-in diff/merge/push/pull
|
||||
- Strong data history
|
||||
- Good for auditable relational datasets
|
||||
- Mature conceptual model
|
||||
|
||||
### Dolt Disadvantages for Fusion
|
||||
|
||||
- Heavy runtime dependency
|
||||
- Not SQLite-compatible
|
||||
- Requires major persistence refactor
|
||||
- Does not handle Fusion domain conflicts automatically
|
||||
- Does not solve file/blob sync cleanly
|
||||
- Harder npm distribution story
|
||||
- Risky for local CLI UX
|
||||
|
||||
### Fusion-Native Advantages
|
||||
|
||||
- Keeps current SQLite
|
||||
- Minimal disruption
|
||||
- Tailored conflict semantics
|
||||
- Can sync only the right tables
|
||||
- Easier dashboard integration
|
||||
- Easier to bundle and test
|
||||
- Works with current `.fusion/` layout
|
||||
- Can evolve incrementally
|
||||
|
||||
### Fusion-Native Disadvantages
|
||||
|
||||
- More custom code
|
||||
- Conflict logic must be carefully designed
|
||||
- Sync cursor correctness is hard
|
||||
- Requires robust test coverage
|
||||
- More engineering effort than delegating to an existing system
|
||||
|
||||
However, Fusion’s domain is specialized enough that custom sync semantics are likely unavoidable either way.
|
||||
|
||||
## Decision
|
||||
|
||||
Do not switch to Beads.
|
||||
|
||||
Do not replace SQLite with Dolt yet.
|
||||
|
||||
Build native sync first.
|
||||
|
||||
Recommended phased plan:
|
||||
|
||||
1. **Classify all tables**
|
||||
- synced
|
||||
- append-only
|
||||
- local-only
|
||||
- encrypted/explicit
|
||||
- blob-backed
|
||||
2. **Add sync event log**
|
||||
- append-only
|
||||
- origin node
|
||||
- sequence/cursor
|
||||
- entity revision
|
||||
3. **Implement task/settings sync first**
|
||||
- tasks
|
||||
- task documents
|
||||
- settings
|
||||
- activity log
|
||||
4. **Add blob sync**
|
||||
- content-addressed task files
|
||||
5. **Add dashboard conflict UI**
|
||||
- task conflicts
|
||||
- settings conflicts
|
||||
- agent-assisted resolution
|
||||
6. **Prototype Dolt separately**
|
||||
- feature flag or branch only
|
||||
- measure install size, query compatibility, performance, and conflict ergonomics
|
||||
|
||||
Final recommendation:
|
||||
|
||||
> Keep SQLite as Fusion’s embedded source of truth. Build a Fusion-native sync layer. Treat Dolt as an optional future backend or audit/export target. Treat Beads as product inspiration, not infrastructure.
|
||||
Reference in New Issue
Block a user