feat(events): migrate event store to eventcore 0.9 with eventcore-fs #117
No reviewers
Labels
No labels
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Slipstream/emc!117
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/eventcore-fs-migration"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Replaces EMC's bespoke filesystem event log (
model/events/v1/*.json, a customparent-linked event DAG with hand-rolled conflict detection) and the
external SQLite operational store with a single committed, git-mergeable
eventcore_fs::FileEventStorerooted atmodel/events. Upgrades toeventcore 0.9 and drops
eventcore-sqlite.eventcore = 0.9, addeventcore-fs,eventcore-types;remove
eventcore-sqlite.executeagainst aFileEventStore; onlymodel/events/events/*.jsonl(immutable per-transaction files) is committed.The store writes its own
.gitignore/.gitattributes;tmp/,index/,.eventcore/,locks/, and.lockstay machine-local. No more SQLite cacheoutside the repo, and no more custom JSON export.
ProjectedModel::from_eventsnow folds the persistedEmcEventstream read back from the store; Lean/Quint/review artifacts areregenerated exactly as before.
workflow/slice) maps onto eventcore-fs's structural fork (two transactions
extending a stream from the same base version).
emc list conflictsreportsforks;
emc resolve conflict <stream-id> <branch-transaction-id>reconciles bykeeping the chosen branch (a recorded N-parent merge transaction).
EmcEvent::WorkflowConnectedandEmcEvent::WorkflowTransitionEvidenceAddedwere lossy relative to the richexported payloads (they dropped
source_control/target_view). Both are nowenriched so navigation transitions survive the store round-trip — this was the
whole event type that previously only round-tripped through the JSON log.
ExportedEventenvelope/DAG/bespoke-conflict code whilekeeping
ExportedEventBodyand its codecs (still used on the write path andinside
SliceFactEvent).Rationale
eventcore 0.9 ships
eventcore-fs, a file-based, git-mergeable event store thatprovides exactly the offline-collaboration merge semantics EMC had been
approximating with its own committed JSON DAG. Adopting it removes a whole
parallel persistence layer (the SQLite operational store plus the custom export
format and conflict detector), so there is one source of truth that both
validates commands (eventcore command invariants) and drives projection, and the
merge story is owned by the library.
Verification
cargo fmt --all --check,cargo clippy --all-targets --all-features -- -D warnings,cargo build, and the copyright-headers check all pass.cargo testsuite is green, including the cucumber and MCP integrationsuites.
and reconciles it via the chosen branch; the existing
check_rebuilds_*suiteverifies
emc checkregenerates every artifact family from the store.🤖 Generated with Claude Code
This PR migrates the event store to use
eventcore-fsinstead of a custom filesystem event log and SQLite operational store. The changes appear well-structured, but careful attention should be paid to the handling of new fields in events and the transition from SQLite to ensure no loss of functionality. Overall, the migration seems beneficial for simplifying the persistence layer.Walkthrough
/model/directory, which is relevant for the new event store setup.eventcore-fsand removedeventcore-sqlite. This is a significant change that requires ensuring all functionalities are preserved.EmcEventvariants with additional fields. This change requires ensuring these fields are correctly populated and used.eventcore-fs. This involves changes in how events are stored and retrieved, impacting the entire event handling logic.LLM usage and cost
Estimated total USD: $0.131804 via https://api.openai.com and https://api.openai.com
🟡 Warning: The
eventcoredependency version has been updated from 0.8.0 to 0.9.0. Ensure that all breaking changes in the new version are handled appropriately in the codebase.🟡 Warning: The
eventcore-sqlitedependency has been removed and replaced witheventcore-fs. Ensure that all functionalities provided byeventcore-sqliteare now correctly handled byeventcore-fs.🟡 Warning: The
EmcEvent::WorkflowTransitionEvidenceAddedandEmcEvent::WorkflowConnectedevents have been enriched withsource_controlandtarget_viewfields. Ensure that these fields are correctly populated and utilized throughout the application.🟡 Warning: Lines 454–458: The
ConnectWorkflowCommandnow includessource_controlandtarget_view. Ensure these fields are correctly handled in all relevant parts of the application.@ -91,751 +73,355 @@ pub(crate) fn lock_project_runtime(project_root: &Path) -> Result<ProjectRuntimeOk(ProjectRuntimeLock { file })🟡 Warning: The
ensure_event_storefunction replaces the previous SQLite cache provisioning. Ensure that this new implementation correctly initializes the event store as expected.New commits pushed, approval review dismissed automatically according to repository settings
The PR migrates the event store to use
eventcore_fs::FileEventStore, removing the custom filesystem event log and SQLite store. The changes appear well-structured, but ensure that all directory references and test setups are correctly updated.Walkthrough
Δ since
c3e332a:src/core/project.rs:
model/events/v1directory. Ensure no dependencies on this directory remain.tests/mcp_stdio.rs:
create_slice_update_forkinstead ofcreate_concurrent_slice_update_conflict. Verify the new function sets up the test scenarios correctly.tests/verify_project.rs:
WorkflowReadinessDeclaredevents, indicating a change in verification logic. Ensure all necessary verification steps are still covered.LLM usage and cost
Estimated total USD: $0.039519 via https://api.openai.com and https://api.openai.com
🟡 Warning: Lines 603–607: The function
create_slice_update_forkreplacescreate_concurrent_slice_update_conflict. Ensure that the new function accurately reflects the intended test setup and that all necessary conditions for the test are met.Addressing the
auto_review🟡 warnings (both reviews approved; these are advisory "ensure X" notes). Each is verified:WorkflowTransitionEvidenceAdded/WorkflowConnectedenriched withsource_control/target_view— these fields were the reason the migration needed them:EmcEventwas lossy vs the old exported payload, so navigation transitions would have lost their endpoints. They are populated in the commands (ConnectWorkflowCommand,AddWorkflowFactCommand::to_event) from the sourceWorkflowConnection/WorkflowTransitionEvidenceRecord, and reconstructed inProjectedModel::apply_event(usingWorkflowTransitionRecord::new_with_navigation_endpoints/WorkflowTransitionEvidenceRecord::new_with_navigation_endpoints). Coverage:check_rebuilds_workflow_transition_evidence_from_exported_eventsandcheck_rebuilds_workflow_connections_from_exported_eventsrebuild artifacts from the store and assert the navigation endpoints survive the round-trip;internal_semantic_testsasserts the new fields serialize.ConnectWorkflowCommandsource_control/target_view handling — same as (1); the command copies them fromconnection.source_control()/target_view()and the projection emits navigation transitions only when both are present.ensure_event_storereplacing SQLite provisioning — it opens (creating if absent) theFileEventStoreatmodel/events, which materializesevents/+ git metadata. Verified byevent_store_lives_inside_the_project_repositoryandinit_recovers_artifact_only_project_by_exporting_initial_event.eventcore 0.8 → 0.9 — the command API used here (
execute,CommandLogic::{handle,apply},NewEvents,require!,RetryPolicy) is unchanged across 0.9; the whole suite compiles and 423/423 tests pass.eventcore-sqlite→eventcore-fs— SQLite was a derived validation cache; its functionality (command validation + projection input + conflict detection) is now served by the single committedFileEventStore: commandsexecuteagainst it, projection readsEmcEventback viaread_all_emc_events, and conflicts use eventcore-fs forks (list_forks/reconcile). Covered by thecheck_rebuilds_*suite and the two-replica fork/reconcile tests.create_slice_update_forktest helper — it builds a genuine eventcore-fs fork by cloning the project into a second replica (stripping replica-local store state so it mints a freshreplica_id), making divergentupdate slicecommits in each, and unioning the committed transactions — exactly how agit mergeof two offline clones produces a fork. The MCPlist_conflicts/resolve_conflicttools then operate on that real fork.Full
cargo nextest run(the CI test command) passes 423/423; clippy-D warningsand fmt are clean.