Skip to content

Feed random search wins into local repairs and recover blocked deep passes - #142

Merged
RetroGameDeveloper merged 3 commits into
mainfrom
feat/deep-repair-feedback
Oct 29, 2026
Merged

RetroGameDeveloper merged 3 commits into
mainfrom
feat/deep-repair-feedback

Conversation

@RetroGameDeveloper

@RetroGameDeveloper RetroGameDeveloper commented Oct 29, 2026 •

Copy link
Copy Markdown

What changes

  • After a random rewrite improves the saved candidate, deep search immediately tries up to 32 local proposals against its new diff, chaining saved improvements. All work shares the original deadline, compile allowance, cache and cancellation/claim handling.
  • Add bounded constant/copy reuse and final integer shift/scale reuse candidates to shared automatic/manual repair paths. The normal compiler and exact judge remain authoritative.
  • Reverify score-zero/open functions and record a fresh exact verdict even when the scalar score cannot improve below zero.
  • Recover an otherwise unbuildable ROM draft when one unambiguous plain shared return declaration conflicts with its definition. Try a candidate-only return alignment, preserve the broken source in attempt history, guard publication against changed inputs, and rebase its measured score honestly. The shared header is not edited. This may lower the displayed draft percentage.
  • Retry the two formerly blocked pass states under the new rules, preserving unrelated completed passes. Explicit Repeat remains available for older completed functions.
  • Retain local-repair family evidence and refinement burst counts for future analysis.

Validation

  • 101 focused tests pass on the final commit, including the random/local feedback loop in ROM and imported-project modes, shared limits and leases, baseline recovery/races, exact-verdict bookkeeping, and a pinned real-MIPS compiler test recovering an exact synthetic object through constant reuse.
  • Full local suite: 2114 passed, 156 skipped (514.88 seconds). The final winner-evidence follow-up was also verified with the focused suite. Ruff, whitespace checks and the GUI regression script pass. Platform CI is still running.
  • The macOS package builds and the installed app restarts successfully. All 295 packaged source/UI files match this checkout; the live project-wide pass resumes automatically.
  • Private five-function regional racing-game replay: 401 candidate evaluations with a 100-candidate cap per function. The already-exact/incorrectly-open function becomes matched after one fresh judge call. The conflicting draft now compiles (fresh baseline 215) and improves to 200; its old unbuildable draft had a stale score of 115. Three register-only near misses retain scores 5, 10 and 15. No new source match is claimed. No private game source/data is included in this PR.

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.

@github-actions github-actions Bot added the enhancement New feature or request label Oct 29, 2026
@RetroGameDeveloper
RetroGameDeveloper merged commit 0a96a5c into main Oct 29, 2026
8 checks passed
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant