feat(dashboard): expose build timeout & insight extraction in settings UI

Both settings already exist in the Settings schema and are honored by the
engine, but neither had a control in the dashboard, so users could only
change them by hand-editing config.json while the app was closed (the
running app rewrites config.json from its DB, clobbering live file edits).

- Add 'Build/Verification Timeout (minutes)' to the Scheduling section,
  next to the existing stuck-task timeout (same minutes<->ms conversion).
- Add 'Enable Insight Extraction' + cron schedule to the Memory section,
  next to the existing auto-summarize controls.

Both are placed in their existing project-scoped sections. Follow-up: a
global-defaults counterpart could be added if maintainers want these
settable at the user/global level too.
This commit is contained in:
ddonaldson130
2026-07-06 22:03:08 -04:00
parent 765218f80f
commit f72585ce77
2 changed files with 22 additions and 0 deletions

View File

@@ -112,6 +112,19 @@ export function MemorySection({ scopeBanner, form, setForm, memory }: MemorySect
</div>
</>)}
<div className="form-group">
<label htmlFor="insightExtractionEnabled" className="checkbox-label">
<input id="insightExtractionEnabled" type="checkbox" checked={form.insightExtractionEnabled || false} onChange={(e) => setForm((f) => ({ ...f, insightExtractionEnabled: e.target.checked }))}/>{t("settings.memory.enableInsightExtraction", " Enable Insight Extraction ")}</label>
<small>{t("settings.memory.periodicallyExtractDurableInsightsFromCompletedTasks", "Periodically extract durable insights/learnings from completed tasks into memory")}</small>
</div>
{(form.insightExtractionEnabled || false) && (
<div className="form-group">
<label htmlFor="insightExtractionSchedule">{t("settings.memory.scheduleCron", "Schedule (cron)")}</label>
<input id="insightExtractionSchedule" type="text" className="input" value={form.insightExtractionSchedule ?? "0 2 * * *"} onChange={(e) => setForm((f) => ({ ...f, insightExtractionSchedule: e.target.value }))} placeholder={t("settings.memory.02", "0 2 * * *")}/>
<small>{t("settings.memory.cronExpressionForInsightExtractionScheduleDefaultDaily", "Cron expression for insight extraction schedule (default: daily at 2 AM)")}</small>
</div>)}
<div style={{ borderTop: "1px solid var(--border)", margin: "var(--space-lg) 0" }}/>
<div className="form-group">

View File

@@ -106,6 +106,15 @@ export function SchedulingSection({ scopeBanner, form, setForm, globalMaxConcurr
}}/>
<small>{t("settings.scheduling.timeoutInMinutesForDetectingStuckTasksWhen", "Timeout in minutes for detecting stuck tasks. When a task's agent session shows no activity for longer than this duration, the task is terminated and retried. Leave empty to disable. Suggested: 10.")}</small>
</div>
<div className="form-group">
<label htmlFor="buildTimeoutMs">{t("settings.scheduling.buildTimeoutMinutes", "Build/Verification Timeout (minutes)")}</label>
<input id="buildTimeoutMs" type="number" min={1} step={1} value={form.buildTimeoutMs ? Math.round(form.buildTimeoutMs / 60000) : ""} onChange={(e) => {
const val = e.target.value;
const num = Number(val);
setForm((f) => ({ ...f, buildTimeoutMs: val && num > 0 ? num * 60000 : undefined }));
}}/>
<small>{t("settings.scheduling.maximumTimeInMinutesForBuildVerificationCommands", "Maximum time in minutes for build/verification commands before they are killed. Raise for large monorepo or Docker builds. Default: 5.")}</small>
</div>
<div className="form-group">
<label htmlFor="staleHighFanoutBlockerAgeThresholdMs">{t("settings.scheduling.staleHighFanOutEscalationHours", "Stale High Fan-out Escalation (hours)")}</label>
<input id="staleHighFanoutBlockerAgeThresholdMs" type="number" min={1} step={1} value={form.staleHighFanoutBlockerAgeThresholdMs ? Math.round(form.staleHighFanoutBlockerAgeThresholdMs / 3600000) : ""} onChange={(e) => {