Skip to content

Commit e17a13e

Browse files
authored
Merge pull request #730 from Extra-Chill/fix/728-artifact-cleanup-stale-lock
Surface stale lock cleanup guidance
2 parents 9462007 + 79668a8 commit e17a13e

2 files changed

Lines changed: 54 additions & 13 deletions

File tree

inc/Cli/Commands/WorkspaceCommand.php

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,17 +1318,51 @@ private function render_cleanup_control_result( array $result, array $assoc_args
13181318
* @return array<string,mixed>
13191319
*/
13201320
private function attach_current_workspace_lock_status( array $result ): array {
1321-
if ( isset($result['locks']) || ! class_exists(Workspace::class) || ! class_exists(WorkspaceMutationLock::class) ) {
1321+
if ( ! isset($result['locks']) && class_exists(Workspace::class) && class_exists(WorkspaceMutationLock::class) ) {
1322+
try {
1323+
$workspace = new Workspace();
1324+
$result['locks'] = WorkspaceMutationLock::status($workspace->get_path());
1325+
} catch ( \Throwable $e ) {
1326+
$result['locks'] = array(
1327+
'error' => $e->getMessage(),
1328+
);
1329+
}
1330+
}
1331+
1332+
return $this->attach_stale_lock_recommendation($result);
1333+
}
1334+
1335+
/**
1336+
* Promote safe stale-lock remediation above the detailed lock evidence.
1337+
*
1338+
* @param array<string,mixed> $result Cleanup result.
1339+
* @return array<string,mixed>
1340+
*/
1341+
private function attach_stale_lock_recommendation( array $result ): array {
1342+
$report = $result['locks']['stale_locks'] ?? null;
1343+
if ( ! is_array($report) || (int) ( $report['count'] ?? 0 ) <= 0 ) {
13221344
return $result;
13231345
}
13241346

1325-
try {
1326-
$workspace = new Workspace();
1327-
$result['locks'] = WorkspaceMutationLock::status($workspace->get_path());
1328-
} catch ( \Throwable $e ) {
1329-
$result['locks'] = array(
1330-
'error' => $e->getMessage(),
1331-
);
1347+
$protected = 0;
1348+
foreach ( array( 'database', 'filesystem' ) as $source ) {
1349+
foreach ( (array) ( $report[ $source ] ?? array() ) as $row ) {
1350+
if ( is_array($row) && empty($row['safe_to_prune']) ) {
1351+
++$protected;
1352+
}
1353+
}
1354+
}
1355+
1356+
$result['stale_lock_summary'] = array(
1357+
'stale_database_locks' => (int) ( $report['database_count'] ?? 0 ),
1358+
'stale_filesystem_locks' => (int) ( $report['filesystem_count'] ?? 0 ),
1359+
'active_protected_locks' => $protected,
1360+
'preview_command' => (string) ( $report['preview_command'] ?? 'wp datamachine-code workspace worktree locks --prune-stale --dry-run --format=json' ),
1361+
'prune_command' => (string) ( $report['apply_command'] ?? 'wp datamachine-code workspace worktree locks --prune-stale --format=json' ),
1362+
);
1363+
1364+
if ( 0 === $protected ) {
1365+
$result['recommended_next_step'] = $result['stale_lock_summary']['prune_command'];
13321366
}
13331367

13341368
return $result;

tests/smoke-worktree-cleanup-cli.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,11 +1342,17 @@ public function execute( array $input ): array
13421342
WP_CLI::$logs = array();
13431343
WP_CLI::$successes = array();
13441344
$command->cleanup(array( 'until-empty' ), array( 'mode' => 'artifacts', 'limit' => 11, 'max-passes' => 3, 'budget-seconds' => 60, 'force' => true, 'format' => 'json' ));
1345+
$until_empty_json = json_decode(WP_CLI::$logs[0] ?? '', true);
13451346
datamachine_code_cleanup_assert('artifacts' === ( $cleanup_until_empty_ability->last_input['mode'] ?? '' ), 'cleanup until-empty forwards artifact mode');
13461347
datamachine_code_cleanup_assert(11 === (int) ( $cleanup_until_empty_ability->last_input['limit'] ?? 0 ), 'cleanup until-empty forwards apply limit');
13471348
datamachine_code_cleanup_assert(3 === (int) ( $cleanup_until_empty_ability->last_input['max_passes'] ?? 0 ), 'cleanup until-empty forwards pass cap');
13481349
datamachine_code_cleanup_assert(60 === (int) ( $cleanup_until_empty_ability->last_input['budget_seconds'] ?? 0 ), 'cleanup until-empty forwards time budget');
13491350
datamachine_code_cleanup_assert(true === (bool) ( $cleanup_until_empty_ability->last_input['force'] ?? false ), 'cleanup until-empty forwards force flag');
1351+
datamachine_code_cleanup_assert('wp datamachine-code workspace worktree locks --prune-stale --format=json' === (string) ( $until_empty_json['recommended_next_step'] ?? '' ), 'cleanup until-empty JSON promotes safe stale lock prune command');
1352+
datamachine_code_cleanup_assert(1 === (int) ( $until_empty_json['stale_lock_summary']['stale_database_locks'] ?? 0 ), 'cleanup until-empty JSON summarizes stale DB locks at top level');
1353+
datamachine_code_cleanup_assert(0 === (int) ( $until_empty_json['stale_lock_summary']['stale_filesystem_locks'] ?? -1 ), 'cleanup until-empty JSON summarizes stale filesystem locks at top level');
1354+
datamachine_code_cleanup_assert(0 === (int) ( $until_empty_json['stale_lock_summary']['active_protected_locks'] ?? -1 ), 'cleanup until-empty JSON summarizes protected lock count at top level');
1355+
datamachine_code_cleanup_assert(1 === (int) ( $until_empty_json['locks']['stale_locks']['database_count'] ?? 0 ), 'cleanup until-empty JSON keeps detailed stale lock evidence');
13501356

13511357
WP_CLI::$logs = array();
13521358
WP_CLI::$successes = array();
@@ -1356,11 +1362,12 @@ public function execute( array $input ): array
13561362
datamachine_code_cleanup_assert('inventory' === ( $cleanup_run_ability->last_input['mode'] ?? '' ), 'cleanup run can schedule inventory mode');
13571363

13581364
WP_CLI::$logs = array();
1359-
WP_CLI::$successes = array();
1360-
$command->cleanup(array( 'status', 'cleanup-run-20260504193024-abc123' ), array( 'format' => 'json' ));
1361-
$db_status_json = json_decode(WP_CLI::$logs[0] ?? '', true);
1362-
datamachine_code_cleanup_assert('cleanup-run-20260504193024-abc123' === ( $cleanup_status_ability->last_input['run_id'] ?? '' ), 'DB cleanup run IDs are routed to cleanup status ability');
1363-
datamachine_code_cleanup_assert('planned' === ( $db_status_json['state'] ?? '' ), 'DB cleanup run status does not route to job-backed status parser');
1365+
WP_CLI::$successes = array();
1366+
$command->cleanup(array( 'status', 'cleanup-run-20260504193024-abc123' ), array( 'format' => 'json' ));
1367+
$db_status_json = json_decode(WP_CLI::$logs[0] ?? '', true);
1368+
datamachine_code_cleanup_assert('cleanup-run-20260504193024-abc123' === ( $cleanup_status_ability->last_input['run_id'] ?? '' ), 'DB cleanup run IDs are routed to cleanup status ability');
1369+
datamachine_code_cleanup_assert('planned' === ( $db_status_json['state'] ?? '' ), 'DB cleanup run status does not route to job-backed status parser');
1370+
datamachine_code_cleanup_assert('wp datamachine-code workspace worktree locks --prune-stale --format=json' === (string) ( $db_status_json['recommended_next_step'] ?? '' ), 'cleanup status JSON promotes safe stale lock prune command');
13641371
datamachine_code_cleanup_assert(1 === (int) ( $db_status_json['locks']['stale_locks']['database_count'] ?? 0 ), 'cleanup status JSON surfaces stale DB locks');
13651372
datamachine_code_cleanup_assert('wp datamachine-code workspace worktree locks --prune-stale --dry-run --format=json' === (string) ( $db_status_json['locks']['stale_locks']['preview_command'] ?? '' ), 'cleanup status JSON includes exact stale lock preview command');
13661373
datamachine_code_cleanup_assert('wp datamachine-code workspace worktree locks --prune-stale --format=json' === (string) ( $db_status_json['locks']['stale_locks']['apply_command'] ?? '' ), 'cleanup status JSON includes exact stale lock apply command');

0 commit comments

Comments
 (0)