import { d as resolveIsNixMode } from "./paths-C9FmTW1x.js";
import { H as isRich, U as theme, V as colorize, j as danger } from "./agent-paths-BySKyq9I.js";
import { Nu as listChannelPlugins, dd as formatCliCommand } from "./agent-scope-CLn_Ws3B.js";
import { d as sanitizeAgentId } from "./session-key-LmCHAJTQ.js";
import { d as defaultRuntime } from "./errors-Dx3S3Nrp.js";
import "./github-copilot-token-BA45-q56.js";
import "./chat-envelope-D_wSv26N.js";
import "./pairing-token-BFGorDQo.js";
import "./ip-D_T5zbZS.js";
import "./ws-cvQhrVP3.js";
import "./device-identity-DzUZ06fL.js";
import "./federation-BrNm7xtG.js";
import "./call-s6DNIELo.js";
import { C as parseAbsoluteTimeMs, T as formatDurationHuman, a as withTaskCoordinationRequest, g as formatCronEscalationPasses, h as formatCronEscalationContext, n as planTaskExecutionPolicy, v as formatCronRunLoadedSkills, x as resolveCronStaggerMs, y as formatCronTaskRunDetail } from "./task-planner-BW6kdamv.js";
import { C as resolveTaskWorkerSystemdServiceName, S as resolveTaskWorkerLaunchAgentLabel, T as resolveTaskWorkerWindowsTaskScriptName, c as TASK_WORKER_SERVICE_KIND, d as formatTaskWorkerServiceDescription, f as normalizeTaskWorkerName, l as TASK_WORKER_SERVICE_MARKER, w as resolveTaskWorkerWindowsTaskName } from "./constants-C2y93ya8.js";
import { t as formatDocsLink } from "./links-BeUKckiL.js";
import "./progress-CDqdg8f8.js";
import { n as parsePositiveIntOrUndefined } from "./helpers-btYENKQf.js";
import { n as inheritOptionFromParent } from "./command-options-DEPpN8NK.js";
import { n as callGatewayFromCli, t as addGatewayClientOptions } from "./gateway-rpc-C9uKnQRG.js";
import { r as isGatewayDaemonRuntime, t as DEFAULT_GATEWAY_DAEMON_RUNTIME } from "./daemon-runtime-B7q74R3U.js";
import "./managed-up-BykEd-7K.js";
import { c as buildTaskWorkerServiceEnvironment, m as resolvePreferredNodePath, o as emitNodeRuntimeWarning, r as resolveGatewayDevMode, v as resolveTaskWorkerProgramArguments } from "./daemon-install-helpers-CG_Lmgua.js";
import "./systemd-ZvgpcrfV.js";
import { t as resolveGatewayService } from "./service-DbZp-Ejz.js";
import "./service-audit-B5uApPZ5.js";
import { t as formatRuntimeStatus } from "./runtime-format-DcJFjE87.js";
import { d as runServiceStart, f as runServiceStop, g as installDaemonServiceAndEmit, h as createDaemonActionContext, m as buildDaemonServiceSnapshot, p as runServiceUninstall, t as createCliStatusTextStyles, u as runServiceRestart } from "./shared-Br_rWHZI.js";
import fs from "node:fs";
import crypto from "node:crypto";

//#region src/cli/cron-cli/shared.ts
const getCronChannelOptions = () => ["last", ...listChannelPlugins().map((plugin) => plugin.id)].join("|");
async function warnIfCronSchedulerDisabled(opts) {
	try {
		const res = await callGatewayFromCli("cron.status", opts, {});
		if (res?.enabled === true) return;
		const store = typeof res?.storePath === "string" ? res.storePath : "";
		defaultRuntime.error([
			"warning: task scheduler is disabled in the Gateway; tasks are saved but will not run automatically.",
			"Re-enable with `cron.enabled: true` (or remove `cron.enabled: false`) and restart the Gateway.",
			store ? `store: ${store}` : ""
		].filter(Boolean).join("\n"));
	} catch {}
}
function parseDurationMs(input) {
	const raw = input.trim();
	if (!raw) return null;
	const match = raw.match(/^(\d+(?:\.\d+)?)(ms|s|m|h|d)$/i);
	if (!match) return null;
	const n = Number.parseFloat(match[1] ?? "");
	if (!Number.isFinite(n) || n <= 0) return null;
	const unit = (match[2] ?? "").toLowerCase();
	const factor = unit === "ms" ? 1 : unit === "s" ? 1e3 : unit === "m" ? 6e4 : unit === "h" ? 36e5 : 864e5;
	return Math.floor(n * factor);
}
function parseAt(input) {
	const raw = input.trim();
	if (!raw) return null;
	const absolute = parseAbsoluteTimeMs(raw);
	if (absolute !== null) return new Date(absolute).toISOString();
	const dur = parseDurationMs(raw);
	if (dur !== null) return new Date(Date.now() + dur).toISOString();
	return null;
}
const CRON_ID_PAD = 36;
const CRON_NAME_PAD = 24;
const CRON_SCHEDULE_PAD = 32;
const CRON_NEXT_PAD = 10;
const CRON_LAST_PAD = 10;
const CRON_STATUS_PAD = 9;
const CRON_TARGET_PAD = 9;
const CRON_AGENT_PAD = 10;
const pad = (value, width) => value.padEnd(width);
const truncate = (value, width) => {
	if (value.length <= width) return value;
	if (width <= 3) return value.slice(0, width);
	return `${value.slice(0, width - 3)}...`;
};
const formatIsoMinute = (iso) => {
	const parsed = parseAbsoluteTimeMs(iso);
	const d = new Date(parsed ?? NaN);
	if (Number.isNaN(d.getTime())) return "-";
	const isoStr = d.toISOString();
	return `${isoStr.slice(0, 10)} ${isoStr.slice(11, 16)}Z`;
};
const formatSpan = (ms) => {
	if (ms < 6e4) return "<1m";
	if (ms < 36e5) return `${Math.round(ms / 6e4)}m`;
	if (ms < 864e5) return `${Math.round(ms / 36e5)}h`;
	return `${Math.round(ms / 864e5)}d`;
};
const formatRelative = (ms, nowMs) => {
	if (!ms) return "-";
	const delta = ms - nowMs;
	const label = formatSpan(Math.abs(delta));
	return delta >= 0 ? `in ${label}` : `${label} ago`;
};
const formatSchedule = (schedule) => {
	if (schedule.kind === "at") return `at ${formatIsoMinute(schedule.at)}`;
	if (schedule.kind === "every") return `every ${formatDurationHuman(schedule.everyMs)}`;
	const base = schedule.tz ? `cron ${schedule.expr} @ ${schedule.tz}` : `cron ${schedule.expr}`;
	const staggerMs = resolveCronStaggerMs(schedule);
	if (staggerMs <= 0) return `${base} (exact)`;
	return `${base} (stagger ${formatDurationHuman(staggerMs)})`;
};
const formatStatus = (job) => {
	if (!job.enabled) return "disabled";
	if (job.state.runningAtMs) return "running";
	return job.state.lastStatus ?? "idle";
};
function printCronList(jobs, runtime = defaultRuntime) {
	if (jobs.length === 0) {
		runtime.log("No scheduled tasks.");
		return;
	}
	const rich = isRich();
	const header = [
		pad("ID", CRON_ID_PAD),
		pad("Name", CRON_NAME_PAD),
		pad("Schedule", CRON_SCHEDULE_PAD),
		pad("Next", CRON_NEXT_PAD),
		pad("Last", CRON_LAST_PAD),
		pad("Status", CRON_STATUS_PAD),
		pad("Target", CRON_TARGET_PAD),
		pad("Agent", CRON_AGENT_PAD)
	].join(" ");
	runtime.log(rich ? theme.heading(header) : header);
	const now = Date.now();
	for (const job of jobs) {
		const idLabel = pad(job.id, CRON_ID_PAD);
		const nameLabel = pad(truncate(job.name, CRON_NAME_PAD), CRON_NAME_PAD);
		const scheduleLabel = pad(truncate(formatSchedule(job.schedule), CRON_SCHEDULE_PAD), CRON_SCHEDULE_PAD);
		const nextLabel = pad(job.enabled ? formatRelative(job.state.nextRunAtMs, now) : "-", CRON_NEXT_PAD);
		const lastLabel = pad(formatRelative(job.state.lastRunAtMs, now), CRON_LAST_PAD);
		const statusRaw = formatStatus(job);
		const statusLabel = pad(statusRaw, CRON_STATUS_PAD);
		const targetLabel = pad(job.sessionTarget ?? "-", CRON_TARGET_PAD);
		const agentLabel = pad(truncate(job.agentId ?? "default", CRON_AGENT_PAD), CRON_AGENT_PAD);
		const coloredStatus = (() => {
			if (statusRaw === "ok") return colorize(rich, theme.success, statusLabel);
			if (statusRaw === "error") return colorize(rich, theme.error, statusLabel);
			if (statusRaw === "running") return colorize(rich, theme.warn, statusLabel);
			if (statusRaw === "skipped") return colorize(rich, theme.muted, statusLabel);
			return colorize(rich, theme.muted, statusLabel);
		})();
		const coloredTarget = job.sessionTarget === "isolated" ? colorize(rich, theme.accentBright, targetLabel) : colorize(rich, theme.accent, targetLabel);
		const coloredAgent = job.agentId ? colorize(rich, theme.info, agentLabel) : colorize(rich, theme.muted, agentLabel);
		const line = [
			colorize(rich, theme.accent, idLabel),
			colorize(rich, theme.info, nameLabel),
			colorize(rich, theme.info, scheduleLabel),
			colorize(rich, theme.muted, nextLabel),
			colorize(rich, theme.muted, lastLabel),
			coloredStatus,
			coloredTarget,
			coloredAgent
		].join(" ");
		runtime.log(line.trimEnd());
	}
}
function formatMaybeRelative(ms, nowMs) {
	return ms ? formatRelative(ms, nowMs) : "-";
}
function printCronStatus(status, runtime = defaultRuntime) {
	const now = Date.now();
	const enabled = status.enabled ? "enabled" : "disabled";
	const jobs = Number.isFinite(status.jobs) ? status.jobs : 0;
	runtime.log([
		`Tasks ${enabled}`,
		`${jobs} job${jobs === 1 ? "" : "s"}`,
		`next ${formatMaybeRelative(status.nextWakeAtMs, now)}`
	].join(" · "));
	const queue = status.queue ?? {
		path: "",
		total: 0,
		queued: 0,
		running: 0,
		terminal: 0,
		cancelRequested: 0,
		expiredLeases: 0,
		byStatus: {
			queued: 0,
			running: 0,
			ok: 0,
			error: 0,
			skipped: 0,
			blocked: 0,
			canceled: 0,
			recovered: 0
		},
		workers: [],
		activeRuns: [],
		recentRuns: []
	};
	runtime.log([
		"Queue",
		`${queue.queued} queued`,
		`${queue.running} running`,
		`${queue.expiredLeases} expired lease${queue.expiredLeases === 1 ? "" : "s"}`,
		`${queue.cancelRequested} cancel requested`,
		`${queue.terminal} finished`
	].join(" · "));
	if (queue.workers.length === 0) runtime.log("Workers: no active leases");
	else {
		runtime.log("Workers:");
		for (const worker of queue.workers) runtime.log(`- ${worker.workerId} · ${worker.running} active · ${worker.expired} expired · next lease ${formatMaybeRelative(worker.nextLeaseExpiresAtMs, now)}`);
	}
	if (queue.activeRuns.length > 0) {
		runtime.log("Active runs:");
		for (const run of queue.activeRuns.slice(0, 8)) {
			const lease = run.leaseOwner ? ` · leased by ${run.leaseOwner}${run.leaseExpired ? " (expired)" : ""}` : "";
			const control = run.leaseExpired ? ` · control: fased task clear-stale ${run.runId}` : ` · control: fased task cancel-run ${run.runId}`;
			runtime.log(`- ${run.jobName} · ${run.runId} · ${run.stepId} attempt ${run.attempt}/${run.maxAttempts}${lease}${control}`);
		}
	}
	if (status.storePath) runtime.log(`Store: ${status.storePath}`);
	if (queue.path) runtime.log(`Queue file: ${queue.path}`);
}

