Skip to content

Commit 95ed065

Browse files
committed
Fix cleanup plan lint
1 parent c9ce3a2 commit 95ed065

3 files changed

Lines changed: 116 additions & 87 deletions

File tree

inc/Cli/Commands/WorkspaceCommand.php

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -781,11 +781,11 @@ private function attach_cleanup_run_commands( array $result, string $mode ): arr
781781
}
782782

783783
$result['commands'] = array(
784-
'drain_parent' => sprintf('studio wp datamachine drain --job-id=%d', $job_id),
785-
'status' => sprintf('studio wp datamachine-code workspace cleanup status %s --format=json', $run_id),
786-
'status_verbose' => sprintf('studio wp datamachine-code workspace cleanup status %s --verbose --format=json', $run_id),
787-
'one_command_drain' => sprintf('studio wp datamachine-code workspace cleanup run --mode=%s --drain --format=json', $mode),
788-
'bytes_verification' => sprintf('studio wp datamachine-code workspace cleanup status %s --format=json', $run_id),
784+
'drain_parent' => sprintf('studio wp datamachine drain --job-id=%d', $job_id),
785+
'status' => sprintf('studio wp datamachine-code workspace cleanup status %s --format=json', $run_id),
786+
'status_verbose' => sprintf('studio wp datamachine-code workspace cleanup status %s --verbose --format=json', $run_id),
787+
'one_command_drain' => sprintf('studio wp datamachine-code workspace cleanup run --mode=%s --drain --format=json', $mode),
788+
'bytes_verification' => sprintf('studio wp datamachine-code workspace cleanup status %s --format=json', $run_id),
789789
);
790790

791791
return $result;
@@ -809,8 +809,8 @@ private function drain_cleanup_run_to_status( array $result, array $assoc_args )
809809
return $result;
810810
}
811811

812-
$commands = array();
813-
$errors = array();
812+
$commands = array();
813+
$errors = array();
814814
$max_passes = 10;
815815

816816
$parent_command = sprintf('datamachine drain --job-id=%d', $job_id);
@@ -827,7 +827,7 @@ private function drain_cleanup_run_to_status( array $result, array $assoc_args )
827827
break;
828828
}
829829

