Skip to content

Commit eb2d332

Browse files
authored
Improve cleanup blocker follow-up reports (#657)
1 parent 2735bce commit eb2d332

3 files changed

Lines changed: 137 additions & 13 deletions

File tree

inc/Cleanup/CleanupRemainingWorkSummary.php

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,30 +220,53 @@ function ( array $command ) use ( &$seen ): bool {
220220
private static function command_for_reason( string $reason, string $bucket ): array {
221221
$command = match ( $reason ) {
222222
'needs_metadata_reconcile', 'lifecycle_reconciliation_candidate', 'repaired_metadata' => self::METADATA_RECONCILE_COMMAND,
223-
'dirty_worktree', 'unpushed_commits', 'probe_timeout', 'plan_mismatch' => 'studio wp datamachine-code workspace cleanup run --mode=retention --dry-run --format=json',
223+
'dirty_worktree' => 'git -C <worktree-path> status --short --branch --untracked-files=normal',
224+
'unpushed_commits' => 'git -C <worktree-path> log --oneline --decorate @{u}..HEAD',
225+
'stale_worktree_marker' => 'git -C <primary-path> worktree prune --dry-run --verbose',
226+
'primary_missing' => 'studio wp datamachine-code workspace show <repo>',
227+
'probe_timeout', 'plan_mismatch' => 'studio wp datamachine-code workspace cleanup run --mode=retention --dry-run --format=json',
224228
'artifact_already_removed', 'artifact_plan_mismatch' => 'studio wp datamachine-code workspace cleanup run --mode=artifacts --dry-run --format=json',
225229
default => 'studio wp datamachine-code workspace cleanup run --mode=retention --dry-run --format=json',
226230
};
227231

228-
return array(
232+
$entry = array(
229233
'bucket' => $bucket . ':' . $reason,
230234
'command' => $command,
231235
'destructive' => false,
232236
'apply_destructive' => false,
233237
'why' => self::reason_remediation($reason),
234238
);
239+
240+
$alternative = self::reason_alternative($reason);
241+
if ( '' !== $alternative ) {
242+
$entry['alternative'] = $alternative;
243+
}
244+
245+
return $entry;
235246
}
236247

237248
private static function reason_remediation( string $reason ): string {
238249
return match ( $reason ) {
239-
'dirty_worktree' => 'Inspect dirty files before applying cleanup; artifact-only dirt may be removable through artifact cleanup, source dirt needs review.',
250+
'dirty_worktree' => 'Inspect dirty files before applying cleanup; classify artifact-only dirt versus source edits before preserving, committing, or cleaning up.',
240251
'artifact_plan_mismatch', 'plan_mismatch' => 'Regenerate a fresh plan because the saved row no longer matches current filesystem or branch state.',
241252
'artifact_plan_not_current', 'artifact_already_removed' => 'Regenerate artifact cleanup evidence; the saved artifact row is no longer a current candidate.',
242253
'needs_metadata_reconcile' => 'Run metadata reconciliation so DMC can classify the worktree without a full cleanup scan.',
243254
'lifecycle_reconciliation_candidate' => 'Run lifecycle reconciliation to collect PR/merge signals before emitting removal rows.',
244-
'unpushed_commits' => 'Push, merge, or intentionally abandon commits before retrying cleanup.',
255+
'unpushed_commits' => 'Inspect commits ahead of upstream so the operator can push, merge, preserve, or intentionally abandon before retrying cleanup.',
256+
'stale_worktree_marker' => 'Preview stale git worktree metadata pruning and repair registry metadata only after confirming the marker is stale.',
257+
'primary_missing' => 'Recover, adopt, or recreate the missing primary checkout before worktree removal can be routed through git safely.',
245258
'probe_timeout' => 'Retry the review path with a smaller bounded page or investigate the git probe timeout.',
246259
default => 'Run the review command to refresh evidence before applying cleanup.',
247260
};
248261
}
262+
263+
private static function reason_alternative( string $reason ): string {
264+
return match ( $reason ) {
265+
'dirty_worktree' => 'studio wp datamachine-code workspace cleanup run --mode=retention --dry-run --only=dirty_worktree --verbose --format=json',
266+
'unpushed_commits' => 'studio wp datamachine-code workspace cleanup run --mode=retention --dry-run --only=unpushed_commits --verbose --format=json',
267+
'stale_worktree_marker' => self::METADATA_RECONCILE_COMMAND,
268+
'primary_missing' => 'If the checkout is gone, recreate it with `studio wp datamachine-code workspace clone <remote-url> --name=<repo>` or adopt the existing primary checkout with `studio wp datamachine-code workspace adopt <path> --name=<repo>`.',
269+
default => '',
270+
};
271+
}
249272
}

inc/Workspace/WorkspaceWorktreeCleanupEngine.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1729,6 +1729,34 @@ private function worktree_cleanup_skipped_next_commands( array $skipped_by_reaso
17291729
'why' => 'Dirty paths are limited to declared reconstructable artifact directories, so artifact cleanup can shed them without force-removing source worktrees.',
17301730
'destructive' => false,
17311731
),
1732+
'dirty_worktree' => array(
1733+
'label' => 'Inspect dirty files before retrying cleanup',
1734+
'command' => 'git -C <worktree-path> status --short --branch --untracked-files=normal',
1735+
'alternative' => 'studio wp datamachine-code workspace cleanup run --mode=retention --dry-run --only=dirty_worktree --verbose --format=json',
1736+
'why' => 'Shows the exact dirty paths so operators can distinguish generated artifacts from source edits and decide whether to clean, commit, or preserve the worktree.',
1737+
'destructive' => false,
1738+
),
1739+
'unpushed_commits' => array(
1740+
'label' => 'Inspect commits ahead of upstream before cleanup',
1741+
'command' => 'git -C <worktree-path> log --oneline --decorate @{u}..HEAD',
1742+
'alternative' => 'studio wp datamachine-code workspace cleanup run --mode=retention --dry-run --only=unpushed_commits --verbose --format=json',
1743+
'why' => 'Lists the protected commits so operators can push, merge, preserve, or intentionally abandon them before retrying cleanup.',
1744+
'destructive' => false,
1745+
),
1746+
'stale_worktree_marker' => array(
1747+
'label' => 'Preview stale git worktree marker pruning',
1748+
'command' => 'git -C <primary-path> worktree prune --dry-run --verbose',
1749+
'alternative' => 'studio wp datamachine-code workspace worktree reconcile-metadata --dry-run --format=json',
1750+
'why' => 'Confirms stale git metadata before any prune or registry repair, keeping cleanup non-destructive by default.',
1751+
'destructive' => false,
1752+
),
1753+
'primary_missing' => array(
1754+
'label' => 'Recover or adopt the missing primary checkout',
1755+
'command' => 'studio wp datamachine-code workspace show <repo>',
1756+
'alternative' => 'Recreate with `studio wp datamachine-code workspace clone <remote-url> --name=<repo>` or adopt an existing checkout with `studio wp datamachine-code workspace adopt <path> --name=<repo>`.',
1757+
'why' => 'Git worktree removal must be routed through the primary checkout, so operators need primary path and remote evidence before repairing or preserving rows.',
1758+
'destructive' => false,
1759+
),
17321760
'lifecycle_reconciliation_candidate' => array(
17331761
'label' => 'Run DMC-owned lifecycle reconciliation before cleanup eligibility',
17341762
'command' => 'studio wp datamachine-code workspace worktree cleanup --dry-run --format=json',

0 commit comments

Comments
 (0)