import { ensureDbOpen } from "../bootstrap/dynamic-tools.js";
import { sanitizeCompleteMilestoneParams } from "../bootstrap/sanitize-complete-milestone.js";
import {
	loadWriteGateSnapshot,
	shouldBlockContextArtifactSaveInSnapshot,
} from "../bootstrap/write-gate.js";
import { saveArtifactToDb } from "../db-writer.js";
import { getErrorMessage } from "../error-utils.js";
import { GATE_REGISTRY } from "../gate-registry.js";
import { checkSafeIds } from "../safety/safe-id.js";
import {
	getMilestone,
	getSliceStatusSummary,
	getSliceTaskCounts,
	readTransaction,
	saveGateResult,
	setSliceUatVerdict,
} from "../sf-db.js";
import { invalidateStateCache } from "../state.js";
import { buildAutonomousUokContext } from "../uok/auto-uok-ctx.js";
import { extractVerdict } from "../verdict-parser.js";
import { logError, logWarning } from "../workflow-logger.js";
import { handleCompleteMilestone } from "./complete-milestone.js";
import { handleCompleteSlice } from "./complete-slice.js";
import { handleCompleteTask } from "./complete-task.js";
import { handlePlanMilestone } from "./plan-milestone.js";
import { handlePlanSlice } from "./plan-slice.js";
import { handleReassessRoadmap } from "./reassess-roadmap.js";
import { handleReplanSlice } from "./replan-slice.js";
import { handleValidateMilestone } from "./validate-milestone.js";
export const SUPPORTED_SUMMARY_ARTIFACT_TYPES = [
	"SUMMARY",
	"RESEARCH",
	"CONTEXT",
	"ASSESSMENT",
	"CONTEXT-DRAFT",
];
export function isSupportedSummaryArtifactType(artifactType) {
	return SUPPORTED_SUMMARY_ARTIFACT_TYPES.includes(artifactType);
}
export async function executeSummarySave(params, basePath = process.cwd()) {
	const dbAvailable = await ensureDbOpen(basePath);
	if (!dbAvailable) {
		return {
			content: [
				{
					type: "text",
					text: "Error: SF database is not available. Cannot save artifact.",
				},
			],
			details: { operation: "save_summary", error: "db_unavailable" },
			isError: true,
		};
	}
	if (!isSupportedSummaryArtifactType(params.artifact_type)) {
		return {
			content: [
				{
					type: "text",
					text: `Error: Invalid artifact_type "${params.artifact_type}". Must be one of: ${SUPPORTED_SUMMARY_ARTIFACT_TYPES.join(", ")}`,
				},
			],
			details: { operation: "save_summary", error: "invalid_artifact_type" },
			isError: true,
		};
	}
	// Reject path-traversal in any ID before they reach string interpolation
	// below — this is the chokepoint. See safety/safe-id.ts for rationale and
	// the validation-safe-id-path-segments self-feedback entry.
	const idCheck = checkSafeIds({
		milestoneId: params.milestone_id,
		sliceId: params.slice_id,
		taskId: params.task_id,
	});
	if (idCheck) {
		return {
			content: [
				{
					type: "text",
					text: `Error saving artifact: ${idCheck.message}`,
				},
			],
			details: {
				operation: "save_summary",
				error: "unsafe_id",
				field: idCheck.fieldName,
				reason: idCheck.reason,
			},
			isError: true,
		};
	}
	const contextGuard = shouldBlockContextArtifactSaveInSnapshot(
		loadWriteGateSnapshot(basePath),
		params.artifact_type,
		params.milestone_id ?? null,
		params.slice_id ?? null,
	);
	if (contextGuard.block) {
		const reason = contextGuard.reason ?? "context write blocked";
		return {
			content: [
				{
					type: "text",
					text: `Error saving artifact: ${reason}`,
				},
			],
			details: {
				operation: "save_summary",
				error: "context_write_blocked",
				reason,
			},
			isError: true,
		};
	}
	try {
		let relativePath;
		if (params.task_id && params.slice_id) {
			relativePath = `milestones/${params.milestone_id}/slices/${params.slice_id}/tasks/${params.task_id}-${params.artifact_type}.md`;
		} else if (params.slice_id) {
			relativePath = `milestones/${params.milestone_id}/slices/${params.slice_id}/${params.slice_id}-${params.artifact_type}.md`;
		} else {
			relativePath = `milestones/${params.milestone_id}/${params.milestone_id}-${params.artifact_type}.md`;
		}
		await saveArtifactToDb(
			{
				path: relativePath,
				artifact_type: params.artifact_type,
				content: params.content,
				milestone_id: params.milestone_id,
				slice_id: params.slice_id,
				task_id: params.task_id,
			},
			basePath,
		);
		// Persist UAT verdict to DB when an ASSESSMENT is saved at slice scope.
		// This makes checkNeedsRunUat DB-only — no file fallback needed.
		if (
			params.artifact_type === "ASSESSMENT" &&
			params.slice_id &&
			!params.task_id
		) {
			try {
				const verdict = extractVerdict(params.content);
				if (verdict) {
					setSliceUatVerdict(params.milestone_id, params.slice_id, verdict);
				}
			} catch {
				// Non-fatal — verdict check will still fall through to backfill
			}
		}
		// Terminal transition for research units: After successful RESEARCH artifact save,
		// research units must terminate or become unable to call planning/milestone-generation tools.
		// This prevents the dr-repo M008/S01 issue where research continued into planning.
		if (params.artifact_type === "RESEARCH") {
			return {
				content: [
					{
						type: "text",
						text: `Saved ${params.artifact_type} artifact to ${relativePath}\n\nResearch unit terminal transition: this research unit has completed its primary artifact and should terminate. Further planning or milestone-generation tools will be blocked.`,
					},
				],
				details: {
					operation: "save_summary",
					path: relativePath,
					artifact_type: params.artifact_type,
					terminal_transition: true,
					unit_type: "research",
				},
			};
		}
		return {
			content: [
				{
					type: "text",
					text: `Saved ${params.artifact_type} artifact to ${relativePath}`,
				},
			],
			details: {
				operation: "save_summary",
				path: relativePath,
				artifact_type: params.artifact_type,
			},
		};
	} catch (err) {
		const msg = getErrorMessage(err);
		logError("tool", `save_summary tool failed: ${msg}`, {
			tool: "save_summary",
			error: String(err),
		});
		return {
			content: [{ type: "text", text: `Error saving artifact: ${msg}` }],
			details: { operation: "save_summary", error: msg },
			isError: true,
		};
	}
}
export async function executeTaskComplete(params, basePath = process.cwd()) {
	const dbAvailable = await ensureDbOpen(basePath);
	if (!dbAvailable) {
		return {
			content: [
				{
					type: "text",
					text: "Error: SF database is not available. Cannot complete task.",
				},
			],
			details: { operation: "complete_task", error: "db_unavailable" },
			isError: true,
		};
	}
	try {
		const coerced = { ...params };
		coerced.verificationEvidence = (params.verificationEvidence ?? []).map(
			(v) =>
				typeof v === "string"
					? {
							command: v,
							exitCode: -1,
							verdict: "unknown (coerced from string)",
							durationMs: 0,
						}
					: v,
		);
		const result = await handleCompleteTask(coerced, basePath);
		if ("error" in result) {
			return {
				content: [
					{ type: "text", text: `Error completing task: ${result.error}` },
				],
				details: { operation: "complete_task", error: result.error },
				isError: true,
			};
		}
		// SF ADR-011 P2: optional escalation payload. Only honored when the
		// phases.mid_execution_escalation preference is true. When false (default),
		// any escalation field on the params is silently ignored — keeps the
		// payload backwards-compatible for callers that always send it.
		let escalationPath;
		let escalationStatus;
		let escalationError;
		let escalationDisabled = false;
		if (params.escalation) {
			try {
				const { loadEffectiveSFPreferences } = await import(
					"../preferences.js"
				);
				const prefs = loadEffectiveSFPreferences()?.preferences;
				if (prefs?.phases?.mid_execution_escalation === true) {
					const { buildEscalationArtifact, writeEscalationArtifact } =
						await import("../escalation.js");
					const artifact = buildEscalationArtifact({
						taskId: result.taskId,
						sliceId: result.sliceId,
						milestoneId: result.milestoneId,
						question: params.escalation.question,
						options: params.escalation.options,
						recommendation: params.escalation.recommendation,
						recommendationRationale: params.escalation.recommendationRationale,
						continueWithDefault: params.escalation.continueWithDefault,
					});
					escalationPath = writeEscalationArtifact(basePath, artifact);
					escalationStatus = params.escalation.continueWithDefault
						? "awaiting-review"
						: "pending";
				} else {
					// Feature flag is off — surface this so the agent knows the payload
					// was dropped and can either turn the feature on or just make the
					// decision themselves.
					escalationDisabled = true;
				}
			} catch (err) {
				// Escalation is additive — never block task completion if it fails,
				// but DO tell the agent so they don't think the issue was recorded.
				escalationError = getErrorMessage(err);
				logError(
					"tool",
					`complete_task escalation write failed: ${escalationError}`,
					{ tool: "complete_task", op: "escalation" },
				);
			}
		}
		const baseText = `Completed task ${result.taskId} (${result.sliceId}/${result.milestoneId})`;
		const escalationSuffix = escalationStatus
			? ` — escalation ${escalationStatus} at ${escalationPath}`
			: escalationError
				? ` — WARNING: escalation payload was REJECTED (${escalationError}); the next executor will NOT see your decision. Either fix the payload and retry, or make the choice yourself and document it in the summary.`
				: escalationDisabled
					? ` — note: escalation payload was DROPPED because phases.mid_execution_escalation is disabled; document the choice in the summary instead.`
					: "";
		return {
			content: [
				{
					type: "text",
					text: baseText + escalationSuffix,
				},
			],
			details: {
				operation: "complete_task",
				taskId: result.taskId,
				sliceId: result.sliceId,
				milestoneId: result.milestoneId,
				summaryPath: result.summaryPath,
				...(escalationPath ? { escalationArtifactPath: escalationPath } : {}),
				...(escalationStatus ? { escalationStatus } : {}),
			},
		};
	} catch (err) {
		const msg = getErrorMessage(err);
		logError("tool", `complete_task tool failed: ${msg}`, {
			tool: "complete_task",
			error: String(err),
		});
		return {
			content: [{ type: "text", text: `Error completing task: ${msg}` }],
			details: { operation: "complete_task", error: msg },
			isError: true,
		};
	}
}
export async function executeSliceComplete(params, basePath = process.cwd()) {
	const dbAvailable = await ensureDbOpen(basePath);
	if (!dbAvailable) {
		return {
			content: [
				{
					type: "text",
					text: "Error: SF database is not available. Cannot complete slice.",
				},
			],
			details: { operation: "complete_slice", error: "db_unavailable" },
			isError: true,
		};
	}
	try {
		const splitPair = (s) => {
			const m = s.match(/^(.+?)\s*(?:—|-)\s+(.+)$/);
			return m ? [m[1].trim(), m[2].trim()] : [s.trim(), ""];
		};
		const wrapArray = (v) => (v == null ? [] : Array.isArray(v) ? v : [v]);
		const coerced = { ...params };
		coerced.provides = wrapArray(params.provides);
		coerced.keyFiles = wrapArray(params.keyFiles);
		coerced.keyDecisions = wrapArray(params.keyDecisions);
		coerced.patternsEstablished = wrapArray(params.patternsEstablished);
		coerced.observabilitySurfaces = wrapArray(params.observabilitySurfaces);
		coerced.requirementsSurfaced = wrapArray(params.requirementsSurfaced);
		coerced.drillDownPaths = wrapArray(params.drillDownPaths);
		coerced.affects = wrapArray(params.affects);
		coerced.filesModified = wrapArray(params.filesModified).map((f) => {
			if (typeof f !== "string") return f;
			const [path, description] = splitPair(f);
			return { path, description };
		});
		coerced.requires = wrapArray(params.requires).map((r) => {
			if (typeof r !== "string") return r;
			const [slice, provides] = splitPair(r);
			return { slice, provides };
		});
		coerced.requirementsAdvanced = wrapArray(params.requirementsAdvanced).map(
			(r) => {
				if (typeof r !== "string") return r;
				const [id, how] = splitPair(r);
				return { id, how };
			},
		);
		coerced.requirementsValidated = wrapArray(params.requirementsValidated).map(
			(r) => {
				if (typeof r !== "string") return r;
				const [id, proof] = splitPair(r);
				return { id, proof };
			},
		);
		coerced.requirementsInvalidated = wrapArray(
			params.requirementsInvalidated,
		).map((r) => {
			if (typeof r !== "string") return r;
			const [id, what] = splitPair(r);
			return { id, what };
		});
		const result = await handleCompleteSlice(coerced, basePath);
		if ("error" in result) {
			return {
				content: [
					{ type: "text", text: `Error completing slice: ${result.error}` },
				],
				details: { operation: "complete_slice", error: result.error },
				isError: true,
			};
		}
		return {
			content: [
				{
					type: "text",
					text: `Completed slice ${result.sliceId} (${result.milestoneId})`,
				},
			],
			details: {
				operation: "complete_slice",
				sliceId: result.sliceId,
				milestoneId: result.milestoneId,
				summaryPath: result.summaryPath,
				uatPath: result.uatPath,
			},
		};
	} catch (err) {
		const msg = getErrorMessage(err);
		logError("tool", `complete_slice tool failed: ${msg}`, {
			tool: "complete_slice",
			error: String(err),
		});
		return {
			content: [{ type: "text", text: `Error completing slice: ${msg}` }],
			details: { operation: "complete_slice", error: msg },
			isError: true,
		};
	}
}
export async function executeCompleteMilestone(
	params,
	basePath = process.cwd(),
) {
	const dbAvailable = await ensureDbOpen(basePath);
	if (!dbAvailable) {
		return {
			content: [
				{
					type: "text",
					text: "Error: SF database is not available. Cannot complete milestone.",
				},
			],
			details: { operation: "complete_milestone", error: "db_unavailable" },
			isError: true,
		};
	}
	try {
		const sanitized = sanitizeCompleteMilestoneParams(params);
		const result = await handleCompleteMilestone(sanitized, basePath);
		if ("error" in result) {
			return {
				content: [
					{ type: "text", text: `Error completing milestone: ${result.error}` },
				],
				details: { operation: "complete_milestone", error: result.error },
				isError: true,
			};
		}
		return {
			content: [
				{
					type: "text",
					text: `Completed milestone ${result.milestoneId}. Summary written to ${result.summaryPath}`,
				},
			],
			details: {
				operation: "complete_milestone",
				milestoneId: result.milestoneId,
				summaryPath: result.summaryPath,
			},
		};
	} catch (err) {
		const msg = getErrorMessage(err);
		logError("tool", `complete_milestone tool failed: ${msg}`, {
			tool: "complete_milestone",
			error: String(err),
		});
		return {
			content: [{ type: "text", text: `Error completing milestone: ${msg}` }],
			details: { operation: "complete_milestone", error: msg },
			isError: true,
		};
	}
}
export async function executeValidateMilestone(
	params,
	basePath = process.cwd(),
) {
	const dbAvailable = await ensureDbOpen(basePath);
	if (!dbAvailable) {
		return {
			content: [
				{
					type: "text",
					text: "Error: SF database is not available. Cannot validate milestone.",
				},
			],
			details: { operation: "validate_milestone", error: "db_unavailable" },
			isError: true,
		};
	}
	try {
		const result = await handleValidateMilestone(params, basePath);
		if ("error" in result) {
			return {
				content: [
					{ type: "text", text: `Error validating milestone: ${result.error}` },
				],
				details: { operation: "validate_milestone", error: result.error },
				isError: true,
			};
		}
		return {
			content: [
				{
					type: "text",
					text: `Validated milestone ${result.milestoneId} — verdict: ${result.verdict}. Written to ${result.validationPath}`,
				},
			],
			details: {
				operation: "validate_milestone",
				milestoneId: result.milestoneId,
				verdict: result.verdict,
				validationPath: result.validationPath,
			},
		};
	} catch (err) {
		const msg = getErrorMessage(err);
		logError("tool", `validate_milestone tool failed: ${msg}`, {
			tool: "validate_milestone",
			error: String(err),
		});
		return {
			content: [{ type: "text", text: `Error validating milestone: ${msg}` }],
			details: { operation: "validate_milestone", error: msg },
			isError: true,
		};
	}
}
export async function executeReassessRoadmap(params, basePath = process.cwd()) {
	const dbAvailable = await ensureDbOpen(basePath);
	if (!dbAvailable) {
		return {
			content: [
				{
					type: "text",
					text: "Error: SF database is not available. Cannot reassess roadmap.",
				},
			],
			details: { operation: "reassess_roadmap", error: "db_unavailable" },
			isError: true,
		};
	}
	try {
		const result = await handleReassessRoadmap(params, basePath);
		if ("error" in result) {
			return {
				content: [
					{ type: "text", text: `Error reassessing roadmap: ${result.error}` },
				],
				details: { operation: "reassess_roadmap", error: result.error },
				isError: true,
			};
		}
		return {
			content: [
				{
					type: "text",
					text: `Reassessed roadmap for milestone ${result.milestoneId} after ${result.completedSliceId}`,
				},
			],
			details: {
				operation: "reassess_roadmap",
				milestoneId: result.milestoneId,
				completedSliceId: result.completedSliceId,
				assessmentPath: result.assessmentPath,
				roadmapPath: result.roadmapPath,
			},
		};
	} catch (err) {
		const msg = getErrorMessage(err);
		logError("tool", `reassess_roadmap tool failed: ${msg}`, {
			tool: "reassess_roadmap",
			error: String(err),
		});
		return {
			content: [{ type: "text", text: `Error reassessing roadmap: ${msg}` }],
			details: { operation: "reassess_roadmap", error: msg },
			isError: true,
		};
	}
}
export async function executeSaveGateResult(params, basePath = process.cwd()) {
	const dbAvailable = await ensureDbOpen(basePath);
	if (!dbAvailable) {
		return {
			content: [{ type: "text", text: "Error: SF database is not available." }],
			details: { operation: "save_gate_result", error: "db_unavailable" },
			isError: true,
		};
	}
	// Source of truth: gate-registry.ts. Every declared GateId is accepted,
	// so adding a new gate in one place automatically flows through here.
	const validGates = Object.keys(GATE_REGISTRY);
	if (!validGates.includes(params.gateId)) {
		return {
			content: [
				{
					type: "text",
					text: `Error: Invalid gateId "${params.gateId}". Must be one of: ${validGates.join(", ")}`,
				},
			],
			details: { operation: "save_gate_result", error: "invalid_gate_id" },
			isError: true,
		};
	}
	const validVerdicts = ["pass", "flag", "omitted"];
	if (!validVerdicts.includes(params.verdict)) {
		return {
			content: [
				{
					type: "text",
					text: `Error: Invalid verdict "${params.verdict}". Must be one of: ${validVerdicts.join(", ")}`,
				},
			],
			details: { operation: "save_gate_result", error: "invalid_verdict" },
			isError: true,
		};
	}
	try {
		let effectiveVerdict = params.verdict;
		let effectiveRationale = params.rationale;
		if (effectiveVerdict === "omitted") {
			const def = GATE_REGISTRY[params.gateId];
			const minWords = def?.minOmissionWords ?? 0;
			if (minWords > 0) {
				const wordCount = effectiveRationale
					.trim()
					.split(/\s+/)
					.filter(Boolean).length;
				if (wordCount < minWords) {
					effectiveVerdict = "flag";
					effectiveRationale = `[⚠ Rationale too short — ${wordCount} words, ${minWords} required for omission] ${effectiveRationale}`;
				}
			}
		}
		saveGateResult({
			milestoneId: params.milestoneId,
			sliceId: params.sliceId,
			gateId: params.gateId,
			taskId: params.taskId ?? "",
			verdict: effectiveVerdict,
			rationale: effectiveRationale,
			findings: params.findings ?? "",
		});
		invalidateStateCache();
		return {
			content: [
				{
					type: "text",
					text: `Gate ${params.gateId} result saved: verdict=${params.verdict}`,
				},
			],
			details: {
				operation: "save_gate_result",
				gateId: params.gateId,
				verdict: params.verdict,
			},
		};
	} catch (err) {
		const msg = getErrorMessage(err);
		logError("tool", `record_gate failed: ${msg}`, {
			tool: "record_gate",
			error: String(err),
		});
		return {
			content: [{ type: "text", text: `Error saving gate result: ${msg}` }],
			details: { operation: "save_gate_result", error: msg },
			isError: true,
		};
	}
}
export async function executePlanMilestone(params, basePath = process.cwd()) {
	const dbAvailable = await ensureDbOpen(basePath);
	if (!dbAvailable) {
		return {
			content: [
				{
					type: "text",
					text: "Error: SF database is not available. Cannot plan milestone.",
				},
			],
			details: { operation: "plan_milestone", error: "db_unavailable" },
			isError: true,
		};
	}
	try {
		const result = await handlePlanMilestone(params, basePath);
		if ("error" in result) {
			return {
				content: [
					{ type: "text", text: `Error planning milestone: ${result.error}` },
				],
				details: { operation: "plan_milestone", error: result.error },
				isError: true,
			};
		}
		return {
			content: [
				{
					type: "text",
					text: `Planned milestone ${result.milestoneId}${result.title ? `: ${result.title}` : ""}`,
				},
			],
			details: {
				operation: "plan_milestone",
				milestoneId: result.milestoneId,
				title: result.title,
				sliceCount: result.sliceCount,
				firstSliceId: result.firstSliceId,
				firstSliceTitle: result.firstSliceTitle,
				roadmapPath: result.roadmapPath,
			},
		};
	} catch (err) {
		const msg = getErrorMessage(err);
		logError("tool", `plan_milestone tool failed: ${msg}`, {
			tool: "plan_milestone",
			error: String(err),
		});
		return {
			content: [{ type: "text", text: `Error planning milestone: ${msg}` }],
			details: { operation: "plan_milestone", error: msg },
			isError: true,
		};
	}
}
/**
 * Build a schema-v2 UOK run-context for plan_slice from the singleton
 * autonomous session, when one is active.
 *
 * Lazy-imports auto/session.js so headless/test code paths that never
 * touch the autonomous loop don't pay the load cost. Returns null when
 * no session is active or when buildAutonomousUokContext rejects the
 * inputs (e.g. missing traceId); callers treat null as "fall through to
 * the legacy NULL-column write".
 */
