@@ -71,6 +71,7 @@ class WorkspaceCommand extends BaseCommand {
7171 'ability ' => 'datamachine-code/workspace-worktree-active-no-signal-remote-clean-apply ' ,
7272 'input_builder ' => 'build_worktree_active_no_signal_input ' ,
7373 ),
74+ 'active-no-signal-drain ' => array ( 'ability ' => 'datamachine-code/workspace-worktree-active-no-signal-drain ' ),
7475 'refresh-context ' => array ( 'ability ' => 'datamachine-code/workspace-worktree-refresh-context ' ),
7576 'finalize ' => array ( 'ability ' => 'datamachine-code/workspace-worktree-finalize ' ),
7677 'mark-cleanup-eligible ' => array ( 'ability ' => 'datamachine-code/workspace-worktree-finalize ' ),
@@ -3220,6 +3221,7 @@ private function renderGitOperationResult( string $operation, array $result, arr
32203221 * active-no-signal-report, active-no-signal-finalized-apply,
32213222 * active-no-signal-equivalent-clean-apply,
32223223 * active-no-signal-merged-apply, active-no-signal-remote-clean-apply,
3224+ * active-no-signal-drain,
32233225 * refresh-context, finalize, mark-cleanup-eligible.
32243226 *
32253227 * [<repo>]
@@ -3419,13 +3421,15 @@ private function renderGitOperationResult( string $operation, array $result, arr
34193421 * audit.
34203422 *
34213423 * [--passes=<count>]
3422- * : For `abandoned`, maximum apply passes to run after marking eligible rows.
3424+ * : For `abandoned` and `active-no-signal-drain` , maximum apply passes to run after marking eligible rows.
34233425 * For `cleanup-eligible-drain`, maximum bounded cleanup-eligible apply
34243426 * passes to run. Preview mode always runs one non-destructive pass.
34253427 *
34263428 * [--stage=<stage>]
34273429 * : For `abandoned`, resume from a specific orchestration stage. Supported
34283430 * values: reconcile, finalized, equivalent-clean, merged, remote-clean, bounded.
3431+ * For `active-no-signal-drain`, supported values are finalized,
3432+ * equivalent-clean, merged, remote-clean, and bounded.
34293433 *
34303434 * [--offset=<count>]
34313435 * : For `cleanup --dry-run`, `cleanup-artifacts --dry-run`,
@@ -3543,6 +3547,8 @@ private function renderGitOperationResult( string $operation, array $result, arr
35433547 * # One operator pass for abandoned worktrees: reconcile, mark safe rows, remove eligible rows, and report blockers
35443548 * wp datamachine-code workspace worktree abandoned --format=json
35453549 * wp datamachine-code workspace worktree abandoned --apply --force --limit=100 --passes=5 --until-budget=120s --format=json
3550+ * wp datamachine-code workspace worktree active-no-signal-drain --format=json
3551+ * wp datamachine-code workspace worktree active-no-signal-drain --apply --limit=100 --passes=5 --until-budget=120s --format=json
35463552 *
35473553 * # Adopt/reconcile unmanaged worktree metadata before cleanup
35483554 * wp datamachine-code workspace worktree reconcile-metadata --dry-run --limit=25 --offset=0 --until-budget=30s --format=json
@@ -3590,7 +3596,7 @@ public function worktree( array $args, array $assoc_args ): void {
35903596 $ operation = $ args [0 ] ?? '' ;
35913597
35923598 if ( '' === $ operation ) {
3593- WP_CLI ::error ('Usage: wp datamachine-code workspace worktree <add|list|remove|prune|locks|cleanup|cleanup-artifacts|abandoned|bounded-cleanup-eligible-apply|cleanup-eligible-drain|emergency-cleanup|reconcile-metadata|backfill-origin-session|active-no-signal-report|active-no-signal-finalized-apply|active-no-signal-equivalent-clean-apply|active-no-signal-merged-apply|active-no-signal-remote-clean-apply|refresh-context|finalize|mark-cleanup-eligible> [<repo>] [<branch>] [--flags] ' );
3599+ WP_CLI ::error ('Usage: wp datamachine-code workspace worktree <add|list|remove|prune|locks|cleanup|cleanup-artifacts|abandoned|bounded-cleanup-eligible-apply|cleanup-eligible-drain|emergency-cleanup|reconcile-metadata|backfill-origin-session|active-no-signal-report|active-no-signal-finalized-apply|active-no-signal-equivalent-clean-apply|active-no-signal-merged-apply|active-no-signal-remote-clean-apply|active-no-signal-drain| refresh-context|finalize|mark-cleanup-eligible> [<repo>] [<branch>] [--flags] ' );
35943600 return ;
35953601 }
35963602
@@ -3604,6 +3610,16 @@ public function worktree( array $args, array $assoc_args ): void {
36043610 return ;
36053611 }
36063612
3613+ if ( 'active-no-signal-drain ' === $ operation ) {
3614+ $ result = $ this ->run_worktree_active_no_signal_drain ($ assoc_args );
3615+ if ( is_wp_error ($ result ) ) {
3616+ $ this ->render_workspace_error ($ result );
3617+ return ;
3618+ }
3619+ $ this ->render_worktree_abandoned_result ($ result , $ assoc_args );
3620+ return ;
3621+ }
3622+
36073623 if ( 'locks ' === $ operation ) {
36083624 $ workspace = new Workspace ();
36093625 $ workspace_path = $ workspace ->get_path ();
@@ -3992,6 +4008,41 @@ private function run_worktree_abandoned_orchestration( array $assoc_args ): arra
39924008 return $ ability ->execute ($ input );
39934009 }
39944010
4011+ /**
4012+ * Run the active/no-signal drain ability from CLI flags.
4013+ *
4014+ * @param array<string,mixed> $assoc_args CLI args.
4015+ * @return array<string,mixed>|\WP_Error
4016+ */
4017+ private function run_worktree_active_no_signal_drain ( array $ assoc_args ): array |\WP_Error {
4018+ if ( ! empty ($ assoc_args ['force ' ]) ) {
4019+ return new \WP_Error ('active_no_signal_drain_refuses_force ' , 'Active/no-signal drain will not force cleanup. Protected blockers remain blocked. ' , array ( 'status ' => 400 ));
4020+ }
4021+ if ( ! empty ($ assoc_args ['discard-unpushed ' ]) ) {
4022+ return new \WP_Error ('active_no_signal_drain_refuses_unpushed_discard ' , 'Active/no-signal drain will not discard unpushed commits. ' , array ( 'status ' => 400 ));
4023+ }
4024+
4025+ $ ability = wp_get_ability ('datamachine-code/workspace-worktree-active-no-signal-drain ' );
4026+ if ( ! $ ability ) {
4027+ return new \WP_Error ('active_no_signal_drain_ability_missing ' , 'Worktree active/no-signal drain ability not available: datamachine-code/workspace-worktree-active-no-signal-drain ' , array ( 'status ' => 500 ));
4028+ }
4029+
4030+ $ input = array (
4031+ 'apply ' => ! empty ($ assoc_args ['apply ' ]),
4032+ 'source ' => self ::CLEANUP_CLI_SOURCE ,
4033+ );
4034+ foreach ( array ( 'limit ' , 'passes ' , 'offset ' , 'stage ' ) as $ key ) {
4035+ if ( array_key_exists ($ key , $ assoc_args ) ) {
4036+ $ input [ $ key ] = $ assoc_args [ $ key ];
4037+ }
4038+ }
4039+ if ( isset ($ assoc_args ['until-budget ' ]) ) {
4040+ $ input ['until_budget ' ] = $ assoc_args ['until-budget ' ];
4041+ }
4042+
4043+ return $ ability ->execute ($ input );
4044+ }
4045+
39954046 /**
39964047 * Render abandoned worktree cleanup result.
39974048 *
0 commit comments