@@ -5346,6 +5346,9 @@ private function render_worktree_metadata_reconciliation_result( array $result,
53465346 private function render_worktree_active_no_signal_report_result ( array $ result , array $ assoc_args ): void {
53475347 $ format = isset ($ assoc_args ['format ' ]) ? (string ) $ assoc_args ['format ' ] : 'table ' ;
53485348 if ( 'json ' === $ format ) {
5349+ if ( empty ($ assoc_args ['verbose ' ]) ) {
5350+ $ result = WorkspaceCompactOutput::cleanup_result ($ result );
5351+ }
53495352 $ this ->renderer ()->json ($ result );
53505353 return ;
53515354 }
@@ -5436,6 +5439,9 @@ private function render_worktree_active_no_signal_report_result( array $result,
54365439 private function render_worktree_active_no_signal_finalized_apply_result ( array $ result , array $ assoc_args ): void {
54375440 $ format = isset ($ assoc_args ['format ' ]) ? (string ) $ assoc_args ['format ' ] : 'table ' ;
54385441 if ( 'json ' === $ format ) {
5442+ if ( empty ($ assoc_args ['verbose ' ]) ) {
5443+ $ result = WorkspaceCompactOutput::cleanup_result ($ result );
5444+ }
54395445 $ this ->renderer ()->json ($ result );
54405446 return ;
54415447 }
@@ -5526,6 +5532,9 @@ private function render_worktree_active_no_signal_finalized_apply_result( array
55265532 private function render_worktree_active_no_signal_equivalent_clean_apply_result ( array $ result , array $ assoc_args ): void {
55275533 $ format = isset ($ assoc_args ['format ' ]) ? (string ) $ assoc_args ['format ' ] : 'table ' ;
55285534 if ( 'json ' === $ format ) {
5535+ if ( empty ($ assoc_args ['verbose ' ]) ) {
5536+ $ result = WorkspaceCompactOutput::cleanup_result ($ result );
5537+ }
55295538 $ this ->renderer ()->json ($ result );
55305539 return ;
55315540 }
@@ -5616,6 +5625,9 @@ private function render_worktree_active_no_signal_equivalent_clean_apply_result(
56165625 private function render_worktree_active_no_signal_merged_apply_result ( array $ result , array $ assoc_args ): void {
56175626 $ format = isset ($ assoc_args ['format ' ]) ? (string ) $ assoc_args ['format ' ] : 'table ' ;
56185627 if ( 'json ' === $ format ) {
5628+ if ( empty ($ assoc_args ['verbose ' ]) ) {
5629+ $ result = WorkspaceCompactOutput::cleanup_result ($ result );
5630+ }
56195631 $ this ->renderer ()->json ($ result );
56205632 return ;
56215633 }
@@ -5706,6 +5718,9 @@ private function render_worktree_active_no_signal_merged_apply_result( array $re
57065718 private function render_worktree_active_no_signal_remote_clean_apply_result ( array $ result , array $ assoc_args ): void {
57075719 $ format = isset ($ assoc_args ['format ' ]) ? (string ) $ assoc_args ['format ' ] : 'table ' ;
57085720 if ( 'json ' === $ format ) {
5721+ if ( empty ($ assoc_args ['verbose ' ]) ) {
5722+ $ result = WorkspaceCompactOutput::cleanup_result ($ result );
5723+ }
57095724 $ this ->renderer ()->json ($ result );
57105725 return ;
57115726 }
@@ -5945,7 +5960,7 @@ private function flatten_artifact_cleanup_rows( array $rows ): array {
59455960 private function render_worktree_bounded_cleanup_eligible_apply_result ( array $ result , array $ assoc_args ): void {
59465961 $ format = isset ($ assoc_args ['format ' ]) ? (string ) $ assoc_args ['format ' ] : 'table ' ;
59475962 if ( 'json ' === $ format ) {
5948- $ report = ! empty ($ assoc_args ['verbose ' ]) ? $ result : $ this -> compact_worktree_bounded_cleanup_eligible_apply_json ($ result );
5963+ $ report = ! empty ($ assoc_args ['verbose ' ]) ? $ result : WorkspaceCompactOutput:: cleanup_result ($ result );
59495964 $ this ->renderer ()->json ($ report );
59505965 return ;
59515966 }
@@ -6183,57 +6198,6 @@ private function render_worktree_cleanup_eligible_drain_result( array $result, a
61836198 }
61846199 }
61856200
6186- /**
6187- * Compact bounded cleanup JSON for chat/operator output.
6188- *
6189- * @param array<string,mixed> $result Full bounded apply result.
6190- * @return array<string,mixed>
6191- */
6192- private function compact_worktree_bounded_cleanup_eligible_apply_json ( array $ result ): array {
6193- $ summary = (array ) ( $ result ['summary ' ] ?? array () );
6194- $ candidates = (array ) ( $ result ['candidates ' ] ?? array () );
6195- $ removed = (array ) ( $ result ['removed ' ] ?? array () );
6196- $ skipped = (array ) ( $ result ['skipped ' ] ?? array () );
6197- $ buckets = $ this ->build_cleanup_blocker_buckets ($ skipped );
6198- $ actions = $ this ->build_cleanup_next_actions ($ buckets , (array ) ( $ summary ['skipped_next_commands ' ] ?? array () ));
6199-
6200- $ compact_summary = array_merge (
6201- $ summary ,
6202- array (
6203- 'processed ' => (int ) ( $ summary ['processed ' ] ?? $ summary ['inspected ' ] ?? count ($ candidates ) ),
6204- 'would_remove ' => (int ) ( $ summary ['would_remove ' ] ?? ( ! empty ($ result ['dry_run ' ]) ? count ($ candidates ) : 0 ) ),
6205- 'removed ' => (int ) ( $ summary ['removed ' ] ?? count ($ removed ) ),
6206- 'skipped ' => max ( (int ) ( $ summary ['skipped ' ] ?? 0 ), count ($ skipped ) ),
6207- 'bytes_reclaimed ' => (int ) ( $ summary ['bytes_reclaimed ' ] ?? 0 ),
6208- 'skipped_by_reason ' => array_map (fn ( $ bucket ) => (int ) ( $ bucket ['count ' ] ?? 0 ), $ buckets ),
6209- 'blocker_bucket_count ' => count ($ buckets ),
6210- )
6211- );
6212-
6213- $ report = array (
6214- 'success ' => (bool ) ( $ result ['success ' ] ?? true ),
6215- 'mode ' => (string ) ( $ result ['mode ' ] ?? 'bounded_cleanup_eligible_apply ' ),
6216- 'dry_run ' => ! empty ($ result ['dry_run ' ]),
6217- 'destructive ' => ! empty ($ result ['destructive ' ]),
6218- 'workspace_path ' => $ result ['workspace_path ' ] ?? null ,
6219- 'generated_at ' => $ result ['generated_at ' ] ?? null ,
6220- 'summary ' => $ compact_summary ,
6221- 'blocker_buckets ' => $ buckets ,
6222- 'next_actions ' => $ actions ,
6223- 'active_no_signal_triage ' => (array ) ( $ result ['active_no_signal_triage ' ] ?? array () ),
6224- 'candidates ' => $ this ->compact_cleanup_rows ($ candidates , 25 ),
6225- 'removed ' => $ this ->compact_cleanup_rows ($ removed , 25 ),
6226- 'continuation ' => $ this ->compact_cleanup_continuation ( (array ) ( $ result ['continuation ' ] ?? $ result ['pagination ' ] ?? array () ) ),
6227- 'evidence ' => $ this ->compact_cleanup_evidence ( (array ) ( $ result ['evidence ' ] ?? array () ), $ skipped ),
6228- );
6229-
6230- if ( ! empty ($ result ['job_backed ' ]) ) {
6231- $ report ['job_backed ' ] = true ;
6232- }
6233-
6234- return array_filter ($ report , fn ( $ value ) => null !== $ value );
6235- }
6236-
62376201 /**
62386202 * Render concise active/no-signal triage preview from bounded cleanup output.
62396203 *
@@ -6283,187 +6247,6 @@ private function render_active_no_signal_triage_preview( array $preview ): void
62836247 }
62846248 }
62856249
6286- /**
6287- * Build skipped blocker buckets with bounded examples.
6288- *
6289- * @param array<int,array<string,mixed>> $rows Skipped rows.
6290- * @return array<string,array<string,mixed>>
6291- */
6292- private function build_cleanup_blocker_buckets ( array $ rows ): array {
6293- $ buckets = array ();
6294- foreach ( $ rows as $ row ) {
6295- $ reason_code = (string ) ( $ row ['reason_code ' ] ?? 'unknown ' );
6296- if ( ! isset ($ buckets [ $ reason_code ]) ) {
6297- $ buckets [ $ reason_code ] = array (
6298- 'count ' => 0 ,
6299- 'examples ' => array (),
6300- 'reason ' => (string ) ( $ row ['reason ' ] ?? '' ),
6301- );
6302- }
6303- ++$ buckets [ $ reason_code ]['count ' ];
6304- if ( count ($ buckets [ $ reason_code ]['examples ' ]) < 3 ) {
6305- $ buckets [ $ reason_code ]['examples ' ][] = $ this ->compact_cleanup_row ($ row );
6306- }
6307- }
6308-
6309- ksort ($ buckets );
6310- return $ buckets ;
6311- }
6312-
6313- /**
6314- * Build compact next actions for unresolved blocker classes.
6315- *
6316- * @param array<string,array<string,mixed>> $buckets Blocker buckets.
6317- * @param array<int,array<string,mixed>> $commands Existing cleanup command hints.
6318- * @return array<int,array<string,mixed>>
6319- */
6320- private function build_cleanup_next_actions ( array $ buckets , array $ commands ): array {
6321- $ by_reason = array ();
6322- foreach ( $ commands as $ command ) {
6323- $ reason_code = (string ) ( $ command ['reason_code ' ] ?? '' );
6324- if ( '' !== $ reason_code ) {
6325- $ by_reason [ $ reason_code ] = $ command ;
6326- }
6327- }
6328-
6329- $ defaults = array (
6330- 'active_no_signal ' => array (
6331- 'command ' => 'studio wp datamachine-code workspace worktree active-no-signal-report --limit=25 --offset=0 --format=json ' ,
6332- 'destructive ' => false ,
6333- ),
6334- 'needs_metadata_reconcile ' => array (
6335- 'command ' => 'studio wp datamachine-code workspace worktree reconcile-metadata --dry-run --limit=25 --offset=0 --until-budget=30s --format=json ' ,
6336- 'destructive ' => false ,
6337- ),
6338- 'lifecycle_reconciliation_candidate ' => array (
6339- 'command ' => 'studio wp datamachine-code workspace worktree cleanup --dry-run --format=json ' ,
6340- 'destructive ' => false ,
6341- ),
6342- 'dirty_worktree ' => array (
6343- 'command ' => 'git -C <worktree-path> status --short --branch --untracked-files=normal ' ,
6344- 'destructive ' => false ,
6345- ),
6346- 'unpushed_commits ' => array (
6347- 'command ' => 'git -C <worktree-path> log --oneline --decorate @{u}..HEAD ' ,
6348- 'destructive ' => false ,
6349- ),
6350- 'stale_worktree_marker ' => array (
6351- 'command ' => 'git -C <primary-path> worktree prune --dry-run --verbose ' ,
6352- 'destructive ' => false ,
6353- ),
6354- 'primary_missing ' => array (
6355- 'command ' => 'studio wp datamachine-code workspace show <repo> ' ,
6356- 'destructive ' => false ,
6357- ),
6358- 'submodule_worktree ' => array (
6359- 'command ' => 'git -C <worktree-path> submodule status --recursive ' ,
6360- 'destructive ' => false ,
6361- ),
6362- 'remove_timeout ' => array (
6363- 'command ' => 'studio wp datamachine-code workspace worktree bounded-cleanup-eligible-apply --limit=25 --remove-timeout=<seconds> ' ,
6364- 'destructive ' => true ,
6365- ),
6366- );
6367-
6368- $ actions = array ();
6369- foreach ( $ buckets as $ reason_code => $ bucket ) {
6370- $ hint = $ by_reason [ $ reason_code ] ?? $ defaults [ $ reason_code ] ?? array (
6371- 'command ' => 'Re-run with --verbose --format=json and inspect this reason_code before retrying cleanup. ' ,
6372- 'destructive ' => false ,
6373- );
6374- $ actions [] = array (
6375- 'reason_code ' => $ reason_code ,
6376- 'count ' => (int ) ( $ bucket ['count ' ] ?? 0 ),
6377- 'command ' => (string ) ( $ hint ['command ' ] ?? '' ),
6378- 'alternative ' => (string ) ( $ hint ['alternative ' ] ?? '' ),
6379- 'destructive ' => ! empty ($ hint ['destructive ' ]),
6380- );
6381- }
6382-
6383- return $ actions ;
6384- }
6385-
6386- /**
6387- * Compact a bounded cleanup continuation without full handle lists.
6388- *
6389- * @param array<string,mixed> $continuation Continuation payload.
6390- * @return array<string,mixed>
6391- */
6392- private function compact_cleanup_continuation ( array $ continuation ): array {
6393- if ( empty ($ continuation ) ) {
6394- return array ();
6395- }
6396-
6397- $ handles = array_values (array_filter (array_map ('strval ' , (array ) ( $ continuation ['remaining_handles ' ] ?? array () ))));
6398- unset($ continuation ['remaining_handles ' ]);
6399- if ( ! isset ($ continuation ['remaining_total ' ]) && isset ($ continuation ['total ' ]) ) {
6400- $ continuation ['remaining_total ' ] = (int ) $ continuation ['total ' ];
6401- }
6402- $ continuation ['remaining_handles_count ' ] = count ($ handles );
6403- $ continuation ['remaining_handles_examples ' ] = array_slice ($ handles , 0 , 10 );
6404- if ( count ($ handles ) > 10 ) {
6405- $ continuation ['remaining_handles_truncated ' ] = true ;
6406- }
6407-
6408- return $ continuation ;
6409- }
6410-
6411- /**
6412- * Compact evidence while removing full skipped handle lists.
6413- *
6414- * @param array<string,mixed> $evidence Evidence payload.
6415- * @param array<int,array<string,mixed>> $skipped Skipped rows.
6416- * @return array<string,mixed>
6417- */
6418- private function compact_cleanup_evidence ( array $ evidence , array $ skipped ): array {
6419- $ skipped_handles = array_values (array_filter (array_map (fn ( $ row ) => (string ) ( $ row ['handle ' ] ?? '' ), $ skipped )));
6420- unset($ evidence ['skipped_handles ' ]);
6421- $ evidence ['skipped_handles_count ' ] = count ($ skipped_handles );
6422- $ evidence ['skipped_handles_examples ' ] = array_slice ($ skipped_handles , 0 , 10 );
6423- if ( count ($ skipped_handles ) > 10 ) {
6424- $ evidence ['skipped_handles_truncated ' ] = true ;
6425- }
6426- $ evidence ['full_detail_hint ' ] = 'Re-run with --verbose --format=json for full skipped rows and handle lists. ' ;
6427-
6428- return $ evidence ;
6429- }
6430-
6431- /**
6432- * Compact cleanup rows to the fields operators need first.
6433- *
6434- * @param array<int,array<string,mixed>> $rows Rows to compact.
6435- * @param int $limit Maximum rows.
6436- * @return array<int,array<string,mixed>>
6437- */
6438- private function compact_cleanup_rows ( array $ rows , int $ limit ): array {
6439- return array_map (fn ( $ row ) => $ this ->compact_cleanup_row ( (array ) $ row ), array_slice ($ rows , 0 , $ limit ));
6440- }
6441-
6442- /**
6443- * Compact one cleanup row.
6444- *
6445- * @param array<string,mixed> $row Cleanup row.
6446- * @return array<string,mixed>
6447- */
6448- private function compact_cleanup_row ( array $ row ): array {
6449- $ compact = array (
6450- 'handle ' => $ row ['handle ' ] ?? null ,
6451- 'repo ' => $ row ['repo ' ] ?? null ,
6452- 'branch ' => $ row ['branch ' ] ?? null ,
6453- 'reason_code ' => $ row ['reason_code ' ] ?? $ row ['signal ' ] ?? null ,
6454- 'reason ' => isset ($ row ['reason ' ]) ? $ this ->shorten_cleanup_reason ( (string ) $ row ['reason ' ] ) : null ,
6455- 'path ' => $ row ['path ' ] ?? null ,
6456- );
6457-
6458- foreach ( array ( 'size_bytes ' , 'artifact_size_bytes ' , 'dirty ' , 'unpushed ' , 'created_at ' , 'liveness ' , 'pr_url ' ) as $ field ) {
6459- if ( array_key_exists ($ field , $ row ) ) {
6460- $ compact [ $ field ] = $ row [ $ field ];
6461- }
6462- }
6463-
6464- return array_filter ($ compact , fn ( $ value ) => null !== $ value && '' !== $ value && array () !== $ value );
6465- }
6466-
64676250 private function render_worktree_emergency_cleanup_result ( array $ result , array $ assoc_args ): void {
64686251 $ format = isset ($ assoc_args ['format ' ]) ? (string ) $ assoc_args ['format ' ] : 'table ' ;
64696252 if ( 'json ' === $ format ) {
0 commit comments