Skip to content

Community feature roadmap: 7 local mod-management features (F7→F1 by ROI) #243

Description

@Y4rd13

Context

Batch of feature ideas proposed by Nexus user ElDiablo59 (18 May 2026). All seven are local mod-management features that stay within the Nexus API policy — no mod-page content surfaced in-app, no auto-update. Each was checked against the actual code on both main and nexus-compliant before writing this roadmap (feasibility study, "no assumptions").

Feature numbers below are written F1..F7 (not #1..#7) on purpose, to avoid GitHub auto-linking them to unrelated issues/PRs.

Strategy

  • Build on nexus-compliant first → PR → claude[bot] review + CI gates → re-review until approved → cherry-pick PR to main.
  • Backend infra for all 7 is byte-identical across editions (verified empty git diff main..nexus-compliant on every relevant backend file) → backend changes cherry-pick cleanly.
  • Frontend host files diverge (SettingsPage.tsx, GameDetailPage.tsx, DashboardPage.tsx, Sidebar.tsx, router/index.tsx, types/api.ts, hooks/queries.ts, hooks/mutations.ts) → those edits are applied manually per branch, never merged (dual-release rule).
  • Scope: each feature ships complete in its PR (not MVP). The two research-heavy ones (F1 log formats, F4 framework version sources) get their deep technical investigation inside their own cycle.
  • Policy: all 7 are local-only. The only network call across the set is F4's read-only Nexus version lookup, which reuses the already-shipped self-update pattern.

Order (by ROI / risk) and tracking

  • F7 — Reverse dependency warning (backend already exists; frontend wiring)
  • F6 — Change / activity log (clone of DeployJournalEntry; emit at existing choke points)
  • F2 — Unified health / pre-launch check (reuses updates + drift + the existing Play gate)
  • F3 — Diagnostics export (export precedent from profiles; wire real version + specs)
  • F5 — Save game backups (clean deploy hook; save-path detection + real-copy service are greenfield)
  • F4 — Framework mod monitor (existence is easy; per-framework version detection is the hard part)
  • F1 — In-app mod error reader (log parsing fully greenfield; external/volatile formats)

Each feature gets its own design spec (docs/superpowers/specs/) → implementation plan → PR before any code is written for it.


F7 — Reverse dependency warning

Goal: before disabling/uninstalling a mod, warn the user which installed mods declare it as a requirement.

Verified — already exists:

  • GET /api/v1/games/{game}/install/installed/{mod_id}/dependents returns the installed mods that require the target — routers/install.py:267-311.
  • Schemas DependentModOut / DependentsResultschemas/install.py:127-135.
  • Requirement data persisted in NexusModRequirement (models/nexus.py:46), populated from the GraphQL modRequirements fragment via upsert_mod_requirements (services/nexus_helpers.py:149).

Verified — missing: zero references to dependents anywhere in frontend/src/. Toggle has no confirmation dialog; uninstall uses a generic ConfirmDialog. DisableConfirmDialog.tsx exposes a children slot for injecting a warning.

Acceptance criteria (full scope):

  • DependentsResult/DependentModOut added to types/api.ts; a useDependents query hook.
  • Pre-uninstall and pre-disable(toggle) check, in both list and card views, listing dependent mods (name + "View on Nexus").
  • Warning is overridable (confirm-to-proceed), not a hard block.
  • Handle data completeness: if a requiring mod's requirements were never synced, the check can under-report — decide whether to fetch on-demand.
  • Tests.

Open product decisions: warn-and-confirm vs hard-block; fetch missing requirement rows on-demand (API cost) vs cached-only.


F6 — Change / activity log

Goal: timestamped, scrollable history of meaningful actions (install, uninstall, enable, disable, update/download, deploy, undeploy).

Verified — building blocks:

  • DeployJournalEntry (models/install.py:67-77) is an exact structural precedent for an append-only timestamped log, read/processed at startup (main.py:56-63).
  • Every action is a single service function that already emits the human-readable summary line the feature wants: install_mod/uninstall_mod/toggle_mod (services/install_service.py:69/281/353, log lines ~:262/:349/:483), deploy/undeploy (services/vfs/deploy_service.py:439/227), create_and_start_download (services/download_service.py:40).
  • New tables are auto-created by create_db_and_tables() (database.py) — no column migration needed for a brand-new table.

Verified — missing: no structured/queryable action-history table exists (greenfield); today actions only hit unstructured rippermod.log.

Acceptance criteria (full scope):

  • ActivityLog model + a record_activity(...) helper called from all choke points.
  • Captures action, target mod, detail (counts/version), timestamp, status (success/failed/partial).
  • Read router (paginated, filterable by game) + schema.
  • Frontend view (page or Settings tab) + VirtualTable + query hook.
  • Retention/pruning policy (don't grow unbounded).
  • Undo where clean: enable⇄disable, deploy⇄undeploy, install→uninstall. Uninstall is not reversible (does shutil.rmtree + session.delete) — surface as non-undoable.
  • Tests.

Open product decisions: per-game vs app-wide view; new top-level page vs Settings tab; include endorse/track and the app-update download as logged actions?; retention policy; undo scope for v1.


F2 — Unified health / pre-launch check

Goal: one action that scans for the problems that most often break launch; optionally auto-runs on "Play".

Verified — building blocks:

  • A real game launcher already exists: Tauri launch_game (frontend/src-tauri/src/lib.rs:266) + handleLaunch with a pre-launch gate chain (frontend/src/pages/GameDetailPage.tsx:235,263) + Play button (:443). A health gate slots into handleLaunch.
  • Conflicts engine is the sibling pattern to mirror (services/conflicts/engine.py, routers/conflicts.py, ConflictsInbox.tsx).

Verified — signal availability:

  • (a) missing/disabled requirements: computable — InstalledMod.nexus_mod_id ↔ NexusModRequirement.required_mod_id + InstalledMod.disabled.
  • (c) version mismatches: reuse services/update_service.py + routers/updates.py.
  • (d) incomplete/failed installs: no status/failed flag on InstalledMod — use deployed=False on an enabled mod and/or detect_drift().missing > 0.
  • (b) "wrong directory": NOT directly computable today — VFS drift reports link integrity (missing/foreign), not layout correctness; needs new logic.

Acceptance criteria (full scope):

  • Aggregator endpoint (e.g. GET .../health) returning [{mod, problem_kind, severity, suggested_fix}] covering all four categories, including a concrete definition + implementation of the "wrong directory" check.
  • Frontend health panel/widget (mirror ConflictSummaryWidget/ConflictsInbox).
  • Optional pre-launch gate wired into handleLaunch (warn/abort).
  • Tests.

Open product decisions: precise definition of "wrong directory" (foreign/untracked files vs empty layout-transform vs other); auto-run-on-Play default; block vs warn.


F3 — Diagnostics / support export

Goal: one-click bundle: app logs + full mod list (names, versions, enabled, load order) + app/system/game-version info.

Verified — building blocks:

  • File-export precedent: profile export (services/profile_service.py:289) + frontend save() + writeTextFile (ProfileManager.tsx). Tauri dialog/fs/opener plugins present on both branches.
  • Data available: installed mods (InstalledModOut), load order (modlist_service.get_modlist_view), game version (services/game_version.py:12), app logs at data_dir/logs/rippermod.log (+ rotations) (main.py:18-38).

Verified — gaps:

  • Backend version is hardcoded/stale: FastAPI(version="0.1.0") (main.py:118); __APP_VERSION__ is frontend-only.
  • PCSpecs capture is unwired — model + POST /settings/specs/capture exist (models/settings.py:15-26, routers/settings.py:79-85) but nothing calls them and the backend does not auto-detect specs.
  • Binary .zip write needs fs:allow-write-file (capability currently only grants fs:allow-write-text-file).

Acceptance criteria (full scope):

  • Backend assembles a bundle (logs + a manifest with mods/versions/enabled/load-order + real app version + system specs incl. OS/CPU/RAM/GPU + game version).
  • Secret redaction: the bundle must never contain the Nexus API key or any secret.
  • Frontend export button + save dialog; capability addition if a .zip is used.
  • Real backend version injection (build/env) and a specs-capture path (psutil/platform + GPU source).
  • Tests.

Open product decisions: .zip vs single JSON; specs source (server-side psutil vs frontend); how to inject the real backend version.


F5 — Save game backups

Goal: auto-copy CP2077 saves before a deploy (or other risky change); rolling retention; restore.

Verified — building blocks:

  • deploy() is the single composition entry point (services/vfs/deploy_service.py:439), reached from 3 call sites — one hook covers all deploys.
  • is_game_running guard (services/vfs/primitives.py:165); data_dir writability checked by /health/deep (main.py:164).

Verified — greenfield / caveats:

  • The app does not know the save path today (it knows install_path, not the Saved-Games dir). No Saved Games/CD Projekt reference anywhere.
  • No real file-copy primitive exists — the whole VFS is hardlinks/junctions. A hardlink would not protect a save (shared inode → shared corruption); backups must be byte copies (shutil.copy2/copytree).
  • Profile export backs up mod lists, not save files.

Acceptance criteria (full scope):

  • Save-path detection (Steam/GOG/Epic) + a user-overridable setting + fallback.
  • Copy + rolling-retention service (real copies, configurable retention); restore + list + manual-backup endpoints.
  • Pre-deploy hook (decide coverage for toggle/uninstall/undeploy too); failure policy.
  • Frontend Settings card + restore confirmation.
  • Tests.

Open product decisions: retention policy (count/size/age); storage location (data_dir/backups/<game>/<ts>); failure policy (best-effort vs abort-deploy); coverage scope; Steam Cloud / OneDrive-redirected Saved Games caveats.


F4 — Framework mod monitor

Goal: a panel showing install status + version of RED4ext, redscript, ArchiveXL, TweakXL, Codeware, and Cyber Engine Tweaks; highlight missing/disabled/outdated.

Verified — building blocks:

  • constants.py (CYBERPUNK_DEFAULT_PATHS) already enumerates each framework's directory.
  • find_untracked_files (services/vfs/untracked.py:14) is the only code path that sees files the app did not install (frameworks are often installed manually).
  • Version-compare reuse: useModSummary / mod_summary (routers/nexus.py:159) + is_newer_version (lib/version.ts) — essentially useAppUpdateCheck × 6.
  • NexusModRequirement.required_mod_id already records framework Nexus IDs (they appear as other mods' requirements) — useful for name→ID mapping.

Verified — greenfield / the hard part:

  • No framework registry / known-ID concept exists (e.g. ArchiveXL has 0 hits in source).
  • Version detection is essentially absentinstalled_version is parsed from the Nexus filename and is empty for manually-installed frameworks. Reliable version detection requires reading each framework's own version from disk (sidecar file / DLL FileVersion / RED4ext logs) — per-framework reverse-engineering, no precedent.

Acceptance criteria (full scope):

  • Framework registry: Nexus mod IDs + characteristic marker paths + a per-framework version source.
  • Disk-based existence + own-version extraction for all 6, including manually-installed ones.
  • Outdated detection via Nexus latest version.
  • Endpoint GET .../frameworks; frontend status widget.
  • Tests.

Open product decisions: "disabled" semantics for manually-installed frameworks; per-framework version source (research item); panel placement (Dashboard vs GameDetail tab).


F1 — In-app mod error reader

Goal: after a game session, parse the logs the game/frameworks write (redscript compiler, RED4ext, ArchiveXL, TweakXL, CET — under r6/logs, red4ext/logs, etc.), surface load failures / compile errors / warnings, and attribute each to the responsible mod.

Verified — building blocks:

  • Game dir is known (Game.install_path, models/game.py); the standard log dirs sit under it by convention (derivable, though not currently tracked — absent from GAME_REGISTRY).
  • Attribution mechanism exists: InstalledModFile.relative_path + _build_file_to_mod_map (services/modlist_service.py:45). CET/REDmod report by mod folder name, so attribution also needs folder-name matching (InstalledMod.name/staging_dir).

Verified — greenfield / risk:

  • Zero existing log-reading code (r6/logs/red4ext/logs appear nowhere). Fully greenfield.
  • Log formats are external, undocumented, and version-volatile — the main maintenance risk.
  • No game-exit hook (only is_game_running); the view parses whatever is on disk.

Acceptance criteria (full scope):

  • Log discovery for all in-scope sources, derived from the install dir.
  • Robust parsers per format (redscript, RED4ext, ArchiveXL, TweakXL, CET) with severity classification.
  • Error model + mod attribution (path + folder-name).
  • Frontend errors view + parse/refresh trigger.
  • Tests against real log fixtures.

Open product decisions: which formats count as "complete"; parse trigger (manual refresh vs on window focus); fixture sourcing.


Generated from a code-verified feasibility study across main and nexus-compliant. Per-feature specs and plans will be linked here as each cycle starts.


Progress

Updated 2026-05-22.Roadmap complete — all 7 features (F1–F7) shipped to both editions, plus two perf follow-ups (health + install) off the event loop.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions