From 23064cab955d2dc7a43ab6bc5f6faa28ce0d9bfe Mon Sep 17 00:00:00 2001 From: Joshua Date: Sun, 19 Jul 2026 16:55:56 +0100 Subject: [PATCH] feat(web): cockpit picker for nightly proposal repos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a "Nightly proposals" section to AutomodePanel: a nightlyProposalSweep toggle and a proposalRepos editor matching the allowedRepos textarea pattern, both saved via the existing policy.update mutation. Entries not present in allowedRepos get an inline "won't run โ€” repo not in allowedRepos" marker since the sweep skips them. Adds a display line for the sweep window (proposes from 20:00 London) and an opted-in repo count. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_012iKX4FLtG8KhduZfXevgjx --- apps/web/src/components/gits/GitsCockpit.tsx | 58 ++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/apps/web/src/components/gits/GitsCockpit.tsx b/apps/web/src/components/gits/GitsCockpit.tsx index 254f3ec4621..15845df9cea 100644 --- a/apps/web/src/components/gits/GitsCockpit.tsx +++ b/apps/web/src/components/gits/GitsCockpit.tsx @@ -4264,6 +4264,8 @@ function AutomodePanel({ requireIntegrateApproval, requireDestructiveApproval, autoEnqueueProposals, + nightlyProposalSweep, + proposalRepos, goalTitle, goalRepo, goalModel, @@ -4281,6 +4283,8 @@ function AutomodePanel({ onRequireIntegrateApprovalChange, onRequireDestructiveApprovalChange, onAutoEnqueueProposalsChange, + onNightlyProposalSweepChange, + onProposalReposChange, onGoalTitleChange, onGoalRepoChange, onGoalModelChange, @@ -4313,6 +4317,8 @@ function AutomodePanel({ requireIntegrateApproval: boolean; requireDestructiveApproval: boolean; autoEnqueueProposals: boolean; + nightlyProposalSweep: boolean; + proposalRepos: string; goalTitle: string; goalRepo: string; goalModel: string; @@ -4330,6 +4336,8 @@ function AutomodePanel({ onRequireIntegrateApprovalChange: (value: boolean) => void; onRequireDestructiveApprovalChange: (value: boolean) => void; onAutoEnqueueProposalsChange: (value: boolean) => void; + onNightlyProposalSweepChange: (value: boolean) => void; + onProposalReposChange: (value: string) => void; onGoalTitleChange: (value: string) => void; onGoalRepoChange: (value: string) => void; onGoalModelChange: (value: string) => void; @@ -4365,6 +4373,12 @@ function AutomodePanel({ : actionError instanceof Error ? actionError.message : null; + const proposalRepoList = parseLines(proposalRepos); + const allowedRepoList = parseLines(allowedRepos); + const proposalReposNotAllowed = proposalRepoList.filter( + (repo) => + !allowedRepoList.some((a) => repo === a || repo.startsWith(a.endsWith("/") ? a : a + "/")), + ); return (
@@ -4619,6 +4633,38 @@ function AutomodePanel({ +
+ +

+ Proposes from 20:00 London ยท{" "} + {nightlyProposalSweep + ? `${formatCount(proposalRepoList.length)} repos opted in` + : "sweep disabled"} +

+