@@ -6198,57 +6198,6 @@ private function render_worktree_cleanup_eligible_drain_result( array $result, a
61986198 }
61996199 }
62006200
6201- /**
6202- * Compact bounded cleanup JSON for chat/operator output.
6203- *
6204- * @param array<string,mixed> $result Full bounded apply result.
6205- * @return array<string,mixed>
6206- */
6207- private function compact_worktree_bounded_cleanup_eligible_apply_json ( array $ result ): array {
6208- $ summary = (array ) ( $ result ['summary ' ] ?? array () );
6209- $ candidates = (array ) ( $ result ['candidates ' ] ?? array () );
6210- $ removed = (array ) ( $ result ['removed ' ] ?? array () );
6211- $ skipped = (array ) ( $ result ['skipped ' ] ?? array () );
6212- $ buckets = $ this ->build_cleanup_blocker_buckets ($ skipped );
6213- $ actions = $ this ->build_cleanup_next_actions ($ buckets , (array ) ( $ summary ['skipped_next_commands ' ] ?? array () ));
6214-
6215- $ compact_summary = array_merge (
6216- $ summary ,
6217- array (
6218- 'processed ' => (int ) ( $ summary ['processed ' ] ?? $ summary ['inspected ' ] ?? count ($ candidates ) ),
6219- 'would_remove ' => (int ) ( $ summary ['would_remove ' ] ?? ( ! empty ($ result ['dry_run ' ]) ? count ($ candidates ) : 0 ) ),
6220- 'removed ' => (int ) ( $ summary ['removed ' ] ?? count ($ removed ) ),
6221- 'skipped ' => max ( (int ) ( $ summary ['skipped ' ] ?? 0 ), count ($ skipped ) ),
6222- 'bytes_reclaimed ' => (int ) ( $ summary ['bytes_reclaimed ' ] ?? 0 ),
6223- 'skipped_by_reason ' => array_map (fn ( $ bucket ) => (int ) ( $ bucket ['count ' ] ?? 0 ), $ buckets ),
6224- 'blocker_bucket_count ' => count ($ buckets ),
6225- )
6226- );
6227-
6228- $ report = array (
6229- 'success ' => (bool ) ( $ result ['success ' ] ?? true ),
6230- 'mode ' => (string ) ( $ result ['mode ' ] ?? 'bounded_cleanup_eligible_apply ' ),
6231- 'dry_run ' => ! empty ($ result ['dry_run ' ]),
6232- 'destructive ' => ! empty ($ result ['destructive ' ]),
6233- 'workspace_path ' => $ result ['workspace_path ' ] ?? null ,
6234- 'generated_at ' => $ result ['generated_at ' ] ?? null ,
6235- 'summary ' => $ compact_summary ,
6236- 'blocker_buckets ' => $ buckets ,
6237- 'next_actions ' => $ actions ,
6238- 'active_no_signal_triage ' => (array ) ( $ result ['active_no_signal_triage ' ] ?? array () ),
6239- 'candidates ' => $ this ->compact_cleanup_rows ($ candidates , 25 ),
6240- 'removed ' => $ this ->compact_cleanup_rows ($ removed , 25 ),
6241- 'continuation ' => $ this ->compact_cleanup_continuation ( (array ) ( $ result ['continuation ' ] ?? $ result ['pagination ' ] ?? array () ) ),
6242- 'evidence ' => $ this ->compact_cleanup_evidence ( (array ) ( $ result ['evidence ' ] ?? array () ), $ skipped ),
6243- );
6244-
6245- if ( ! empty ($ result ['job_backed ' ]) ) {
6246- $ report ['job_backed ' ] = true ;
6247- }
6248-
6249- return array_filter ($ report , fn ( $ value ) => null !== $ value );
6250- }
6251-
62526201 /**
62536202 * Render concise active/no-signal triage preview from bounded cleanup output.
62546203 *
@@ -6298,187 +6247,6 @@ private function render_active_no_signal_triage_preview( array $preview ): void
62986247 }
62996248 }
63006249
6301- /**
6302- * Build skipped blocker buckets with bounded examples.
6303- *
6304- * @param array<int,array<string,mixed>> $rows Skipped rows.
6305- * @return array<string,array<string,mixed>>
6306- */
6307- private function build_cleanup_blocker_buckets ( array $ rows ): array {
6308- $ buckets = array ();
6309- foreach ( $ rows as $ row ) {
6310- $ reason_code = (string ) ( $ row ['reason_code ' ] ?? 'unknown ' );
6311- if ( ! isset ($ buckets [ $ reason_code ]) ) {
6312- $ buckets [ $ reason_code ] = array (
6313- 'count ' => 0 ,
6314- 'examples ' => array (),
6315- 'reason ' => (string ) ( $ row ['reason ' ] ?? '' ),
6316- );
6317- }
6318- ++$ buckets [ $ reason_code ]['count ' ];
6319- if ( count ($ buckets [ $ reason_code ]['examples ' ]) < 3 ) {
6320- $ buckets [ $ reason_code ]['examples ' ][] = $ this ->compact_cleanup_row ($ row );
6321- }
6322- }
6323-
6324- ksort ($ buckets );
6325- return $ buckets ;
6326- }
6327-
6328- /**
6329- * Build compact next actions for unresolved blocker classes.
6330- *
6331- * @param array<string,array<string,mixed>> $buckets Blocker buckets.
6332- * @param array<int,array<string,mixed>> $commands Existing cleanup command hints.
6333- * @return array<int,array<string,mixed>>
6334- */
6335- private function build_cleanup_next_actions ( array $ buckets , array $ commands ): array {
6336- $ by_reason = array ();
6337- foreach ( $ commands as $ command ) {
6338- $ reason_code = (string ) ( $ command ['reason_code ' ] ?? '' );
6339- if ( '' !== $ reason_code ) {
6340- $ by_reason [ $ reason_code ] = $ command ;
6341- }
6342- }
6343-
6344- $ defaults = array (
6345- 'active_no_signal ' => array (
6346- 'command ' => 'studio wp datamachine-code workspace worktree active-no-signal-report --limit=25 --offset=0 --format=json ' ,
6347- 'destructive ' => false ,
6348- ),
6349- 'needs_metadata_reconcile ' => array (
6350- 'command ' => 'studio wp datamachine-code workspace worktree reconcile-metadata --dry-run --limit=25 --offset=0 --until-budget=30s --format=json ' ,
6351- 'destructive ' => false ,
6352- ),
6353- 'lifecycle_reconciliation_candidate ' => array (
6354- 'command ' => 'studio wp datamachine-code workspace worktree cleanup --dry-run --format=json ' ,
6355- 'destructive ' => false ,
6356- ),
6357- 'dirty_worktree ' => array (
6358- 'command ' => 'git -C <worktree-path> status --short --branch --untracked-files=normal ' ,
6359- 'destructive ' => false ,
6360- ),
6361- 'unpushed_commits ' => array (
6362- 'command ' => 'git -C <worktree-path> log --oneline --decorate @{u}..HEAD ' ,
6363- 'destructive ' => false ,
6364- ),
6365- 'stale_worktree_marker ' => array (
6366- 'command ' => 'git -C <primary-path> worktree prune --dry-run --verbose ' ,
6367- 'destructive ' => false ,
6368- ),
6369- 'primary_missing ' => array (
6370- 'command ' => 'studio wp datamachine-code workspace show <repo> ' ,
6371- 'destructive ' => false ,
6372- ),
6373- 'submodule_worktree ' => array (
6374- 'command ' => 'git -C <worktree-path> submodule status --recursive ' ,
6375- 'destructive ' => false ,
6376- ),
6377- 'remove_timeout ' => array (
6378- 'command ' => 'studio wp datamachine-code workspace worktree bounded-cleanup-eligible-apply --limit=25 --remove-timeout=<seconds> ' ,
6379- 'destructive ' => true ,
6380- ),
6381- );
6382-
6383- $ actions = array ();
6384- foreach ( $ buckets as $ reason_code => $ bucket ) {
6385- $ hint = $ by_reason [ $ reason_code ] ?? $ defaults [ $ reason_code ] ?? array (
6386- 'command ' => 'Re-run with --verbose --format=json and inspect this reason_code before retrying cleanup. ' ,
6387- 'destructive ' => false ,
6388- );
6389- $ actions [] = array (
6390- 'reason_code ' => $ reason_code ,
6391- 'count ' => (int ) ( $ bucket ['count ' ] ?? 0 ),
6392- 'command ' => (string ) ( $ hint ['command ' ] ?? '' ),
6393- 'alternative ' => (string ) ( $ hint ['alternative ' ] ?? '' ),
6394- 'destructive ' => ! empty ($ hint ['destructive ' ]),
6395- );
6396- }
6397-
6398- return $ actions ;
6399- }
6400-
6401- /**
6402- * Compact a bounded cleanup continuation without full handle lists.
6403- *
6404- * @param array<string,mixed> $continuation Continuation payload.
6405- * @return array<string,mixed>
6406- */
6407- private function compact_cleanup_continuation ( array $ continuation ): array {
6408- if ( empty ($ continuation ) ) {
6409- return array ();
6410- }
6411-
6412- $ handles = array_values (array_filter (array_map ('strval ' , (array ) ( $ continuation ['remaining_handles ' ] ?? array () ))));
6413- unset($ continuation ['remaining_handles ' ]);
6414- if ( ! isset ($ continuation ['remaining_total ' ]) && isset ($ continuation ['total ' ]) ) {
6415- $ continuation ['remaining_total ' ] = (int ) $ continuation ['total ' ];
6416- }
6417- $ continuation ['remaining_handles_count ' ] = count ($ handles );
6418- $ continuation ['remaining_handles_examples ' ] = array_slice ($ handles , 0 , 10 );
6419- if ( count ($ handles ) > 10 ) {
6420- $ continuation ['remaining_handles_truncated ' ] = true ;
6421- }
6422-
6423- return $ continuation ;
6424- }
6425-
6426- /**
6427- * Compact evidence while removing full skipped handle lists.
6428- *
6429- * @param array<string,mixed> $evidence Evidence payload.
6430- * @param array<int,array<string,mixed>> $skipped Skipped rows.
6431- * @return array<string,mixed>
6432- */
6433- private function compact_cleanup_evidence ( array $ evidence , array $ skipped ): array {
6434- $ skipped_handles = array_values (array_filter (array_map (fn ( $ row ) => (string ) ( $ row ['handle ' ] ?? '' ), $ skipped )));
6435- unset($ evidence ['skipped_handles ' ]);
6436- $ evidence ['skipped_handles_count ' ] = count ($ skipped_handles );
6437- $ evidence ['skipped_handles_examples ' ] = array_slice ($ skipped_handles , 0 , 10 );
6438- if ( count ($ skipped_handles ) > 10 ) {
6439- $ evidence ['skipped_handles_truncated ' ] = true ;
6440- }
6441- $ evidence ['full_detail_hint ' ] = 'Re-run with --verbose --format=json for full skipped rows and handle lists. ' ;
6442-
6443- return $ evidence ;
6444- }
6445-
6446- /**
6447- * Compact cleanup rows to the fields operators need first.
6448- *
6449- * @param array<int,array<string,mixed>> $rows Rows to compact.
6450- * @param int $limit Maximum rows.
6451- * @return array<int,array<string,mixed>>
6452- */
6453- private function compact_cleanup_rows ( array $ rows , int $ limit ): array {
6454- return array_map (fn ( $ row ) => $ this ->compact_cleanup_row ( (array ) $ row ), array_slice ($ rows , 0 , $ limit ));
6455- }
6456-
6457- /**
6458- * Compact one cleanup row.
6459- *
6460- * @param array<string,mixed> $row Cleanup row.
6461- * @return array<string,mixed>
6462- */
6463- private function compact_cleanup_row ( array $ row ): array {
6464- $ compact = array (
6465- 'handle ' => $ row ['handle ' ] ?? null ,
6466- 'repo ' => $ row ['repo ' ] ?? null ,
6467- 'branch ' => $ row ['branch ' ] ?? null ,
6468- 'reason_code ' => $ row ['reason_code ' ] ?? $ row ['signal ' ] ?? null ,
6469- 'reason ' => isset ($ row ['reason ' ]) ? $ this ->shorten_cleanup_reason ( (string ) $ row ['reason ' ] ) : null ,
6470- 'path ' => $ row ['path ' ] ?? null ,
6471- );
6472-
6473- foreach ( array ( 'size_bytes ' , 'artifact_size_bytes ' , 'dirty ' , 'unpushed ' , 'created_at ' , 'liveness ' , 'pr_url ' ) as $ field ) {
6474- if ( array_key_exists ($ field , $ row ) ) {
6475- $ compact [ $ field ] = $ row [ $ field ];
6476- }
6477- }
6478-
6479- return array_filter ($ compact , fn ( $ value ) => null !== $ value && '' !== $ value && array () !== $ value );
6480- }
6481-
64826250 private function render_worktree_emergency_cleanup_result ( array $ result , array $ assoc_args ): void {
64836251 $ format = isset ($ assoc_args ['format ' ]) ? (string ) $ assoc_args ['format ' ] : 'table ' ;
64846252 if ( 'json ' === $ format ) {
0 commit comments