diff --git a/apps/gittensory-ui/public/openapi.json b/apps/gittensory-ui/public/openapi.json index 5723f6d736..537eddf78a 100644 --- a/apps/gittensory-ui/public/openapi.json +++ b/apps/gittensory-ui/public/openapi.json @@ -8090,6 +8090,26 @@ ] } } + }, + "autoMaintain": { + "type": "object", + "properties": { + "requireApprovals": { + "type": "integer" + }, + "mergeMethod": { + "type": "string", + "enum": [ + "merge", + "squash", + "rebase" + ] + } + }, + "required": [ + "requireApprovals", + "mergeMethod" + ] } }, "required": [ diff --git a/apps/gittensory-ui/src/components/site/app-panels/maintainer-settings.tsx b/apps/gittensory-ui/src/components/site/app-panels/maintainer-settings.tsx index 05edfeaa5b..19e45bc238 100644 --- a/apps/gittensory-ui/src/components/site/app-panels/maintainer-settings.tsx +++ b/apps/gittensory-ui/src/components/site/app-panels/maintainer-settings.tsx @@ -40,8 +40,30 @@ type MaintainerSettings = { requireLinkedIssue: boolean; badgeEnabled: boolean; commandAuthorization: CommandAuthorization; + autonomy: Partial>; + autoMaintain: { requireApprovals: number; mergeMethod: AutoMergeMethod }; }; +type AutonomyLevel = "observe" | "suggest" | "propose" | "auto_with_approval" | "auto"; +type AgentActionClass = "review" | "request_changes" | "approve" | "merge" | "close" | "label"; +type AutoMergeMethod = "merge" | "squash" | "rebase"; + +const AUTONOMY_LEVELS: AutonomyLevel[] = [ + "observe", + "suggest", + "propose", + "auto_with_approval", + "auto", +]; +const AGENT_ACTION_CLASSES: AgentActionClass[] = [ + "review", + "request_changes", + "approve", + "merge", + "close", + "label", +]; + type Message = { kind: "ok" | "err"; text: string }; const GATE_MODE_OPTIONS: Array<[GateMode, string]> = [ @@ -84,6 +106,8 @@ const EDITABLE_KEYS: Array = [ "requireLinkedIssue", "badgeEnabled", "commandAuthorization", + "autonomy", + "autoMaintain", ]; type SelectFieldDef = { @@ -277,7 +301,19 @@ export function MaintainerSettings({ reviewability }: { reviewability: Array<{ p credentials: "include", silentStatus: true, }); - setSettings(result.ok ? result.data : null); + // Default the agent-layer fields defensively so the editor renders even against an older response shape. + setSettings( + result.ok + ? { + ...result.data, + autonomy: result.data.autonomy ?? {}, + autoMaintain: result.data.autoMaintain ?? { + requireApprovals: 1, + mergeMethod: "squash", + }, + } + : null, + ); setLoading(false); }, [repoFullName]); @@ -443,6 +479,76 @@ export function MaintainerSettings({ reviewability }: { reviewability: Array<{ p ) : null} +
+

Auto-maintain (agent layer)

+

+ Per-action autonomy: observe (watch only) →{" "} + suggest →{" "} + propose →{" "} + auto_with_approval →{" "} + auto. Deny-by-default — anything left at{" "} + observe never acts. +

+
+ {AGENT_ACTION_CLASSES.map((actionClass) => ( + + ))} +
+
+ + +
+
+