@@ -626,8 +626,8 @@ public function execute( array $input ): array // phpcs:ignore Generic.CodeAnal
626626 }
627627 }
628628
629- class FakeListAbility
630- {
629+ class FakeListAbility
630+ {
631631 public function execute ( array $ input ): array // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
632632 {
633633 return array (
@@ -673,12 +673,57 @@ public function execute( array $input ): array // phpcs:ignore Generic.CodeAnal
673673 ),
674674 ),
675675 );
676- }
677- }
678-
679- class FakeCleanupRunAbility
680- {
681- public array $ last_input = array ();
676+ }
677+ }
678+
679+ class FakeWorkspaceListAbility
680+ {
681+ public function execute ( array $ input ): array // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
682+ {
683+ return array (
684+ 'success ' => true ,
685+ 'path ' => '/workspace ' ,
686+ 'repos ' => array (
687+ array (
688+ 'name ' => 'repo ' ,
689+ 'repo ' => 'repo ' ,
690+ 'branch ' => 'main ' ,
691+ 'remote ' => 'https://example.com/repo.git ' ,
692+ 'git ' => true ,
693+ 'is_worktree ' => false ,
694+ 'path ' => '/workspace/repo ' ,
695+ ),
696+ array (
697+ 'name ' => 'repo@feature-one ' ,
698+ 'repo ' => 'repo ' ,
699+ 'branch ' => 'feature/one ' ,
700+ 'git ' => true ,
701+ 'is_worktree ' => true ,
702+ 'path ' => '/workspace/repo@feature-one ' ,
703+ ),
704+ array (
705+ 'name ' => 'docs@cleanup ' ,
706+ 'repo ' => 'docs ' ,
707+ 'branch ' => 'cleanup ' ,
708+ 'git ' => false ,
709+ 'is_worktree ' => true ,
710+ 'path ' => '/workspace/docs@cleanup ' ,
711+ ),
712+ array (
713+ 'name ' => 'context-docs ' ,
714+ 'repo ' => 'docs ' ,
715+ 'git ' => true ,
716+ 'is_context ' => true ,
717+ 'path ' => '/workspace/docs ' ,
718+ ),
719+ ),
720+ );
721+ }
722+ }
723+
724+ class FakeCleanupRunAbility
725+ {
726+ public array $ last_input = array ();
682727
683728 public function execute ( array $ input ): array
684729 {
@@ -691,11 +736,31 @@ public function execute( array $input ): array
691736 'mode ' => (string ) ( $ input ['mode ' ] ?? '' ),
692737 'task_type ' => 'workspace_retention_cleanup ' ,
693738 );
694- }
695- }
696-
697- class FakeCleanupStatusAbility
698- {
739+ }
740+ }
741+
742+ class FakeCleanupPlanAbility
743+ {
744+ public array $ last_input = array ();
745+
746+ public function execute ( array $ input ): array
747+ {
748+ $ this ->last_input = $ input ;
749+ return array (
750+ 'success ' => true ,
751+ 'run_id ' => 'cleanup-run-20260612000000-test ' ,
752+ 'plan_id ' => 'cleanup-plan-test ' ,
753+ 'inputs ' => $ input ,
754+ 'summary ' => array (
755+ 'total_rows ' => 2 ,
756+ 'total_size_bytes ' => 4096 ,
757+ ),
758+ );
759+ }
760+ }
761+
762+ class FakeCleanupStatusAbility
763+ {
699764 public array $ last_input = array ();
700765
701766 public function execute ( array $ input ): array
@@ -887,17 +952,21 @@ public function execute( array $input ): array
887952 $ active_merged_ability = new FakeActiveNoSignalAbility ('merged-apply ' );
888953 $ active_remote_clean_ability = new FakeActiveNoSignalAbility ('remote-clean-apply ' );
889954 $ reconcile_metadata_ability = new FakeReconcileMetadataAbility ();
890- $ bounded_apply_ability = new FakeBoundedCleanupEligibleApplyAbility ();
891- $ prune_ability = new FakePruneAbility ();
892- $ list_ability = new FakeListAbility ();
893- $ cleanup_run_ability = new FakeCleanupRunAbility ();
894- $ cleanup_status_ability = new FakeCleanupStatusAbility ();
955+ $ bounded_apply_ability = new FakeBoundedCleanupEligibleApplyAbility ();
956+ $ prune_ability = new FakePruneAbility ();
957+ $ list_ability = new FakeListAbility ();
958+ $ workspace_list_ability = new FakeWorkspaceListAbility ();
959+ $ cleanup_run_ability = new FakeCleanupRunAbility ();
960+ $ cleanup_plan_ability = new FakeCleanupPlanAbility ();
961+ $ cleanup_status_ability = new FakeCleanupStatusAbility ();
895962 $ hygiene_ability = new FakeHygieneAbility ();
896963 $ get_jobs_ability = new FakeGetJobsAbility ();
897964 $ retry_job_ability = new FakeRetryJobAbility ();
898965 $ fail_job_ability = new FakeFailJobAbility ();
899- $ GLOBALS ['__abilities ' ] = array (
900- 'datamachine-code/workspace-cleanup-run ' => $ cleanup_run_ability ,
966+ $ GLOBALS ['__abilities ' ] = array (
967+ 'datamachine-code/workspace-list ' => $ workspace_list_ability ,
968+ 'datamachine-code/workspace-cleanup-plan ' => $ cleanup_plan_ability ,
969+ 'datamachine-code/workspace-cleanup-run ' => $ cleanup_run_ability ,
901970 'datamachine-code/workspace-cleanup-apply ' => $ cleanup_status_ability ,
902971 'datamachine-code/workspace-cleanup-status ' => $ cleanup_status_ability ,
903972 'datamachine-code/workspace-cleanup-resume ' => $ cleanup_status_ability ,
@@ -943,14 +1012,51 @@ public function execute( array $input ): array
9431012 datamachine_code_cleanup_assert (str_contains ($ doc_comment , 'workspace cleanup plan --mode=retention ' ), 'worktree examples include DB-backed cleanup plan ' );
9441013 datamachine_code_cleanup_assert (str_contains ($ doc_comment , 'workspace cleanup run --mode=retention ' ), 'worktree examples include task-backed cleanup run ' );
9451014 datamachine_code_cleanup_assert (! str_contains ($ doc_comment , '> cleanup-plan.json ' ), 'worktree examples do not normalize cleanup-plan file redirection ' );
946- datamachine_code_cleanup_assert (! str_contains ($ doc_comment , '> artifact-plan.json ' ), 'worktree examples do not normalize artifact-plan file redirection ' );
947- datamachine_code_cleanup_assert (! str_contains ($ doc_comment , '> emergency-plan.json ' ), 'worktree examples do not normalize emergency-plan file redirection ' );
948- datamachine_code_cleanup_assert (! str_contains ($ doc_comment , '> reconcile-plan.json ' ), 'worktree examples do not normalize reconcile-plan file redirection ' );
949-
950- echo "\n[0b] task-backed workspace cleanup run/status/control output \n" ;
951- WP_CLI ::$ logs = array ();
952- WP_CLI ::$ successes = array ();
953- $ command ->cleanup (array ( 'run ' ), array ( 'mode ' => 'retention ' , 'format ' => 'json ' ));
1015+ datamachine_code_cleanup_assert (! str_contains ($ doc_comment , '> artifact-plan.json ' ), 'worktree examples do not normalize artifact-plan file redirection ' );
1016+ datamachine_code_cleanup_assert (! str_contains ($ doc_comment , '> emergency-plan.json ' ), 'worktree examples do not normalize emergency-plan file redirection ' );
1017+ datamachine_code_cleanup_assert (! str_contains ($ doc_comment , '> reconcile-plan.json ' ), 'worktree examples do not normalize reconcile-plan file redirection ' );
1018+
1019+ echo "\n[0a2] workspace list compact triage output \n" ;
1020+ WP_CLI ::$ logs = array ();
1021+ WP_CLI ::$ successes = array ();
1022+ $ command ->list_repos (array (), array ( 'summary ' => true ));
1023+ datamachine_code_cleanup_assert (in_array ('Workspace: /workspace ' , WP_CLI ::$ logs , true ), 'workspace list --summary prints workspace path ' );
1024+ datamachine_code_cleanup_assert (in_array ('table:5:metric,count ' , WP_CLI ::$ logs , true ), 'workspace list --summary prints compact metric counts ' );
1025+ datamachine_code_cleanup_assert (in_array ('table:2:repo,primary,worktree,context,total ' , WP_CLI ::$ logs , true ), 'workspace list --summary groups counts by repo ' );
1026+
1027+ WP_CLI ::$ logs = array ();
1028+ WP_CLI ::$ successes = array ();
1029+ $ command ->list_repos (array (), array ( 'summary ' => true , 'format ' => 'json ' ));
1030+ $ list_summary_json = json_decode (WP_CLI ::$ logs [0 ] ?? '' , true );
1031+ datamachine_code_cleanup_assert (4 === (int ) ( $ list_summary_json ['total ' ] ?? 0 ), 'workspace list --summary JSON keeps total count ' );
1032+ datamachine_code_cleanup_assert (2 === (int ) ( $ list_summary_json ['worktree ' ] ?? 0 ), 'workspace list --summary JSON counts worktrees ' );
1033+ datamachine_code_cleanup_assert (1 === (int ) ( $ list_summary_json ['non_git ' ] ?? 0 ), 'workspace list --summary JSON counts non-git rows ' );
1034+
1035+ echo "\n[0b] task-backed workspace cleanup run/status/control output \n" ;
1036+ WP_CLI ::$ logs = array ();
1037+ WP_CLI ::$ successes = array ();
1038+ $ command ->cleanup (array ( 'plan ' ), array ( 'mode ' => 'retention ' ));
1039+ datamachine_code_cleanup_assert ('retention ' === ( $ cleanup_plan_ability ->last_input ['mode ' ] ?? '' ), 'cleanup plan receives retention mode ' );
1040+ datamachine_code_cleanup_assert (false === ( $ cleanup_plan_ability ->last_input ['include_artifacts ' ] ?? true ), 'retention cleanup plan skips exhaustive artifact scan by default ' );
1041+ datamachine_code_cleanup_assert (true === ( $ cleanup_plan_ability ->last_input ['include_worktrees ' ] ?? false ), 'retention cleanup plan keeps inventory worktree planning enabled ' );
1042+ datamachine_code_cleanup_assert (in_array ('Planning cleanup (retention; worktree inventory only)... ' , WP_CLI ::$ logs , true ), 'human cleanup plan reports bounded scan profile before planning ' );
1043+ datamachine_code_cleanup_assert (in_array ('Artifacts: skipped for bounded retention planning; run `wp datamachine-code workspace cleanup plan --mode=artifacts` when you want artifact rows. ' , WP_CLI ::$ logs , true ), 'human cleanup plan shows explicit artifact follow-up command ' );
1044+
1045+ WP_CLI ::$ logs = array ();
1046+ WP_CLI ::$ successes = array ();
1047+ $ command ->cleanup (array ( 'plan ' ), array ( 'mode ' => 'retention ' , 'include-artifacts ' => true , 'format ' => 'json ' ));
1048+ datamachine_code_cleanup_assert (true === ( $ cleanup_plan_ability ->last_input ['include_artifacts ' ] ?? false ), 'retention cleanup plan can explicitly include artifacts ' );
1049+ datamachine_code_cleanup_assert ('{ ' === substr (WP_CLI ::$ logs [0 ] ?? '' , 0 , 1 ), 'json cleanup plan output is not prefixed by progress text ' );
1050+
1051+ WP_CLI ::$ logs = array ();
1052+ WP_CLI ::$ successes = array ();
1053+ $ command ->cleanup (array ( 'plan ' ), array ( 'mode ' => 'artifacts ' , 'format ' => 'json ' ));
1054+ datamachine_code_cleanup_assert (true === ( $ cleanup_plan_ability ->last_input ['include_artifacts ' ] ?? false ), 'artifact cleanup plan includes artifact scan ' );
1055+ datamachine_code_cleanup_assert (false === ( $ cleanup_plan_ability ->last_input ['include_worktrees ' ] ?? true ), 'artifact cleanup plan skips worktree removal rows ' );
1056+
1057+ WP_CLI ::$ logs = array ();
1058+ WP_CLI ::$ successes = array ();
1059+ $ command ->cleanup (array ( 'run ' ), array ( 'mode ' => 'retention ' , 'format ' => 'json ' ));
9541060 $ run_json = json_decode (WP_CLI ::$ logs [0 ] ?? '' , true );
9551061 datamachine_code_cleanup_assert ('jobs_queued ' === ( $ run_json ['state ' ] ?? '' ), 'cleanup run queues a system task ' );
9561062 datamachine_code_cleanup_assert ('cleanup-run-123 ' === ( $ run_json ['run_id ' ] ?? '' ), 'cleanup run returns stable run id ' );
0 commit comments