Skip to content

Add manager save version migrations and profile metadata#16

Open
DaKongOlta wants to merge 1 commit into
mainfrom
codex/add-manager_save_version-and-migrate-data
Open

Add manager save version migrations and profile metadata#16
DaKongOlta wants to merge 1 commit into
mainfrom
codex/add-manager_save_version-and-migrate-data

Conversation

@DaKongOlta

@DaKongOlta DaKongOlta commented Feb 17, 2026

Copy link
Copy Markdown
Owner

Summary

  • add a dedicated MANAGER_SAVE_VERSION constant and persist it with manager saves
  • introduce a migration pipeline in normalizeManagerState to backfill facilities and sponsor slots while logging issues
  • include manager version metadata in profile export/import and validate save compatibility during import

Testing

  • not run (project has no automated tests)

Codex Task

Summary by Sourcery

Introduce versioned manager save handling with migration support and propagate manager metadata through profile export/import.

Enhancements:

  • Add a manager save version constant and store it alongside manager state.
  • Add a migration pipeline during manager state normalization to backfill and sanitize facilities and sponsor data across versions.
  • Include sponsors as a structured part of manager team state with corresponding sanitization.
  • Embed manager version metadata in profile snapshots and propagate it through import/export, including user-facing import status messaging.
  • Strengthen manager state persistence by ensuring valid version fields before saving and cloning state defensively for profile operations.

@sourcery-ai

sourcery-ai Bot commented Feb 17, 2026

Copy link
Copy Markdown

Reviewer's Guide

Introduces a versioned manager save format with a migration pipeline, extends manager state normalization to handle facilities and sponsors robustly, and enriches profile export/import with manager metadata and compatibility checks.

Sequence diagram for profile import and manager save version migration

sequenceDiagram
  actor User
  participant FileInput
  participant App
  participant applyProfileSnapshot
  participant ManagerNormalizer as normalizeManagerState
  participant MigrationPipeline as MANAGER_MIGRATIONS

  User->>FileInput: Select profile file
  FileInput-->>App: FileReader result (JSON string)
  App->>App: JSON.parse(reader.result)
  App->>applyProfileSnapshot: snapshot

  applyProfileSnapshot->>applyProfileSnapshot: validate snapshot object
  applyProfileSnapshot->>applyProfileSnapshot: parse managerMeta.saveVersion
  applyProfileSnapshot->>applyProfileSnapshot: fallback to snapshot.manager.saveVersion
  applyProfileSnapshot->>applyProfileSnapshot: clamp and compare to MANAGER_SAVE_VERSION
  alt incomingSaveVersion > MANAGER_SAVE_VERSION
    applyProfileSnapshot-->>App: throw Error(incompatible save version)
    App-->>User: showSettingsNotice(error, danger)
  else compatible save version
    applyProfileSnapshot->>applyProfileSnapshot: warn if manager version differs from default
    applyProfileSnapshot->>ManagerNormalizer: normalizeManagerState(snapshot.manager)
    ManagerNormalizer->>ManagerNormalizer: deep clone working state
    ManagerNormalizer->>ManagerNormalizer: determine saveVersion
    ManagerNormalizer->>MigrationPipeline: applyMigrations(working, saveVersion)
    MigrationPipeline-->>ManagerNormalizer: migrated state
    ManagerNormalizer-->>applyProfileSnapshot: normalized ManagerState

    applyProfileSnapshot->>applyProfileSnapshot: ensureFreeAgentPool()
    applyProfileSnapshot->>applyProfileSnapshot: restore gp, ui, raceSettings
    applyProfileSnapshot-->>App: info {version, managerSaveVersion, managerVersion}

    App->>App: build label with profile and managerSaveVersion
    App-->>User: showSettingsNotice(label, success)
  end
Loading

Class diagram for updated manager state, sponsors, and profile metadata

classDiagram
  class ManagerState {
    number version
    number saveVersion
    number seasonYear
    number week
    string selectedTeam
    Map~string,TeamState~ teams
    DriverAgent[] freeAgents
  }

  class TeamState {
    string team
    number budget
    Upgrades upgrades
    Facilities facilities
    Sponsors sponsors
    Contract[] roster
    number form
  }

  class Upgrades {
    number engine
    number aero
    number systems
  }

  class Facilities {
    number engine
    number aero
    number systems
  }

  class Sponsors {
    string[] primary
    string[] secondary
    string[] partners
  }

  class DriverAgent {
    string driver
    number morale
    number askingSalary
  }

  class Contract {
    string driver
    number salary
    number length
  }

  class ProfileSnapshot {
    string version
    string exportedAt
    ManagerMeta managerMeta
    ManagerState manager
    GpSnapshot gp
    UiSnapshot ui
    RaceSettingsSnapshot raceSettings
  }

  class ManagerMeta {
    number version
    number saveVersion
  }

  class GpSnapshot {
    boolean active
    number raceIndex
    TableEntry[] table
  }

  class UiSnapshot {
  }

  class RaceSettingsSnapshot {
  }

  class ManagerNormalizer {
    normalizeManagerState(state)
  }

  class MigrationPipeline {
    MANAGER_SAVE_VERSION
    MANAGER_MIGRATIONS
    applyMigrations(state, saveVersion)
  }

  ManagerState "1" -- "many" TeamState : teams
  TeamState "1" -- "1" Upgrades : upgrades
  TeamState "1" -- "1" Facilities : facilities
  TeamState "1" -- "1" Sponsors : sponsors
  ManagerState "1" -- "many" DriverAgent : freeAgents
  ManagerState "1" -- "1" ManagerNormalizer : normalizedBy
  ManagerNormalizer "1" -- "1" MigrationPipeline : uses
  MigrationPipeline "1" --> "1" ManagerState : migrates
  ProfileSnapshot "1" -- "1" ManagerState : manager
  ProfileSnapshot "1" -- "1" ManagerMeta : managerMeta
  ProfileSnapshot "1" -- "1" GpSnapshot : gp
  ProfileSnapshot "1" -- "1" UiSnapshot : ui
  ProfileSnapshot "1" -- "1" RaceSettingsSnapshot : raceSettings
Loading

File-Level Changes

Change Details Files
Introduce a dedicated manager save version and persist it with manager state.
  • Add MANAGER_SAVE_VERSION constant alongside PROFILE_EXPORT_VERSION.
  • Include saveVersion in newly created manager state objects.
  • Ensure persistManagerState stamps managerState with current saveVersion and a valid manager version before saving.
script.js
Add migration and normalization logic for manager saves, including facilities and sponsors.
  • Define createDefaultSponsors and sanitizeSponsors helpers and wire them into default manager state creation and normalization.
  • Add MANAGER_MIGRATIONS map with initial migration to backfill teams, facilities, and sponsor slots while logging inconsistencies.
  • Refactor normalizeManagerState to deep-clone incoming state, derive and clamp saveVersion and manager version, run migrations up to MANAGER_SAVE_VERSION, and consistently use the working copy for teams, selection, and free agents.
script.js
Enrich profile export/import with manager metadata and compatibility validation.
  • Update collectProfileSnapshot to clone managerState safely, normalize manager version/saveVersion, and emit a managerMeta block plus normalized manager snapshot.
  • Extend applyProfileSnapshot to parse managerMeta, validate incoming saveVersion against runtime support, log manager version mismatches, and return import info including manager versions.
  • Adjust profile import UI handler to incorporate manager save version into the success label when available.
script.js

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • There is quite a bit of duplicated logic for parsing and normalizing numeric versions (manager version, saveVersion) across normalizeManagerState, collectProfileSnapshot, and applyProfileSnapshot; consider extracting a small helper (e.g. parseIntOrNaN / normalizeVersionNumber) to keep the behavior consistent and easier to change.
  • The migration functions in MANAGER_MIGRATIONS currently both mutate the passed-in state and return it, but the return value is ignored in normalizeManagerState; either rely solely on mutation (and drop the return state) or have normalizeManagerState use the returned value to make the intent clearer.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- There is quite a bit of duplicated logic for parsing and normalizing numeric versions (manager version, saveVersion) across `normalizeManagerState`, `collectProfileSnapshot`, and `applyProfileSnapshot`; consider extracting a small helper (e.g. `parseIntOrNaN` / `normalizeVersionNumber`) to keep the behavior consistent and easier to change.
- The migration functions in `MANAGER_MIGRATIONS` currently both mutate the passed-in state and return it, but the return value is ignored in `normalizeManagerState`; either rely solely on mutation (and drop the `return state`) or have `normalizeManagerState` use the returned value to make the intent clearer.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 15b195f2e4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread script.js
}
}

working.saveVersion = MANAGER_SAVE_VERSION;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject unsupported manager save versions

When saveVersion is newer than MANAGER_SAVE_VERSION, this code only warns and then forcefully rewrites working.saveVersion to the current runtime version. In a downgrade scenario (opening localStorage written by a newer app), unknown fields are discarded during normalization and the next persistManagerState() call can permanently overwrite the newer save with downgraded data, so this path should fail fast like applyProfileSnapshot does for profile imports.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant