From 61f8f058f219f0f4a9e21c17f96a78b0c2000fa5 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 15 Jan 2026 08:31:31 +0000 Subject: [PATCH] Fix manifest infinite loop from incomplete entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../Core/Manifest/_Manifest_Builder_Helper.php | 2 +- .../Core/Manifest/_Manifest_Quality_Helper.php | 13 ++++++++++++- .../Core/Manifest/_Manifest_Scanner_Helper.php | 8 ++++---- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/app/RSpade/Core/Manifest/_Manifest_Builder_Helper.php b/app/RSpade/Core/Manifest/_Manifest_Builder_Helper.php index aa7db12fa..99d321057 100755 --- a/app/RSpade/Core/Manifest/_Manifest_Builder_Helper.php +++ b/app/RSpade/Core/Manifest/_Manifest_Builder_Helper.php @@ -83,7 +83,7 @@ class _Manifest_Builder_Helper // This creates a map of className => filename (not full metadata to save space) // NOTE: Class override detection (rsx/ vs app/RSpade/) happens earlier in _check_unique_base_class_names() foreach (Manifest::$data['data']['files'] as $file => $filedata) { - if ($filedata['extension'] == $ext && !empty($filedata['class'])) { + if (isset($filedata['extension']) && $filedata['extension'] == $ext && !empty($filedata['class'])) { $class_name = $filedata['class']; // Duplicates should have been caught by _check_unique_base_class_names() diff --git a/app/RSpade/Core/Manifest/_Manifest_Quality_Helper.php b/app/RSpade/Core/Manifest/_Manifest_Quality_Helper.php index f1d64757f..c9f6c6f1e 100755 --- a/app/RSpade/Core/Manifest/_Manifest_Quality_Helper.php +++ b/app/RSpade/Core/Manifest/_Manifest_Quality_Helper.php @@ -310,21 +310,32 @@ class _Manifest_Quality_Helper // Valid override: exactly one file in rsx/, rest in app/RSpade/ if (count($rsx_files) === 1 && count($framework_files) >= 1) { + $did_change = false; // Rename framework files to .upstream and remove from manifest foreach ($framework_files as $framework_file) { $full_framework_path = base_path($framework_file); $upstream_path = $full_framework_path . '.upstream'; if (file_exists($full_framework_path) && !file_exists($upstream_path)) { + // Normal case: rename to .upstream rename($full_framework_path, $upstream_path); console_debug('MANIFEST', "Class override: {$class_name} - moved {$framework_file} to .upstream"); + $did_change = true; + } elseif (file_exists($full_framework_path) && file_exists($upstream_path)) { + // Self-healing: both .php and .php.upstream exist (e.g., after framework update) + // Remove the .php file since .upstream is the correct archived version + unlink($full_framework_path); + console_debug('MANIFEST', "Class override: {$class_name} - removed duplicate {$framework_file} (upstream already exists)"); + $did_change = true; } // Remove from manifest data so it won't be indexed unset(Manifest::$data['data']['files'][$framework_file]); } - Manifest::$_needs_manifest_restart = true; + if ($did_change) { + Manifest::$_needs_manifest_restart = true; + } continue; } diff --git a/app/RSpade/Core/Manifest/_Manifest_Scanner_Helper.php b/app/RSpade/Core/Manifest/_Manifest_Scanner_Helper.php index 8b5e31ccf..6c5218166 100755 --- a/app/RSpade/Core/Manifest/_Manifest_Scanner_Helper.php +++ b/app/RSpade/Core/Manifest/_Manifest_Scanner_Helper.php @@ -168,8 +168,8 @@ class _Manifest_Scanner_Helper $current_size = filesize($absolute_path); - // Stage 1: Size check - if ($old['size'] != $current_size) { + // Stage 1: Size check (guard for incomplete manifest entries) + if (!isset($old['size']) || $old['size'] != $current_size) { // Only show the message once per page load if (!Manifest::$__shown_rescan_message) { console_debug('MANIFEST', '* File ' . $file . ' has changed size, triggering manifest rescan *'); @@ -180,9 +180,9 @@ class _Manifest_Scanner_Helper return true; } - // Stage 2: mtime check + // Stage 2: mtime check (guard for incomplete manifest entries) $current_mtime = filemtime($absolute_path); - if ($old['mtime'] != $current_mtime) { + if (!isset($old['mtime']) || $old['mtime'] != $current_mtime) { // Only show the message once per page load if (!Manifest::$__shown_rescan_message) { console_debug('MANIFEST', '* File ' . $file . ' has changed mtime, triggering manifest rescan *');