Skip to content

Commit 73d5e2e

Browse files
authored
Merge pull request #585 from Extra-Chill/fix-abandoned-cleanup-compact-json
Compact abandoned cleanup JSON blockers
2 parents 688d0af + 9031e8f commit 73d5e2e

2 files changed

Lines changed: 90 additions & 12 deletions

File tree

inc/Cli/Commands/WorkspaceCommand.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3316,6 +3316,9 @@ private function merge_worktree_abandoned_blockers( array $existing, array $inco
33163316
*/
33173317
private function render_worktree_abandoned_result( array $result, array $assoc_args ): void {
33183318
if ( 'json' === (string) ( $assoc_args['format'] ?? '' ) ) {
3319+
if ( empty($assoc_args['verbose']) ) {
3320+
$result = $this->compact_worktree_abandoned_result($result);
3321+
}
33193322
$json = wp_json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
33203323
WP_CLI::log(false === $json ? '{}' : $json);
33213324
return;
@@ -3390,6 +3393,48 @@ private function render_worktree_abandoned_result( array $result, array $assoc_a
33903393
}
33913394
}
33923395

3396+
/**
3397+
* Trim large abandoned cleanup JSON output while preserving summary counts.
3398+
*
3399+
* @param array<string,mixed> $result Abandoned cleanup result.
3400+
* @return array<string,mixed>
3401+
*/
3402+
private function compact_worktree_abandoned_result( array $result ): array {
3403+
$blocked = (array) ( $result['blocked'] ?? array() );
3404+
if ( count($blocked) <= 25 ) {
3405+
return $result;
3406+
}
3407+
3408+
$examples_by_reason = array();
3409+
foreach ( $blocked as $row ) {
3410+
if ( ! is_array($row) ) {
3411+
continue;
3412+
}
3413+
3414+
$reason = (string) ( $row['reason_code'] ?? 'unknown' );
3415+
if ( count($examples_by_reason[ $reason ] ?? array()) >= 3 ) {
3416+
continue;
3417+
}
3418+
3419+
$examples_by_reason[ $reason ][] = array(
3420+
'handle' => (string) ( $row['handle'] ?? '' ),
3421+
'repo' => (string) ( $row['repo'] ?? '' ),
3422+
'branch' => (string) ( $row['branch'] ?? '' ),
3423+
'reason_code' => $reason,
3424+
'reason' => (string) ( $row['reason'] ?? '' ),
3425+
'unpushed' => isset($row['unpushed']) ? (int) $row['unpushed'] : null,
3426+
);
3427+
}
3428+
3429+
$result['blocked_examples'] = $examples_by_reason;
3430+
$result['evidence']['blocked_truncated'] = true;
3431+
$result['evidence']['blocked_full_rows'] = count($blocked);
3432+
$result['evidence']['blocked_full_hint'] = 'Re-run with --verbose --format=json to include full blocked rows.';
3433+
$result['blocked'] = array();
3434+
3435+
return $result;
3436+
}
3437+
33933438
/**
33943439
* Render CLI output for worktree operations.
33953440
*

tests/smoke-worktree-cleanup-cli.php

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -539,23 +539,13 @@ class FakeBoundedCleanupEligibleApplyAbility
539539
{
540540
public array $last_input = array();
541541
public array $inputs = array();
542+
public int $extra_skipped = 0;
542543

543544
public function execute( array $input ): array
544545
{
545546
$this->last_input = $input;
546547
$this->inputs[] = $input;
547-
return array(
548-
'success' => true,
549-
'mode' => 'bounded_cleanup_eligible_apply',
550-
'dry_run' => ! empty($input['dry_run']),
551-
'summary' => array(
552-
'inspected' => 3,
553-
'would_remove' => ! empty($input['dry_run']) ? 1 : 0,
554-
'removed' => empty($input['dry_run']) ? 1 : 0,
555-
'skipped' => 2,
556-
'bytes_reclaimed' => empty($input['dry_run']) ? 4096 : 0,
557-
),
558-
'skipped' => array(
548+
$skipped = array(
559549
array(
560550
'handle' => 'repo@dirty',
561551
'repo' => 'repo',
@@ -576,7 +566,30 @@ public function execute( array $input ): array
576566
'dirty' => 0,
577567
'unpushed' => 2,
578568
),
569+
);
570+
for ( $i = 0; $i < $this->extra_skipped; ++$i ) {
571+
$skipped[] = array(
572+
'handle' => 'repo@blocked-' . $i,
573+
'repo' => 'repo',
574+
'branch' => 'blocked-' . $i,
575+
'path' => '/workspace/repo@blocked-' . $i,
576+
'reason_code' => 0 === $i % 2 ? 'active_no_signal' : 'needs_metadata_reconcile',
577+
'reason' => 'large blocked output fixture',
578+
);
579+
}
580+
581+
return array(
582+
'success' => true,
583+
'mode' => 'bounded_cleanup_eligible_apply',
584+
'dry_run' => ! empty($input['dry_run']),
585+
'summary' => array(
586+
'inspected' => 3,
587+
'would_remove' => ! empty($input['dry_run']) ? 1 : 0,
588+
'removed' => empty($input['dry_run']) ? 1 : 0,
589+
'skipped' => 2,
590+
'bytes_reclaimed' => empty($input['dry_run']) ? 4096 : 0,
579591
),
592+
'skipped' => $skipped,
580593
);
581594
}
582595
}
@@ -1145,6 +1158,26 @@ public function execute( array $input ): array
11451158
datamachine_code_cleanup_assert(2 === (int) ( $abandoned_json['summary']['blocked'] ?? 0 ), 'abandoned summary reports blocked rows');
11461159
datamachine_code_cleanup_assert(1 === (int) ( $abandoned_json['summary']['blocked_by_reason']['unpushed_commits'] ?? 0 ), 'abandoned preserves unpushed-commit blocker evidence');
11471160

1161+
$bounded_apply_ability->extra_skipped = 30;
1162+
WP_CLI::$logs = array();
1163+
WP_CLI::$successes = array();
1164+
$command->worktree(array( 'abandoned' ), array( 'apply' => true, 'force' => true, 'stage' => 'bounded', 'limit' => 10, 'passes' => 1, 'format' => 'json' ));
1165+
$abandoned_compact_json = json_decode(WP_CLI::$logs[0] ?? '', true);
1166+
datamachine_code_cleanup_assert(JSON_ERROR_NONE === json_last_error(), 'abandoned compact JSON output parses cleanly');
1167+
datamachine_code_cleanup_assert(32 === (int) ( $abandoned_compact_json['summary']['blocked'] ?? 0 ), 'abandoned compact JSON keeps blocked summary count');
1168+
datamachine_code_cleanup_assert(array() === ( $abandoned_compact_json['blocked'] ?? null ), 'abandoned compact JSON omits full blocked rows');
1169+
datamachine_code_cleanup_assert(true === ( $abandoned_compact_json['evidence']['blocked_truncated'] ?? false ), 'abandoned compact JSON records blocked truncation evidence');
1170+
datamachine_code_cleanup_assert(isset($abandoned_compact_json['blocked_examples']['active_no_signal'][0]['handle']), 'abandoned compact JSON includes grouped blocked examples');
1171+
1172+
WP_CLI::$logs = array();
1173+
WP_CLI::$successes = array();
1174+
$command->worktree(array( 'abandoned' ), array( 'apply' => true, 'force' => true, 'stage' => 'bounded', 'limit' => 10, 'passes' => 1, 'verbose' => true, 'format' => 'json' ));
1175+
$abandoned_verbose_json = json_decode(WP_CLI::$logs[0] ?? '', true);
1176+
datamachine_code_cleanup_assert(JSON_ERROR_NONE === json_last_error(), 'abandoned verbose JSON output parses cleanly');
1177+
datamachine_code_cleanup_assert(32 === count($abandoned_verbose_json['blocked'] ?? array()), 'abandoned verbose JSON keeps full blocked rows');
1178+
datamachine_code_cleanup_assert(! isset($abandoned_verbose_json['evidence']['blocked_truncated']), 'abandoned verbose JSON does not report truncation');
1179+
$bounded_apply_ability->extra_skipped = 0;
1180+
11481181
$reconcile_call_count = count($reconcile_metadata_ability->inputs);
11491182
WP_CLI::$logs = array();
11501183
WP_CLI::$successes = array();

0 commit comments

Comments
 (0)