feat(foundry): add manual task owner change via UI dropdown

Add an owner dropdown to the Overview tab that lets users reassign task
ownership to any organization member. The owner's GitHub credentials are
used for git operations in the sandbox.

Full-stack implementation:
- Backend: changeTaskOwnerManually action on task actor, routed through
  org actor's changeWorkspaceTaskOwner action, with primaryUser schema
  columns on both task and org index tables
- Client: changeOwner method on workspace client (mock + remote)
- Frontend: owner dropdown in right sidebar Overview tab showing org
  members, with avatar and role display
- Shared: TaskWorkspaceChangeOwnerInput type and primaryUser fields on
  workspace snapshot types

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Nathan Flurry 2026-03-16 17:04:26 -07:00
parent b1b785ae79
commit 3684e2e5f5
18 changed files with 647 additions and 11 deletions

View file

@ -128,6 +128,10 @@ export interface WorkspaceTaskSummary {
activeSessionId: string | null;
/** Summary of sessions — no transcript content. */
sessionsSummary: WorkspaceSessionSummary[];
/** GitHub login of the current primary user (task owner). */
primaryUserLogin: string | null;
/** Avatar URL of the current primary user. */
primaryUserAvatarUrl: string | null;
}
/** Full task detail — only fetched when viewing a specific task. */
@ -218,6 +222,10 @@ export interface WorkspaceTask {
fileTree: WorkspaceFileTreeNode[];
minutesUsed: number;
activeSandboxId?: string | null;
/** GitHub login of the current primary user (task owner). */
primaryUserLogin?: string | null;
/** Avatar URL of the current primary user. */
primaryUserAvatarUrl?: string | null;
}
export interface WorkspaceRepo {
@ -295,6 +303,18 @@ export interface TaskWorkspaceSetSessionUnreadInput extends TaskWorkspaceSession
unread: boolean;
}
export interface TaskWorkspaceChangeOwnerInput {
repoId: string;
taskId: string;
/** User ID of the target owner (from FoundryOrganizationMember.id). */
targetUserId: string;
/** Display name to use as fallback if GitHub login cannot be resolved. */
targetUserName: string;
/** Email to use as fallback if GitHub email cannot be resolved. */
targetUserEmail: string;
authSessionId?: string;
}
export interface TaskWorkspaceDiffInput {
repoId: string;
taskId: string;