Skip to content

Commit 564dc7b

Browse files
committed
feat: expose worktree safety fields for orchestrators
1 parent 645037f commit 564dc7b

3 files changed

Lines changed: 42 additions & 3 deletions

File tree

inc/Cli/Commands/WorkspaceCommand.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4529,8 +4529,9 @@ private function renderWorktreeResult( string $operation, array $result, array $
45294529
function ( $wt ) {
45304530
$skipped = (array) ( $wt['fields_skipped'] ?? array() );
45314531
$dirty = $wt['dirty'] ?? null;
4532+
$unpushed = $wt['unpushed'] ?? null;
45324533
$size = $wt['size_bytes'] ?? null;
4533-
return array(
4534+
$item = array(
45344535
'handle' => $wt['handle'] ?? '',
45354536
'repo' => $wt['repo'] ?? '',
45364537
'kind' => ! empty($wt['is_primary']) ? 'primary' : 'worktree',
@@ -4562,12 +4563,21 @@ function ( $wt ) {
45624563
'task_full' => $wt['task'] ?? null,
45634564
'path' => $wt['path'] ?? '',
45644565
);
4566+
if ( null !== $dirty && null !== $unpushed ) {
4567+
$item['safety'] = array(
4568+
'dirty' => 0 !== (int) $dirty,
4569+
'unpushed' => 0 !== (int) $unpushed,
4570+
'primary' => ! empty($wt['is_primary']),
4571+
);
4572+
}
4573+
4574+
return $item;
45654575
},
45664576
$worktrees
45674577
);
45684578
$fields = array( 'handle', 'repo', 'kind', 'branch', 'head', 'dirty', 'state', 'liveness', 'last_seen_at', 'owner', 'agent', 'session', 'task', 'pr', 'age_days', 'size', 'artifacts', 'stale', 'path' );
45694579
if ( in_array( (string) ( $assoc_args['format'] ?? '' ), array( 'json', 'yaml' ), true) ) {
4570-
$fields = array( 'handle', 'repo', 'kind', 'branch', 'head', 'dirty', 'state', 'created_at', 'liveness', 'liveness_reason', 'last_seen_at', 'owner_full', 'session_full', 'task_full', 'pr', 'age_days', 'size_bytes', 'artifact_size_bytes', 'artifact_paths', 'stale', 'fields_skipped', 'metadata', 'path' );
4580+
$fields = array( 'handle', 'repo', 'kind', 'branch', 'head', 'dirty', 'safety', 'state', 'created_at', 'liveness', 'liveness_reason', 'last_seen_at', 'owner_full', 'session_full', 'task_full', 'pr', 'age_days', 'size_bytes', 'artifact_size_bytes', 'artifact_paths', 'stale', 'fields_skipped', 'metadata', 'path' );
45714581
}
45724582
$skipped_global = (array) ( $result['fields_skipped'] ?? array() );
45734583
if ( ! empty($skipped_global) && ! in_array( (string) ( $assoc_args['format'] ?? '' ), array( 'json', 'yaml', 'csv' ), true) ) {

inc/Workspace/WorkspaceWorktreeLifecycle.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -847,8 +847,13 @@ public function worktree_list( ?string $repo = null, ?string $state = null, arra
847847
$dirty_files = is_wp_error($dirty_result)
848848
? 0
849849
: count(array_filter(array_map('trim', explode("\n", $dirty_result['output'] ?? ''))));
850+
$unpushed_commits = $this->count_unpushed_commits($wt['path']);
851+
if ( is_wp_error($unpushed_commits) ) {
852+
return $unpushed_commits;
853+
}
850854
} else {
851-
$dirty_files = null;
855+
$dirty_files = null;
856+
$unpushed_commits = null;
852857
}
853858

854859
$metadata_key = null;
@@ -911,6 +916,7 @@ public function worktree_list( ?string $repo = null, ?string $state = null, arra
911916
'head' => $wt['head'],
912917
'path' => $wt['path'],
913918
'dirty' => $dirty_files,
919+
'unpushed' => $unpushed_commits,
914920
'created_at' => $created_at,
915921
'lifecycle_state' => $lifecycle_state,
916922
'pr_url' => is_array($metadata) ? ( $metadata['pr_url'] ?? null ) : null,
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
$root = dirname(__DIR__);
6+
$cli_source = file_get_contents($root . '/inc/Cli/Commands/WorkspaceCommand.php');
7+
$list_source = file_get_contents($root . '/inc/Workspace/WorkspaceWorktreeLifecycle.php');
8+
9+
if ( false === $cli_source || false === $list_source ) {
10+
throw new RuntimeException('Unable to read worktree list sources.');
11+
}
12+
13+
foreach ( array( "'dirty' => 0 !== (int) \$dirty", "'unpushed' => 0 !== (int) \$unpushed", "'primary' => ! empty(\$wt['is_primary'])" ) as $expected ) {
14+
if ( ! str_contains($cli_source, $expected) ) {
15+
throw new RuntimeException(sprintf('Worktree list safety mapping is missing %s.', $expected));
16+
}
17+
}
18+
19+
if ( ! str_contains($list_source, '$unpushed_commits = $this->count_unpushed_commits($wt[\'path\']);') ) {
20+
throw new RuntimeException('Status-enabled worktree listings must reuse the unpushed commit probe.');
21+
}
22+
23+
echo "worktree-list-orchestrator-safety: ok\n";

0 commit comments

Comments
 (0)