@@ -646,23 +646,26 @@ public function worktree_cleanup_merged( array $opts = array() ): array|\WP_Erro
646646 }
647647
648648 $ protected_branches = array ( 'main ' , 'master ' , 'trunk ' , 'develop ' , 'HEAD ' );
649- $ candidates = array ();
650- $ skipped = array ();
649+ $ candidates = array ();
650+ $ skipped = array ();
651+
651652 /** @var array<string,mixed> $github_cache */
652- $ github_cache = array ();
653- $ all_worktrees = array_values (array_filter ( (array ) $ listing ['worktrees ' ], fn ( $ wt ) => empty ($ wt ['is_primary ' ])));
654- $ total_worktrees = count ($ all_worktrees );
655- $ worktrees = array_slice ($ all_worktrees , $ offset , $ limit );
656- $ checked = 0 ;
657- $ processed = 0 ;
658- $ removed_count = 0 ;
653+ $ github_cache = array ();
654+
655+ $ all_worktrees = array_values (array_filter ( (array ) $ listing ['worktrees ' ], fn ( $ wt ) => empty ($ wt ['is_primary ' ])));
656+ $ total_worktrees = count ($ all_worktrees );
657+ $ worktrees = array_slice ($ all_worktrees , $ offset , $ limit );
658+ $ checked = 0 ;
659+ $ processed = 0 ;
660+ $ removed_count = 0 ;
659661
660662 $ this ->emit_worktree_cleanup_progress ($ progress , 'start ' , '' , $ checked , $ total_worktrees , $ candidates , $ skipped , $ removed_count , $ started_at );
661663
662664 // Fetch + prune each primary once per repo, but keep status/disk probes inside
663665 // the row loop so budgeted dry-runs can return partial evidence promptly.
664666 /** @var array<string,bool> $fetched */
665- $ fetched = array ();
667+ $ fetched = array ();
668+
666669 /** @var array<string,\WP_Error> $fetch_timeouts */
667670 $ fetch_timeouts = array ();
668671
@@ -915,14 +918,14 @@ public function worktree_cleanup_merged( array $opts = array() ): array|\WP_Erro
915918 continue ;
916919 }
917920
918- if ( isset ( $ fetch_timeouts [ $ repo ]) && is_wp_error ($ fetch_timeouts [ $ repo ]) ) {
921+ if ( isset ($ fetch_timeouts [ $ repo ]) ) {
919922 $ skipped [] = $ this ->build_worktree_probe_failure_skip ($ handle , $ repo , $ branch , $ wt_path , $ created_at , $ metadata , $ disk_fields , $ fetch_timeouts [ $ repo ]);
920923 continue ;
921924 }
922925
923926 if ( empty ($ fetched [ $ repo ]) ) {
924927 $ fetch = $ this ->run_git ($ primary_path , 'fetch --prune --quiet origin ' , self ::CLEANUP_GIT_PROBE_TIMEOUT );
925- if ( is_wp_error ( $ fetch ) && $ this ->is_git_timeout_error ($ fetch ) ) {
928+ if ( $ this ->is_git_timeout_error ($ fetch ) ) {
926929 $ fetch_timeouts [ $ repo ] = $ fetch ;
927930 $ skipped [] = $ this ->build_worktree_probe_failure_skip ($ handle , $ repo , $ branch , $ wt_path , $ created_at , $ metadata , $ disk_fields , $ fetch );
928931 continue ;
@@ -1585,7 +1588,7 @@ function () use ( $repo, $branch, $wt_path, $force ) {
15851588 'evidence ' => array (
15861589 'elapsed_ms ' => (int ) round (( microtime (true ) - $ started_at ) * 1000 ),
15871590 'inventory_total ' => count ($ all_candidates ),
1588- 'removed_handles ' => array_values (array_filter (array_map (fn ( $ row ) => (string ) ( $ row ['handle ' ] ?? '' ) , $ removed ))),
1591+ 'removed_handles ' => array_values (array_filter (array_map (fn ( $ row ) => (string ) $ row ['handle ' ], $ removed ))),
15891592 'skipped_handles ' => array_values (array_filter (array_map (fn ( $ row ) => (string ) ( $ row ['handle ' ] ?? '' ), $ skipped ))),
15901593 'source ' => $ source ,
15911594 ),
@@ -2449,7 +2452,7 @@ private function build_current_remote_tracking_clean_cleanup_evidence( string $h
24492452
24502453 $ remote_ref = 'refs/remotes/origin/ ' . $ branch ;
24512454 $ remote = $ this ->run_git ($ primary_path , sprintf ('rev-parse --verify --quiet %s ' , escapeshellarg ($ remote_ref )), self ::CLEANUP_GIT_PROBE_TIMEOUT );
2452- if ( is_wp_error ($ remote ) || $ this -> is_git_timeout_error ( $ remote ) ) {
2455+ if ( is_wp_error ($ remote ) ) {
24532456 return new \WP_Error ('remote_tracking_missing ' , 'remote tracking branch no longer exists ' );
24542457 }
24552458
@@ -2696,7 +2699,7 @@ private function build_active_no_signal_evidence_row( array $row, array &$github
26962699 $ branch = $ head_branch ;
26972700 } else {
26982701 $ branch_probe = $ this ->run_git ($ path , 'branch --show-current ' , self ::CLEANUP_GIT_PROBE_TIMEOUT );
2699- if ( ! is_wp_error ( $ branch_probe ) && ! $ this -> is_git_timeout_error ($ branch_probe ) ) {
2702+ if ( ! is_wp_error ($ branch_probe ) ) {
27002703 $ actual_branch = trim ( (string ) ( $ branch_probe ['output ' ] ?? '' ) );
27012704 if ( '' !== $ actual_branch ) {
27022705 $ branch = $ actual_branch ;
@@ -2768,7 +2771,7 @@ function () use ( $primary_path, $remote_ref, &$probe_cache ) {
27682771 return $ this ->cached_active_no_signal_remote_tracking_probe ($ primary_path , $ remote_ref , $ probe_cache );
27692772 }
27702773 );
2771- $ out ['remote_tracking ' ] = ! is_wp_error ($ remote ) && ! $ this -> is_git_timeout_error ( $ remote ) ;
2774+ $ out ['remote_tracking ' ] = ! is_wp_error ($ remote );
27722775
27732776 $ default_ref = $ this ->time_worktree_probe (
27742777 $ out ['probe_timings_ms ' ],
@@ -2786,7 +2789,7 @@ function () use ( $primary_path, $default_ref, $branch, &$probe_cache ) {
27862789 return $ this ->cached_active_no_signal_commits_outside_default_probe ($ primary_path , $ default_ref , $ branch , $ probe_cache );
27872790 }
27882791 );
2789- if ( ! is_wp_error ($ outside ) && ! $ this -> is_git_timeout_error ( $ outside ) ) {
2792+ if ( ! is_wp_error ($ outside ) ) {
27902793 $ out ['commits_outside_default ' ] = (int ) trim ( (string ) ( $ outside ['output ' ] ?? '' ));
27912794 }
27922795
@@ -2945,7 +2948,7 @@ private function build_clean_upstream_equivalence_evidence( string $primary_path
29452948 );
29462949
29472950 $ cherry = $ this ->run_git ($ wt_path , sprintf ('cherry %s HEAD ' , escapeshellarg ($ default_ref )), self ::CLEANUP_GIT_PROBE_TIMEOUT );
2948- if ( ! is_wp_error ($ cherry ) && ! $ this -> is_git_timeout_error ( $ cherry ) ) {
2951+ if ( ! is_wp_error ($ cherry ) ) {
29492952 $ lines = array_values (array_filter (array_map ('trim ' , explode ("\n" , (string ) ( $ cherry ['output ' ] ?? '' )))));
29502953 foreach ( $ lines as $ line ) {
29512954 if ( str_starts_with ($ line , '- ' ) ) {
@@ -2964,7 +2967,7 @@ private function build_clean_upstream_equivalence_evidence( string $primary_path
29642967 }
29652968
29662969 $ head = $ this ->run_git ($ wt_path , 'rev-parse --verify HEAD ' , self ::CLEANUP_GIT_PROBE_TIMEOUT );
2967- if ( is_wp_error ($ head ) || $ this -> is_git_timeout_error ( $ head ) ) {
2970+ if ( is_wp_error ($ head ) ) {
29682971 return $ evidence ;
29692972 }
29702973
@@ -2974,7 +2977,7 @@ private function build_clean_upstream_equivalence_evidence( string $primary_path
29742977 }
29752978
29762979 $ contains = $ this ->run_git ($ primary_path , sprintf ('branch -r --contains %s ' , escapeshellarg (trim ( (string ) ( $ head ['output ' ] ?? '' )))), self ::CLEANUP_GIT_PROBE_TIMEOUT );
2977- if ( is_wp_error ($ contains ) || $ this -> is_git_timeout_error ( $ contains ) ) {
2980+ if ( is_wp_error ($ contains ) ) {
29782981 return $ evidence ;
29792982 }
29802983
@@ -3052,7 +3055,7 @@ private function build_dirty_unpushed_upstream_equivalence_evidence( string $pri
30523055 );
30533056
30543057 $ cherry = $ this ->time_worktree_probe ($ evidence ['probe_timings_ms ' ], 'git_cherry ' , fn () => $ this ->run_git ($ wt_path , sprintf ('cherry %s HEAD ' , escapeshellarg ($ default_ref )), self ::CLEANUP_GIT_PROBE_TIMEOUT ));
3055- if ( ! is_wp_error ($ cherry ) && ! $ this -> is_git_timeout_error ( $ cherry ) ) {
3058+ if ( ! is_wp_error ($ cherry ) ) {
30563059 $ lines = array_values (array_filter (array_map ('trim ' , explode ("\n" , (string ) ( $ cherry ['output ' ] ?? '' )))));
30573060 foreach ( $ lines as $ line ) {
30583061 if ( str_starts_with ($ line , '- ' ) ) {
@@ -3068,19 +3071,19 @@ private function build_dirty_unpushed_upstream_equivalence_evidence( string $pri
30683071
30693072 $ tracked = $ this ->time_worktree_probe ($ evidence ['probe_timings_ms ' ], 'tracked_dirty_paths ' , fn () => $ this ->run_git ($ wt_path , 'diff --name-only HEAD ' , self ::CLEANUP_GIT_PROBE_TIMEOUT ));
30703073 $ paths = array ();
3071- if ( ! is_wp_error ($ tracked ) && ! $ this -> is_git_timeout_error ( $ tracked ) ) {
3074+ if ( ! is_wp_error ($ tracked ) ) {
30723075 $ paths = array_merge ($ paths , array_values (array_filter (array_map ('trim ' , explode ("\n" , (string ) ( $ tracked ['output ' ] ?? '' ))))));
30733076 }
30743077
30753078 $ untracked = $ this ->time_worktree_probe ($ evidence ['probe_timings_ms ' ], 'untracked_paths ' , fn () => $ this ->run_git ($ wt_path , 'ls-files --others --exclude-standard ' , self ::CLEANUP_GIT_PROBE_TIMEOUT ));
3076- if ( ! is_wp_error ($ untracked ) && ! $ this -> is_git_timeout_error ( $ untracked ) ) {
3079+ if ( ! is_wp_error ($ untracked ) ) {
30773080 foreach ( array_values (array_filter (array_map ('trim ' , explode ("\n" , (string ) ( $ untracked ['output ' ] ?? '' ))))) as $ path ) {
30783081 $ paths [] = $ path ;
30793082 ++$ evidence ['dirty_paths ' ]['untracked ' ];
30803083 }
30813084 }
30823085
3083- $ paths = array_values (array_unique (array_filter ($ paths, fn ( $ path ) => '' !== ( string ) $ path )));
3086+ $ paths = array_values (array_unique (array_filter ($ paths )));
30843087 $ evidence ['dirty_paths ' ]['total ' ] = count ($ paths );
30853088 $ inspect_paths = array_slice ($ paths , 0 , $ path_inspection_limit );
30863089 $ evidence ['dirty_paths ' ]['inspected ' ] = count ($ inspect_paths );
@@ -3131,7 +3134,7 @@ private function classify_dirty_paths_against_default( string $primary_path, str
31313134 $ path_args = implode (' ' , array_map ('escapeshellarg ' , $ paths ));
31323135 $ existing = $ this ->run_git ($ primary_path , sprintf ('ls-tree -r --name-only %s -- %s ' , escapeshellarg ($ default_ref ), $ path_args ), self ::CLEANUP_GIT_PROBE_TIMEOUT );
31333136 $ changed = $ this ->run_git ($ wt_path , sprintf ('diff --name-only %s -- %s ' , escapeshellarg ($ default_ref ), $ path_args ), self ::CLEANUP_GIT_PROBE_TIMEOUT );
3134- if ( is_wp_error ($ existing ) || is_wp_error ($ changed ) || $ this -> is_git_timeout_error ( $ existing ) || $ this -> is_git_timeout_error ( $ changed ) ) {
3137+ if ( is_wp_error ($ existing ) || is_wp_error ($ changed ) ) {
31353138 return array ();
31363139 }
31373140
@@ -3200,7 +3203,7 @@ private function classify_dirty_unpushed_effective_status( array $evidence ): st
32003203 private function classify_dirty_path_against_default ( string $ primary_path , string $ wt_path , string $ default_ref , string $ path ): array {
32013204 $ kind = $ this ->is_generated_or_artifact_path ($ path ) ? 'generated_or_artifact ' : 'source_like ' ;
32023205 $ exists = $ this ->run_git ($ primary_path , sprintf ('cat-file -e %s ' , escapeshellarg ($ default_ref . ': ' . $ path )), self ::CLEANUP_GIT_PROBE_TIMEOUT );
3203- if ( $ this ->is_git_timeout_error ($ exists ) ) {
3206+ if ( is_wp_error ( $ exists ) && $ this ->is_git_timeout_error ($ exists ) ) {
32043207 return array (
32053208 'path ' => $ path ,
32063209 'bucket ' => 'unknown ' ,
@@ -3217,7 +3220,7 @@ private function classify_dirty_path_against_default( string $primary_path, stri
32173220 }
32183221
32193222 $ diff = $ this ->run_git ($ wt_path , sprintf ('diff --name-only %s -- %s ' , escapeshellarg ($ default_ref ), escapeshellarg ($ path )), self ::CLEANUP_GIT_PROBE_TIMEOUT );
3220- if ( $ this ->is_git_timeout_error ($ diff ) ) {
3223+ if ( is_wp_error ( $ diff ) && $ this ->is_git_timeout_error ($ diff ) ) {
32213224 return array (
32223225 'path ' => $ path ,
32233226 'bucket ' => 'unknown ' ,
@@ -3355,9 +3358,9 @@ private function describe_active_no_signal_action( array $row ): string {
33553358 *
33563359 * @param array $candidate Inventory candidate row.
33573360 * @param bool $force Allow dirty worktrees.
3358- * @return array<string,mixed>|\WP_Error
3359- */
3360- private function revalidate_bounded_cleanup_eligible_candidate ( array $ candidate , bool $ force ): array | \ WP_Error {
3361+ * @return array<string,mixed>
3362+ */
3363+ private function revalidate_bounded_cleanup_eligible_candidate ( array $ candidate , bool $ force ): array {
33613364 $ handle = (string ) ( $ candidate ['handle ' ] ?? '' );
33623365 $ repo = (string ) ( $ candidate ['repo ' ] ?? '' );
33633366 $ branch = (string ) ( $ candidate ['branch ' ] ?? '' );
@@ -3838,7 +3841,7 @@ private function build_no_merge_signal_evidence( string $primary_path, string $b
38383841
38393842 $ remote_ref = 'refs/remotes/origin/ ' . $ branch ;
38403843 $ remote = $ this ->run_git ($ primary_path , sprintf ('rev-parse --verify --quiet %s ' , escapeshellarg ($ remote_ref )), self ::CLEANUP_GIT_PROBE_TIMEOUT );
3841- if ( ! is_wp_error ($ remote ) && ! $ this -> is_git_timeout_error ( $ remote ) ) {
3844+ if ( ! is_wp_error ($ remote ) ) {
38423845 $ evidence ['remote_branch ' ] = 'still_exists ' ;
38433846 $ evidence ['classification ' ] = 'remote_branch_still_exists ' ;
38443847 } elseif ( $ this ->is_git_timeout_error ($ remote ) ) {
@@ -3856,7 +3859,7 @@ private function build_no_merge_signal_evidence( string $primary_path, string $b
38563859 sprintf ('rev-list --count %s..%s ' , escapeshellarg ($ default_ref ), escapeshellarg ('refs/heads/ ' . $ branch )),
38573860 self ::CLEANUP_GIT_PROBE_TIMEOUT
38583861 );
3859- if ( ! is_wp_error ($ outside ) && ! $ this -> is_git_timeout_error ( $ outside ) ) {
3862+ if ( ! is_wp_error ($ outside ) ) {
38603863 $ outside_count = (int ) trim ( (string ) ( $ outside ['output ' ] ?? '' ));
38613864 $ evidence ['commits_outside_default ' ] = $ outside_count ;
38623865 $ evidence ['local_default_relation ' ] = 0 === $ outside_count ? 'default_contained ' : 'has_unique_commits ' ;
@@ -4164,7 +4167,8 @@ private function classify_artifact_only_dirty_worktree( string $repo, string $pa
41644167
41654168 $ path_part = trim (substr ($ line , 3 ));
41664169 if ( str_contains ($ path_part , ' -> ' ) ) {
4167- $ path_part = trim ( (string ) substr (strrchr ($ path_part , '> ' ), 1 ));
4170+ $ rename_target = strrchr ($ path_part , '> ' );
4171+ $ path_part = false === $ rename_target ? '' : trim (substr ($ rename_target , 1 ));
41684172 }
41694173 $ path_part = trim ($ path_part , ' / ' );
41704174 if ( '' === $ path_part ) {
@@ -4234,8 +4238,7 @@ private function get_worktree_artifact_profile( string $repo, string $path ): ar
42344238 * @param string $repo Repo name.
42354239 * @param string $path Worktree path.
42364240 */
4237- $ filtered = apply_filters ('datamachine_code_worktree_artifact_profile ' , $ profile , $ repo , $ path );
4238- return is_array ($ filtered ) ? $ filtered : $ profile ;
4241+ return apply_filters ('datamachine_code_worktree_artifact_profile ' , $ profile , $ repo , $ path );
42394242 }
42404243
42414244 /**
@@ -4310,7 +4313,7 @@ private function sort_worktree_cleanup_rows( array $rows, string $sort ): array
43104313 * @return array<int,array<string,mixed>>
43114314 */
43124315 private function summarize_top_worktree_rows ( array $ rows , string $ field ): array {
4313- $ rows = array_values (array_filter ($ rows , fn ( $ row ) => isset ($ row [ $ field ]) && null !== $ row [ $ field ] && (int ) $ row [ $ field ] > 0 ));
4316+ $ rows = array_values (array_filter ($ rows , fn ( $ row ) => isset ($ row [ $ field ]) && (int ) $ row [ $ field ] > 0 ));
43144317 usort ($ rows , fn ( $ a , $ b ) => (int ) ( $ b [ $ field ] ?? 0 ) <=> (int ) ( $ a [ $ field ] ?? 0 ));
43154318
43164319 return array_map (
@@ -4631,7 +4634,7 @@ private function classify_dirty_obsolete_on_default_branch(
46314634 // the caller's `$fetched` tracker so this never double-fetches.
46324635 if ( empty ($ fetched [ $ repo ]) ) {
46334636 $ fetch = $ this ->run_git ($ primary_path , 'fetch --prune --quiet origin ' , self ::CLEANUP_GIT_PROBE_TIMEOUT );
4634- if ( is_wp_error ( $ fetch ) && $ this ->is_git_timeout_error ($ fetch ) ) {
4637+ if ( $ this ->is_git_timeout_error ($ fetch ) ) {
46354638 $ fetch_timeouts [ $ repo ] = $ fetch ;
46364639 return null ;
46374640 }
@@ -4651,7 +4654,7 @@ private function classify_dirty_obsolete_on_default_branch(
46514654 sprintf ('rev-parse --verify --quiet %s ' , escapeshellarg ($ default_ref . '^{commit} ' )),
46524655 self ::CLEANUP_GIT_PROBE_TIMEOUT
46534656 );
4654- if ( $ this -> is_git_timeout_error ( $ default_resolve ) || is_wp_error ($ default_resolve ) ) {
4657+ if ( is_wp_error ($ default_resolve ) ) {
46554658 return null ;
46564659 }
46574660
@@ -4706,7 +4709,7 @@ private function classify_dirty_obsolete_on_default_branch(
47064709 'diff --name-only HEAD ' ,
47074710 self ::CLEANUP_GIT_PROBE_TIMEOUT
47084711 );
4709- if ( $ this -> is_git_timeout_error ( $ tracked ) || is_wp_error ($ tracked ) ) {
4712+ if ( is_wp_error ($ tracked ) ) {
47104713 return null ;
47114714 }
47124715
@@ -4731,7 +4734,7 @@ private function classify_dirty_obsolete_on_default_branch(
47314734 sprintf ('cat-file -e %s ' , escapeshellarg ($ default_ref . ': ' . $ path )),
47324735 self ::CLEANUP_GIT_PROBE_TIMEOUT
47334736 );
4734- if ( $ this ->is_git_timeout_error ($ probe ) ) {
4737+ if ( is_wp_error ( $ probe ) && $ this ->is_git_timeout_error ($ probe ) ) {
47354738 return null ;
47364739 }
47374740 if ( is_wp_error ($ probe ) ) {
@@ -4971,7 +4974,7 @@ private function find_pr_for_branch_direct( string $slug, string $branch, array
49714974 }
49724975
49734976 $ parts = explode ('/ ' , $ slug , 2 );
4974- $ owner = $ parts [0 ] ?? '' ;
4977+ $ owner = $ parts [0 ];
49754978 if ( '' === $ owner || empty ($ parts [1 ]) ) {
49764979 $ github_cache [ $ cache_key ] = null ;
49774980 return null ;
@@ -5062,7 +5065,7 @@ private function get_cleanup_github_lookup( string $slug, array &$github_cache )
50625065 }
50635066
50645067 $ parts = explode ('/ ' , $ slug , 2 );
5065- $ owner = $ parts [0 ] ?? '' ;
5068+ $ owner = $ parts [0 ];
50665069 if ( '' === $ owner || empty ($ parts [1 ]) ) {
50675070 $ github_cache [ $ slug ] = null ;
50685071 return null ;
@@ -5185,9 +5188,8 @@ private function run_git( string $repo_path, string $git_args, int $timeout_seco
51855188 * Determine whether a git result is a timeout error.
51865189 *
51875190 * @param mixed $result Git result.
5188- * @return bool
5189- * @phpstan-assert-if-true \WP_Error $result
5190- */
5191+ * @return bool
5192+ */
51915193 private function is_git_timeout_error ( mixed $ result ): bool {
51925194 if ( ! is_wp_error ($ result ) ) {
51935195 return false ;
0 commit comments