Skip to content

Fix scan destroying/mistitling pre-arranged libraries; add bulk metadata refresh - #11

Merged
dev-nick421 merged 7 commits into
mainfrom
claude/gracious-dirac-bf453b
Jul 16, 2026
Merged

dev-nick421 merged 7 commits into
mainfrom
claude/gracious-dirac-bf453b

Conversation

@dev-nick421

@dev-nick421 dev-nick421 commented Jul 16, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Critical fix: detectInputs only recognized an already-processed game folder if the database had a matching Game row. On a fresh database (reinstall) or a library arranged outside of a scan, a correctly-structured folder (artwork/ + data/*.zip) was queued as raw scan input, then re-matched, compressed into a zip inside itself, and deleted as a "source" once done — silently destroying an already-complete game. Structured folders are now recognized on sight regardless of DB state and are adopted instead of reprocessed.
  • Adoption recovers title/year/IGDB ID from the folder name via a new naming-scheme reverse-parser, so an orphaned folder's title is read from its name properly instead of falling back to the whole scheme-shaped string (e.g. never "Clair Obscur Expedition 33 - 2025 [305152]" as the title).
  • A scan run (manual or scheduled) previously finished silently — new/adopted games just appeared with no feedback. Both the scanner and a new bulk metadata refresher now broadcast a completion summary over the WebSocket, surfaced as a toast anywhere in the app.
  • New bulk "Refresh Metadata" action on Manage Games (POST /api/games/refresh-metadata), behind a single "Refresh metadata" button (next to "Add custom game") that opens a modal with a mode dropdown and a Start button: "Refresh all" unconditionally re-fetches metadata + artwork for every game (fixes wrong-but-present fields); "Find missing metadata" only fills in blank fields, leaving everything else untouched. Neither ever moves/renames gamePath/archivePath — a metadata correction stays a cheap update, not a relocation.
  • Editing a game tagged "Missing info" now highlights exactly the blank fields (amber label + exclamation icon + input ring), computed from the same fields the badge itself is based on.
  • Documented a code comment convention in AGENTS.md: keep comments general, skip tracker issue references (they rot once an issue closes/renumbers), and don't force a comment where the code already reads clearly.

Test plan

  • api: npm test — 87 tests passing (scanner, naming, metadata refresher, games routes)
  • web: npm test — 5 tests passing, plus a production build
  • Manually verified end-to-end in a browser: scan-adoption of a pre-arranged folder, scan-complete toast on both the Settings and Library pages, the Manage Games bulk refresh modal flow, and the missing-field highlighting in the edit modal

claude and others added 6 commits July 16, 2026 08:55
detectInputs only excluded folders it could match against a Game row in the
DB. A folder with gameledger's own structure (artwork/ + data/*.zip) but no
DB row — e.g. after a reinstall with a fresh database, or a library
copied/hand-arranged in the same naming scheme — was queued as raw scan
input. The pipeline would then re-match it, compress the folder into a zip
nested inside itself, and delete the whole folder as the "source" on
success, destroying an already-complete game.

Structured folders are now recognized on sight and never queued as raw
input, regardless of what the database knows. Orphaned ones (no matching
Game row) are adopted instead: the IGDB ID is recovered from the folder/zip
name via a new reverse-parser for the naming scheme, existing artwork/
archive paths are reused as-is, and metadata is refreshed from IGDB on a
best-effort basis.
Scan progress streamed live per-job over the WebSocket, but nothing marked
the run as a whole done — games (or adopted folders) just appeared with no
feedback, especially noticeable off the Settings page or for scheduled scans.

The scanner now broadcasts one 'scan' summary event when scanAll() finishes
(games added, folders adopted, unmatched, failed, or cancelled). The frontend
picks it up via a small global toast store/host mounted at the app root, so
the notification shows up regardless of which page is open.
adoptFolder's fallback (when IGDB can't be reached at adopt time - e.g.
credentials not yet re-entered on a reinstall) used cleanSourceName() on the
whole folder name, which only strips dots/underscores. For a folder like
"Clair Obscur Expedition 33 - 2025 [305152]" that left the year and IGDB ID
baked into the title verbatim instead of just "Clair Obscur Expedition 33".

naming.js now exposes parseFolderName(), extending the existing IGDB-ID
reverse-parser to also recover the title and release year encoded by the
active naming scheme. adoptFolder uses those as the fallback name/year when
IGDB metadata isn't available, instead of the raw scheme-shaped string.
extractIgdbId() is now a thin wrapper over parseFolderName().
Adopted/scanned games can end up with wrong-but-present or blank metadata
fields (e.g. the folder-name-as-title bug from before this fix) with no way
to correct them in bulk short of editing each one by hand.

New POST /api/games/refresh-metadata (services/metadataRefresh.js), with two
modes matching the issue: "all" unconditionally re-fetches metadata and
wipes+redownloads artwork for every game (fixes wrong-but-present fields);
"missing" only fills in blank fields (summary/genres/platforms/rating/
releaseYear/cover), leaving everything else untouched. Neither mode moves or
renames gamePath/archivePath - per the naming-system invariant, a metadata
correction is a cheap update, not a relocation. Fire-and-forget like /scan,
with progress and a completion summary broadcast over the WebSocket.

Manage Games gets two buttons for the two modes, a "Missing info" badge per
game, and a live progress indicator; the completion summary surfaces via the
existing global toast host and reloads the table.
Not every change needs a comment, and comments shouldn't tie themselves to a
specific tracker issue -- that context rots once the issue closes or gets
renumbered. Comments should describe the invariant/why in general terms; the
origin belongs in the commit message or PR description instead.
Replace the two standalone "Refresh all"/"Fill in missing" buttons with a
single "Refresh metadata" button (next to "Add custom game") that opens a
modal with a mode dropdown and a Start button.

Editing a game with the "Missing info" badge now highlights exactly the
blank fields (amber label + exclamation icon + ring on the input), computed
from the same fields the badge itself is based on, so it's obvious what to
fill in without guessing.
@dev-nick421 dev-nick421 reopened this Jul 16, 2026
@dev-nick421
dev-nick421 merged commit cd76470 into main Jul 16, 2026
4 checks passed
@dev-nick421
dev-nick421 deleted the claude/gracious-dirac-bf453b branch July 16, 2026 11:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants