v3.0.0-rc.1 Cannot Detect or Migrate v2 Estates
Bug Report: v3.0.0-rc.1 Cannot Detect or Migrate v2 Estates
Summary
synthesist v3.0.0-rc.1 fails to detect v2 Automerge-based estates, reporting them as "fresh" instead of "2.x". This prevents all v2-to-v3 migration workflows from functioning. The issue occurs regardless of estate structure (compacted vs. with incremental changes) or directory layout (isolated vs. in-repo).
Environment
- v3 binary:
v3.0.0-rc.1(darwin-arm64) - v2 binary tested:
v2.5.2(darwin-arm64, for comparison) - Platform: macOS (Apple Silicon)
- Estate size: ~9530 claims, 16 trees, 19 sessions (production-scale)
Expected Behavior
When synthesist v3.0.0-rc.1 encounters a v2 estate (containing genesis.amc, snapshot.amc, and config.toml with schema_version = "0.1"), it should:
synthesist migrate status→ report"current_version": "2.x"with pending migrationssynthesist migrate v2-to-v3 --dry-run→ plan the migration without errorsynthesist migrate run→ execute thev2.x-to-v3.0.0-pre.1migrationsynthesist status→ read v2 claims (at least in read-only mode, if not full migration)
Actual Behavior
v3 reports the v2 estate as "fresh" (v3 native) in all scenarios:
$ synthesist migrate status
{"current_version":"fresh","migrated_at":null,"pending":[],"status":"store is at latest"}
$ synthesist migrate v2-to-v3 --dry-run
error: no applicable migration: store is fresh -- no migration needed.
Run `synthesist migrate list` to see available migrations, or `synthesist migrate status`
to check the current schema version.
$ synthesist status
{"claim_counts":{},"ready_tasks":[],"sessions":[],"total_claims":0,"trees":[]}Impact: All v2-to-v3 migration paths are blocked. Users cannot migrate production estates.
Reproduction
We tested three different scenarios. All exhibit the same failure:
Scenario 1: Compacted v2 Estate (Isolated Directory)
# Copy production v2 estate (compacted, no changes/ directory)
mkdir -p ~/tmp/synthesist-v3-test
cp -r /path/to/v2/estate/claims ~/tmp/synthesist-v3-test/
# Verify v2.5.2 can read it
~/.local/share/mise/installs/http-synthesist/2.5.2/synthesist \
--data-dir ~/tmp/synthesist-v3-test status
# → {"total_claims":9530,"trees":[...],"sessions":[...]} ✓ Works
# Attempt v3 migration
synthesist --data-dir ~/tmp/synthesist-v3-test migrate status
# → {"current_version":"fresh",...} ✗ BrokenEstate structure:
claims/
├── config.toml # schema_version = "0.1"
├── genesis.amc # 122 bytes
└── snapshot.amc # 2.4 MB (compacted)Scenario 2: v2 Estate with Incremental Changes
# Reconstruct pre-compaction v2 estate from git history
# (estate with 150 incremental .amc files in claims/changes/)
mkdir -p ~/tmp/v2-pre-compact/claims/changes
# ... extract genesis.amc, snapshot.amc, config.toml, and changes/*.amc from git ...
# Verify structure
ls ~/tmp/v2-pre-compact/claims/
# config.toml genesis.amc snapshot.amc changes/
ls ~/tmp/v2-pre-compact/claims/changes/ | wc -l
# 150
# Attempt v3 migration
synthesist --data-dir ~/tmp/v2-pre-compact migrate v2-to-v3 --dry-run
# → error: no applicable migration: store is freshEstate structure:
claims/
├── changes/
│ ├── 06c03c5a...aaeb0.amc # 7.9 MB
│ ├── 095db27c...c0ec7f.amc # 8.7 MB
│ └── ... (148 more)
├── config.toml
├── genesis.amc
└── snapshot.amcScenario 3: In-Repo Worktree
# Create git worktree with v3 binary, pointing at v2 estate
cd /path/to/repo
git worktree add .worktrees/v3-test -b v3-test
cd .worktrees/v3-test
synthesist migrate status
# → {"current_version":"fresh",...} ✗ Broken
# Verify v2.5.2 still works in same location
~/.local/share/mise/installs/http-synthesist/2.5.2/synthesist status
# → {"total_claims":9530,...} ✓ WorksAdditional Evidence
Export/Import Path Also Fails
# Export from v2
~/.local/share/mise/installs/http-synthesist/2.5.2/synthesist \
--data-dir ~/tmp/synthesist-v3-test export > v2-export.json
ls -lh v2-export.json
# -rw-r--r-- 14M v2-export.json
# Import into fresh v3 estate
mkdir -p ~/tmp/v3-import && cd ~/tmp/v3-import
synthesist init
synthesist import ../synthesist-v3-test/v2-export.json
# → {"imported":0,"skipped":9530}
synthesist status
# → {"total_claims":0,...}v3 skips all 9530 claims from the v2 export without error, resulting in an empty estate.
Version Detection Always Returns "fresh"
Even with all v2 artifacts present, migrate status never reports "current_version": "2.x":
# Fresh v3 init (expected)
synthesist init && synthesist migrate status
# → "current_version":"fresh" ✓ Correct
# v2 compacted estate (unexpected)
synthesist --data-dir ~/tmp/synthesist-v3-test migrate status
# → "current_version":"fresh" ✗ Wrong (should be "2.x")
# v2 estate with changes/ (unexpected)
synthesist --data-dir ~/tmp/v2-pre-compact migrate status
# → "current_version":"fresh" ✗ Wrong (should be "2.x")Analysis
v3's version detection logic does not appear to check for v2 indicators:
- Does not check
config.toml: The file containsschema_version = "0.1"(v2 format), but v3 ignores it - Does not detect
.amcfiles: Presence ofgenesis.amc,snapshot.amc, orchanges/*.amcis not recognized as v2 - Defaults to "fresh": When no v3-specific markers (e.g.,
claims/_schema.json,claims/*/log.jsonl) are found, v3 assumes a fresh estate rather than checking for v2 files
Expected Detection Logic
v3 should detect v2 estates by checking for:
claims/config.tomlwithschema_version = "0.1"(v2 marker), OR- Presence of
claims/genesis.amc+claims/snapshot.amc(Automerge files), OR claims/changes/*.amc(incremental change files)
If any of these are found, migrate status should return "current_version": "2.x" and make the v2.x-to-v3.0.0-pre.1 migration available.
Registered Migration
v3 knows about the v2-to-v3 migration:
$ synthesist migrate list
{
"migrations": [{
"description": "Translate v2 Automerge .amc claims to v3 per-asserter JSON-LD logs",
"from_version": "2.x",
"name": "v2.x-to-v3.0.0-pre.1",
"to_version": "3.0.0-pre.1"
}]
}But it never triggers because version detection fails to identify v2 estates as "2.x".
Impact
Severity: Blocker for v3 adoption
- Users with production v2 estates cannot migrate to v3
- The RC documentation describes v2-to-v3 migration as a supported path, but it is non-functional
- No workaround exists (export/import path also fails)
- All v3 features are inaccessible to existing v2 users until this is fixed
Recommended Fix
Update synthesist migrate status and the migration runner's version detection to:
- Check for
claims/config.tomland parseschema_versionfield - If
schema_version = "0.1", report"current_version": "2.x" - If
.amcfiles exist but noconfig.toml, infer v2 format - Only default to "fresh" if no v2 or v3 markers are found
This would unblock the registered v2.x-to-v3.0.0-pre.1 migration and allow the migrate run / migrate v2-to-v3 commands to execute.
Test Case for Validation
Once fixed, the following should succeed:
# Given: a v2 estate with config.toml (schema_version = "0.1"), genesis.amc, snapshot.amc
synthesist migrate status
# → "current_version": "2.x", pending: ["v2.x-to-v3.0.0-pre.1"]
synthesist migrate v2-to-v3 --dry-run
# → plan output (no error)
synthesist migrate v2-to-v3
# → successful migration, estate converted to v3 format
synthesist migrate status
# → "current_version": "3.0.0-pre.1" or laterReporter Context
We're testing v3.0.0-rc.1 for production adoption in a zeel-dev monorepo with 9530 claims accumulated over 2+ years. We performed isolated testing (Phase 1) in temporary directories and worktrees to avoid affecting the production estate. Happy to provide additional logs, estate samples, or test any patches.
Tested binaries:
- v2.5.2:
~/.local/share/mise/installs/http-synthesist/2.5.2/synthesist(checksum: blake3:b1ac479e95...) - v3.0.0-rc.1: mise-installed from GitLab package generic/synthesist/v3.0.0-rc.1/synthesist-darwin-arm64 (checksum: blake3:21c1d7a22e...)