//#endregion
//#region src/cli/cron-cli/register.cron-add.ts
function registerCronStatusCommand(cron) {
	addGatewayClientOptions(cron.command("status").description("Show task scheduler status").option("--json", "Output JSON", false).action(async (opts) => {
		try {
			const res = await callGatewayFromCli("cron.status", opts, {});
			if (opts.json) {
				defaultRuntime.log(JSON.stringify(res, null, 2));
				return;
			}
			printCronStatus(res, defaultRuntime);
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
}
function registerCronListCommand(cron) {
	addGatewayClientOptions(cron.command("list").description("List scheduled tasks").option("--all", "Include disabled tasks", false).option("--json", "Output JSON", false).action(async (opts) => {
		try {
			const res = await callGatewayFromCli("cron.list", opts, { includeDisabled: Boolean(opts.all) });
			if (opts.json) {
				defaultRuntime.log(JSON.stringify(res, null, 2));
				return;
			}
			printCronList(res?.jobs ?? [], defaultRuntime);
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
}
function registerCronAddCommand(cron) {
	addGatewayClientOptions(cron.command("add").alias("create").description("Add a scheduled task").requiredOption("--name <name>", "Task name").option("--description <text>", "Optional description").option("--disabled", "Create task disabled", false).option("--delete-after-run", "Delete one-shot task after it succeeds", false).option("--keep-after-run", "Keep one-shot task after it succeeds", false).option("--agent <id>", "Agent id for this task").option("--session <target>", "Session target (main|isolated)").option("--session-key <key>", "Session key for task routing (e.g. agent:my-agent:my-session)").option("--wake <mode>", "Wake mode (now|next-heartbeat)", "now").option("--at <when>", "Run once at time (ISO) or +duration (e.g. 20m)").option("--every <duration>", "Run every duration (e.g. 10m, 1h)").option("--cron <expr>", "Cron expression (5-field or 6-field with seconds)").option("--tz <iana>", "Timezone for cron expressions (IANA)", "").option("--stagger <duration>", "Cron stagger window (e.g. 30s, 5m)").option("--exact", "Disable cron staggering (set stagger to 0)", false).option("--system-event <text>", "System event payload (main session)").option("--message <text>", "Agent message payload").option("--thinking <level>", "Thinking level for agent tasks (off|minimal|low|medium|high)").option("--model <model>", "Model override for agent tasks (provider/model or alias)").option("--timeout-seconds <n>", "Timeout seconds for agent tasks").option("--announce", "Announce summary to a chat (subagent-style)", false).option("--deliver", "Deprecated (use --announce). Announces a summary to a chat.").option("--no-deliver", "Disable announce delivery and skip main-session summary").option("--channel <channel>", `Delivery channel (${getCronChannelOptions()})`, "last").option("--to <dest>", "Delivery destination (E.164, Telegram chatId, or Discord channel/user)").option("--best-effort-deliver", "Do not fail the task if delivery fails", false).option("--json", "Output JSON", false).action(async (opts, cmd) => {
		try {
			const staggerRaw = typeof opts.stagger === "string" ? opts.stagger.trim() : "";
			const useExact = Boolean(opts.exact);
			if (staggerRaw && useExact) throw new Error("Choose either --stagger or --exact, not both");
			const schedule = (() => {
				const at = typeof opts.at === "string" ? opts.at : "";
				const every = typeof opts.every === "string" ? opts.every : "";
				const cronExpr = typeof opts.cron === "string" ? opts.cron : "";
				if ([
					Boolean(at),
					Boolean(every),
					Boolean(cronExpr)
				].filter(Boolean).length !== 1) throw new Error("Choose exactly one schedule: --at, --every, or --cron");
				if ((useExact || staggerRaw) && !cronExpr) throw new Error("--stagger/--exact are only valid with --cron");
				if (at) {
					const atIso = parseAt(at);
					if (!atIso) throw new Error("Invalid --at; use ISO time or duration like 20m");
					return {
						kind: "at",
						at: atIso
					};
				}
				if (every) {
					const everyMs = parseDurationMs(every);
					if (!everyMs) throw new Error("Invalid --every; use e.g. 10m, 1h, 1d");
					return {
						kind: "every",
						everyMs
					};
				}
				const staggerMs = (() => {
					if (useExact) return 0;
					if (!staggerRaw) return;
					const parsed = parseDurationMs(staggerRaw);
					if (!parsed) throw new Error("Invalid --stagger; use e.g. 30s, 1m, 5m");
					return parsed;
				})();
				return {
					kind: "cron",
					expr: cronExpr,
					tz: typeof opts.tz === "string" && opts.tz.trim() ? opts.tz.trim() : void 0,
					staggerMs
				};
			})();
			const wakeMode = (typeof opts.wake === "string" ? opts.wake : "now").trim() || "now";
			if (wakeMode !== "now" && wakeMode !== "next-heartbeat") throw new Error("--wake must be now or next-heartbeat");
			const agentId = typeof opts.agent === "string" && opts.agent.trim() ? sanitizeAgentId(opts.agent.trim()) : void 0;
			const hasAnnounce = Boolean(opts.announce) || opts.deliver === true;
			const hasNoDeliver = opts.deliver === false;
			if ([hasAnnounce, hasNoDeliver].filter(Boolean).length > 1) throw new Error("Choose at most one of --announce or --no-deliver");
			const payload = (() => {
				const systemEvent = typeof opts.systemEvent === "string" ? opts.systemEvent.trim() : "";
				const message = typeof opts.message === "string" ? opts.message.trim() : "";
				if ([Boolean(systemEvent), Boolean(message)].filter(Boolean).length !== 1) throw new Error("Choose exactly one payload: --system-event or --message");
				if (systemEvent) return {
					kind: "systemEvent",
					text: systemEvent
				};
				const timeoutSeconds = parsePositiveIntOrUndefined(opts.timeoutSeconds);
				return {
					kind: "agentTurn",
					message,
					model: typeof opts.model === "string" && opts.model.trim() ? opts.model.trim() : void 0,
					thinking: typeof opts.thinking === "string" && opts.thinking.trim() ? opts.thinking.trim() : void 0,
					timeoutSeconds: timeoutSeconds && Number.isFinite(timeoutSeconds) ? timeoutSeconds : void 0
				};
			})();
			const sessionSource = (typeof cmd?.getOptionValueSource === "function" ? (name) => cmd.getOptionValueSource(name) : () => void 0)("session");
			const sessionTargetRaw = typeof opts.session === "string" ? opts.session.trim() : "";
			const inferredSessionTarget = payload.kind === "agentTurn" ? "isolated" : "main";
			const sessionTarget = sessionSource === "cli" ? sessionTargetRaw || "" : inferredSessionTarget;
			if (sessionTarget !== "main" && sessionTarget !== "isolated") throw new Error("--session must be main or isolated");
			if (opts.deleteAfterRun && opts.keepAfterRun) throw new Error("Choose --delete-after-run or --keep-after-run, not both");
			if (sessionTarget === "main" && payload.kind !== "systemEvent") throw new Error("Main-session tasks require --system-event (systemEvent).");
			if (sessionTarget === "isolated" && payload.kind !== "agentTurn") throw new Error("Isolated tasks require --message (agentTurn).");
			if ((opts.announce || typeof opts.deliver === "boolean") && (sessionTarget !== "isolated" || payload.kind !== "agentTurn")) throw new Error("--announce/--no-deliver require --session isolated.");
			const deliveryMode = sessionTarget === "isolated" && payload.kind === "agentTurn" ? hasAnnounce ? "announce" : hasNoDeliver ? "none" : "announce" : void 0;
			const name = (typeof opts.name === "string" ? opts.name : "").trim();
			if (!name) throw new Error("--name is required");
			const description = typeof opts.description === "string" && opts.description.trim() ? opts.description.trim() : void 0;
			const sessionKey = typeof opts.sessionKey === "string" && opts.sessionKey.trim() ? opts.sessionKey.trim() : void 0;
			const res = await callGatewayFromCli("cron.add", opts, {
				name,
				description,
				enabled: !opts.disabled,
				deleteAfterRun: opts.deleteAfterRun ? true : opts.keepAfterRun ? false : void 0,
				agentId,
				sessionKey,
				schedule,
				sessionTarget,
				wakeMode,
				payload,
				delivery: deliveryMode ? {
					mode: deliveryMode,
					channel: typeof opts.channel === "string" && opts.channel.trim() ? opts.channel.trim() : void 0,
					to: typeof opts.to === "string" && opts.to.trim() ? opts.to.trim() : void 0,
					bestEffort: opts.bestEffortDeliver ? true : void 0
				} : void 0
			});
			defaultRuntime.log(JSON.stringify(res, null, 2));
			await warnIfCronSchedulerDisabled(opts);
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
}

//#endregion
//#region src/cli/cron-cli/register.cron-edit.ts
const assignIf = (target, key, value, shouldAssign) => {
	if (shouldAssign) target[key] = value;
};
function registerCronEditCommand(cron) {
	addGatewayClientOptions(cron.command("edit").description("Edit a scheduled task").argument("<id>", "Task id").option("--name <name>", "Set name").option("--description <text>", "Set description").option("--enable", "Enable task", false).option("--disable", "Disable task", false).option("--delete-after-run", "Delete one-shot task after it succeeds", false).option("--keep-after-run", "Keep one-shot task after it succeeds", false).option("--session <target>", "Session target (main|isolated)").option("--agent <id>", "Set agent id").option("--clear-agent", "Unset agent and use default", false).option("--session-key <key>", "Set session key for task routing").option("--clear-session-key", "Unset session key", false).option("--wake <mode>", "Wake mode (now|next-heartbeat)").option("--at <when>", "Set one-shot time (ISO) or duration like 20m").option("--every <duration>", "Set interval duration like 10m").option("--cron <expr>", "Set cron expression").option("--tz <iana>", "Timezone for cron expressions (IANA)").option("--stagger <duration>", "Cron stagger window (e.g. 30s, 5m)").option("--exact", "Disable cron staggering (set stagger to 0)").option("--system-event <text>", "Set systemEvent payload").option("--message <text>", "Set agentTurn payload message").option("--thinking <level>", "Thinking level for agent tasks").option("--model <model>", "Model override for agent tasks").option("--timeout-seconds <n>", "Timeout seconds for agent tasks").option("--announce", "Announce summary to a chat (subagent-style)").option("--deliver", "Deprecated (use --announce). Announces a summary to a chat.").option("--no-deliver", "Disable announce delivery").option("--channel <channel>", `Delivery channel (${getCronChannelOptions()})`).option("--to <dest>", "Delivery destination (E.164, Telegram chatId, or Discord channel/user)").option("--best-effort-deliver", "Do not fail task if delivery fails").option("--no-best-effort-deliver", "Fail task when delivery fails").action(async (id, opts) => {
		try {
			if (opts.session === "main" && opts.message) throw new Error("Main-session tasks cannot use --message; use --system-event or --session isolated.");
			if (opts.session === "isolated" && opts.systemEvent) throw new Error("Isolated tasks cannot use --system-event; use --message or --session main.");
			if (opts.announce && typeof opts.deliver === "boolean") throw new Error("Choose --announce or --no-deliver (not multiple).");
			const staggerRaw = typeof opts.stagger === "string" ? opts.stagger.trim() : "";
			const useExact = Boolean(opts.exact);
			if (staggerRaw && useExact) throw new Error("Choose either --stagger or --exact, not both");
			const requestedStaggerMs = (() => {
				if (useExact) return 0;
				if (!staggerRaw) return;
				const parsed = parseDurationMs(staggerRaw);
				if (!parsed) throw new Error("Invalid --stagger; use e.g. 30s, 1m, 5m");
				return parsed;
			})();
			const patch = {};
			if (typeof opts.name === "string") patch.name = opts.name;
			if (typeof opts.description === "string") patch.description = opts.description;
			if (opts.enable && opts.disable) throw new Error("Choose --enable or --disable, not both");
			if (opts.enable) patch.enabled = true;
			if (opts.disable) patch.enabled = false;
			if (opts.deleteAfterRun && opts.keepAfterRun) throw new Error("Choose --delete-after-run or --keep-after-run, not both");
			if (opts.deleteAfterRun) patch.deleteAfterRun = true;
			if (opts.keepAfterRun) patch.deleteAfterRun = false;
			if (typeof opts.session === "string") patch.sessionTarget = opts.session;
			if (typeof opts.wake === "string") patch.wakeMode = opts.wake;
			if (opts.agent && opts.clearAgent) throw new Error("Use --agent or --clear-agent, not both");
			if (typeof opts.agent === "string" && opts.agent.trim()) patch.agentId = sanitizeAgentId(opts.agent.trim());
			if (opts.clearAgent) patch.agentId = null;
			if (opts.sessionKey && opts.clearSessionKey) throw new Error("Use --session-key or --clear-session-key, not both");
			if (typeof opts.sessionKey === "string" && opts.sessionKey.trim()) patch.sessionKey = opts.sessionKey.trim();
			if (opts.clearSessionKey) patch.sessionKey = null;
			if ([
				opts.at,
				opts.every,
				opts.cron
			].filter(Boolean).length > 1) throw new Error("Choose at most one schedule change");
			if ((requestedStaggerMs !== void 0 || typeof opts.tz === "string") && (opts.at || opts.every)) throw new Error("--stagger/--exact/--tz are only valid for cron schedules");
			if (opts.at) {
				const atIso = parseAt(String(opts.at));
				if (!atIso) throw new Error("Invalid --at");
				patch.schedule = {
					kind: "at",
					at: atIso
				};
			} else if (opts.every) {
				const everyMs = parseDurationMs(String(opts.every));
				if (!everyMs) throw new Error("Invalid --every");
				patch.schedule = {
					kind: "every",
					everyMs
				};
			} else if (opts.cron) patch.schedule = {
				kind: "cron",
				expr: String(opts.cron),
				tz: typeof opts.tz === "string" && opts.tz.trim() ? opts.tz.trim() : void 0,
				staggerMs: requestedStaggerMs
			};
			else if (requestedStaggerMs !== void 0 || typeof opts.tz === "string") {
				const existing = ((await callGatewayFromCli("cron.list", opts, { includeDisabled: true }))?.jobs ?? []).find((job) => job.id === id);
				if (!existing) throw new Error(`unknown task id: ${id}`);
				if (existing.schedule.kind !== "cron") throw new Error("Current task is not a cron schedule; use --cron to convert first");
				const tz = typeof opts.tz === "string" ? opts.tz.trim() || void 0 : existing.schedule.tz;
				patch.schedule = {
					kind: "cron",
					expr: existing.schedule.expr,
					tz,
					staggerMs: requestedStaggerMs !== void 0 ? requestedStaggerMs : existing.schedule.staggerMs
				};
			}
			const hasSystemEventPatch = typeof opts.systemEvent === "string";
			const model = typeof opts.model === "string" && opts.model.trim() ? opts.model.trim() : void 0;
			const thinking = typeof opts.thinking === "string" && opts.thinking.trim() ? opts.thinking.trim() : void 0;
			const timeoutSeconds = opts.timeoutSeconds ? Number.parseInt(String(opts.timeoutSeconds), 10) : void 0;
			const hasTimeoutSeconds = Boolean(timeoutSeconds && Number.isFinite(timeoutSeconds));
			const hasDeliveryModeFlag = opts.announce || typeof opts.deliver === "boolean";
			const hasDeliveryTarget = typeof opts.channel === "string" || typeof opts.to === "string";
			const hasBestEffort = typeof opts.bestEffortDeliver === "boolean";
			const hasAgentTurnPatch = typeof opts.message === "string" || Boolean(model) || Boolean(thinking) || hasTimeoutSeconds || hasDeliveryModeFlag || hasDeliveryTarget || hasBestEffort;
			if (hasSystemEventPatch && hasAgentTurnPatch) throw new Error("Choose at most one payload change");
			if (hasSystemEventPatch) patch.payload = {
				kind: "systemEvent",
				text: String(opts.systemEvent)
			};
			else if (hasAgentTurnPatch) {
				const payload = { kind: "agentTurn" };
				assignIf(payload, "message", String(opts.message), typeof opts.message === "string");
				assignIf(payload, "model", model, Boolean(model));
				assignIf(payload, "thinking", thinking, Boolean(thinking));
				assignIf(payload, "timeoutSeconds", timeoutSeconds, hasTimeoutSeconds);
				patch.payload = payload;
			}
			if (hasDeliveryModeFlag || hasDeliveryTarget || hasBestEffort) {
				const delivery = { mode: opts.announce || opts.deliver === true ? "announce" : opts.deliver === false ? "none" : "announce" };
				if (typeof opts.channel === "string") {
					const channel = opts.channel.trim();
					delivery.channel = channel ? channel : void 0;
				}
				if (typeof opts.to === "string") {
					const to = opts.to.trim();
					delivery.to = to ? to : void 0;
				}
				if (typeof opts.bestEffortDeliver === "boolean") delivery.bestEffort = opts.bestEffortDeliver;
				patch.delivery = delivery;
			}
			const res = await callGatewayFromCli("cron.update", opts, {
				id,
				patch
			});
			defaultRuntime.log(JSON.stringify(res, null, 2));
			await warnIfCronSchedulerDisabled(opts);
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
}

//#endregion
//#region src/cli/cron-cli/register.cron-simple.ts
const QUEUE_CONTROL_METHODS = {
	cancel: "cron.queue.cancel",
	retry: "cron.queue.retry",
	"clear-stale": "cron.queue.clearStale"
};
function parseRepairAction(raw) {
	switch (raw.trim().toLowerCase()) {
		case "configure":
		case "config":
		case "setup": return "configure_source";
		case "add-source":
		case "add-trusted-source":
		case "source":
		case "trusted-source": return "add_trusted_source";
		case "retry":
		case "replace":
		case "retry-replacement": return "retry_replacement";
		case "stop-source":
		case "stop-path":
		case "stop": return "stop_source_path";
		default: return null;
	}
}
function repairResultLines(id, result) {
	const lines = [result.ok ? result.message || `Task ${id} repaired.` : `Could not repair task ${id}: ${result.reason}`];
	if (result.setupCommand) lines.push(result.setupCommand);
	if (result.setupPath) lines.push(`Open ${result.setupPath}`);
	if (result.ok && result.action !== "configure_source") lines.push(`Use fased task run ${id} or fased task runs --id ${id} to inspect it.`);
	return lines;
}
function sourceStatus(source) {
	if (source.active === false) return "disabled";
	if (source.lastOutcome && source.lastOutcome !== "ok") return source.lastQualityBand ? `${source.lastOutcome}/${source.lastQualityBand}` : source.lastOutcome;
	return source.lastQualityBand ?? "active";
}
function sourceScore(source) {
	return `${typeof source.lastQualityScore === "number" && Number.isFinite(source.lastQualityScore) ? source.lastQualityScore.toFixed(2) : "n/a"} · ok ${source.successCount ?? 0} · fail ${source.failureCount ?? 0}`;
}
function flowLine(flow) {
	return [
		flow.flowId,
		flow.status,
		flow.goal,
		flow.currentStep ? `step ${flow.currentStep}` : "",
		flow.agentId ? `agent ${flow.agentId}` : ""
	].filter(Boolean).join(" · ");
}
function formatFlowDetail(flow, tasks) {
	const lines = [
		"Workflow run:",
		`flowId: ${flow.flowId}`,
		`status: ${flow.status}`,
		`goal: ${flow.goal}`,
		`agent: ${flow.agentId ?? "n/a"}`,
		`notify: ${flow.notifyPolicy}`,
		`currentStep: ${flow.currentStep ?? "n/a"}`,
		`definition: ${flow.definitionId ?? "n/a"}`,
		`createdAt: ${new Date(flow.createdAt).toISOString()}`,
		`updatedAt: ${new Date(flow.updatedAt).toISOString()}`,
		`endedAt: ${flow.endedAt ? new Date(flow.endedAt).toISOString() : "n/a"}`,
		`tasks: ${tasks.length}`
	];
	for (const task of tasks) {
		if (!task || typeof task !== "object" || Array.isArray(task)) continue;
		const record = task;
		lines.push(`- ${formatUnknownField(record.taskId, "unknown")} ${formatUnknownField(record.status, "unknown")} ${formatUnknownField(record.task, "")}`);
	}
	return lines.join("\n");
}
function formatUnknownField(value, fallback) {
	if (value === null || value === void 0) return fallback;
	if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return String(value);
	return JSON.stringify(value);
}
function readWorkflowJsonFile(filePath) {
	const raw = fs.readFileSync(filePath, "utf8");
	const parsed = JSON.parse(raw);
	if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("Workflow file must contain a JSON object.");
	return parsed;
}
function workflowGraphParamsFromFile(opts) {
	return {
		...readWorkflowJsonFile(opts.file),
		...opts.agent ? { agentId: opts.agent } : {},
		...opts.sessionKey ? { sessionKey: opts.sessionKey } : {},
		...opts.name ? { name: opts.name } : {},
		...opts.task ? { task: opts.task } : {},
		...opts.notify ? { notifyPolicy: opts.notify } : {}
	};
}
function formatSourceLine(source) {
	return `• ${source.id} · ${sourceStatus(source)} · ${source.kind} · ${source.taskType ?? "general"} · ${sourceScore(source)} · ${source.source}`;
}
function formatSourceDetail(source) {
	const lines = [
		`Trusted source: ${source.id}`,
		`Status: ${sourceStatus(source)}`,
		`Kind: ${source.kind}`,
		`Source: ${source.source}`,
		`Task type: ${source.taskType ?? "general"}`,
		`Agent: ${source.agentId ?? "any"}`,
		`Session: ${source.sessionKey ?? "any"}`,
		`Uses: ${source.useCount ?? 0}`,
		`Successes: ${source.successCount ?? 0}`,
		`Failures: ${source.failureCount ?? 0}`
	];
	if (source.lastQualityBand || typeof source.lastQualityScore === "number") lines.push(`Last quality: ${source.lastQualityBand ?? "unknown"}${typeof source.lastQualityScore === "number" ? ` · ${source.lastQualityScore.toFixed(2)}` : ""}`);
	if (source.lastOutcome) lines.push(`Last outcome: ${source.lastOutcome}`);
	if (source.lastError) lines.push(`Last error: ${source.lastError}`);
	if (source.createdAtMs) lines.push(`Created: ${new Date(source.createdAtMs).toISOString()}`);
	if (source.lastRunAtMs) lines.push(`Last run: ${new Date(source.lastRunAtMs).toISOString()}`);
	return lines.join("\n");
}
function parseAgentList(raw) {
	return Array.from(new Set((raw ?? "").split(",").map((entry) => entry.trim()).filter(Boolean)));
}
function taskPromptText(job) {
	return job.payload.kind === "agentTurn" ? job.payload.message : job.payload.text;
}
function latestRunEntry(res) {
	const [entry] = runEntries(res);
	return entry && typeof entry === "object" ? entry : void 0;
}
function runEntries(res) {
	return (res && typeof res === "object" && Array.isArray(res.entries) ? res.entries : []).filter((entry) => Boolean(entry && typeof entry === "object"));
}
function formatRunAge(ms, nowMs = Date.now()) {
	if (!ms || !Number.isFinite(ms)) return "n/a";
	const seconds = Math.max(0, Math.round((nowMs - ms) / 1e3));
	if (seconds < 60) return `${seconds}s ago`;
	const minutes = Math.round(seconds / 60);
	if (minutes < 60) return `${minutes}m ago`;
	const hours = Math.round(minutes / 60);
	if (hours < 48) return `${hours}h ago`;
	return `${Math.round(hours / 24)}d ago`;
}
function formatDuration(ms) {
	if (typeof ms !== "number" || !Number.isFinite(ms)) return;
	if (ms < 1e3) return `${Math.round(ms)}ms`;
	if (ms < 6e4) return `${Math.round(ms / 100) / 10}s`;
	return `${Math.round(ms / 1e3 / 60)}m`;
}
function describeRunSource(entry) {
	const source = entry.policy?.resultSource;
	const adapter = entry.policy?.resultAdapter;
	if (source === "direct-tool") return `direct tool${adapter ? ` ${adapter}` : ""}`;
	if (source === "direct-text") return "direct text";
	if (entry.policy?.modelUsed === false) return entry.policy.effectiveExecutionMode ?? "no model";
	if (entry.model) return `model ${entry.model}`;
	return entry.policy?.effectiveExecutionMode ?? "unknown";
}
function describeRunDelivery(status) {
	return status ?? "unknown";
}
function formatRunUsage(entry) {
	const usage = entry.usage;
	if (!usage) return;
	const total = typeof usage.total_tokens === "number" ? usage.total_tokens : void 0;
	const input = typeof usage.input_tokens === "number" ? usage.input_tokens : void 0;
	const output = typeof usage.output_tokens === "number" ? usage.output_tokens : void 0;
	const parts = [
		total !== void 0 ? `tokens ${total} total` : void 0,
		input !== void 0 ? `${input} in` : void 0,
		output !== void 0 ? `${output} out` : void 0
	].filter(Boolean);
	return parts.length > 0 ? parts.join(" · ") : void 0;
}
function formatFallbackLastRun(id, entry, previousEntries = []) {
	const lines = [
		`Latest run: ${id}`,
		`Task: ${id}`,
		`Status: ${entry.status ?? "unknown"}`,
		`When: ${formatRunAge(entry.ts)} (${new Date(entry.ts).toISOString()})`,
		`Source: ${describeRunSource(entry)}`,
		`Delivery: ${describeRunDelivery(entry.deliveryStatus)}`
	];
	const duration = formatDuration(entry.durationMs);
	if (duration) lines.push(`Duration: ${duration}`);
	const usage = formatRunUsage(entry);
	if (usage) lines.push(`Usage: ${usage}`);
	if (entry.policy?.planner) lines.push(`Planner: ${entry.policy.planner.strategy} · ${entry.policy.planner.rationale}`);
	const loadedSkills = formatCronRunLoadedSkills(entry.policy);
	if (loadedSkills) lines.push(loadedSkills);
	if (entry.policy?.adaptive) lines.push(`Adaptive next: ${entry.policy.adaptive.route} · ${entry.policy.adaptive.reason} · ${entry.policy.adaptive.sampleSize} sample${entry.policy.adaptive.sampleSize === 1 ? "" : "s"}`);
	if (entry.policy?.evaluator) lines.push(`Evaluator: ${entry.policy.evaluator.action} · ${entry.policy.evaluator.reason}`);
	const escalationContext = formatCronEscalationContext({
		entry,
		previousEntries
	});
	if (escalationContext) lines.push(escalationContext);
	lines.push(...formatCronEscalationPasses({
		entry,
		previousEntries
	}));
	if (entry.error) lines.push(`Error: ${entry.error}`);
	else if (entry.summary) lines.push(`Summary: ${entry.summary}`);
	if (entry.sessionKey) {
		lines.push(`Session: ${entry.sessionKey}`);
		lines.push(`Transcript: /chat?session=${encodeURIComponent(entry.sessionKey)}`);
	}
	if (entry.policy?.runCheckpoint?.runId) lines.push(`Run: ${entry.policy.runCheckpoint.runId}`);
	return lines.join("\n");
}
async function loadCronJobForCli(id, opts) {
	const job = (await callGatewayFromCli("cron.list", opts, { includeDisabled: true })).jobs?.find((candidate) => candidate.id === id);
	if (!job) throw new Error(`Task not found: ${id}`);
	return job;
}
function sourceListParams(opts) {
	return {
		includeInactive: opts.all === true,
		...typeof opts.agent === "string" && opts.agent.trim() ? { agentId: opts.agent.trim() } : {},
		...typeof opts.session === "string" && opts.session.trim() ? { sessionKey: opts.session.trim() } : {},
		...typeof opts.taskType === "string" && opts.taskType.trim() ? { taskType: opts.taskType.trim() } : {},
		...typeof opts.query === "string" && opts.query.trim() ? { query: opts.query.trim() } : {}
	};
}
function registerCronToggleCommand(params) {
	addGatewayClientOptions(params.cron.command(params.name).description(params.description).argument("<id>", "Task id").action(async (id, opts) => {
		try {
			const res = await callGatewayFromCli("cron.update", opts, {
				id,
				patch: { enabled: params.enabled }
			});
			defaultRuntime.log(JSON.stringify(res, null, 2));
			await warnIfCronSchedulerDisabled(opts);
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
}
function registerQueueControlCommand(params) {
	addGatewayClientOptions(params.cron.command(params.name).description(params.description).argument("<runId>", "Task queue run id").option("--reason <text>", "Optional operator reason").option("--json", "Output JSON", false).action(async (runId, opts) => {
		try {
			const reason = typeof opts.reason === "string" && opts.reason.trim() ? opts.reason.trim() : void 0;
			const res = await callGatewayFromCli(QUEUE_CONTROL_METHODS[params.action], opts, {
				runId,
				reason
			});
			if (opts.json) {
				defaultRuntime.log(JSON.stringify(res, null, 2));
				return;
			}
			const message = typeof res?.message === "string" ? String(res.message) : `${params.successVerb} ${runId}.`;
			defaultRuntime.log(`${message} Run: ${runId}`);
			if (params.action === "retry" || params.action === "clear-stale") defaultRuntime.log("Use `fased task runs --id <task-id>` or Agent > Tasks to inspect the result.");
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
}
function registerCronSimpleCommands(cron) {
	addGatewayClientOptions(cron.command("rm").alias("remove").alias("delete").description("Remove a scheduled task").argument("<id>", "Task id").option("--json", "Output JSON", false).action(async (id, opts) => {
		try {
			const res = await callGatewayFromCli("cron.remove", opts, { id });
			defaultRuntime.log(JSON.stringify(res, null, 2));
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
	registerCronToggleCommand({
		cron,
		name: "enable",
		description: "Enable a scheduled task",
		enabled: true
	});
	registerCronToggleCommand({
		cron,
		name: "disable",
		description: "Disable a scheduled task",
		enabled: false
	});
	addGatewayClientOptions(cron.command("approve").description("Approve a task's local Agent coordination and run it now").argument("<id>", "Task id").option("--no-run", "Only record approval; do not start a run").option("--json", "Output JSON", false).action(async (id, opts) => {
		try {
			const approvedAtMs = Date.now();
			const updated = await callGatewayFromCli("cron.update", opts, {
				id,
				patch: { state: { coordinationApprovedAtMs: approvedAtMs } }
			});
			const shouldRun = opts.run !== false;
			let runResult = null;
			if (shouldRun) runResult = await callGatewayFromCli("cron.run", opts, {
				id,
				mode: "force"
			});
			if (opts.json) {
				defaultRuntime.log(JSON.stringify({
					ok: true,
					id,
					approvedAtMs,
					updated,
					run: runResult
				}, null, 2));
				return;
			}
			defaultRuntime.log(shouldRun ? `Approved coordination for ${id} and started a run.` : `Approved coordination for ${id}.`);
			defaultRuntime.log(`Use fased task runs --id ${id} to find the run, then fased task run-show <run-id> to inspect task-room evidence.`);
			await warnIfCronSchedulerDisabled(opts);
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
	addGatewayClientOptions(cron.command("repair").alias("recover").description("Recover a blocked task source path").argument("<id>", "Task id").argument("<action>", "configure|add-source|retry|stop-source").argument("[value...]", "Trusted source text or source node id").option("--source <text>", "Trusted source URL or note for add-source").option("--source-node-id <id>", "Source graph node id for stop-source").option("--json", "Output JSON", false).action(async (id, actionRaw, valueParts, opts) => {
		try {
			const action = parseRepairAction(String(actionRaw));
			if (!action) throw new Error("Unknown repair action. Use configure, add-source, retry, or stop-source.");
			const joinedValue = Array.isArray(valueParts) ? valueParts.join(" ").trim() : "";
			const source = action === "add_trusted_source" ? typeof opts.source === "string" && opts.source.trim() ? opts.source.trim() : joinedValue : void 0;
			const sourceNodeId = action === "stop_source_path" ? typeof opts.sourceNodeId === "string" && opts.sourceNodeId.trim() ? opts.sourceNodeId.trim() : joinedValue || void 0 : void 0;
			if (action === "add_trusted_source" && !source) throw new Error("add-source requires a trusted source URL or note.");
			const result = await callGatewayFromCli("cron.repair", opts, {
				id,
				action,
				...source ? { source } : {},
				...sourceNodeId ? { sourceNodeId } : {}
			});
			if (opts.json) {
				defaultRuntime.log(JSON.stringify(result, null, 2));
				return;
			}
			defaultRuntime.log(repairResultLines(id, result).join("\n"));
			if (!result.ok) defaultRuntime.exit(1);
			await warnIfCronSchedulerDisabled(opts);
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
	const sources = cron.command("sources").description("Inspect and manage task trusted sources");
	addGatewayClientOptions(sources.command("list").description("List trusted sources learned or added for tasks").option("--all", "Include disabled sources", false).option("--agent <id>", "Filter by Agent id").option("--session <key>", "Filter by session key").option("--task-type <type>", "Filter by task type").option("--query <text>", "Filter by source text, id, label, or status").option("--json", "Output JSON", false).action(async (opts) => {
		try {
			const result = await callGatewayFromCli("cron.sources.list", opts, sourceListParams(opts));
			if (opts.json) {
				defaultRuntime.log(JSON.stringify(result, null, 2));
				return;
			}
			if (result.sources.length === 0) {
				defaultRuntime.log("No trusted task sources.");
				return;
			}
			defaultRuntime.log([
				"Trusted task sources",
				"",
				...result.sources.map(formatSourceLine)
			].join("\n"));
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
	addGatewayClientOptions(sources.command("add").description("Add a trusted source URL or note to a task").argument("<taskId>", "Task id").argument("<source...>", "Trusted source URL or note").option("--json", "Output JSON", false).action(async (taskId, sourceParts, opts) => {
		try {
			const source = Array.isArray(sourceParts) ? sourceParts.join(" ").trim() : "";
			if (!source) throw new Error("Trusted source add requires a source URL or note.");
			const result = await callGatewayFromCli("cron.repair", opts, {
				id: taskId,
				action: "add_trusted_source",
				source
			});
			if (opts.json) {
				defaultRuntime.log(JSON.stringify(result, null, 2));
				return;
			}
			defaultRuntime.log(repairResultLines(taskId, result).join("\n"));
			if (!result.ok) defaultRuntime.exit(1);
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
	addGatewayClientOptions(sources.command("show").description("Show one trusted task source").argument("<id>", "Trusted source id").option("--json", "Output JSON", false).action(async (id, opts) => {
		try {
			const source = (await callGatewayFromCli("cron.sources.list", opts, {
				includeInactive: true,
				query: id
			})).sources.find((entry) => entry.id === id);
			if (!source) throw new Error(`Trusted source not found: ${id}`);
			defaultRuntime.log(opts.json ? JSON.stringify(source, null, 2) : formatSourceDetail(source));
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
	for (const command of [{
		name: "enable",
		active: true,
		verb: "Enabled"
	}, {
		name: "disable",
		active: false,
		verb: "Disabled"
	}]) addGatewayClientOptions(sources.command(command.name).description(`${command.verb} a trusted task source`).argument("<id>", "Trusted source id").option("--json", "Output JSON", false).action(async (id, opts) => {
		try {
			const result = await callGatewayFromCli("cron.sources.update", opts, {
				id,
				active: command.active
			});
			if (opts.json) {
				defaultRuntime.log(JSON.stringify(result, null, 2));
				return;
			}
			if (!result.ok || !result.source) throw new Error(result.reason ?? `Trusted source not found: ${id}`);
			defaultRuntime.log(`${command.verb} trusted source ${result.source.id}.`);
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
	addGatewayClientOptions(sources.command("forget").alias("remove").alias("rm").description("Forget a trusted task source").argument("<id>", "Trusted source id").option("--json", "Output JSON", false).action(async (id, opts) => {
		try {
			const result = await callGatewayFromCli("cron.sources.remove", opts, { id });
			if (opts.json) {
				defaultRuntime.log(JSON.stringify(result, null, 2));
				return;
			}
			if (!result.ok) throw new Error(result.reason ?? `Trusted source not found: ${id}`);
			defaultRuntime.log(`Forgot trusted source ${result.id ?? id}.`);
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
	addGatewayClientOptions(cron.command("runs").description("Show task run log (JSONL-backed)").requiredOption("--id <id>", "Task id").option("--limit <n>", "Max entries (default 50)", "50").action(async (opts) => {
		try {
			const limitRaw = Number.parseInt(String(opts.limit ?? "50"), 10);
			const limit = Number.isFinite(limitRaw) && limitRaw > 0 ? limitRaw : 50;
			const res = await callGatewayFromCli("cron.runs", opts, {
				id: String(opts.id),
				limit
			});
			defaultRuntime.log(JSON.stringify(res, null, 2));
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
	addGatewayClientOptions(cron.command("last").description("Show the latest task run with source, delivery, and transcript details").argument("<id>", "Task id").option("--json", "Output JSON", false).action(async (id, opts) => {
		try {
			const res = await callGatewayFromCli("cron.runs", opts, {
				id: String(id),
				limit: 3
			});
			const entries = runEntries(res);
			const entry = latestRunEntry(res);
			if (!entry) {
				defaultRuntime.log(`No runs recorded for ${id} yet.\nUse fased task run ${id} to run it now.`);
				return;
			}
			if (opts.json) {
				defaultRuntime.log(JSON.stringify({ entry }, null, 2));
				return;
			}
			const runId = entry.policy?.runCheckpoint?.runId?.trim();
			if (runId) try {
				const detail = await callGatewayFromCli("cron.runDetail", opts, { runId });
				defaultRuntime.log(formatCronTaskRunDetail(detail, { previousLogEntries: entries.slice(1) }));
				return;
			} catch {}
			defaultRuntime.log(formatFallbackLastRun(String(id), entry, entries.slice(1)));
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
	addGatewayClientOptions(cron.command("run-show").alias("show-run").alias("run-detail").description("Show one queued task run with checkpoint, delivery, and transcript details").argument("<runId>", "Task queue run id").option("--json", "Output JSON", false).action(async (runId, opts) => {
		try {
			const res = await callGatewayFromCli("cron.runDetail", opts, { runId });
			if (opts.json) {
				defaultRuntime.log(JSON.stringify(res, null, 2));
				return;
			}
			defaultRuntime.log(formatCronTaskRunDetail(res));
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
	const flow = cron.command("flow").description("Inspect ledger-backed workflow runs");
	addGatewayClientOptions(flow.command("list").description("List workflow runs").option("--agent <id>", "Filter by Agent id").option("--status <status>", "Filter by status, active, terminal, or all", "all").option("--limit <n>", "Max workflow runs (default 50)", "50").option("--json", "Output JSON", false).action(async (opts) => {
		try {
			const limitRaw = Number.parseInt(String(opts.limit ?? "50"), 10);
			const limit = Number.isFinite(limitRaw) && limitRaw > 0 ? limitRaw : 50;
			const result = await callGatewayFromCli("tasks.flow.list", opts, {
				...typeof opts.agent === "string" && opts.agent.trim() ? { agentId: opts.agent.trim() } : {},
				status: opts.status,
				limit
			});
			if (opts.json) {
				defaultRuntime.log(JSON.stringify(result, null, 2));
				return;
			}
			if (!result.flows.length) {
				defaultRuntime.log("No workflow runs recorded.");
				return;
			}
			defaultRuntime.log(`Workflow runs: ${result.total}`);
			for (const entry of result.flows) defaultRuntime.log(flowLine(entry));
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
	addGatewayClientOptions(flow.command("show").description("Show one workflow run").argument("<flowId>", "Workflow run id").option("--json", "Output JSON", false).action(async (flowId, opts) => {
		try {
			const result = await callGatewayFromCli("tasks.flow.detail", opts, { flowId: String(flowId) });
			if (opts.json) {
				defaultRuntime.log(JSON.stringify(result, null, 2));
				return;
			}
			if (!result.flow) throw new Error(`Workflow run not found: ${flowId}`);
			defaultRuntime.log(formatFlowDetail(result.flow, result.tasks ?? []));
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
	addGatewayClientOptions(flow.command("cancel").description("Cancel an active workflow run").argument("<flowId>", "Workflow run id").option("--reason <reason>", "Cancellation reason").option("--json", "Output JSON", false).action(async (flowId, opts) => {
		try {
			const result = await callGatewayFromCli("tasks.flow.cancel", opts, {
				flowId: String(flowId),
				...typeof opts.reason === "string" && opts.reason.trim() ? { reason: opts.reason.trim() } : {}
			});
			if (opts.json) {
				defaultRuntime.log(JSON.stringify(result, null, 2));
				return;
			}
			defaultRuntime.log(result.flow ? `Cancelled workflow run ${result.flow.flowId} (${result.flow.status}).` : `Cancelled workflow run ${flowId}.`);
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
	const workflow = cron.command("workflow").description("Preview and run structured workflows");
	addGatewayClientOptions(workflow.command("preview").description("Validate a structured workflow graph JSON file").requiredOption("--file <path>", "Workflow graph JSON file").option("--agent <id>", "Agent id override").option("--session-key <key>", "Session key override").option("--name <name>", "Workflow name override").option("--task <task>", "Workflow task label override").option("--notify <policy>", "Notify policy override").option("--json", "Output JSON", false).action(async (opts) => {
		try {
			const result = await callGatewayFromCli("tasks.workflow.graph.preview", opts, workflowGraphParamsFromFile(opts));
			if (opts.json) {
				defaultRuntime.log(JSON.stringify(result, null, 2));
				return;
			}
			defaultRuntime.log(`Workflow graph ok: ${result.graph.nodes.length} nodes · ${result.graph.edges.length} edges`);
			if (result.warnings.length) defaultRuntime.log(`Warnings:\n${result.warnings.map((line) => `- ${line}`).join("\n")}`);
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
	addGatewayClientOptions(workflow.command("run").description("Run a structured workflow graph JSON file").requiredOption("--file <path>", "Workflow graph JSON file").option("--agent <id>", "Agent id override").option("--session-key <key>", "Session key override").option("--name <name>", "Workflow name override").option("--task <task>", "Workflow task label override").option("--notify <policy>", "Notify policy override").option("--json", "Output JSON", false).action(async (opts) => {
		try {
			const result = await callGatewayFromCli("tasks.workflow.graph.run", opts, workflowGraphParamsFromFile(opts));
			if (opts.json) {
				defaultRuntime.log(JSON.stringify(result, null, 2));
				return;
			}
			defaultRuntime.log(result.task ? `Workflow graph run ${result.task.taskId ?? "recorded"}: ${result.task.status ?? "unknown"}` : "Workflow graph run recorded.");
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
	addGatewayClientOptions(cron.command("run").description("Run a scheduled task now").argument("<id>", "Task id").option("--force", "Run now (default; accepted for compatibility)", false).option("--due", "Run only when due (default behavior in older versions)", false).action(async (id, opts) => {
		try {
			const res = await callGatewayFromCli("cron.run", opts, {
				id,
				mode: opts.due && !opts.force ? "due" : "force"
			});
			defaultRuntime.log(JSON.stringify(res, null, 2));
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
	addGatewayClientOptions(cron.command("ask").description("Ask selected local Agents for task-room evidence, then run the task").argument("<id>", "Task id").requiredOption("--agent <ids>", "Agent id or comma-separated Agent ids to consult").option("--mode <mode>", "consult or parallel", "consult").option("--no-approve", "Queue the Agent consult without approving it").option("--no-run", "Only update the task; do not start a run").option("--json", "Output JSON", false).action(async (id, opts) => {
		try {
			const agents = parseAgentList(opts.agent);
			if (agents.length === 0) throw new Error("Use --agent <id> to choose at least one Agent.");
			const mode = opts.mode === "parallel" ? "parallel" : "consult";
			const job = await loadCronJobForCli(id, opts);
			const nowMs = Date.now();
			const executionPolicy = withTaskCoordinationRequest({
				policy: job.executionPolicy,
				message: taskPromptText(job),
				agents,
				mode,
				requireApproval: opts.approve !== false
			});
			const pendingCoordination = {
				reason: `User requested task-room evidence from ${agents.join(", ")}.`,
				signal: "manual_agent_request",
				agents,
				mode,
				createdAtMs: nowMs,
				sourceRunAtMs: nowMs
			};
			const updated = await callGatewayFromCli("cron.update", opts, {
				id,
				patch: {
					executionPolicy,
					state: {
						pendingCoordination,
						...opts.approve === false ? {} : { coordinationApprovedAtMs: nowMs }
					}
				}
			});
			const shouldRun = opts.run !== false;
			let runResult = null;
			if (shouldRun) runResult = await callGatewayFromCli("cron.run", opts, {
				id,
				mode: "force"
			});
			if (opts.json) {
				defaultRuntime.log(JSON.stringify({
					ok: true,
					id,
					agents,
					mode,
					pendingCoordination,
					updated,
					run: runResult
				}, null, 2));
				return;
			}
			defaultRuntime.log(shouldRun ? `Queued Agent evidence from ${agents.join(", ")} for ${id} and started a run.` : `Queued Agent evidence from ${agents.join(", ")} for ${id}.`);
			defaultRuntime.log(`Use fased task last ${id} or fased task run-show <run-id> to inspect task-room evidence.`);
			await warnIfCronSchedulerDisabled(opts);
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
	registerQueueControlCommand({
		cron,
		name: "cancel-run",
		action: "cancel",
		description: "Cancel an active queued or leased task run",
		successVerb: "Canceled run"
	});
	registerQueueControlCommand({
		cron,
		name: "retry-run",
		action: "retry",
		description: "Retry a failed, blocked, canceled, or recovered task run",
		successVerb: "Queued run retry"
	});
	registerQueueControlCommand({
		cron,
		name: "clear-stale",
		action: "clear-stale",
		description: "Clear an expired task run lease and requeue the run",
		successVerb: "Cleared stale lease for run"
	});
}

//#endregion
//#region src/cli/cron-cli/register.cron-smoke.ts
function smokeSuffix() {
	return crypto.randomBytes(4).toString("hex");
}
function futureAtIso() {
	return new Date(Date.now() + 36e5).toISOString();
}
function parseSmokeJsonInput(raw) {
	const trimmed = raw?.trim();
	if (!trimmed) return;
	const parsed = JSON.parse(trimmed);
	if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("--input must be a JSON object.");
	return parsed;
}
function resolveSmokeAgentId(opts) {
	return typeof opts.agent === "string" && opts.agent.trim() ? sanitizeAgentId(opts.agent.trim()) : void 0;
}
function resolveSmokeSessionKey(opts, suffix) {
	const explicit = typeof opts.sessionKey === "string" ? opts.sessionKey.trim() : "";
	if (explicit) return explicit;
	return `agent:${resolveSmokeAgentId(opts) ?? "main"}:task-smoke:${suffix}`;
}
function resolveSmokeDelivery(opts) {
	const channel = typeof opts.channel === "string" ? opts.channel.trim() : "";
	const to = typeof opts.to === "string" ? opts.to.trim() : "";
	if (!channel && !to) return { mode: "none" };
	if (!channel || !to) throw new Error("Use both --channel and --to for delivery smoke, or neither.");
	return {
		mode: "announce",
		channel,
		to,
		bestEffort: opts.bestEffortDeliver ? true : void 0
	};
}
function baseSmokeJob(params) {
	return {
		name: `Task smoke ${params.label} ${params.suffix}`,
		description: "Temporary Task OS smoke proof task.",
		enabled: true,
		deleteAfterRun: false,
		agentId: resolveSmokeAgentId(params.opts),
		sessionKey: resolveSmokeSessionKey(params.opts, params.suffix),
		schedule: {
			kind: "at",
			at: futureAtIso()
		},
		sessionTarget: "isolated",
		wakeMode: "next-heartbeat",
		payload: {
			kind: "agentTurn",
			message: params.message
		},
		delivery: params.delivery ?? { mode: "none" },
		executionPolicy: params.executionPolicy
	};
}
function buildSmokeJobs(opts) {
	const suffix = smokeSuffix();
	const delivery = resolveSmokeDelivery(opts);
	const jobs = [baseSmokeJob({
		opts,
		suffix,
		label: "no-model",
		message: "Task smoke no-model check.",
		delivery,
		executionPolicy: {
			triggerKind: "manual",
			executionMode: "no-model",
			memoryScope: "none",
			skillScope: "none",
			modelPolicy: { mode: "none" },
			budget: { maxRunsPerHour: 5 }
		}
	})];
	const skill = typeof opts.skill === "string" ? opts.skill.trim() : "";
	if (skill) jobs.push(baseSmokeJob({
		opts,
		suffix,
		label: `skill-${skill}`,
		message: `Task smoke skill-only check for ${skill}.`,
		delivery,
		executionPolicy: {
			triggerKind: "manual",
			executionMode: "skill-only",
			memoryScope: "none",
			skillScope: "selected",
			allowedSkills: [skill],
			skillAction: {
				toolName: skill,
				input: parseSmokeJsonInput(opts.input)
			},
			modelPolicy: { mode: "none" },
			budget: { maxRunsPerHour: 5 }
		}
	}));
	const model = typeof opts.model === "string" ? opts.model.trim() : "";
	if (model) jobs.push(baseSmokeJob({
		opts,
		suffix,
		label: "model",
		message: "Task smoke model check. Reply with a single short sentence.",
		delivery,
		executionPolicy: {
			triggerKind: "manual",
			executionMode: "agent-turn",
			memoryScope: "none",
			skillScope: "none",
			modelPolicy: {
				mode: "task-override",
				model
			},
			budget: {
				maxTokensPerRun: 12e3,
				maxRunsPerHour: 5
			}
		}
	}));
	return jobs;
}
function repairSmokeRunId(suffix, label) {
	return `repair-smoke-${suffix}-${label}`;
}
function repairSmokeJob(params) {
	const message = "Analyze live market risk with approved source repair smoke context.";
	return {
		name: `Task smoke repair ${params.label} ${params.suffix}`,
		description: "Temporary Task repair smoke proof task.",
		enabled: false,
		deleteAfterRun: false,
		agentId: resolveSmokeAgentId(params.opts),
		sessionKey: resolveSmokeSessionKey(params.opts, params.suffix),
		schedule: {
			kind: "at",
			at: futureAtIso()
		},
		sessionTarget: "isolated",
		wakeMode: "next-heartbeat",
		payload: {
			kind: "agentTurn",
			message
		},
		delivery: { mode: "none" },
		executionPolicy: planTaskExecutionPolicy({
			message,
			policy: {
				triggerKind: "manual",
				executionMode: "auto",
				memoryScope: "search",
				skillScope: "agent-default",
				modelPolicy: { mode: "auto" }
			}
		})
	};
}
function repairSmokeState(params) {
	const now = Date.now();
	return {
		lastStatus: "blocked",
		lastRunStatus: "blocked",
		stopReason: "needsSources:needs_user_source",
		lastGraphRepairStop: {
			code: "needs_user_source",
			reason: "Repair smoke needs a trusted source before retrying.",
			sourceNodeId: "source-fetch-web-search",
			atMs: now
		},
		lastRunCheckpoint: {
			runId: repairSmokeRunId(params.suffix, params.label),
			phase: "finished",
			trigger: "manual",
			attempt: 1,
			startedAtMs: now,
			heartbeatAtMs: now,
			completedAtMs: now
		}
	};
}
function taskSmokeSummary(step) {
	const job = step.job;
	const state = job?.state;
	const status = state?.lastRunStatus ?? state?.lastStatus ?? (job?.enabled ? "created" : "done");
	return [
		`${taskSmokeStepFailed(step) ? "failed" : "ok"} ${step.label}`,
		job?.id ? `id ${job.id}` : "",
		status ? `status ${status}` : "",
		state?.needsAccess?.reason ? `needs access ${state.needsAccess.reason}` : "",
		state?.lastDeliveryStatus ? `delivery ${state.lastDeliveryStatus}` : "",
		step.repairs?.length ? `repairs ${step.repairs.map((probe) => `${probe.action} ${probe.ok ? "ok" : "failed"}`).join(", ")}` : "",
		state?.lastError ? `last error ${state.lastError}` : "",
		state?.lastRunSessionKey ? `session ${state.lastRunSessionKey}` : "",
		step.cleaned === true ? "cleaned" : step.cleaned === false ? "kept" : "",
		step.error ? `error ${step.error}` : ""
	].filter(Boolean).join(" · ");
}
function taskSmokeStepFailed(step) {
	if (step.error) return true;
	if (step.repairSmoke) return step.repairs?.some((probe) => probe.error || probe.ok === false) ?? false;
	const status = step.job?.state?.lastRunStatus ?? step.job?.state?.lastStatus;
	return status === "error" || status === "blocked";
}
async function runSmokeStep(opts, input) {
	let job;
	let step;
	try {
		job = await callGatewayFromCli("cron.add", opts, input, { progress: false });
		if (!job?.id) throw new Error("cron.add did not return a task id.");
		const run = await callGatewayFromCli("cron.run", opts, {
			id: job.id,
			mode: "force"
		}, { progress: false });
		const listed = await callGatewayFromCli("cron.list", opts, { includeDisabled: true }, { progress: false });
		job = (Array.isArray(listed) ? listed : listed.jobs ?? []).find((entry) => entry.id === job?.id) ?? job;
		step = {
			label: input.name,
			job,
			run
		};
	} catch (err) {
		step = {
			label: input.name,
			job,
			error: err instanceof Error ? err.message : String(err)
		};
	}
	if (job?.id && !opts.keep) try {
		await callGatewayFromCli("cron.remove", opts, { id: job.id }, { progress: false });
		step.cleaned = true;
	} catch {
		step.cleaned = false;
	}
	else if (job?.id && opts.keep) step.cleaned = false;
	return step;
}
async function runRepairSmokeStep(params) {
	const input = repairSmokeJob({
		opts: params.opts,
		suffix: params.suffix,
		label: params.label
	});
	let job;
	const repairs = [];
	let step;
	try {
		job = await callGatewayFromCli("cron.add", params.opts, input, { progress: false });
		if (!job?.id) throw new Error("cron.add did not return a task id.");
		job = await callGatewayFromCli("cron.update", params.opts, {
			id: job.id,
			patch: { state: repairSmokeState({
				suffix: params.suffix,
				label: params.label
			}) }
		}, { progress: false });
		const detail = await callGatewayFromCli("cron.runDetail", params.opts, { runId: repairSmokeRunId(params.suffix, params.label) }, { progress: false });
		const detailOk = Boolean(detail?.recommendedRepairActions?.length);
		if (!detailOk) throw new Error("cron.runDetail did not return repair recommendations.");
		const result = await callGatewayFromCli("cron.repair", params.opts, {
			id: job.id,
			action: params.action,
			...params.source ? { source: params.source } : {},
			...params.sourceNodeId ? { sourceNodeId: params.sourceNodeId } : {}
		}, { progress: false });
		repairs.push({
			action: params.action,
			ok: result.ok,
			detailOk,
			message: result.ok ? result.message : result.reason,
			setupPath: result.setupPath
		});
		job = result.job ?? job;
		step = {
			label: input.name,
			job,
			detail,
			repairs,
			repairSmoke: true
		};
	} catch (err) {
		step = {
			label: input.name,
			job,
			repairs,
			repairSmoke: true,
			error: err instanceof Error ? err.message : String(err)
		};
	}
	if (job?.id && !params.opts.keep) try {
		await callGatewayFromCli("cron.remove", params.opts, { id: job.id }, { progress: false });
		step.cleaned = true;
	} catch {
		step.cleaned = false;
	}
	else if (job?.id && params.opts.keep) step.cleaned = false;
	return step;
}
async function runRepairSmokeSteps(opts) {
	const suffix = smokeSuffix();
	return [
		await runRepairSmokeStep({
			opts,
			suffix,
			label: "configure",
			action: "configure_source"
		}),
		await runRepairSmokeStep({
			opts,
			suffix,
			label: "add-source",
			action: "add_trusted_source",
			source: "https://example.com/fased-task-repair-smoke"
		}),
		await runRepairSmokeStep({
			opts,
			suffix,
			label: "retry",
			action: "retry_replacement"
		}),
		await runRepairSmokeStep({
			opts,
			suffix,
			label: "stop-source",
			action: "stop_source_path",
			sourceNodeId: "source-fetch-web-search"
		})
	];
}
function registerCronSmokeCommand(cron) {
	addGatewayClientOptions(cron.command("smoke").alias("doctor").description("Run temporary Task OS proof tasks through the Gateway").option("--agent <id>", "Agent id for smoke tasks").option("--session-key <key>", "Session key for smoke tasks").option("--keep", "Keep temporary smoke tasks instead of deleting them", false).option("--json", "Output JSON", false).option("--channel <channel>", "Delivery channel to test, for example telegram").option("--to <target>", "Delivery target to test, for example Telegram chat id").option("--best-effort-deliver", "Do not fail delivery smoke when delivery fails", false).option("--model <provider/model>", "Optional model-backed task smoke").option("--skill <tool>", "Optional deterministic skill-only task smoke").option("--input <json>", "JSON input for --skill", "{}").option("--repair", "Smoke task repair recommendations and recovery actions", false).action(async (opts) => {
		try {
			const jobs = buildSmokeJobs(opts);
			const steps = [];
			for (const job of jobs) steps.push(await runSmokeStep(opts, job));
			if (opts.repair) steps.push(...await runRepairSmokeSteps(opts));
			await warnIfCronSchedulerDisabled(opts);
			if (opts.json) {
				defaultRuntime.log(JSON.stringify({
					ok: steps.every((step) => !taskSmokeStepFailed(step)),
					steps
				}, null, 2));
				return;
			}
			defaultRuntime.log("Task smoke");
			for (const step of steps) defaultRuntime.log(`- ${taskSmokeSummary(step)}`);
			if (steps.some((step) => taskSmokeStepFailed(step))) defaultRuntime.exit(1);
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	}));
}

//#endregion
//#region src/commands/task-worker-install-helpers.ts
function resolveTaskWorkerId(params) {
	const explicit = params.workerId?.trim();
	if (explicit) return explicit;
	return [
		"task-worker",
		normalizeTaskWorkerName(params.profile) ?? void 0,
		normalizeTaskWorkerName(params.name) ?? void 0
	].filter((value) => Boolean(value)).join(":");
}
async function buildTaskWorkerInstallPlan(params) {
	const devMode = params.devMode ?? resolveGatewayDevMode();
	const nodePath = params.nodePath ?? await resolvePreferredNodePath({
		env: params.env,
		runtime: params.runtime
	});
	const workerId = resolveTaskWorkerId({
		name: params.name,
		profile: params.env.FASED_PROFILE,
		workerId: params.workerId
	});
	const { programArguments, workingDirectory } = await resolveTaskWorkerProgramArguments({
		workerId,
		maxRuns: params.maxRuns,
		pollMs: params.pollMs,
		dev: devMode,
		runtime: params.runtime,
		nodePath
	});
	await emitNodeRuntimeWarning({
		env: params.env,
		runtime: params.runtime,
		nodeProgram: programArguments[0],
		warn: params.warn,
		title: "Task worker runtime"
	});
	const environment = buildTaskWorkerServiceEnvironment({
		env: params.env,
		name: params.name
	});
	return {
		programArguments,
		workingDirectory,
		environment,
		description: formatTaskWorkerServiceDescription({
			name: params.name,
			profile: params.env.FASED_PROFILE,
			version: environment.FASED_SERVICE_VERSION
		}),
		workerId
	};
}

//#endregion
//#region src/daemon/task-worker-service.ts
function withTaskWorkerServiceEnv(env, name) {
	return {
		...env,
		FASED_TASK_WORKER_NAME: name,
		FASED_LAUNCHD_LABEL: resolveTaskWorkerLaunchAgentLabel({
			name,
			profile: env.FASED_PROFILE
		}),
		FASED_SYSTEMD_UNIT: resolveTaskWorkerSystemdServiceName({
			name,
			profile: env.FASED_PROFILE
		}),
		FASED_WINDOWS_TASK_NAME: resolveTaskWorkerWindowsTaskName({
			name,
			profile: env.FASED_PROFILE
		}),
		FASED_TASK_SCRIPT_NAME: resolveTaskWorkerWindowsTaskScriptName({
			name,
			profile: env.FASED_PROFILE
		}),
		FASED_LOG_PREFIX: name ? `task-worker-${name}` : "task-worker",
		FASED_SERVICE_MARKER: TASK_WORKER_SERVICE_MARKER,
		FASED_SERVICE_KIND: TASK_WORKER_SERVICE_KIND
	};
}
function withTaskWorkerInstallEnv(args, name) {
	return {
		...args,
		env: withTaskWorkerServiceEnv(args.env, name),
		environment: {
			...args.environment,
			...withTaskWorkerServiceEnv(args.environment ?? {}, name)
		}
	};
}
function resolveTaskWorkerService(name) {
	const base = resolveGatewayService();
	return {
		...base,
		install: async (args) => {
			return base.install(withTaskWorkerInstallEnv(args, name));
		},
		uninstall: async (args) => {
			return base.uninstall({
				...args,
				env: withTaskWorkerServiceEnv(args.env, name)
			});
		},
		stop: async (args) => {
			return base.stop({
				...args,
				env: withTaskWorkerServiceEnv(args.env ?? {}, name)
			});
		},
		restart: async (args) => {
			return base.restart({
				...args,
				env: withTaskWorkerServiceEnv(args.env ?? {}, name)
			});
		},
		isLoaded: async (args) => {
			return base.isLoaded({ env: withTaskWorkerServiceEnv(args.env ?? {}, name) });
		},
		readCommand: (env) => base.readCommand(withTaskWorkerServiceEnv(env, name)),
		readRuntime: (env) => base.readRuntime(withTaskWorkerServiceEnv(env, name))
	};
}

//#endregion
//#region src/cli/cron-cli/task-worker-service.ts
function parsePositiveInt$1(value, fallback) {
	const raw = typeof value === "string" || typeof value === "number" ? String(value) : "";
	const parsed = Number.parseInt(raw, 10);
	return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
}
function describeError(err) {
	if (err instanceof Error) return err.message;
	if (typeof err === "string") return err;
	return "Unknown error";
}
function renderTaskWorkerStartHints(name) {
	const suffix = name ? ` --name ${name}` : "";
	const base = [formatCliCommand(`fased task worker install${suffix}`), formatCliCommand(`fased task worker start${suffix}`)];
	switch (process.platform) {
		case "darwin": return [...base, `launchctl bootstrap gui/$UID ~/Library/LaunchAgents/${resolveTaskWorkerLaunchAgentLabel({
			name,
			profile: process.env.FASED_PROFILE
		})}.plist`];
		case "linux": return [...base, `systemctl --user start ${resolveTaskWorkerSystemdServiceName({
			name,
			profile: process.env.FASED_PROFILE
		})}.service`];
		case "win32": return [...base, `schtasks /Run /TN "${resolveTaskWorkerWindowsTaskName({
			name,
			profile: process.env.FASED_PROFILE
		})}"`];
		default: return base;
	}
}
async function runTaskWorkerServiceInstall(opts) {
	const json = Boolean(opts.json);
	const { stdout, warnings, emit, fail } = createDaemonActionContext({
		action: "install",
		json
	});
	if (resolveIsNixMode(process.env)) {
		fail("Nix mode detected; task worker service install is disabled.");
		return;
	}
	const runtimeRaw = opts.runtime ? String(opts.runtime) : DEFAULT_GATEWAY_DAEMON_RUNTIME;
	if (!isGatewayDaemonRuntime(runtimeRaw)) {
		fail("Invalid --runtime (use \"node\" or \"bun\")");
		return;
	}
	const service = resolveTaskWorkerService(opts.name);
	let loaded = false;
	try {
		loaded = await service.isLoaded({ env: process.env });
	} catch (err) {
		fail(`Task worker service check failed: ${describeError(err)}`);
		return;
	}
	if (loaded && !opts.force) {
		emit({
			ok: true,
			result: "already-installed",
			message: `Task worker service already ${service.loadedText}.`,
			service: buildDaemonServiceSnapshot(service, loaded),
			warnings: warnings.length ? warnings : void 0
		});
		if (!json) {
			defaultRuntime.log(`Task worker service already ${service.loadedText}.`);
			defaultRuntime.log(`Reinstall with: ${formatCliCommand(`fased task worker install${opts.name ? ` --name ${opts.name}` : ""} --force`)}`);
		}
		return;
	}
	const maxRuns = parsePositiveInt$1(opts.maxRuns, 1);
	const pollMs = parsePositiveInt$1(opts.pollMs, 1e3);
	const plan = await buildTaskWorkerInstallPlan({
		env: process.env,
		name: opts.name,
		workerId: opts.workerId,
		maxRuns,
		pollMs,
		runtime: runtimeRaw,
		warn: (message) => {
			if (json) warnings.push(message);
			else defaultRuntime.log(message);
		}
	});
	await installDaemonServiceAndEmit({
		serviceNoun: "Task worker",
		service,
		warnings,
		emit,
		fail,
		install: async () => {
			await service.install({
				env: process.env,
				stdout,
				programArguments: plan.programArguments,
				workingDirectory: plan.workingDirectory,
				environment: plan.environment,
				description: plan.description
			});
		}
	});
	if (!json) defaultRuntime.log(`Task worker id: ${plan.workerId}`);
}
async function runTaskWorkerServiceStatus(opts) {
	const json = Boolean(opts.json);
	const service = resolveTaskWorkerService(opts.name);
	const loaded = await service.isLoaded({ env: process.env }).catch(() => false);
	const runtime = await service.readRuntime(process.env).catch((err) => ({
		status: "unknown",
		detail: describeError(err)
	}));
	const command = await service.readCommand(process.env).catch(() => null);
	const payload = {
		ok: true,
		service: buildDaemonServiceSnapshot(service, loaded),
		runtime,
		command
	};
	if (json) {
		defaultRuntime.log(JSON.stringify(payload, null, 2));
		return;
	}
	const styles = createCliStatusTextStyles();
	defaultRuntime.log(`${styles.label("Service:")} ${service.label} (${loaded ? service.loadedText : service.notLoadedText})`);
	defaultRuntime.log(`${styles.label("Runtime:")} ${formatRuntimeStatus(runtime) ?? "unknown"}`);
	if ("pid" in runtime && typeof runtime.pid === "number") defaultRuntime.log(`${styles.label("PID:")} ${runtime.pid}`);
	if (runtime.detail) defaultRuntime.log(`${styles.label("Detail:")} ${runtime.detail}`);
	if (command?.programArguments?.length) defaultRuntime.log(`${styles.label("Command:")} ${command.programArguments.join(" ")}`);
	if (command?.sourcePath) defaultRuntime.log(`${styles.label("Service file:")} ${command.sourcePath}`);
}
async function runTaskWorkerServiceUninstall(opts) {
	await runServiceUninstall({
		serviceNoun: "Task worker",
		service: resolveTaskWorkerService(opts.name),
		opts,
		stopBeforeUninstall: true,
		assertNotLoadedAfterUninstall: true
	});
}
async function runTaskWorkerServiceStart(opts) {
	await runServiceStart({
		serviceNoun: "Task worker",
		service: resolveTaskWorkerService(opts.name),
		renderStartHints: () => renderTaskWorkerStartHints(opts.name),
		opts
	});
}
async function runTaskWorkerServiceStop(opts) {
	await runServiceStop({
		serviceNoun: "Task worker",
		service: resolveTaskWorkerService(opts.name),
		opts
	});
}
async function runTaskWorkerServiceRestart(opts) {
	await runServiceRestart({
		serviceNoun: "Task worker",
		service: resolveTaskWorkerService(opts.name),
		renderStartHints: () => renderTaskWorkerStartHints(opts.name),
		opts
	});
}

//#endregion
//#region src/cli/cron-cli/register.cron-worker.ts
function parsePositiveInt(value, fallback) {
	const raw = typeof value === "string" || typeof value === "number" ? String(value) : "";
	const parsed = Number.parseInt(raw, 10);
	return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
}
function parseNonNegativeInt(value, fallback) {
	const raw = typeof value === "string" || typeof value === "number" ? String(value) : "";
	const parsed = Number.parseInt(raw, 10);
	return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
}
function formatWorkerResult(result, workerId) {
	const processed = result.processed ?? 0;
	if (processed <= 0) return `Task worker ${workerId}: no queued task runs.`;
	const lines = [`Task worker ${workerId}: processed ${processed} run(s).`];
	for (const outcome of result.outcomes ?? []) {
		const status = outcome.status ?? "unknown";
		const delivery = outcome.delivered === true ? "delivered" : outcome.delivered === false ? "not-delivered" : "";
		const model = outcome.model ? outcome.provider ? `${outcome.provider}/${outcome.model}` : outcome.model : "";
		lines.push([
			`- ${outcome.jobId ?? "unknown"}`,
			status,
			delivery,
			model,
			outcome.sessionKey ? `session ${outcome.sessionKey}` : "",
			outcome.error ? `error ${outcome.error}` : ""
		].filter(Boolean).join(" · "));
	}
	return lines.join("\n");
}
function sleep(ms) {
	return new Promise((resolve) => setTimeout(resolve, ms));
}
function resolveWorkerInstallOptions(opts, command) {
	const parentWorkerId = inheritOptionFromParent(command, "workerId");
	const parentMaxRuns = inheritOptionFromParent(command, "maxRuns");
	const parentPollMs = inheritOptionFromParent(command, "pollMs");
	const parentJson = inheritOptionFromParent(command, "json");
	return {
		name: typeof opts.name === "string" ? opts.name : void 0,
		workerId: typeof opts.workerId === "string" ? opts.workerId : parentWorkerId,
		maxRuns: opts.maxRuns === "1" && parentMaxRuns ? parentMaxRuns : opts.maxRuns,
		pollMs: opts.pollMs === "1000" && parentPollMs ? parentPollMs : opts.pollMs,
		runtime: typeof opts.runtime === "string" ? opts.runtime : void 0,
		force: Boolean(opts.force),
		json: Boolean(opts.json || parentJson)
	};
}
function resolveWorkerLifecycleOptions(opts, command) {
	const parentJson = inheritOptionFromParent(command, "json");
	return {
		...opts,
		json: Boolean(opts.json || parentJson)
	};
}
function registerCronWorkerCommand(cron) {
	const worker = cron.command("worker").description("Run an external task worker that leases queued task runs").option("--once", "Process one queue batch and exit", false).option("--max-runs <n>", "Maximum queued runs to lease per batch", "1").option("--poll-ms <n>", "Poll delay when no work is available", "1000").option("--idle-exit-ms <n>", "Exit after this much idle time; 0 disables", "0").option("--worker-id <id>", "Worker id written into queue leases").option("--json", "Output JSON", false).option("--quiet", "Only print batches that process work", false).action(async (opts) => {
		try {
			const [{ loadConfig }, { createDefaultDeps }, { buildGatewayCronService }] = await Promise.all([
				import("./agent-scope-CLn_Ws3B.js").then((n) => n.wn),
				import("./deps-CBapZnsi.js").then((n) => n.r),
				import("./server-cron-V9GBrg1S.js").then((n) => n.n)
			]);
			const workerId = typeof opts.workerId === "string" && opts.workerId.trim() ? opts.workerId.trim() : `task-worker:${process.pid}`;
			const maxRuns = parsePositiveInt(opts.maxRuns, 1);
			const pollMs = parsePositiveInt(opts.pollMs, 1e3);
			const idleExitMs = parseNonNegativeInt(opts.idleExitMs, 0);
			const state = buildGatewayCronService({
				cfg: loadConfig(),
				deps: createDefaultDeps(),
				broadcast: () => void 0
			});
			const runOnce = async () => await state.cron.work({
				maxRuns,
				leaseOwner: workerId
			});
			if (opts.once) {
				const result = await runOnce();
				defaultRuntime.log(opts.json ? JSON.stringify(result, null, 2) : formatWorkerResult(result, workerId));
				return;
			}
			let stopping = false;
			const stop = () => {
				stopping = true;
			};
			process.once("SIGINT", stop);
			process.once("SIGTERM", stop);
			let idleSinceMs = null;
			while (!stopping) {
				const result = await runOnce();
				if (opts.json) defaultRuntime.log(JSON.stringify(result, null, 2));
				else if (!opts.quiet || (result.processed ?? 0) > 0) defaultRuntime.log(formatWorkerResult(result, workerId));
				if ((result.processed ?? 0) > 0) idleSinceMs = null;
				else {
					idleSinceMs ??= Date.now();
					if (idleExitMs > 0 && Date.now() - idleSinceMs >= idleExitMs) break;
				}
				await sleep(pollMs);
			}
		} catch (err) {
			defaultRuntime.error(danger(String(err)));
			defaultRuntime.exit(1);
		}
	});
	worker.command("install").description("Install a managed task worker service").option("--name <name>", "Named worker service for running multiple workers").option("--worker-id <id>", "Worker id written into queue leases").option("--max-runs <n>", "Maximum queued runs to lease per batch", "1").option("--poll-ms <n>", "Poll delay when no work is available", "1000").option("--runtime <runtime>", "Service runtime (node|bun). Default: node").option("--force", "Reinstall/overwrite if already installed", false).option("--json", "Output JSON", false).action((opts, command) => runTaskWorkerServiceInstall(resolveWorkerInstallOptions(opts, command)));
	worker.command("status").description("Show managed task worker service status").option("--name <name>", "Named worker service").option("--json", "Output JSON", false).action((opts, command) => runTaskWorkerServiceStatus(resolveWorkerLifecycleOptions(opts, command)));
	worker.command("start").description("Start the managed task worker service").option("--name <name>", "Named worker service").option("--json", "Output JSON", false).action((opts, command) => runTaskWorkerServiceStart(resolveWorkerLifecycleOptions(opts, command)));
	worker.command("stop").description("Stop the managed task worker service").option("--name <name>", "Named worker service").option("--json", "Output JSON", false).action((opts, command) => runTaskWorkerServiceStop(resolveWorkerLifecycleOptions(opts, command)));
	worker.command("restart").description("Restart the managed task worker service").option("--name <name>", "Named worker service").option("--json", "Output JSON", false).action((opts, command) => runTaskWorkerServiceRestart(resolveWorkerLifecycleOptions(opts, command)));
	worker.command("uninstall").description("Uninstall the managed task worker service").option("--name <name>", "Named worker service").option("--json", "Output JSON", false).action((opts, command) => runTaskWorkerServiceUninstall(resolveWorkerLifecycleOptions(opts, command)));
}

//#endregion
//#region src/cli/cron-cli/register.ts
function registerCronCli(program, opts = {}) {
	const commandName = opts.commandName ?? "cron";
	const cron = program.command(commandName).description(opts.description ?? (commandName === "cron" ? "Manage scheduled Agent tasks (compatibility alias)" : "Manage scheduled Agent tasks")).addHelpText("after", () => `\n${theme.muted("Docs:")} ${formatDocsLink(opts.docsPath ?? "/cli/task", opts.docsLabel ?? "docs.fased.ai/cli/task")}\n`);
	registerCronStatusCommand(cron);
	registerCronListCommand(cron);
	registerCronAddCommand(cron);
	registerCronSimpleCommands(cron);
	registerCronSmokeCommand(cron);
	registerCronEditCommand(cron);
	registerCronWorkerCommand(cron);
}
function registerTaskCli(program) {
	registerCronCli(program, {
		commandName: "task",
		description: "Manage scheduled Agent tasks",
		docsPath: "/cli/task",
		docsLabel: "docs.fased.ai/cli/task"
	});
}

//#endregion
export { registerCronCli, registerTaskCli };