Add project-first execution workspace policies

This commit is contained in:
Dotta
2026-03-10 09:03:31 -05:00
parent 3120c72372
commit b83a87f42f
22 changed files with 7046 additions and 114 deletions

View File

@@ -78,6 +78,11 @@ export type {
ProjectGoalRef,
ProjectWorkspace,
WorkspaceRuntimeService,
ExecutionWorkspaceStrategyType,
ExecutionWorkspaceMode,
ExecutionWorkspaceStrategy,
ProjectExecutionWorkspacePolicy,
IssueExecutionWorkspaceSettings,
Issue,
IssueAssigneeAdapterOverrides,
IssueComment,
@@ -157,9 +162,11 @@ export {
type UpdateProject,
type CreateProjectWorkspace,
type UpdateProjectWorkspace,
projectExecutionWorkspacePolicySchema,
createIssueSchema,
createIssueLabelSchema,
updateIssueSchema,
issueExecutionWorkspaceSettingsSchema,
checkoutIssueSchema,
addIssueCommentSchema,
linkIssueApprovalSchema,

View File

@@ -11,7 +11,14 @@ export type {
} from "./agent.js";
export type { AssetImage } from "./asset.js";
export type { Project, ProjectGoalRef, ProjectWorkspace } from "./project.js";
export type { WorkspaceRuntimeService } from "./workspace-runtime.js";
export type {
WorkspaceRuntimeService,
ExecutionWorkspaceStrategyType,
ExecutionWorkspaceMode,
ExecutionWorkspaceStrategy,
ProjectExecutionWorkspacePolicy,
IssueExecutionWorkspaceSettings,
} from "./workspace-runtime.js";
export type {
Issue,
IssueAssigneeAdapterOverrides,

View File

@@ -1,6 +1,7 @@
import type { IssuePriority, IssueStatus } from "../constants.js";
import type { Goal } from "./goal.js";
import type { Project, ProjectWorkspace } from "./project.js";
import type { IssueExecutionWorkspaceSettings } from "./workspace-runtime.js";
export interface IssueAncestorProject {
id: string;
@@ -73,6 +74,7 @@ export interface Issue {
requestDepth: number;
billingCode: string | null;
assigneeAdapterOverrides: IssueAssigneeAdapterOverrides | null;
executionWorkspaceSettings: IssueExecutionWorkspaceSettings | null;
startedAt: Date | null;
completedAt: Date | null;
cancelledAt: Date | null;

View File

@@ -1,5 +1,5 @@
import type { ProjectStatus } from "../constants.js";
import type { WorkspaceRuntimeService } from "./workspace-runtime.js";
import type { ProjectExecutionWorkspacePolicy, WorkspaceRuntimeService } from "./workspace-runtime.js";
export interface ProjectGoalRef {
id: string;
@@ -35,6 +35,7 @@ export interface Project {
leadAgentId: string | null;
targetDate: string | null;
color: string | null;
executionWorkspacePolicy: ProjectExecutionWorkspacePolicy | null;
workspaces: ProjectWorkspace[];
primaryWorkspace: ProjectWorkspace | null;
archivedAt: Date | null;

View File

@@ -1,3 +1,31 @@
export type ExecutionWorkspaceStrategyType = "project_primary" | "git_worktree";
export type ExecutionWorkspaceMode = "inherit" | "project_primary" | "isolated" | "agent_default";
export interface ExecutionWorkspaceStrategy {
type: ExecutionWorkspaceStrategyType;
baseRef?: string | null;
branchTemplate?: string | null;
worktreeParentDir?: string | null;
}
export interface ProjectExecutionWorkspacePolicy {
enabled: boolean;
defaultMode?: "project_primary" | "isolated";
allowIssueOverride?: boolean;
workspaceStrategy?: ExecutionWorkspaceStrategy | null;
workspaceRuntime?: Record<string, unknown> | null;
branchPolicy?: Record<string, unknown> | null;
pullRequestPolicy?: Record<string, unknown> | null;
cleanupPolicy?: Record<string, unknown> | null;
}
export interface IssueExecutionWorkspaceSettings {
mode?: ExecutionWorkspaceMode;
workspaceStrategy?: ExecutionWorkspaceStrategy | null;
workspaceRuntime?: Record<string, unknown> | null;
}
export interface WorkspaceRuntimeService {
id: string;
companyId: string;

View File

@@ -49,16 +49,19 @@ export {
updateProjectSchema,
createProjectWorkspaceSchema,
updateProjectWorkspaceSchema,
projectExecutionWorkspacePolicySchema,
type CreateProject,
type UpdateProject,
type CreateProjectWorkspace,
type UpdateProjectWorkspace,
type ProjectExecutionWorkspacePolicy,
} from "./project.js";
export {
createIssueSchema,
createIssueLabelSchema,
updateIssueSchema,
issueExecutionWorkspaceSettingsSchema,
checkoutIssueSchema,
addIssueCommentSchema,
linkIssueApprovalSchema,
@@ -66,6 +69,7 @@ export {
type CreateIssue,
type CreateIssueLabel,
type UpdateIssue,
type IssueExecutionWorkspaceSettings,
type CheckoutIssue,
type AddIssueComment,
type LinkIssueApproval,

View File

@@ -1,6 +1,23 @@
import { z } from "zod";
import { ISSUE_PRIORITIES, ISSUE_STATUSES } from "../constants.js";
const executionWorkspaceStrategySchema = z
.object({
type: z.enum(["project_primary", "git_worktree"]).optional(),
baseRef: z.string().optional().nullable(),
branchTemplate: z.string().optional().nullable(),
worktreeParentDir: z.string().optional().nullable(),
})
.strict();
export const issueExecutionWorkspaceSettingsSchema = z
.object({
mode: z.enum(["inherit", "project_primary", "isolated", "agent_default"]).optional(),
workspaceStrategy: executionWorkspaceStrategySchema.optional().nullable(),
workspaceRuntime: z.record(z.unknown()).optional().nullable(),
})
.strict();
export const issueAssigneeAdapterOverridesSchema = z
.object({
adapterConfig: z.record(z.unknown()).optional(),
@@ -21,6 +38,7 @@ export const createIssueSchema = z.object({
requestDepth: z.number().int().nonnegative().optional().default(0),
billingCode: z.string().optional().nullable(),
assigneeAdapterOverrides: issueAssigneeAdapterOverridesSchema.optional().nullable(),
executionWorkspaceSettings: issueExecutionWorkspaceSettingsSchema.optional().nullable(),
labelIds: z.array(z.string().uuid()).optional(),
});
@@ -39,6 +57,7 @@ export const updateIssueSchema = createIssueSchema.partial().extend({
});
export type UpdateIssue = z.infer<typeof updateIssueSchema>;
export type IssueExecutionWorkspaceSettings = z.infer<typeof issueExecutionWorkspaceSettingsSchema>;
export const checkoutIssueSchema = z.object({
agentId: z.string().uuid(),

View File

@@ -1,6 +1,28 @@
import { z } from "zod";
import { PROJECT_STATUSES } from "../constants.js";
const executionWorkspaceStrategySchema = z
.object({
type: z.enum(["project_primary", "git_worktree"]).optional(),
baseRef: z.string().optional().nullable(),
branchTemplate: z.string().optional().nullable(),
worktreeParentDir: z.string().optional().nullable(),
})
.strict();
export const projectExecutionWorkspacePolicySchema = z
.object({
enabled: z.boolean(),
defaultMode: z.enum(["project_primary", "isolated"]).optional(),
allowIssueOverride: z.boolean().optional(),
workspaceStrategy: executionWorkspaceStrategySchema.optional().nullable(),
workspaceRuntime: z.record(z.unknown()).optional().nullable(),
branchPolicy: z.record(z.unknown()).optional().nullable(),
pullRequestPolicy: z.record(z.unknown()).optional().nullable(),
cleanupPolicy: z.record(z.unknown()).optional().nullable(),
})
.strict();
const projectWorkspaceFields = {
name: z.string().min(1).optional(),
cwd: z.string().min(1).optional().nullable(),
@@ -43,6 +65,7 @@ const projectFields = {
leadAgentId: z.string().uuid().optional().nullable(),
targetDate: z.string().optional().nullable(),
color: z.string().optional().nullable(),
executionWorkspacePolicy: projectExecutionWorkspacePolicySchema.optional().nullable(),
archivedAt: z.string().datetime().optional().nullable(),
};
@@ -56,3 +79,5 @@ export type CreateProject = z.infer<typeof createProjectSchema>;
export const updateProjectSchema = z.object(projectFields).partial();
export type UpdateProject = z.infer<typeof updateProjectSchema>;
export type ProjectExecutionWorkspacePolicy = z.infer<typeof projectExecutionWorkspacePolicySchema>;