async function derivePlanSliceUokContext() {
	let s;
	try {
		const sessionModule = await import("../auto/session.js");
		s = sessionModule.getAutoSession?.();
	} catch {
		return null;
	}
	if (!s || typeof s !== "object") return null;
	const traceId = s.currentTraceId;
	if (typeof traceId !== "string" || traceId.length === 0) return null;
	// AutoSession exposes isYolo(); prefs are loaded at the loop level and
	// not stored on the session singleton, so we don't have them here. The
	// derivePermissionProfile helper degrades gracefully to "high" when
	// prefs is undefined and YOLO is off, which matches the autonomous
	// loop's default.
	return buildAutonomousUokContext({
		s,
		traceId,
		parentTrace: traceId,
	});
}

export async function executePlanSlice(params, basePath = process.cwd()) {
	const dbAvailable = await ensureDbOpen(basePath);
	if (!dbAvailable) {
		return {
			content: [
				{
					type: "text",
					text: "Error: SF database is not available. Cannot plan slice.",
				},
			],
			details: { operation: "plan_slice", error: "db_unavailable" },
			isError: true,
		};
	}
	try {
		// Derive the schema-v2 UOK run-context from the autonomous session
		// when one is active. plan_slice runs as a tool inside an
		// autonomous unit, so the session's currentTraceId is the parent
		// flow id. When the tool is invoked outside an autonomous loop
		// (interactive REPL, headless one-shot), uokContext stays null and
		// the seeded gate rows fall through to the legacy null-column shape.
		const uokContext = await derivePlanSliceUokContext();
		const result = await handlePlanSlice(params, basePath, { uokContext });
		if ("error" in result) {
			return {
				content: [
					{ type: "text", text: `Error planning slice: ${result.error}` },
				],
				details: { operation: "plan_slice", error: result.error },
				isError: true,
			};
		}
		return {
			content: [
				{
					type: "text",
					text: `Planned slice ${result.sliceId} (${result.milestoneId})`,
				},
			],
			details: {
				operation: "plan_slice",
				milestoneId: result.milestoneId,
				sliceId: result.sliceId,
				planPath: result.planPath,
				taskPlanPaths: result.taskPlanPaths,
			},
		};
	} catch (err) {
		const msg = getErrorMessage(err);
		logError("tool", `plan_slice tool failed: ${msg}`, {
			tool: "plan_slice",
			error: String(err),
		});
		return {
			content: [{ type: "text", text: `Error planning slice: ${msg}` }],
			details: { operation: "plan_slice", error: msg },
			isError: true,
		};
	}
}
export async function executeReplanSlice(params, basePath = process.cwd()) {
	const dbAvailable = await ensureDbOpen(basePath);
	if (!dbAvailable) {
		return {
			content: [
				{
					type: "text",
					text: "Error: SF database is not available. Cannot replan slice.",
				},
			],
			details: { operation: "replan_slice", error: "db_unavailable" },
			isError: true,
		};
	}
	try {
		const result = await handleReplanSlice(params, basePath);
		if ("error" in result) {
			return {
				content: [
					{ type: "text", text: `Error replanning slice: ${result.error}` },
				],
				details: { operation: "replan_slice", error: result.error },
				isError: true,
			};
		}
		return {
			content: [
				{
					type: "text",
					text: `Replanned slice ${result.sliceId} (${result.milestoneId})`,
				},
			],
			details: {
				operation: "replan_slice",
				milestoneId: result.milestoneId,
				sliceId: result.sliceId,
				replanPath: result.replanPath,
				planPath: result.planPath,
			},
		};
	} catch (err) {
		const msg = getErrorMessage(err);
		logError("tool", `replan_slice tool failed: ${msg}`, {
			tool: "replan_slice",
			error: String(err),
		});
		return {
			content: [{ type: "text", text: `Error replanning slice: ${msg}` }],
			details: { operation: "replan_slice", error: msg },
			isError: true,
		};
	}
}
export async function executeMilestoneStatus(params, basePath = process.cwd()) {
	try {
		const dbAvailable = await ensureDbOpen(basePath);
		if (!dbAvailable) {
			return {
				content: [
					{ type: "text", text: "Error: SF database is not available." },
				],
				details: { operation: "milestone_status", error: "db_unavailable" },
				isError: true,
			};
		}
		return readTransaction(() => {
			const milestone = getMilestone(params.milestoneId);
			if (!milestone) {
				return {
					content: [
						{
							type: "text",
							text: `Milestone ${params.milestoneId} not found in database.`,
						},
					],
					details: {
						operation: "milestone_status",
						milestoneId: params.milestoneId,
						found: false,
					},
				};
			}
			const sliceStatuses = getSliceStatusSummary(params.milestoneId);
			const slices = sliceStatuses.map((s) => ({
				id: s.id,
				status: s.status,
				taskCounts: getSliceTaskCounts(params.milestoneId, s.id),
			}));
			const result = {
				milestoneId: milestone.id,
				title: milestone.title,
				status: milestone.status,
				createdAt: milestone.created_at,
				completedAt: milestone.completed_at,
				sliceCount: slices.length,
				slices,
			};
			return {
				content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
				details: {
					operation: "milestone_status",
					milestoneId: milestone.id,
					sliceCount: slices.length,
				},
			};
		});
	} catch (err) {
		const msg = getErrorMessage(err);
		logWarning("tool", `milestone_status tool failed: ${msg}`);
		return {
			content: [
				{ type: "text", text: `Error querying milestone status: ${msg}` },
			],
			details: { operation: "milestone_status", error: msg },
			isError: true,
		};
	}
}
