Skip to content

Upgrade backup should include dataDir (database files not backed up) #502

@zylos01

Description

@zylos01

Problem

The 7-step upgrade pipeline (cli/lib/upgrade.js) creates a backup in Step 2 (step2_backup), but only backs up skillDir (~/.claude/skills/<component>/). The dataDir (~/zylos/components/<component>/) is not included in the backup.

This means database files (e.g., recruit.db), config files, and other runtime data in the component's data directory are not preserved before an upgrade.

Impact

During a Recruit ATS upgrade (v0.2.7 → v0.2.8), the migration script contained a bug that triggered CASCADE DELETE on the production SQLite database, destroying all candidate, role, evaluation, and interview data. Because dataDir was not backed up, the data was unrecoverable.

  • 35 candidates lost
  • 108 evaluations lost
  • 28 internal interviews + 160 messages lost
  • No backup available for rollback

Root Cause

In upgrade.js line 387-399, step2_backup only copies ctx.skillDir:

function step2_backup(ctx) {
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
  const backupDir = path.join(ctx.skillDir, '.backup', timestamp);
  copyTree(ctx.skillDir, backupDir, { excludes: ['node_modules', '.backup', '.zylos'] });
  // ...
}

ctx.dataDir is defined in createContext() (line 321) but never used in the backup step.

Proposed Fix

Add dataDir backup to step2_backup:

  1. Copy dataDir contents (especially .db, .json, .sqlite files) to the backup directory alongside the skill backup
  2. Include dataDir in the rollback path so failed upgrades can restore data
  3. Consider backing up only data files (not logs) to keep backup size reasonable

Additional Context

  • dataDir is already referenced in uninstall and info commands (component.js)
  • The cleanup logic (cleanOldBackups) already retains only the latest backup, so storage impact is minimal
  • Components with SQLite databases (recruit, comm-bridge, scheduler) are especially vulnerable without data backup

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions