fix: sfdb-doctor agent partial - lazy imports in agent-end-recovery, db-tools uses milestone-ids.js

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Mikael Hugo 2026-05-10 02:18:55 +02:00
parent a3f2479a4c
commit d6bd49d0b6
6 changed files with 26 additions and 40 deletions

View file

@ -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();

View file

@ -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";

View file

@ -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";

View file

@ -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;

View file

@ -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,

View file

@ -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";