Repository navigation
Feed random search wins into local repairs and recover blocked deep passes - #142
Merged
Merged
Conversation
RetroGameDeveloper
pushed a commit
that referenced
this pull request
Oct 30, 2026
…he database as it changes (#142) * Make ROM progress folders authoritative Synchronize local work and git contributions through progress files, rejudging changed code while protecting concurrent attempts. Share eligible saved matches and better attempts when joining a collaboration room. * Update saves.py * Let room guests join before host approval Import and link guests while they wait for approval, then share saved progress after syncing. Update collaboration, save, speed, and cross-game tests to cover the corrected behavior and isolate project data. * Update test_twins_across_games.py * fix * Preserve progress across syncs, restores, and room joins Persist synchronization baselines and merge external edits safely. Guard restores, preserve failed attempts, and synchronize collaboration feedback and queued progress reliably. Validated with 63 passed and 36 skipped in focused tests, Ruff, and git diff --check. * test fixes * Rooms: saved progress reaches the host, one by one, from its own table - A guest sharing saved work asks for the host's function list (fresh), so the queue isn't skipped after the first sync advanced the cursor (the PR's own test failed on it). - Each candidate is handled on its own: one the host refuses is dropped and logged, the rest still go; only a host that can't be reached keeps the queue for a retry. - The queue lives in its own table (saved_progress), not in the project's config, which every project access parsed; an old config-held queue is moved once. - join_room computes its candidates before the join, so nothing that can fail runs between joining and linking. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Progress folders: never lose a newer match, open with unknown compilers, safer saves - The first sync without a baseline keeps every database match newer than the folder's snapshot, even when the folder has an older file of that name (it was rejudged and replaced both the match and the best). - Manifests carry a rising revision (and saved_at again), so an older folder is known as older after the database was restored or copied without its sync state. - A compiler decompdecomp doesn't have no longer stops a project or a restore from opening (it undid #128): its sources wait unjudged until a compiler is picked; an uninstalled known compiler is asked for only when code must be judged, by name. A restore that fails after importing removes the project it imported. - Header and layout changes keep the last match as a backup until the new code is judged. - Saving to a chosen folder renders from the database, so a broken default folder can't block the backup. - Every write checks the folder, README and card for links pointing outside; joining a saved layout moves the tails' attempts onto the head instead of deleting them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Progress folders sync incrementally: a no-op check is free, one match writes one file Every project read synced the folder: it statted every file, and any database write (a claim, an event) forced a full render, publish and a rewrite of two full copies of every file. On a homemade 18,000-function project a no-op took 0.6 s and one changed match 4.4 s. - SQLite triggers mark only what the folder's render reads (a function's match, best, name or layout; headers, notes, symbols, knowledge), for ROM projects that exist; claims, attempts and events mark nothing, and a write is never failed by a trigger (rows left from a removed project still clean up). - Publishing renders and writes only the marked functions' files, changed headers and the manifest. - An unforced check stats the manifest and the folders, at most every 0.25 s; a forced one (before judging, after a tool that wrote, on save) stats every file, so an in-place edit is seen. - The baseline is one hash per file instead of two copies of every file; old baselines are converted once. - A pull that only changes settings doesn't compile saved code; a compile syncs once before and once after. At 18,000 functions: no-op 607 ms -> 0.05 ms, forced 610 -> 51 ms, one match 4.4 s -> 0.45 s, a claim 4.3 s -> 55 ms. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * A restored save keeps why a function was set aside The progress sync applies the saved layout before the restore's own pass, so a set-aside function was already 'asm' when the restore looked only for 'open' rows to give its reason back: it came back set aside with no reason (a PSP demo test caught it in CI). Both passes now take 'open' and 'asm' rows; matched ones stay untouched. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Progress folders keep overlay twins, and a failed sync changes nothing Tried on a copy of a real PS1 project (28,881 functions at 19,786 addresses: overlays share them): the first read after updating refused with "the saved layout crosses a gap", having already deleted 24,424 functions, matches 5,623 -> 1,010. The saved layout was matched to the database by address alone, so another overlay's function at the same address was taken for a split piece and joined away, and each step committed on its own. - A saved layout that matches the database (name, address, size) is not applied: a folder this app wrote from the same database is not a contribution. - Joins match a function by name and address and take pieces only from its own overlay; they are planned and checked in full before any write, and one that would delete a matched function is refused. - A sync's database changes and the folder's publish are one transaction: any error rolls it all back. - Set-aside entries and rooms' layout and renames go by name and address too; an address shared by overlays is never renamed as a whole. - The speed test's limits are fractions of a full sync timed in the same run (fixed milliseconds failed on CI's shared runners). The same copy now opens in 4.0 s with every row and match, a settings-only pull and a pulled source edit keep every match, and a reopen changes nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Pau Solsona <pausolsonaboada@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changes
Validation
Limits
This implements the prioritized feedback/register work and two recovery fixes. Adaptive project budgets and a pool of alternative search candidates remain planned. Return recovery only handles plain scalar declarations with unchanged compatible parameters; ambiguous declarations stay with review. Existing exact-match rules are unchanged.