- Push optimization: inline content in tree (O(n) → O(1))
- Pull optimization: GraphQL batch fetch (O(n) → O(1))
- Uses GitHub GraphQL API with aliases to fetch multiple files in 1 request
- 100 files = 1 API call (vs 100+ REST API calls before)
- Replaced CDN + Blob API fallback with reliable GraphQL approach
- Rate limit detection and backoff
- Skip push when no changes
- Timestamp-based sync - replaced vector clocks with simple lastModified comparison
- Removed vectorClock from LocalSyncState, Manifest, and all category types
- Replaced compareVectorClocks with compareTimestamps (lastSyncedAt vs updatedAt)
- Removed concurrent state detection (now uses last-write-wins)
- Bumped manifest schema to 3.0
- Checksum-based change detection
- Manifest structure for tracking files
- Tombstones for deletion tracking
- Per-file granularity (not repo-level overwrite)
- Pull-then-push flow (when remote is newer, pull first then push local changes)
- Consolidate logger files - unified logging system with ports & adapters pattern
- Consolidate encoding utilities -
packer.ts&item-packer.tshave identicalcalculateChecksum(),uint8ArrayToBase64(),base64ToUint8Array()- Created
src/shared/encoding-utils.tswith shared encoding functions
- Created
- Extract error handling pattern - pattern
error instanceof Error ? error.message : String(error)repeated in 5+ files- Created
src/shared/error-utils.tswithgetErrorMessage(),getErrorStack(),toError(),isError()
- Created
- Consolidate sync result processing -
background-sync.ts&sync-handler.tshave duplicate write/persist logic- Created
src/shared/sync-result-handler.tswithwritePulledData(),persistLocalState(),processSyncResult()
- Created
- Unify error classes - 6 error classes (
RepoApiError,SyncError,EncryptionError,PackerError,ItemPackerError,MergeError) unified- Created
src/shared/errors.tswithAppErrorbase class and all domain error classes
- Created
- Centralize retry configuration - retry constants scattered across
fetch.ts,constants.ts,retry.ts- Created
src/shared/retry-config.tswithCONFLICT_RETRYandAPI_RETRYconfig objects, pluscalculateBackoff()andsleep()utilities
- Created
- Extract plugin state validation -
if (!state.config || !state.engine)pattern in 3+ files- Created
src/plugin/validation.tswith type guards:hasConfig(),isPluginReady(),isContinuousSyncReady(),isFullyInitialized()
- Created
- Move CryptoOptions type - currently in
operations/types.ts, should be insrc/types/crypto.ts- Created
src/types/crypto.tswithCryptoOptionsandPassphraseOptiontypes, re-exported fromoperations/types.tsfor backward compatibility
- Created
- Review helper duplication -
engine/helpers.tsvsoperations/helpers.tsmay have overlapping functionality- Reviewed: No duplication found.
engine/helpers.tshandles orchestration (checksums, pull/push options),operations/helpers.tshandles low-level operations (tombstones, manifest, context). Complementary, not duplicative.
- Reviewed: No duplication found.
- Consider API client base class -
http-client.tsandgraphql-client.tshave similar initialization patterns- Reviewed: Not worth abstracting. Only ~15 lines similar (config fields). Different APIs (REST vs GraphQL), different methods, different URL patterns. Base class would add complexity without benefit.
- Architecture violation: shared module imported plugin state -
sync-result-handler.tsimportedgetPluginState()from plugin- Refactored
persistLocalState()to accept engine as parameter, callers now handle state updates locally
- Refactored
- Dead code: duplicate
getCryptoOptions- Unused function inengine/types.tsduplicatedbuildCryptoOptionsinengine/helpers.ts- Removed unused
getCryptoOptionsfromengine/types.ts
- Removed unused
- Dead code: unused
removeItemsWithTombstones- Function intombstone.tswas never imported- Removed unused function
-
src/crypto/index.ts- barrel export, check if needed for external API -
src/data/directory-loader.ts -
src/data/parsers.ts -
src/sync/index.ts- barrel export, check if needed for external API -
src/sync/merge/- entire directory (index.ts, json-merge.ts, jsonl-merge.ts, types.ts, utils.ts) -
src/sync/operations/index.ts- barrel export, check if needed for external API -
src/sync/packer.ts
-
@opencode-ai/plugin- verify if peer/runtime dependency -
eslint-plugin-import- remove if not used
-
deriveKeyinsrc/crypto/encrypt.ts -
generateSaltinsrc/crypto/encrypt.ts -
hashPassphraseinsrc/crypto/encrypt.ts -
verifyPassphraseinsrc/crypto/encrypt.ts
-
ensureDirinsrc/data/file-io.ts -
createInitialConfiginsrc/data/state.ts
-
fileLoggerinsrc/logging/file-logger.ts -
syncDebuginsrc/logging/file-logger.ts -
startOperationinsrc/logging/file-logger.ts
-
buildLocalChecksumsinsrc/sync/engine/helpers.ts -
MAX_CONFLICT_RETRIESinsrc/sync/engine/retry.ts - Multiple re-exports in
src/sync/engine/index.ts
-
isTombstoneExpiredinsrc/sync/tombstone.ts -
isItemTombstonedinsrc/sync/tombstone.ts -
getItemsToDeleteinsrc/sync/tombstone.ts -
addTombstonere-export insrc/sync/tombstone.ts -
mergeTombstonesFilesre-export insrc/sync/tombstone.ts -
filterExpiredTombstonesFilere-export insrc/sync/tombstone.ts
-
maybeEncryptinsrc/sync/operations/crypto-helpers.ts -
maybeDecryptinsrc/sync/operations/crypto-helpers.ts -
parseEncryptedDatainsrc/sync/operations/crypto-helpers.ts -
createManifestinsrc/sync/operations/helpers.ts -
getLockFilePathinsrc/sync/local-lock.ts -
readLockinsrc/sync/local-lock.ts -
withLocalLockinsrc/sync/local-lock.ts
-
isErrorinsrc/shared/error-utils.ts -
processSyncResultinsrc/shared/sync-result-handler.ts -
AppError,PackerError,SyncError,MergeError,RepoNotFoundErrorclasses
-
SYNC_CATEGORIESinsrc/types/categories.ts -
isSyncCategoryinsrc/types/categories.ts -
DEFAULT_TOMBSTONE_GRACE_DAYS,CURRENT_SCHEMA_VERSION,createEmptyTombstonesFileinsrc/types/index.ts -
getCategoryForPathinsrc/types/paths.ts
-
LoadedData,LoadErrorinsrc/data/index.ts -
PluginStateinsrc/plugin/index.ts -
MergeConflict,StateProviderinsrc/shared/ -
SyncActioninsrc/sync/engine/routing.ts -
ItemDiffinsrc/sync/item-packer.ts -
CryptoOptionsduplicate exports -
StorageFiles,OperationContext,ChunkDownloadResult,SyncResultinsrc/sync/operations/types.ts -
CategoryInfo,AdvisoryLock,TombstonesFile,PackedCategory,LogLevelinsrc/types/
Note: Many "unused" exports may be intentional public API for package consumers. Review before removing.
- Log when local files are overwritten by remote
- Log when remote files are overwritten by local
- Add --force-local and --force-remote CLI flags for manual resolution
- Show warning on config file overwrites
- Add conflict counter to sync summary
- Add exponential backoff retry logic for GitHub API calls (already implemented in fetch.ts)
- Batch file fetches to reduce API call frequency (GraphQL batch fetch)
- ETag caching for manifest fetch (saves bandwidth, not API calls)
- GitHub webhook for push notifications (eliminate polling)
- Compression improvements for large messages
- Parallel category processing during sync