Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ const ADVISORY_SETTINGS = {
requireLinkedIssue: false,
commandAuthorization: {},
autonomy: {},
autoMaintain: { requireApprovals: 1, mergeMethod: "squash" as const },
agentPaused: false,
agentDryRun: false,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ function normalizeLoadedSettings(data: MaintainerSettingsEditable): MaintainerSe
autonomy: data.autonomy ?? {},
agentPaused: data.agentPaused ?? false,
agentDryRun: data.agentDryRun ?? false,
autoMaintain: data.autoMaintain ?? { requireApprovals: 1, mergeMethod: "squash" },
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { extractPreviewRepoOptions, splitRepoFullName } from "@/lib/maintainer-s
import {
buildMaintainerSettingsSavePayload,
type AgentActionClass,
type AutoMergeMethod,
type AutonomyLevel,
type CommandRole,
type GateMode,
Expand Down Expand Up @@ -195,10 +194,6 @@ export function MaintainerSettings({ reviewability }: { reviewability: Array<{ p
autonomy: result.data.autonomy ?? {},
agentPaused: result.data.agentPaused ?? false,
agentDryRun: result.data.agentDryRun ?? false,
autoMaintain: result.data.autoMaintain ?? {
requireApprovals: 1,
mergeMethod: "squash",
},
}
: null,
);
Expand Down Expand Up @@ -388,41 +383,8 @@ export function MaintainerSettings({ reviewability }: { reviewability: Array<{ p
</label>
))}
</div>
<div className="mt-3 grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
<label className="block">
<span className={LABEL_CLASS}>Approvals before auto-merge</span>
<input
type="number"
min={0}
max={10}
value={settings.autoMaintain.requireApprovals}
onChange={(event) =>
setField("autoMaintain", {
...settings.autoMaintain,
requireApprovals: Math.max(0, Math.min(10, Number(event.target.value) || 0)),
})
}
className={FIELD_CLASS}
/>
</label>
<label className="block">
<span className={LABEL_CLASS}>Merge method</span>
<select
value={settings.autoMaintain.mergeMethod}
onChange={(event) =>
setField("autoMaintain", {
...settings.autoMaintain,
mergeMethod: event.target.value as AutoMergeMethod,
})
}
className={FIELD_CLASS}
>
<option value="merge">merge</option>
<option value="squash">squash</option>
<option value="rebase">rebase</option>
</select>
</label>
</div>
{/* #6445: "Approvals before auto-merge" / "Merge method" removed -- autoMaintain is no longer
DB-backed, config-as-code only via .loopover.yml's settings: block now. */}
<div className="mt-3 flex flex-wrap gap-6">
<ToggleControl
label="Pause all agent actions (kill-switch)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ const SETTINGS: MaintainerSettingsEditable = {
requireLinkedIssue: false,
commandAuthorization: {},
autonomy: {},
autoMaintain: { requireApprovals: 1, mergeMethod: "squash" },
agentPaused: false,
agentDryRun: false,
};
Expand Down
5 changes: 2 additions & 3 deletions apps/loopover-ui/src/lib/maintainer-settings-editable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export type CommandAuthorization = {
export type AutonomyLevel = "observe" | "auto_with_approval" | "auto";
export type AgentActionClass =
"review" | "request_changes" | "approve" | "merge" | "close" | "label";
export type AutoMergeMethod = "merge" | "squash" | "rebase";

export type MaintainerSettingsEditable = {
// #4618/#5373: a prior gateCheckMode field was a deprecated computed read-back, since removed entirely --
Expand All @@ -38,7 +37,8 @@ export type MaintainerSettingsEditable = {
requireLinkedIssue: boolean;
commandAuthorization: CommandAuthorization;
autonomy: Partial<Record<AgentActionClass, AutonomyLevel>>;
autoMaintain: { requireApprovals: number; mergeMethod: AutoMergeMethod };
// #6445: autoMaintain removed -- no longer DB-backed, config-as-code only via .loopover.yml's
// settings: block now (the dashboard can no longer write it).
agentPaused: boolean;
agentDryRun: boolean;
};
Expand All @@ -61,7 +61,6 @@ export const MAINTAINER_SETTINGS_EDITABLE_KEYS: Array<keyof MaintainerSettingsEd
"requireLinkedIssue",
"commandAuthorization",
"autonomy",
"autoMaintain",
"agentPaused",
"agentDryRun",
];
Expand Down
28 changes: 28 additions & 0 deletions migrations/0160_drop_batch_d_config_as_code_columns.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-- Config-as-code migration (loopover#6445/epic #6440): these 19 fields already parse correctly from
-- .loopover.yml's settings: block (confirmed via audit; none are sparse-merge composites, so
-- resolveEffectiveSettings needs no special-casing -- they overlay via the generic
-- {...dbSettings, ...restManifestSettings} spread, same as autoMaintain/commandAuthorization already do).
-- Same dead-column-cleanup shape as the prior Batch A (0157) and Batch B (0158) migrations in this epic.
-- SQLite 3.35+ / D1 supports DROP COLUMN directly.
--
-- agentPaused/agentDryRun (incident kill-switches) and requireFreshRebaseWindowMinutes are explicitly
-- OUT of scope for this migration and stay DB-only -- see the issue body / schema.ts comments.
ALTER TABLE repository_settings DROP COLUMN project_milestone_match_mode;
ALTER TABLE repository_settings DROP COLUMN auto_project_milestone_match_backend;
ALTER TABLE repository_settings DROP COLUMN auto_maintain_json;
ALTER TABLE repository_settings DROP COLUMN contributor_open_pr_cap;
ALTER TABLE repository_settings DROP COLUMN contributor_open_issue_cap;
ALTER TABLE repository_settings DROP COLUMN contributor_cap_label;
ALTER TABLE repository_settings DROP COLUMN contributor_cap_cancel_ci;
ALTER TABLE repository_settings DROP COLUMN review_nag_policy;
ALTER TABLE repository_settings DROP COLUMN review_nag_max_pings;
ALTER TABLE repository_settings DROP COLUMN review_nag_cooldown_days;
ALTER TABLE repository_settings DROP COLUMN review_nag_label;
ALTER TABLE repository_settings DROP COLUMN review_nag_monitored_mentions_json;
ALTER TABLE repository_settings DROP COLUMN auto_close_exempt_logins_json;
ALTER TABLE repository_settings DROP COLUMN account_age_threshold_days;
ALTER TABLE repository_settings DROP COLUMN new_account_label;
ALTER TABLE repository_settings DROP COLUMN command_rate_limit_policy;
ALTER TABLE repository_settings DROP COLUMN command_rate_limit_max_per_window;
ALTER TABLE repository_settings DROP COLUMN command_rate_limit_ai_max_per_window;
ALTER TABLE repository_settings DROP COLUMN command_rate_limit_window_hours;
7 changes: 4 additions & 3 deletions src/api/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -726,10 +726,11 @@ const maintainerSettingsSchema = z
default: z.array(z.enum(["maintainer", "collaborator", "pr_author", "confirmed_miner"])).max(4).optional(),
commands: z.record(z.string().trim().min(1).max(64), z.array(z.enum(["maintainer", "collaborator", "pr_author", "confirmed_miner"])).max(4)).optional(),
}),
// Agent-layer config (#773/#774). The DB layer normalizes both (autonomy: deny-by-default; autoMaintain:
// defaults filled), so a loose record/object here is safe — invalid entries are dropped on persist.
// Agent-layer config (#773/#774). The DB layer normalizes autonomy (deny-by-default), so a loose
// record here is safe — invalid entries are dropped on persist.
// #6445: autoMaintain removed -- no longer DB-backed, config-as-code only via .loopover.yml's
// settings: block now.
autonomy: z.record(z.string().trim().min(1).max(32), z.enum(["observe", "auto_with_approval", "auto"])),
autoMaintain: z.object({ requireApprovals: z.number().int().min(0).max(10).optional(), mergeMethod: z.enum(["merge", "squash", "rebase"]).optional() }),
})
.partial();

Expand Down
Loading
Loading