feat(modes): Ask mode gates autonomous start with Build mode confirmation

When SF would start autonomous execution (startAuto) and the session is
in Ask mode (runControl=manual), it shows a confirm dialog:

  'Switch to Build mode? SF will execute without further prompts.'
  [Switch to Build] [Stay in Ask]

- On confirm: atomically applies the build preset (autonomous +
  unrestricted), then proceeds with execution.
- On decline: returns without starting — user stays in Ask.
- skipModeGate option available for callers that already handle this
  (e.g., explicit /autonomous command after user intent is clear).

This covers all startAuto callers: checkAutoStartAfterDiscuss, guided
flow action buttons, /next, and /autonomous.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Mikael Hugo 2026-05-09 19:56:24 +02:00
parent 0712577f85
commit b9ea000341

View file

@ -189,6 +189,8 @@ import {
setActiveMilestoneId,
} from "./worktree.js";
import { WorktreeResolver } from "./worktree-resolver.js";
import { resolvePreset } from "./operating-model.js";
import { showConfirm } from "../shared/tui.js";
export {
MAX_LIFETIME_DISPATCHES,
@ -1392,6 +1394,27 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
debugLog("startAuto", { phase: "already-active", skipping: true });
return;
}
// Gate: if the user is in Ask mode (manual runControl), ask permission to
// switch to Build mode before starting autonomous execution.
if (s.runControl === "manual" && !options?.skipModeGate) {
const confirmed = await showConfirm(ctx, {
title: "Switch to Build mode?",
message:
"You're in Ask mode. Autonomous execution requires Build mode — SF will execute without further prompts.",
confirmLabel: "Switch to Build",
declineLabel: "Stay in Ask",
});
if (!confirmed) return;
const buildPreset = resolvePreset("build");
s.setMode({
workMode: buildPreset.workMode,
runControl: buildPreset.runControl,
modelMode: buildPreset.modelMode,
permissionProfile: buildPreset.permissionProfile,
reason: "ask-to-build-gate",
});
ctx.ui.notify("Switched to Build mode — starting autonomous execution.", "info");
}
// On a *fresh* start, drop any stale active-tool baseline left by a prior
// auto session that didn't run stopAuto cleanly. Skip on resume: pauseAuto
// leaves the last provider-trimmed active tools in place, so clearing here