diff --git a/src/resources/extensions/sf/bootstrap/agent-end-recovery.js b/src/resources/extensions/sf/bootstrap/agent-end-recovery.js index 88f8e2cdc..e7bfce3c3 100644 --- a/src/resources/extensions/sf/bootstrap/agent-end-recovery.js +++ b/src/resources/extensions/sf/bootstrap/agent-end-recovery.js @@ -1,12 +1,3 @@ -import { - getAutoDashboardData, - getCurrentUnitModelFailures, - isAutoActive, - pauseAuto, - recordCurrentModelFailure, - setCurrentUnitModel, -} from "../auto.js"; -import { isSessionSwitchInFlight, resolveAgentEnd } from "../auto-loop.js"; import { blockModel, isModelBlocked } from "../blocked-models.js"; import { classifyError, @@ -14,7 +5,6 @@ import { isTransient, resetRetryState, } from "../error-classifier.js"; -import { checkAutoStartAfterDiscuss } from "../guided-flow.js"; import { resolveNextModelRoute } from "../model-route-failure.js"; import { resolveModelWithFallbacksForUnit, @@ -63,6 +53,8 @@ function isModelRouteFailure(cls) { ); } async function trySwitchToFallbackModel(args) { + const { getCurrentUnitModelFailures, recordCurrentModelFailure, setCurrentUnitModel } = + await import("../auto.js"); const modelConfig = resolveModelWithFallbacksForUnit(args.unitType, { autoBenchmark: true, }); @@ -120,6 +112,11 @@ async function trySwitchToFallbackModel(args) { return false; } export async function handleAgentEnd(pi, event, ctx) { + const { checkAutoStartAfterDiscuss } = await import("../guided-flow.js"); + const { getAutoDashboardData, isAutoActive, pauseAuto } = + await import("../auto.js"); + const { isSessionSwitchInFlight, resolveAgentEnd } = + await import("../auto-loop.js"); const persistModelChanges = resolvePersistModelChanges(); if (checkAutoStartAfterDiscuss()) { clearDiscussionFlowState(); diff --git a/src/resources/extensions/sf/bootstrap/db-tools.js b/src/resources/extensions/sf/bootstrap/db-tools.js index d7d38b6be..afc395641 100644 --- a/src/resources/extensions/sf/bootstrap/db-tools.js +++ b/src/resources/extensions/sf/bootstrap/db-tools.js @@ -10,7 +10,7 @@ import { findMilestoneIds, getReservedMilestoneIds, nextMilestoneId, -} from "../guided-flow.js"; +} from "../milestone-ids.js"; import { loadEffectiveSFPreferences } from "../preferences.js"; import { ALL_SCHEDULE_KINDS } from "../schedule/schedule-types.js"; import { markResolved, recordSelfFeedback } from "../self-feedback.js"; diff --git a/src/resources/extensions/sf/bootstrap/provider-error-resume.js b/src/resources/extensions/sf/bootstrap/provider-error-resume.js index 9e148af64..fcbfe39bc 100644 --- a/src/resources/extensions/sf/bootstrap/provider-error-resume.js +++ b/src/resources/extensions/sf/bootstrap/provider-error-resume.js @@ -1,22 +1,15 @@ -import { - getAutoCommandContext, - getAutoDashboardData, - startAuto, -} from "../auto.js"; import { resetTransientRetryState } from "./agent-end-recovery.js"; -const defaultDeps = { - getSnapshot: () => getAutoDashboardData(), - resetTransientRetryState, - getCommandContext: () => getAutoCommandContext(), - startAuto, -}; -export async function resumeAutoAfterProviderDelay( - pi, - ctx, - deps = defaultDeps, -) { - const snapshot = deps.getSnapshot(); +export async function resumeAutoAfterProviderDelay(pi, ctx, deps = null) { + const { getAutoCommandContext, getAutoDashboardData, startAuto } = + await import("../auto.js"); + const _deps = deps ?? { + getSnapshot: () => getAutoDashboardData(), + resetTransientRetryState, + getCommandContext: () => getAutoCommandContext(), + startAuto, + }; + const snapshot = _deps.getSnapshot(); if (snapshot.active) return "already-active"; if (!snapshot.paused) return "not-paused"; if (!snapshot.basePath) { @@ -29,7 +22,7 @@ export async function resumeAutoAfterProviderDelay( const commandCtx = typeof ctx.newSession === "function" ? ctx - : (deps.getCommandContext?.() ?? null); + : (_deps.getCommandContext?.() ?? null); if (!commandCtx || typeof commandCtx.newSession !== "function") { ctx.ui.notify( "Provider error recovery delay elapsed, but no command context with newSession was available. Leaving autonomous mode paused.", @@ -40,8 +33,8 @@ export async function resumeAutoAfterProviderDelay( // Reset the transient retry counter before restarting — without this, // consecutiveTransientCount accumulates across pause/resume cycles and // permanently locks out scheduled resume after MAX_TRANSIENT_AUTO_RESUMES errors. - deps.resetTransientRetryState(); - await deps.startAuto(commandCtx, pi, snapshot.basePath, false, { + _deps.resetTransientRetryState(); + await _deps.startAuto(commandCtx, pi, snapshot.basePath, false, { step: snapshot.stepMode, }); return "resumed"; diff --git a/src/resources/extensions/sf/commands/context.js b/src/resources/extensions/sf/commands/context.js index 554254200..44fe4fe08 100644 --- a/src/resources/extensions/sf/commands/context.js +++ b/src/resources/extensions/sf/commands/context.js @@ -1,13 +1,6 @@ import { showNextAction } from "../../shared/tui.js"; -import { - checkRemoteAutoSession, - isAutoActive, - isAutoPaused, - stopAutoRemote, -} from "../auto.js"; import { validateDirectory } from "../validate-directory.js"; import { resolveProjectRoot } from "../worktree.js"; -import { handleStatus } from "./handlers/core.js"; /** * Typed error for when SF is run outside a valid project directory. * Command handlers catch this to show a friendly message instead of a raw exception. @@ -37,6 +30,9 @@ export function projectRoot() { return root; } export async function guardRemoteSession(ctx, _pi) { + const { checkRemoteAutoSession, isAutoActive, isAutoPaused, stopAutoRemote } = + await import("../auto.js"); + const { handleStatus } = await import("./handlers/core.js"); if (isAutoActive() || isAutoPaused()) return true; const remote = checkRemoteAutoSession(projectRoot()); if (!remote.running || !remote.pid) return true; diff --git a/src/resources/extensions/sf/md-importer.js b/src/resources/extensions/sf/md-importer.js index 6966528c6..b829c6752 100644 --- a/src/resources/extensions/sf/md-importer.js +++ b/src/resources/extensions/sf/md-importer.js @@ -6,7 +6,7 @@ import { existsSync, readdirSync, readFileSync } from "node:fs"; import { join } from "node:path"; import { parseContextDependsOn } from "./files.js"; -import { findMilestoneIds } from "./guided-flow.js"; +import { findMilestoneIds } from "./milestone-ids.js"; import { parsePlan, parseRoadmap } from "./parsers.js"; import { milestonesDir, diff --git a/src/resources/extensions/sf/parallel-eligibility.js b/src/resources/extensions/sf/parallel-eligibility.js index 636b963e6..1a46b169f 100644 --- a/src/resources/extensions/sf/parallel-eligibility.js +++ b/src/resources/extensions/sf/parallel-eligibility.js @@ -4,7 +4,7 @@ * Analyzes which milestones can safely run in parallel by checking * dependency satisfaction and file overlap across slice plans. */ -import { findMilestoneIds } from "./guided-flow.js"; +import { findMilestoneIds } from "./milestone-ids.js"; import { getMilestoneSlices, getSliceTasks, isDbAvailable } from "./sf-db.js"; import { deriveState } from "./state.js";