830-
$children = (array) ( $status['evidence']['children'] ?? array() );
830+
$children = (array) ( $status['evidence']['children'] ?? array() );
831831
$active_child_ids = array_values(
832832
array_unique(
833833
array_filter(
@@ -854,17 +854,17 @@ private function drain_cleanup_run_to_status( array $result, array $assoc_args )
854854
}
855855
}
856856

857-
$final = $this->cleanup_run_evidence_store()->read($run_id, false, ! empty($assoc_args['verbose']));
858-
$output = $final instanceof \WP_Error ? $result : $final;
857+
$final = $this->cleanup_run_evidence_store()->read($run_id, false, ! empty($assoc_args['verbose']));
858+
$output = $final instanceof \WP_Error ? $result : $final;
859859
$output['initial_run'] = $result;
860860
$output['drain'] = array(
861-
'success' => array() === $errors,
862-
'commands' => $commands,
863-
'errors' => $errors,
864-
'verify_command' => sprintf('studio wp datamachine-code workspace cleanup status %s --format=json', $run_id),
865-
'bytes_reclaimed' => (int) ( $output['cleanup_items']['bytes_reclaimed'] ?? 0 ),
866-
'freed_human' => (string) ( $output['cleanup_items']['freed_human'] ?? $this->format_bytes(0) ),
867-
'completion_state' => (string) ( $output['state'] ?? 'unknown' ),
861+
'success' => array() === $errors,
862+
'commands' => $commands,
863+
'errors' => $errors,
864+
'verify_command' => sprintf('studio wp datamachine-code workspace cleanup status %s --format=json', $run_id),
865+
'bytes_reclaimed' => (int) ( $output['cleanup_items']['bytes_reclaimed'] ?? 0 ),
866+
'freed_human' => (string) ( $output['cleanup_items']['freed_human'] ?? $this->format_bytes(0) ),
867+
'completion_state' => (string) ( $output['state'] ?? 'unknown' ),
868868
);
869869

870870
return $output;
@@ -877,10 +877,6 @@ private function drain_cleanup_run_to_status( array $result, array $assoc_args )
877877
* @return string Empty string on success.
878878
*/
879879
private function run_wp_cli_command( string $command ): string {
880-
if ( ! method_exists('WP_CLI', 'runcommand') ) {
881-
return 'WP_CLI::runcommand is unavailable; run the reported drain commands manually.';
882-
}
883-
884880
try {
885881
WP_CLI::runcommand(
886882
$command,
@@ -1317,10 +1313,22 @@ private function render_cleanup_drain_summary( array $drain ): void {
13171313
WP_CLI::log('Drain summary:');
13181314
$this->format_items(
13191315
array(
1320-
array( 'metric' => 'success', 'value' => ! empty($drain['success']) ? 'yes' : 'no' ),
1321-
array( 'metric' => 'completion_state', 'value' => (string) ( $drain['completion_state'] ?? 'unknown' ) ),
1322-
array( 'metric' => 'bytes_reclaimed', 'value' => $this->format_bytes($drain['bytes_reclaimed'] ?? 0) ),
1323-
array( 'metric' => 'verify_command', 'value' => (string) ( $drain['verify_command'] ?? '' ) ),
1316+
array(
1317+
'metric' => 'success',
1318+
'value' => ! empty($drain['success']) ? 'yes' : 'no',
1319+
),
1320+
array(
1321+
'metric' => 'completion_state',
1322+
'value' => (string) ( $drain['completion_state'] ?? 'unknown' ),
1323+
),
1324+
array(
1325+
'metric' => 'bytes_reclaimed',
1326+
'value' => $this->format_bytes($drain['bytes_reclaimed'] ?? 0),
1327+
),
1328+
array(
1329+
'metric' => 'verify_command',
1330+
'value' => (string) ( $drain['verify_command'] ?? '' ),
1331+
),
13241332
),
13251333
array( 'metric', 'value' ),
13261334
array( 'format' => 'table' ),
@@ -1379,7 +1387,7 @@ private function render_cleanup_summary_reason_rows( string $label, array $reaso
13791387
}
13801388
WP_CLI::log('');
13811389
WP_CLI::log($label);
1382-
$rows = array();
1390+
$rows = array();
13831391
foreach ( $reasons as $reason => $bucket ) {
13841392
$bucket = (array) $bucket;
13851393
$examples = array_map(fn( $row ) => is_array($row) ? (string) ( $row['handle'] ?? '' ) : (string) $row, (array) ( $bucket['examples'] ?? array() ));
@@ -1458,11 +1466,11 @@ private function render_cleanup_plan_top_reclaimable( array $paths ): void {
14581466
WP_CLI::log('Top reclaimable paths:');
14591467
$rows = array_map(
14601468
fn( $row ) => array(
1461-
'size' => is_array($row) ? $this->format_bytes($row['size_bytes'] ?? 0) : '0 B',
1462-
'category' => is_array($row) ? (string) ( $row['category'] ?? '' ) : '',
1463-
'risk' => is_array($row) ? (string) ( $row['safety_class'] ?? '' ) : '',
1464-
'handle' => is_array($row) ? (string) ( $row['handle'] ?? '' ) : '',
1465-
'path' => is_array($row) ? (string) ( $row['path'] ?? '' ) : '',
1469+
'size' => $this->format_bytes($row['size_bytes'] ?? 0),
1470+
'category' => (string) ( $row['category'] ?? '' ),
1471+
'risk' => (string) ( $row['safety_class'] ?? '' ),
1472+
'handle' => (string) ( $row['handle'] ?? '' ),
1473+
'path' => (string) ( $row['path'] ?? '' ),
14661474
),
14671475
$paths
14681476
);

inc/Workspace/CleanupRunService.php

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414

1515
class CleanupRunService {
1616

17-
private const DEFAULT_APPLY_LIMIT = 25;
18-
private const MAX_APPLY_LIMIT = 100;
17+
private const DEFAULT_APPLY_LIMIT = 25;
18+
private const MAX_APPLY_LIMIT = 100;
1919

2020

2121

@@ -136,9 +136,12 @@ public function apply( string $run_id, array $opts = array() ): array|\WP_Error
136136
'limit' => count($artifact_batch),
137137
)
138138
);
139+
if ( $results['artifact_cleanup'] instanceof \WP_Error ) {
140+
return $results['artifact_cleanup'];
141+
}
139142
$this->record_apply_result($artifact_batch, $results['artifact_cleanup'], 'removed');
140-
$applied_rows += count((array) ( $results['artifact_cleanup']['removed'] ?? array() ));
141-
$skipped_rows += count((array) ( $results['artifact_cleanup']['skipped'] ?? array() ));
143+
$applied_rows += count( (array) ( $results['artifact_cleanup']['removed'] ?? array() ) );
144+
$skipped_rows += count( (array) ( $results['artifact_cleanup']['skipped'] ?? array() ) );
142145
}
143146

144147
$remaining_capacity = max(0, $limit - $processed_rows);
@@ -154,9 +157,12 @@ public function apply( string $run_id, array $opts = array() ): array|\WP_Error
154157
'skip_github' => true,
155158
)
156159
);
160+
if ( $results['worktree_removal'] instanceof \WP_Error ) {
161+
return $results['worktree_removal'];
162+
}
157163
$this->record_apply_result($worktree_batch, $results['worktree_removal'], 'removed');
158-
$applied_rows += count((array) ( $results['worktree_removal']['removed'] ?? array() ));
159-
$skipped_rows += count((array) ( $results['worktree_removal']['skipped'] ?? array() ));
164+
$applied_rows += count( (array) ( $results['worktree_removal']['removed'] ?? array() ) );
165+
$skipped_rows += count( (array) ( $results['worktree_removal']['skipped'] ?? array() ) );
160166
}
161167

162168
$status = $this->status($run_id);

inc/Workspace/WorkspaceCleanupPlan.php

Lines changed: 65 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -284,13 +284,13 @@ private function build_cleanup_plan_summary( array $rows, array $artifact_plan =
284284
$category_total = array_sum(array_map('intval', $category_totals));
285285

286286
return array(
287-
'total_rows' => $total_rows,
288-
'rows_by_type' => $counts,
289-
'byte_totals' => $byte_totals,
290-
'total_size_bytes' => $category_total > 0 ? $category_total : $total_bytes,
291-
'category_totals' => $category_totals,
292-
'top_reclaimable' => $this->cleanup_plan_top_reclaimable_paths($rows, (int) ( $inputs['top_n'] ?? 10 )),
293-
'blockers' => $this->cleanup_plan_blockers($artifact_plan, $worktree_plan),
287+
'total_rows' => $total_rows,
288+
'rows_by_type' => $counts,
289+
'byte_totals' => $byte_totals,
290+
'total_size_bytes' => $category_total > 0 ? $category_total : $total_bytes,
291+
'category_totals' => $category_totals,
292+
'top_reclaimable' => $this->cleanup_plan_top_reclaimable_paths($rows, (int) ( $inputs['top_n'] ?? 10 )),
293+
'blockers' => $this->cleanup_plan_blockers($artifact_plan, $worktree_plan),
294294
'recommended_commands' => $this->cleanup_plan_recommended_commands($inputs),
295295
);
296296
}
@@ -303,10 +303,10 @@ private function build_cleanup_plan_summary( array $rows, array $artifact_plan =
303303
*/
304304
private function cleanup_plan_category_totals( array $rows ): array {
305305
$totals = array(
306-
'whole_worktrees' => 0,
307-
'dependency_artifacts' => 0,
308-
'build_outputs' => 0,
309-
'caches' => 0,
306+
'whole_worktrees' => 0,
307+
'dependency_artifacts' => 0,
308+
'build_outputs' => 0,
309+
'caches' => 0,
310310
);
311311

312312
foreach ( (array) ( $rows['worktree_removal'] ?? array() ) as $row ) {
@@ -320,7 +320,7 @@ private function cleanup_plan_category_totals( array $rows ): array {
320320
if ( ! is_array($artifact) ) {
321321
continue;
322322
}
323-
$category = $this->cleanup_artifact_category( (string) ( $artifact['path'] ?? '' ));
323+
$category = $this->cleanup_artifact_category( (string) ( $artifact['path'] ?? '' ));
324324
$totals[ $category ] += max(0, (int) ( $artifact['size_bytes'] ?? 0 ));
325325
}
326326
}
@@ -361,13 +361,13 @@ private function cleanup_plan_top_reclaimable_paths( array $rows, int $limit ):
361361
continue;
362362
}
363363
$paths[] = array(
364-
'path' => (string) ( $row['path'] ?? '' ),
365-
'handle' => (string) ( $row['handle'] ?? '' ),
366-
'repo' => (string) ( $row['repo'] ?? '' ),
367-
'category' => 'whole_worktrees',
368-
'row_type' => 'worktree_removal',
369-
'safety_class' => (string) ( $row['safety_class'] ?? 'reviewed_destructive' ),
370-
'size_bytes' => max(0, (int) ( $row['size_bytes'] ?? 0 )),
364+
'path' => (string) ( $row['path'] ?? '' ),
365+
'handle' => (string) ( $row['handle'] ?? '' ),
366+
'repo' => (string) ( $row['repo'] ?? '' ),
367+
'category' => 'whole_worktrees',
368+
'row_type' => 'worktree_removal',
369+
'safety_class' => (string) ( $row['safety_class'] ?? 'reviewed_destructive' ),
370+
'size_bytes' => max(0, (int) ( $row['size_bytes'] ?? 0 )),
371371
);
372372
}
373373

@@ -380,13 +380,13 @@ private function cleanup_plan_top_reclaimable_paths( array $rows, int $limit ):
380380
continue;
381381
}
382382
$paths[] = array(
383-
'path' => (string) ( $artifact['path'] ?? '' ),
384-
'handle' => (string) ( $row['handle'] ?? '' ),
385-
'repo' => (string) ( $row['repo'] ?? '' ),
386-
'category' => $this->cleanup_artifact_category( (string) ( $artifact['path'] ?? '' )),
387-
'row_type' => 'artifact_cleanup',
388-
'safety_class' => (string) ( $row['safety_class'] ?? 'safe' ),
389-
'size_bytes' => max(0, (int) ( $artifact['size_bytes'] ?? 0 )),
383+
'path' => (string) ( $artifact['path'] ?? '' ),
384+
'handle' => (string) ( $row['handle'] ?? '' ),
385+
'repo' => (string) ( $row['repo'] ?? '' ),
386+
'category' => $this->cleanup_artifact_category( (string) ( $artifact['path'] ?? '' )),
387+
'row_type' => 'artifact_cleanup',
388+
'safety_class' => (string) ( $row['safety_class'] ?? 'safe' ),
389+
'size_bytes' => max(0, (int) ( $artifact['size_bytes'] ?? 0 )),
390390
);
391391
}
392392
}
@@ -404,7 +404,10 @@ private function cleanup_plan_top_reclaimable_paths( array $rows, int $limit ):
404404
*/
405405
private function cleanup_plan_blockers( array $artifact_plan, array $worktree_plan ): array {
406406
$blockers = array();
407-
foreach ( array( 'artifact_cleanup' => $artifact_plan, 'worktree_removal' => $worktree_plan ) as $type => $plan ) {
407+
foreach ( array(
408+
'artifact_cleanup' => $artifact_plan,
409+
'worktree_removal' => $worktree_plan,
410+
) as $type => $plan ) {
408411
foreach ( (array) ( $plan['skipped'] ?? array() ) as $row ) {
409412
if ( ! is_array($row) ) {
410413
continue;
@@ -414,21 +417,21 @@ private function cleanup_plan_blockers( array $artifact_plan, array $worktree_pl
414417
if ( '' === $repo ) {
415418
$repo = 'unknown';
416419
}
417-
$bytes = max(0, (int) ( $row['artifact_size_bytes'] ?? $row['size_bytes'] ?? 0 ));
418-
$blockers[ $reason ] ??= array(
420+
$bytes = max(0, (int) ( $row['artifact_size_bytes'] ?? $row['size_bytes'] ?? 0 ));
421+
$blockers[ $reason ] ??= array(
419422
'count' => 0,
420423
'size_bytes' => 0,
421424
'repos' => array(),
422425
'examples' => array(),
423426
);
424-
$blockers[ $reason ]['count'] = (int) $blockers[ $reason ]['count'] + 1;
425-
$blockers[ $reason ]['size_bytes'] += $bytes;
427+
$blockers[ $reason ]['count'] = (int) $blockers[ $reason ]['count'] + 1;
428+
$blockers[ $reason ]['size_bytes'] += $bytes;
426429
$blockers[ $reason ]['repos'][ $repo ] ??= array(
427430
'count' => 0,
428431
'size_bytes' => 0,
429432
'examples' => array(),
430433
);
431-
$blockers[ $reason ]['repos'][ $repo ]['count'] = (int) $blockers[ $reason ]['repos'][ $repo ]['count'] + 1;
434+
$blockers[ $reason ]['repos'][ $repo ]['count'] = (int) $blockers[ $reason ]['repos'][ $repo ]['count'] + 1;
432435
$blockers[ $reason ]['repos'][ $repo ]['size_bytes'] += $bytes;
433436
if ( count($blockers[ $reason ]['examples']) < 5 ) {
434437
$blockers[ $reason ]['examples'][] = (string) ( $row['handle'] ?? $row['path'] ?? '' );
@@ -439,9 +442,21 @@ private function cleanup_plan_blockers( array $artifact_plan, array $worktree_pl
439442
}
440443
}
441444

442-
uasort($blockers, fn( $a, $b ) => (int) ( $b['size_bytes'] ?? 0 ) <=> (int) ( $a['size_bytes'] ?? 0 ) ?: (int) ( $b['count'] ?? 0 ) <=> (int) ( $a['count'] ?? 0 ));
445+
uasort($blockers, function ( $a, $b ): int {
446+
$size_compare = (int) ( $b['size_bytes'] ?? 0 ) <=> (int) ( $a['size_bytes'] ?? 0 );
447+
if ( 0 !== $size_compare ) {
448+
return $size_compare;
449+
}
450+
return (int) ( $b['count'] ?? 0 ) <=> (int) ( $a['count'] ?? 0 );
451+
});
443452
foreach ( $blockers as &$bucket ) {
444-
uasort($bucket['repos'], fn( $a, $b ) => (int) ( $b['size_bytes'] ?? 0 ) <=> (int) ( $a['size_bytes'] ?? 0 ) ?: (int) ( $b['count'] ?? 0 ) <=> (int) ( $a['count'] ?? 0 ));
453+
uasort($bucket['repos'], function ( $a, $b ): int {
454+
$size_compare = (int) ( $b['size_bytes'] ?? 0 ) <=> (int) ( $a['size_bytes'] ?? 0 );
455+
if ( 0 !== $size_compare ) {
456+
return $size_compare;
457+
}
458+
return (int) ( $b['count'] ?? 0 ) <=> (int) ( $a['count'] ?? 0 );
459+
});
445460
}
446461
unset($bucket);
447462

@@ -457,28 +472,28 @@ private function cleanup_plan_blockers( array $artifact_plan, array $worktree_pl
457472
private function cleanup_plan_recommended_commands( array $inputs ): array {
458473
$commands = array(
459474
array(
460-
'label' => 'apply_reviewed_plan',
461-
'risk' => 'reviewed_destructive',
462-
'command' => 'studio wp datamachine-code workspace cleanup apply <run-id>',
463-
'when' => 'after reviewing this plan; revalidates every destructive row before removal',
475+
'label' => 'apply_reviewed_plan',
476+
'risk' => 'reviewed_destructive',
477+
'command' => 'studio wp datamachine-code workspace cleanup apply <run-id>',
478+
'when' => 'after reviewing this plan; revalidates every destructive row before removal',
464479
),
465480
array(
466-
'label' => 'inspect_full_plan_json',
467-
'risk' => 'none',
468-
'command' => 'studio wp datamachine-code workspace cleanup plan --mode=retention --format=json',
469-
'when' => 'export the full plan for review or archival',
481+
'label' => 'inspect_full_plan_json',
482+
'risk' => 'none',
483+
'command' => 'studio wp datamachine-code workspace cleanup plan --mode=retention --format=json',
484+
'when' => 'export the full plan for review or archival',
470485
),
471486
array(
472-
'label' => 'resolve_metadata_blockers',
473-
'risk' => 'none',
474-
'command' => 'studio wp datamachine-code workspace worktree reconcile-metadata --dry-run --limit=25 --offset=0 --until-budget=30s --format=json',
475-
'when' => 'metadata blockers prevent classification',
487+
'label' => 'resolve_metadata_blockers',
488+
'risk' => 'none',
489+
'command' => 'studio wp datamachine-code workspace worktree reconcile-metadata --dry-run --limit=25 --offset=0 --until-budget=30s --format=json',
490+
'when' => 'metadata blockers prevent classification',
476491
),
477492
array(
478-
'label' => 'refresh_merge_signals',
479-
'risk' => 'none',
480-
'command' => 'studio wp datamachine-code workspace worktree cleanup --dry-run --format=json',
481-
'when' => 'active or lifecycle rows need full merge/PR signal review',
493+
'label' => 'refresh_merge_signals',
494+
'risk' => 'none',
495+
'command' => 'studio wp datamachine-code workspace worktree cleanup --dry-run --format=json',
496+
'when' => 'active or lifecycle rows need full merge/PR signal review',
482497
),
483498
);
484499

0 commit comments

Comments
 (0)