UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

2,415 lines 100 kB
import { c as isRecord } from "./record-coerce-DItp3I4t.js";
import { t as isPlainObject } from "./plain-object-5a0EzLzX.js";
import { t as isBlockedObjectKey } from "./prototype-keys-CuYw53fZ.js";
import { n as isPathInside } from "./path-safety-Bi0ppMWC.js";
import { T as ConfigIncludeError } from "./redact-BtvPPfTi.js";
import "./utils-P__uGsPB.js";
import { t as sleep } from "./sleep-D7nua6TP.js";
import { n as ok, t as err } from "./result-BQGgYouL.js";
import { t as inheritLegacyDefaultAgentId } from "./legacy.default-agent-owner-BGwEdQRe.js";
import { t as isChannelConfigMetadataKey } from "./config-metadata-aX1D2IMg.js";
import { t as formatErrorMessage } from "./errors-Db3Ymjlb.js";
import { n as replaceFileAtomic, r as replaceFileAtomicSync } from "./replace-file-BAJ-TWzD.js";
import { a as getNodeSqliteKysely, r as executeSqliteQuerySync } from "./kysely-sync-COmh4HWh.js";
import { s as resolveOpenClawStateSqlitePath } from "./openclaw-state-db-schema-version-c1ZL6JGz.js";
import { r as withExistingOpenClawStateDatabaseReadOnly } from "./openclaw-state-db-readonly-BRgmrGHt.js";
import { s as runOpenClawStateWriteTransaction, u as OpenClawStateOwnershipError } from "./openclaw-state-db-BRTnL-D8.js";
import { t as createDedupeCache } from "./dedupe-gst1CUro.js";
import { t as createDeferredCore } from "./deferred-D0La5CRk.js";
import { o as withPluginMetadataSnapshotScope } from "./current-plugin-metadata-snapshot-CmSX4G3W.js";
import { t as getBootstrapChannelPlugin } from "./bootstrap-registry-BtX6YWgO.js";
import { l as loadBundledChannelDoctorContractApi, n as collectDoctorConfigRepairPluginIds, t as applyPluginDoctorCompatibilityMigrations } from "./doctor-contract-registry-DOa9Ye7j.js";
import { t as listDoctorConfiguredChannelIds } from "./configured-channel-ids-BPL8Xd0F.js";
import "./legacy-config-migrations.runtime.models-Ak4QjGte.js";
import { n as LEGACY_CONFIG_MIGRATIONS, t as findLegacyConfigIssues } from "./legacy-D15RYgFr.js";
import { t as migratePersistedImplicitMainRoster } from "./legacy.roster-CQ9vDbV2.js";
import { n as createMergePatch, t as applyMergePatch } from "./merge-patch-DCMj2JVh.js";
import { n as cloneEnvWithPlatformSemantics, s as createConfigRuntimeEnvBase, t as applyConfigEnvVars } from "./config-env-vars-DUfQlcAk.js";
import { n as copyConfigResolutionFacts, p as setConfigResolutionFacts } from "./resolution-facts-Dks1tbik.js";
import { c as getRuntimeConfigSnapshotRefreshHandler, f as loadPinnedRuntimeConfig, g as registerManagedRuntimeConfigWriteOwner, h as preflightRuntimeSnapshotWrite, i as finalizeRuntimeSnapshotWrite, l as getRuntimeConfigSourceSnapshot, m as preflightManagedRuntimeConfigWrite, o as getRuntimeConfigSnapshot, p as notifyRuntimeConfigWriteListeners, r as createRuntimeConfigWriteNotification, u as hasManagedRuntimeConfigWriteOwner, v as registerRuntimeConfigWriteListener } from "./runtime-snapshot-BaQikjTR.js";
import { c as shouldEnableShellEnvFallback, i as loadShellEnvFallback, o as resolveShellEnvFallbackTimeoutMs, s as shouldDeferShellEnvFallback } from "./shell-env-ti8g83F7.js";
import { C as materializeRuntimeConfig, J as loggedConfigWarningFingerprints, N as attachAgentListProjection, P as migrateLegacyContextBudgetConfig, Q as findDuplicateAgentDirs, R as resolveConfigStatMetadata, S as asRuntimeConfig, V as rollbackConfigFileWriteIfUnchanged, X as setBoundedConfigIoWarningEntry, Y as loggedInvalidConfigs, Z as DuplicateAgentDirError, c as resolveManagedUnsetPathsForWrite, d as warnOnConfigMiskeys, f as warnIfJSON5CommentsWillBeStripped, h as validateConfigObjectWithPlugins, i as resolveWriteEnvSnapshotForPath, l as logConfigWarningsOnce, n as configWritePostCommitRollback, q as autoOwnerDisplaySecretByPath, t as ConfigRuntimeRefreshError, u as warnIfConfigFromFuture, x as asResolvedSourceConfig } from "./io.types-BUCjdS5v.js";
import { a as appendConfigAuditRecordSync, h as snapshotConfigAuditProcessInfo, i as appendConfigAuditRecord } from "./io.audit-Dor_5i6r.js";
import { S as GATEWAY_CONFIG_SELECTION_ENV_KEYS, _ as resolveManagedRuntimeEnvBaseline, a as hasConfigMeta, b as snapshotEnv, c as normalizeConfigIoDeps, d as replaceEnvSnapshot, f as resolveConfigForRead, g as resolveGatewayMode, h as resolveConfigSnapshotHash, i as createManagedRuntimeEnvBase, l as parseConfigJson5, m as resolveConfigPathForDeps, o as hashConfigRaw, p as resolveConfigIncludesForRead, r as containsConfigIncludeDirective, s as maybeLoadDotEnvForConfig, t as coerceConfig, y as restoreEnvChangesIfUnchanged } from "./io.read-helpers-ZKp-UiGx.js";
import { t as ConfigMutationConflictError } from "./mutation-conflict-Be0wSyDG.js";
import { n as resolveConfigWidePluginMetadataSnapshot } from "./io.plugin-metadata-BruF5izX.js";
import { r as formatConfigIssueSummary } from "./issue-format-CQvxWNW8.js";
import { i as unsetConfigValueAtPath, n as parseConfigPath, r as setConfigValueAtPath } from "./config-paths-6dxe-LvN.js";
import { t as resolveShellEnvExpectedKeys } from "./shell-env-expected-keys-CIk5gFSi.js";
import { a as throwInvalidConfig } from "./io.invalid-config-xEPg4zuq.js";
import { t as KeyedAsyncQueue } from "./keyed-async-queue-CTreGrmR.js";
import { r as shouldAttemptLastKnownGoodRecovery, t as isPluginLocalInvalidConfigSnapshot } from "./recovery-policy-CsUZ07YX.js";
import { a as includeContributionOwnsBindings, i as includeContributionOwnsAgentRoster } from "./agent-roster-provenance-TGrT9xta.js";
import { n as assertConfigWriteAllowedInCurrentMode } from "./nix-mode-write-guard-uwcnAyQN.js";
import fs from "node:fs";
import { isDeepStrictEqual } from "node:util";
import path from "node:path";
import crypto from "node:crypto";
//#region src/agents/owner-display.ts
const MAX_OWNER_PROMPT_SENDERS = 16;
function exceedsOwnerPromptContentBudget(ownerNumbers) {
	let bytes = 0;
	for (const ownerId of ownerNumbers) {
		bytes += Buffer.byteLength(ownerId, "utf8") + (bytes > 0 ? 2 : 0);
		if (bytes > 980) return true;
	}
	return false;
}
/** Keep owner identity guidance bounded without changing the authorization allowlist. */
function resolveOwnerPromptNumbers(params) {
	const ownerNumbers = params.ownerNumbers;
	if (!ownerNumbers?.length) return;
	if (ownerNumbers.length <= MAX_OWNER_PROMPT_SENDERS && !exceedsOwnerPromptContentBudget(ownerNumbers)) return ownerNumbers;
	const promptOwners = ownerNumbers.slice(0, MAX_OWNER_PROMPT_SENDERS);
	const senderId = params.senderId;
	if (params.senderIsOwner && senderId && ownerNumbers.includes(senderId)) {
		if (!promptOwners.includes(senderId)) promptOwners[promptOwners.length - 1] = senderId;
		if (exceedsOwnerPromptContentBudget(promptOwners) && promptOwners[0] !== senderId) return [senderId, ...promptOwners.filter((ownerId) => ownerId !== senderId)];
	}
	return promptOwners;
}
/**
* Resolve owner display settings for prompt rendering.
* Keep auth secrets decoupled from owner hash secrets.
*/
function resolveOwnerDisplaySetting(_config) {
	return {
		ownerDisplay: "raw",
		ownerDisplaySecret: void 0
	};
}
/**
* Ensure hash mode has a dedicated secret.
* Returns updated config and generated secret when autofill was needed.
*/
function ensureOwnerDisplaySecret(config, _generateSecret) {
	return { config };
}
//#endregion
//#region src/commands/doctor/shared/include-migration-ownership.ts
function containsAuthoredInclude(value) {
	if (Array.isArray(value)) return value.some(containsAuthoredInclude);
	if (!isRecord(value)) return false;
	return Object.hasOwn(value, "$include") || Object.values(value).some(containsAuthoredInclude);
}
/** Classify whether Doctor can safely persist a migration at one resolved config path. */
function classifyConfigPathMigrationOwnership(params) {
	const owners = (params.snapshot.includeProvenance ?? []).filter((entry) => entry.path.length <= params.configPath.length && entry.path.every((segment, index) => segment === params.configPath[index]));
	if (owners.length === 0) return { kind: "direct" };
	const targetPaths = [...new Set(owners.flatMap((owner) => owner.targetPaths ?? (owner.targetPath ? [owner.targetPath] : [])))].toSorted();
	const owner = owners[0];
	const configDir = path.dirname(path.resolve(params.snapshot.path));
	if (owners.length === 1 && owner?.path.length === 1 && owner.path[0] === params.configPath[0] && owner.kind === "single" && !owner.hasSiblingOverrides && owner.targetPath && isPathInside(configDir, path.resolve(owner.targetPath))) return {
		kind: "single-top-level-include",
		targetPath: owner.targetPath
	};
	return {
		kind: "manual",
		targetPaths
	};
}
function readOtelProtocol(config) {
	const root = isRecord(config) ? config : null;
	const diagnostics = isRecord(root?.diagnostics) ? root.diagnostics : null;
	return (isRecord(diagnostics?.otel) ? diagnostics.otel : null)?.protocol;
}
/** Classify ownership for the sole legacy migration that consults resolved config values. */
function classifyOtelGrpcMigrationOwnership(params) {
	if (readOtelProtocol(params.resolvedConfig) !== "grpc") return null;
	const ownership = classifyConfigPathMigrationOwnership({
		snapshot: params.snapshot,
		configPath: [
			"diagnostics",
			"otel",
			"protocol"
		]
	});
	if (ownership.kind !== "direct") return ownership;
	return readOtelProtocol(params.authoredConfig) === "grpc" ? ownership : { kind: "resolved-only" };
}
function isSingleTopLevelIncludeMigration(params) {
	if (!isRecord(params.parsed)) return false;
	const keys = /* @__PURE__ */ new Set([...Object.keys(params.sourceConfig), ...Object.keys(params.candidate)]);
	const sourceConfig = params.sourceConfig;
	const candidate = params.candidate;
	const changed = [...keys].filter((key) => !isDeepStrictEqual(sourceConfig[key], candidate[key]));
	const changedKey = changed.length === 1 ? changed[0] : void 0;
	if (changedKey === void 0) return false;
	const authoredSection = params.parsed[changedKey];
	return isRecord(authoredSection) && Object.keys(authoredSection).length === 1 && typeof authoredSection["$include"] === "string";
}
//#endregion
//#region src/commands/doctor/shared/channel-legacy-config-migrate.ts
function migrateHeartbeatVisibility(raw, changes) {
	const channels = isRecord(raw.channels) ? raw.channels : null;
	if (!channels) return;
	const migrateEntry = (entry, path, preserveEmptyPluginBlock = false) => {
		const heartbeat = isRecord(entry.heartbeat) ? entry.heartbeat : null;
		const keys = heartbeat ? Object.keys(heartbeat) : [];
		if (!heartbeat || preserveEmptyPluginBlock && keys.length === 0 || keys.some((key) => key !== "showOk" && key !== "showAlerts" && key !== "useIndicator")) return;
		if (entry.heartbeatVisibility === void 0) {
			entry.heartbeatVisibility = entry.heartbeat;
			changes.push(`Moved ${path}.heartbeat → ${path}.heartbeatVisibility.`);
		} else changes.push(`Removed ${path}.heartbeat (${path}.heartbeatVisibility already set).`);
		delete entry.heartbeat;
	};
	const defaults = isRecord(channels.defaults) ? channels.defaults : null;
	if (defaults) migrateEntry(defaults, "channels.defaults");
	for (const [channelId, value] of Object.entries(channels)) {
		if (!channelId.trim() || isChannelConfigMetadataKey(channelId) || !isRecord(value)) continue;
		const preserveEmptyPluginBlock = channelId === "feishu";
		migrateEntry(value, `channels.${channelId}`, preserveEmptyPluginBlock);
		const accounts = isRecord(value.accounts) ? value.accounts : null;
		if (!accounts) continue;
		for (const [accountId, account] of Object.entries(accounts)) if (isRecord(account)) migrateEntry(account, `channels.${channelId}.accounts.${accountId}`, preserveEmptyPluginBlock);
	}
}
function resolveBundledChannelCompatibilityNormalizer(channelId) {
	const contractNormalizer = loadBundledChannelDoctorContractApi(channelId)?.normalizeCompatibilityConfig;
	if (typeof contractNormalizer === "function") return contractNormalizer;
	return getBootstrapChannelPlugin(channelId)?.doctor?.normalizeCompatibilityConfig;
}
function collectPluginDoctorCompatibilityIds(params) {
	const unresolvedChannelIds = new Set(params.unresolvedChannelIds);
	return [.../* @__PURE__ */ new Set([...params.unresolvedChannelIds, ...collectDoctorConfigRepairPluginIds(params.raw).filter((pluginId) => !unresolvedChannelIds.has(pluginId))])].toSorted();
}
/** Apply bundled and plugin channel compatibility migrations to a legacy config object. */
function applyChannelDoctorCompatibilityMigrations(cfg, options) {
	let nextCfg = cfg;
	const changes = [];
	migrateHeartbeatVisibility(cfg, changes);
	const unresolvedChannelIds = [];
	for (const channelId of listDoctorConfiguredChannelIds(cfg, {
		configEntryPolicy: "raw",
		sort: "codepoint"
	})) {
		const normalizeCompatibilityConfig = resolveBundledChannelCompatibilityNormalizer(channelId);
		if (!normalizeCompatibilityConfig) {
			unresolvedChannelIds.push(channelId);
			continue;
		}
		const mutation = normalizeCompatibilityConfig({ cfg: nextCfg });
		if (!mutation || mutation.changes.length === 0) continue;
		nextCfg = mutation.config;
		changes.push(...mutation.changes);
	}
	const pluginIds = options?.pluginContracts === false ? [] : collectPluginDoctorCompatibilityIds({
		raw: cfg,
		unresolvedChannelIds
	});
	if (pluginIds.length > 0) {
		const compat = applyPluginDoctorCompatibilityMigrations(nextCfg, {
			config: cfg,
			pluginIds
		});
		nextCfg = compat.config;
		changes.push(...compat.changes);
	}
	return {
		next: nextCfg,
		changes
	};
}
//#endregion
//#region src/commands/doctor/shared/legacy-config-compat.ts
/** Apply all legacy doctor migrations to raw config, returning null when nothing changed. */
function applyLegacyDoctorMigrations(raw, context, options) {
	if (!raw || typeof raw !== "object") return {
		next: null,
		changes: []
	};
	const original = raw;
	const next = structuredClone(original);
	const changes = [];
	for (const migration of LEGACY_CONFIG_MIGRATIONS) migration.apply(next, changes, context);
	const compat = applyChannelDoctorCompatibilityMigrations(next, { pluginContracts: options?.pluginContracts !== false });
	changes.push(...compat.changes);
	if (changes.length === 0) return {
		next: null,
		changes: []
	};
	return {
		next: inheritLegacyDefaultAgentId(original, compat.next),
		changes
	};
}
//#endregion
//#region src/config/io.health-state.ts
const loggedHealthWriteFailures = /* @__PURE__ */ new Map();
function resolveConfigHealthStateEnv(deps) {
	if (deps.env.OPENCLAW_HOME || deps.env.HOME || deps.env.USERPROFILE || deps.env.PREFIX) return deps.env;
	return {
		...deps.env,
		HOME: deps.homedir()
	};
}
function parseConfigHealthFingerprint(value) {
	if (!value) return;
	try {
		const parsed = JSON.parse(value);
		return parsed && typeof parsed === "object" ? parsed : void 0;
	} catch {
		return;
	}
}
function stringifyConfigHealthFingerprint(value) {
	return value ? JSON.stringify(value) : null;
}
function readConfigHealthStateFromStore(deps) {
	try {
		return withExistingOpenClawStateDatabaseReadOnly((database) => {
			const healthDb = getNodeSqliteKysely(database.db);
			const rows = executeSqliteQuerySync(database.db, healthDb.selectFrom("config_health_entries").select([
				"config_path",
				"last_known_good_json",
				"last_promoted_good_json",
				"last_observed_suspicious_signature"
			]).orderBy("config_path", "asc")).rows;
			return { entries: Object.fromEntries(rows.map((row) => [row.config_path, {
				lastKnownGood: parseConfigHealthFingerprint(row.last_known_good_json),
				lastPromotedGood: parseConfigHealthFingerprint(row.last_promoted_good_json),
				lastObservedSuspiciousSignature: row.last_observed_suspicious_signature
			}])) };
		}, { env: resolveConfigHealthStateEnv(deps) }) ?? {};
	} catch (error) {
		if (error instanceof OpenClawStateOwnershipError) throw error;
		return {};
	}
}
function writeConfigHealthStateToStore(deps, state) {
	const env = resolveConfigHealthStateEnv(deps);
	const databasePath = resolveOpenClawStateSqlitePath(env);
	try {
		const entries = Object.entries(state.entries ?? {});
		if (entries.length === 0) return;
		const updatedAtMs = Date.now();
		runOpenClawStateWriteTransaction(({ db }) => {
			const healthDb = getNodeSqliteKysely(db);
			executeSqliteQuerySync(db, healthDb.insertInto("config_health_entries").values(entries.map(([configPath, entry]) => ({
				config_path: configPath,
				last_known_good_json: stringifyConfigHealthFingerprint(entry.lastKnownGood),
				last_promoted_good_json: stringifyConfigHealthFingerprint(entry.lastPromotedGood),
				last_observed_suspicious_signature: entry.lastObservedSuspiciousSignature ?? null,
				updated_at_ms: updatedAtMs
			}))).onConflict((conflict) => conflict.column("config_path").doUpdateSet({
				last_known_good_json: (eb) => eb.ref("excluded.last_known_good_json"),
				last_promoted_good_json: (eb) => eb.ref("excluded.last_promoted_good_json"),
				last_observed_suspicious_signature: (eb) => eb.ref("excluded.last_observed_suspicious_signature"),
				updated_at_ms: (eb) => eb.ref("excluded.updated_at_ms")
			})));
		}, {
			env,
			path: databasePath
		});
		loggedHealthWriteFailures.delete(databasePath);
	} catch (error) {
		if (error instanceof OpenClawStateOwnershipError) throw error;
		const message = formatErrorMessage(error);
		const repeated = loggedHealthWriteFailures.get(databasePath) === message;
		setBoundedConfigIoWarningEntry(loggedHealthWriteFailures, databasePath, message);
		if (!repeated) deps.logger.warn(`Config health-state write failed: ${message}`);
	}
}
//#endregion
//#region src/config/io.observe-state.ts
function readConfigHealthEntry(state, configPath) {
	const entry = state.entries?.[configPath];
	return isRecord(entry) ? entry : {};
}
function updateConfigHealthEntry(state, configPath, entry) {
	return {
		...state,
		entries: {
			...state.entries,
			[configPath]: entry
		}
	};
}
function createConfigHealthFingerprint(params) {
	return {
		hash: params.hash ?? hashConfigRaw(params.raw),
		bytes: Buffer.byteLength(params.raw, "utf-8"),
		mtimeMs: params.stat?.mtimeMs ?? null,
		ctimeMs: params.stat?.ctimeMs ?? null,
		...resolveConfigStatMetadata(params.stat),
		hasMeta: hasConfigMeta(params.parsed),
		gatewayMode: resolveGatewayMode(params.resolved ?? params.parsed),
		observedAt: params.observedAt ?? (/* @__PURE__ */ new Date()).toISOString()
	};
}
function createConfigFingerprintFromRead(params) {
	const parsed = parseConfigJson5(params.raw, params.deps.json5);
	return createConfigHealthFingerprint({
		raw: params.raw,
		parsed: parsed.ok ? parsed.parsed : {},
		stat: params.stat
	});
}
async function readConfigFingerprintForPath(deps, configPath) {
	try {
		return createConfigFingerprintFromRead({
			deps,
			raw: await deps.fs.promises.readFile(configPath, "utf-8"),
			stat: await deps.fs.promises.stat(configPath).catch(() => null)
		});
	} catch {
		return null;
	}
}
function readConfigFingerprintForPathSync(deps, configPath) {
	try {
		const raw = deps.fs.readFileSync(configPath, "utf-8");
		let stat = null;
		try {
			stat = deps.fs.statSync(configPath, { throwIfNoEntry: false }) ?? null;
		} catch {}
		return createConfigFingerprintFromRead({
			deps,
			raw,
			stat
		});
	} catch {
		return null;
	}
}
function createConfigObserveAuditRecord(params) {
	const { current, lastKnownGood, backup } = params;
	return {
		ts: current.observedAt,
		source: "config-io",
		event: "config.observe",
		phase: "read",
		configPath: params.configPath,
		...snapshotConfigAuditProcessInfo(),
		exists: true,
		valid: params.valid,
		hash: current.hash,
		bytes: current.bytes,
		mtimeMs: current.mtimeMs,
		ctimeMs: current.ctimeMs,
		dev: current.dev,
		ino: current.ino,
		mode: current.mode,
		nlink: current.nlink,
		uid: current.uid,
		gid: current.gid,
		hasMeta: current.hasMeta,
		gatewayMode: current.gatewayMode,
		suspicious: params.suspicious,
		lastKnownGoodHash: lastKnownGood?.hash ?? null,
		lastKnownGoodBytes: lastKnownGood?.bytes ?? null,
		lastKnownGoodMtimeMs: lastKnownGood?.mtimeMs ?? null,
		lastKnownGoodCtimeMs: lastKnownGood?.ctimeMs ?? null,
		lastKnownGoodDev: lastKnownGood?.dev ?? null,
		lastKnownGoodIno: lastKnownGood?.ino ?? null,
		lastKnownGoodMode: lastKnownGood?.mode ?? null,
		lastKnownGoodNlink: lastKnownGood?.nlink ?? null,
		lastKnownGoodUid: lastKnownGood?.uid ?? null,
		lastKnownGoodGid: lastKnownGood?.gid ?? null,
		lastKnownGoodGatewayMode: lastKnownGood?.gatewayMode ?? null,
		backupHash: backup?.hash ?? null,
		backupBytes: backup?.bytes ?? null,
		backupMtimeMs: backup?.mtimeMs ?? null,
		backupCtimeMs: backup?.ctimeMs ?? null,
		backupDev: backup?.dev ?? null,
		backupIno: backup?.ino ?? null,
		backupMode: backup?.mode ?? null,
		backupNlink: backup?.nlink ?? null,
		backupUid: backup?.uid ?? null,
		backupGid: backup?.gid ?? null,
		backupGatewayMode: backup?.gatewayMode ?? null,
		clobberedPath: params.clobberedPath ?? null,
		restoredFromBackup: params.restoredFromBackup ?? false,
		restoredBackupPath: params.restoredBackupPath ?? null,
		restoreErrorCode: params.restoreErrorCode ?? null,
		restoreErrorMessage: params.restoreErrorMessage ?? null
	};
}
//#endregion
//#region src/config/io.observe-suspicious.ts
function isUpdateChannelOnlyRoot(value) {
	if (!isRecord(value)) return false;
	const keys = Object.keys(value);
	if (keys.length !== 1 || keys[0] !== "update") return false;
	const update = value.update;
	if (!isRecord(update)) return false;
	return Object.keys(update).length === 1 && typeof update.channel === "string";
}
function resolveConfigObserveSuspiciousReasons(params) {
	const reasons = [];
	const baseline = params.lastKnownGood;
	if (!baseline) return reasons;
	if (baseline.bytes >= 512 && params.bytes < Math.floor(baseline.bytes * .5)) reasons.push(`size-drop-vs-last-good:${baseline.bytes}->${params.bytes}`);
	if (baseline.hasMeta && !params.hasMeta) reasons.push("missing-meta-vs-last-good");
	if (baseline.gatewayMode && !params.gatewayMode) reasons.push("gateway-mode-missing-vs-last-good");
	if (baseline.gatewayMode && isUpdateChannelOnlyRoot(params.parsed)) reasons.push("update-channel-only-root");
	return reasons;
}
//#endregion
//#region src/config/io.observe.ts
function sameFingerprint(left, right) {
	if (!left) return false;
	return left.hash === right.hash && left.bytes === right.bytes && left.mtimeMs === right.mtimeMs && left.ctimeMs === right.ctimeMs && left.dev === right.dev && left.ino === right.ino && left.mode === right.mode && left.nlink === right.nlink && left.uid === right.uid && left.gid === right.gid && left.hasMeta === right.hasMeta && left.gatewayMode === right.gatewayMode;
}
function createObservedFingerprint(snapshot, stat) {
	const raw = snapshot.raw;
	return createConfigHealthFingerprint({
		raw,
		parsed: snapshot.parsed,
		resolved: snapshot.resolved,
		stat,
		hash: resolveConfigSnapshotHash(snapshot) ?? void 0
	});
}
function resolveObservation(params) {
	const entry = readConfigHealthEntry(params.healthState, params.snapshot.path);
	const baseline = entry.lastKnownGood ?? params.backupBaseline;
	return {
		entry,
		baseline,
		suspicious: resolveConfigObserveSuspiciousReasons({
			bytes: params.current.bytes,
			hasMeta: params.current.hasMeta,
			gatewayMode: params.current.gatewayMode,
			parsed: params.snapshot.parsed,
			lastKnownGood: baseline
		})
	};
}
function updateHealthyObservation(params) {
	if (!params.snapshot.valid) return null;
	const nextEntry = {
		...params.entry,
		lastKnownGood: params.current,
		lastObservedSuspiciousSignature: null
	};
	return !sameFingerprint(params.entry.lastKnownGood, params.current) || params.entry.lastObservedSuspiciousSignature !== null ? updateConfigHealthEntry(params.healthState, params.snapshot.path, nextEntry) : null;
}
async function observeConfigSnapshot(deps, snapshot) {
	if (!snapshot.exists || typeof snapshot.raw !== "string") return;
	const current = createObservedFingerprint(snapshot, await deps.fs.promises.stat(snapshot.path).catch(() => null));
	let healthState = readConfigHealthStateFromStore(deps);
	const backupPath = `${snapshot.path}.bak`;
	const backupBaseline = readConfigHealthEntry(healthState, snapshot.path).lastKnownGood ?? await readConfigFingerprintForPath(deps, backupPath) ?? void 0;
	const { entry, baseline, suspicious } = resolveObservation({
		snapshot,
		current,
		healthState,
		backupBaseline
	});
	if (suspicious.length === 0) {
		const nextState = updateHealthyObservation({
			snapshot,
			current,
			entry,
			healthState
		});
		if (nextState) writeConfigHealthStateToStore(deps, nextState);
		return;
	}
	const signature = `${current.hash}:${suspicious.join(",")}`;
	if (entry.lastObservedSuspiciousSignature === signature) return;
	const backup = (baseline?.hash ? baseline : null) ?? await readConfigFingerprintForPath(deps, backupPath);
	deps.logger.warn(`Config observe anomaly: ${snapshot.path} (${suspicious.join(", ")})`);
	await appendConfigAuditRecord({
		env: deps.env,
		homedir: deps.homedir,
		record: createConfigObserveAuditRecord({
			configPath: snapshot.path,
			valid: snapshot.valid,
			current,
			suspicious,
			lastKnownGood: entry.lastKnownGood,
			backup
		})
	});
	healthState = updateConfigHealthEntry(healthState, snapshot.path, {
		...entry,
		lastObservedSuspiciousSignature: signature
	});
	writeConfigHealthStateToStore(deps, healthState);
}
function observeConfigSnapshotSync(deps, snapshot) {
	if (!snapshot.exists || typeof snapshot.raw !== "string") return;
	const current = createObservedFingerprint(snapshot, deps.fs.statSync(snapshot.path, { throwIfNoEntry: false }) ?? null);
	let healthState = readConfigHealthStateFromStore(deps);
	const backupPath = `${snapshot.path}.bak`;
	const backupBaseline = readConfigHealthEntry(healthState, snapshot.path).lastKnownGood ?? readConfigFingerprintForPathSync(deps, backupPath) ?? void 0;
	const { entry, baseline, suspicious } = resolveObservation({
		snapshot,
		current,
		healthState,
		backupBaseline
	});
	if (suspicious.length === 0) {
		const nextState = updateHealthyObservation({
			snapshot,
			current,
			entry,
			healthState
		});
		if (nextState) writeConfigHealthStateToStore(deps, nextState);
		return;
	}
	const signature = `${current.hash}:${suspicious.join(",")}`;
	if (entry.lastObservedSuspiciousSignature === signature) return;
	const backup = (baseline?.hash ? baseline : null) ?? readConfigFingerprintForPathSync(deps, backupPath);
	deps.logger.warn(`Config observe anomaly: ${snapshot.path} (${suspicious.join(", ")})`);
	appendConfigAuditRecordSync({
		env: deps.env,
		homedir: deps.homedir,
		record: createConfigObserveAuditRecord({
			configPath: snapshot.path,
			valid: snapshot.valid,
			current,
			suspicious,
			lastKnownGood: entry.lastKnownGood,
			backup
		})
	});
	healthState = updateConfigHealthEntry(healthState, snapshot.path, {
		...entry,
		lastObservedSuspiciousSignature: signature
	});
	writeConfigHealthStateToStore(deps, healthState);
}
//#endregion
//#region src/config/io.owner-display-secret.ts
/** Retains generated owner display secrets in memory without persisting them into config. */
function retainGeneratedOwnerDisplaySecret(params) {
	const { config, configPath, generatedSecret, state } = params;
	if (!generatedSecret) {
		state.pendingByPath.delete(configPath);
		return config;
	}
	state.pendingByPath.set(configPath, generatedSecret);
	return config;
}
//#endregion
//#region src/config/runtime-overrides.ts
let overrides = {};
function sanitizeOverrideValue(value, seen = /* @__PURE__ */ new WeakSet()) {
	if (Array.isArray(value)) return value.map((entry) => sanitizeOverrideValue(entry, seen));
	if (!isPlainObject(value)) return value;
	if (seen.has(value)) return {};
	seen.add(value);
	const sanitized = {};
	for (const [key, entry] of Object.entries(value)) {
		if (entry === void 0 || isBlockedObjectKey(key)) continue;
		sanitized[key] = sanitizeOverrideValue(entry, seen);
	}
	seen.delete(value);
	return sanitized;
}
function mergeOverrides(base, override) {
	if (!isPlainObject(base) || !isPlainObject(override)) return override;
	const next = { ...base };
	for (const [key, value] of Object.entries(override)) {
		if (value === void 0 || isBlockedObjectKey(key)) continue;
		next[key] = mergeOverrides(base[key], value);
	}
	return next;
}
function applyOverrideTree(cfg, overrideTree) {
	const next = mergeOverrides(cfg, overrideTree);
	if (next.agents === cfg.agents) return inheritLegacyDefaultAgentId(cfg, next);
	return inheritLegacyDefaultAgentId(cfg, attachAgentListProjection(next));
}
/** Return the process-local runtime override tree used by debug config commands. */
function getConfigOverrides() {
	return overrides;
}
/** Clear all process-local runtime overrides. Intended for debug reset flows and tests. */
function resetConfigOverrides() {
	overrides = {};
}
/** Set one runtime override at a parsed config path after sanitizing object values. */
function setConfigOverride(pathRaw, value) {
	const parsed = parseConfigPath(pathRaw);
	if (!parsed.ok) return err(parsed.error);
	setConfigValueAtPath(overrides, parsed.path, sanitizeOverrideValue(value));
	return ok(parsed.path);
}
/** Remove one runtime override path and report whether an override was present. */
function unsetConfigOverride(pathRaw) {
	const parsed = parseConfigPath(pathRaw);
	if (!parsed.ok) return err(parsed.error);
	const removed = unsetConfigValueAtPath(overrides, parsed.path);
	return ok(removed);
}
/** Merge the current runtime overrides over a loaded config without mutating the input config. */
function applyConfigOverrides(cfg) {
	if (!overrides || Object.keys(overrides).length === 0) return cfg;
	return applyOverrideTree(cfg, overrides);
}
/** Capture an immutable applier for the process-local overrides active at this instant. */
function captureConfigOverrideApplier() {
	const capturedOverrides = structuredClone(overrides);
	if (Object.keys(capturedOverrides).length === 0) return (cfg) => cfg;
	return (cfg) => applyOverrideTree(cfg, capturedOverrides);
}
//#endregion
//#region src/config/io.context.ts
function createConfigIoContext(options = {}) {
	const deps = normalizeConfigIoDeps(options);
	const configPath = resolveConfigPathForDeps(deps);
	const pathResolution = {
		env: deps.env,
		homedir: options.homedir
	};
	function observeLoadConfigSnapshot(snapshot) {
		if (deps.observe) observeConfigSnapshotSync(deps, snapshot);
		return snapshot;
	}
	function finalizeLoadedRuntimeConfig(cfg) {
		const duplicates = findDuplicateAgentDirs(cfg, pathResolution);
		if (duplicates.length > 0) throw new DuplicateAgentDirError(duplicates);
		applyConfigEnvVars(cfg, deps.env);
		if ((shouldEnableShellEnvFallback(deps.env) || cfg.env?.shellEnv?.enabled === true) && options.shellEnvFallback !== "defer" && !shouldDeferShellEnvFallback(deps.env)) loadShellEnvFallback({
			enabled: true,
			env: deps.env,
			expectedKeys: resolveShellEnvExpectedKeys(deps.env, cfg),
			logger: deps.logger,
			timeoutMs: cfg.env?.shellEnv?.timeoutMs ?? resolveShellEnvFallbackTimeoutMs(deps.env)
		});
		const pendingValue = autoOwnerDisplaySecretByPath.get(configPath);
		const { config: resolvedConfig, generatedSecret } = ensureOwnerDisplaySecret(cfg, () => pendingValue ?? crypto.randomBytes(32).toString("hex"));
		const finalized = applyConfigOverrides(retainGeneratedOwnerDisplaySecret({
			config: resolvedConfig,
			configPath,
			generatedSecret,
			state: { pendingByPath: autoOwnerDisplaySecretByPath }
		}));
		const inherited = inheritLegacyDefaultAgentId(cfg, finalized);
		copyConfigResolutionFacts(cfg, inherited);
		return inherited;
	}
	function createValidationPluginMetadataSnapshotLoader(params) {
		let snapshot;
		return {
			load: (config) => {
				snapshot ??= resolveConfigWidePluginMetadataSnapshot({
					config,
					env: params.env,
					allowCurrent: params.allowCurrentPluginMetadata
				});
				return { manifestRegistry: snapshot.manifestRegistry };
			},
			getManifestRegistry: () => snapshot?.manifestRegistry,
			getSnapshot: () => snapshot
		};
	}
	function resolveRuntimePreflightSourceConfig(candidate) {
		const env = { ...deps.env };
		const resolvedIncludes = resolveConfigIncludesForRead(candidate, configPath, {
			...deps,
			env
		});
		const resolution = resolveConfigForRead(resolvedIncludes, env, deps.lowerPrecedenceEnv);
		const contextBudgetConfig = migrateLegacyContextBudgetConfig(resolution.resolvedConfigRaw).config;
		return coerceConfig(migratePersistedImplicitMainRoster(contextBudgetConfig, {
			env,
			homedir: deps.homedir
		}).config);
	}
	function prepareRecoveryBackupCandidate(candidate) {
		try {
			const originalEnv = cloneEnvWithPlatformSemantics(deps.env);
			const includeProvenance = [];
			const originalResolvedIncludes = resolveConfigIncludesForRead(candidate.parsed, configPath, {
				...deps,
				env: originalEnv
			}, void 0, void 0, void 0, (event) => {
				const { value: _value, ...ownership } = event;
				includeProvenance.push(ownership);
			});
			const originalResolution = resolveConfigForRead(originalResolvedIncludes, originalEnv, deps.lowerPrecedenceEnv);
			const otelOwnership = classifyOtelGrpcMigrationOwnership({
				snapshot: {
					path: configPath,
					includeProvenance
				},
				authoredConfig: candidate.parsed,
				resolvedConfig: originalResolution.resolvedConfigRaw
			});
			if (otelOwnership && otelOwnership.kind !== "direct") return {
				ok: false,
				reason: otelOwnership.kind === "resolved-only" ? "candidate migration cannot persist an env-resolved diagnostics.otel.protocol repair" : "candidate migration requires an include-owned diagnostics.otel.protocol repair"
			};
			const migrated = applyLegacyDoctorMigrations(candidate.parsed, {
				authoredRaw: candidate.parsed,
				resolvedRaw: originalResolution.resolvedConfigRaw
			});
			const authoredCandidate = migrated.next ?? candidate.parsed;
			const candidateEnv = cloneEnvWithPlatformSemantics(deps.env);
			const resolved = resolveConfigIncludesForRead(authoredCandidate, configPath, {
				...deps,
				env: candidateEnv
			});
			const effectiveConfigRaw = resolveConfigForRead(resolved, candidateEnv, deps.lowerPrecedenceEnv).resolvedConfigRaw;
			const pluginMetadata = createValidationPluginMetadataSnapshotLoader({
				effectiveConfigRaw,
				env: candidateEnv
			});
			const validated = validateConfigObjectWithPlugins(effectiveConfigRaw, {
				...pathResolution,
				env: candidateEnv,
				pluginValidation: options.pluginValidation,
				loadPluginMetadataSnapshot: pluginMetadata.load,
				sourceRaw: authoredCandidate,
				preservedLegacyRootKeys: options.preservedLegacyRootKeys
			});
			if (!validated.ok) {
				const issueSummary = formatConfigIssueSummary(validated.issues.slice(0, 3)) ?? "";
				const detail = issueSummary.length > 800 ? `${issueSummary.slice(0, 799)}…` : issueSummary;
				return {
					ok: false,
					reason: `candidate remains invalid after legacy migration${detail ? `: ${detail}` : ""}`
				};
			}
			return {
				ok: true,
				candidate: {
					config: validated.config,
					parsed: authoredCandidate,
					raw: migrated.next ? JSON.stringify(authoredCandidate, null, 2).trimEnd().concat("\n") : candidate.raw
				}
			};
		} catch (error) {
			return {
				ok: false,
				reason: `candidate preparation failed: ${error instanceof Error ? error.message : String(error)}`
			};
		}
	}
	return {
		deps,
		pathResolution,
		configPath,
		options,
		observeLoadConfigSnapshot,
		finalizeLoadedRuntimeConfig,
		createValidationPluginMetadataSnapshotLoader,
		resolveRuntimePreflightSourceConfig,
		prepareRecoveryBackupCandidate
	};
}
//#endregion
//#region src/config/io.clobber-snapshot.ts
/** Maximum retained clobbered-config snapshots per config file. */
const CONFIG_CLOBBER_SNAPSHOT_LIMIT = 32;
const CONFIG_CLOBBER_LOCK_STALE_MS = 3e4;
const CONFIG_CLOBBER_LOCK_RETRY_MS = 10;
const CONFIG_CLOBBER_LOCK_TIMEOUT_MS = 2e3;
const clobberSnapshotQueue = new KeyedAsyncQueue();
const clobberCapWarnedPaths = createDedupeCache({
	ttlMs: 0,
	maxSize: 4096
});
function formatConfigArtifactTimestamp(ts) {
	return ts.replaceAll(":", "-").replaceAll(".", "-");
}
function isFsErrorCode(error, code) {
	return error instanceof Error && "code" in error && typeof error.code === "string" && error.code === code;
}
function resolveClobberPaths(configPath) {
	const dir = path.dirname(configPath);
	const basename = path.basename(configPath);
	return {
		dir,
		prefix: `${basename}.clobbered.`,
		lockPath: path.join(dir, `${basename}.clobber.lock`)
	};
}
function shouldRemoveStaleLock(mtimeMs, nowMs) {
	return typeof mtimeMs === "number" && nowMs - mtimeMs > CONFIG_CLOBBER_LOCK_STALE_MS;
}
async function acquireClobberLock(deps, lockPath) {
	const startedAt = Date.now();
	while (Date.now() - startedAt < CONFIG_CLOBBER_LOCK_TIMEOUT_MS) try {
		await deps.fs.promises.mkdir(lockPath, { mode: 448 });
		return true;
	} catch (error) {
		if (!isFsErrorCode(error, "EEXIST")) return false;
		if (shouldRemoveStaleLock((await deps.fs.promises.stat(lockPath).catch(() => null))?.mtimeMs, Date.now())) {
			await deps.fs.promises.rmdir(lockPath).catch(() => {});
			continue;
		}
		await sleep(CONFIG_CLOBBER_LOCK_RETRY_MS);
	}
	return false;
}
function acquireClobberLockSync(deps, lockPath) {
	for (let attempt = 0; attempt < 2; attempt++) try {
		deps.fs.mkdirSync(lockPath, { mode: 448 });
		return true;
	} catch (error) {
		if (!isFsErrorCode(error, "EEXIST")) return false;
		if (!shouldRemoveStaleLock(deps.fs.statSync(lockPath, { throwIfNoEntry: false })?.mtimeMs, Date.now())) return false;
		try {
			deps.fs.rmdirSync(lockPath);
		} catch {
			return false;
		}
	}
	return false;
}
function compareClobberedSiblings(left, right) {
	return left.timestampKey.localeCompare(right.timestampKey) || left.mtimeMs - right.mtimeMs || left.name.localeCompare(right.name);
}
function createClobberedSiblingSnapshot(params) {
	return {
		name: params.entry,
		path: path.join(params.dir, params.entry),
		timestampKey: params.entry.slice(params.prefix.length).replace(/-\d{2}$/, ""),
		mtimeMs: params.mtimeMs
	};
}
async function listClobberedSiblings(deps, dir, prefix) {
	try {
		const entries = await deps.fs.promises.readdir(dir);
		const snapshots = [];
		for (const entry of entries) {
			if (!entry.startsWith(prefix)) continue;
			const stat = await deps.fs.promises.stat(path.join(dir, entry)).catch(() => null);
			snapshots.push(createClobberedSiblingSnapshot({
				dir,
				entry,
				prefix,
				mtimeMs: stat?.mtimeMs ?? 0
			}));
		}
		return snapshots.toSorted(compareClobberedSiblings);
	} catch {
		return [];
	}
}
function listClobberedSiblingsSync(deps, dir, prefix) {
	try {
		const snapshots = [];
		for (const entry of deps.fs.readdirSync(dir)) {
			if (!entry.startsWith(prefix)) continue;
			const stat = deps.fs.statSync(path.join(dir, entry), { throwIfNoEntry: false });
			snapshots.push(createClobberedSiblingSnapshot({
				dir,
				entry,
				prefix,
				mtimeMs: stat?.mtimeMs ?? 0
			}));
		}
		return snapshots.toSorted(compareClobberedSiblings);
	} catch {
		return [];
	}
}
function warnClobberCapReached(deps, configPath, existing) {
	if (clobberCapWarnedPaths.check(configPath)) return;
	deps.logger.warn(`Config clobber snapshot cap reached for ${configPath}: ${existing} existing .clobbered.* files; rotating oldest snapshots to preserve the latest forensic copy.`);
}
async function rotateOldestClobberedSiblings(deps, snapshots) {
	const deleteCount = Math.max(0, snapshots.length - CONFIG_CLOBBER_SNAPSHOT_LIMIT + 1);
	for (const snapshot of snapshots.slice(0, deleteCount)) try {
		await deps.fs.promises.unlink(snapshot.path);
	} catch (error) {
		if (!isFsErrorCode(error, "ENOENT")) return false;
	}
	return true;
}
function rotateOldestClobberedSiblingsSync(deps, snapshots) {
	const deleteCount = Math.max(0, snapshots.length - CONFIG_CLOBBER_SNAPSHOT_LIMIT + 1);
	for (const snapshot of snapshots.slice(0, deleteCount)) try {
		deps.fs.unlinkSync(snapshot.path);
	} catch (error) {
		if (!isFsErrorCode(error, "ENOENT")) return false;
	}
	return true;
}
function buildClobberedTargetPath(configPath, observedAt, attempt) {
	const basePath = `${configPath}.clobbered.${formatConfigArtifactTimestamp(observedAt)}`;
	return attempt === 0 ? basePath : `${basePath}-${String(attempt).padStart(2, "0")}`;
}
async function persistBoundedClobberedConfigSnapshot(params) {
	const paths = resolveClobberPaths(params.configPath);
	return await clobberSnapshotQueue.enqueue(paths.lockPath, async () => {
		if (!await acquireClobberLock(params.deps, paths.lockPath)) return null;
		try {
			const existing = await listClobberedSiblings(params.deps, paths.dir, paths.prefix);
			if (existing.length >= CONFIG_CLOBBER_SNAPSHOT_LIMIT) {
				warnClobberCapReached(params.deps, params.configPath, existing.length);
				if (!await rotateOldestClobberedSiblings(params.deps, existing)) return null;
			}
			for (let attempt = 0; attempt < CONFIG_CLOBBER_SNAPSHOT_LIMIT; attempt++) {
				const targetPath = buildClobberedTargetPath(params.configPath, params.observedAt, attempt);
				try {
					await params.deps.fs.promises.writeFile(targetPath, params.raw, {
						encoding: "utf-8",
						mode: 384,
						flag: "wx"
					});
					return targetPath;
				} catch (error) {
					if (!isFsErrorCode(error, "EEXIST")) return null;
				}
			}
			return null;
		} finally {
			await params.deps.fs.promises.rmdir(paths.lockPath).catch(() => {});
		}
	});
}
function persistBoundedClobberedConfigSnapshotSync(params) {
	const paths = resolveClobberPaths(params.configPath);
	if (!acquireClobberLockSync(params.deps, paths.lockPath)) return null;
	try {
		const existing = listClobberedSiblingsSync(params.deps, paths.dir, paths.prefix);
		if (existing.length >= CONFIG_CLOBBER_SNAPSHOT_LIMIT) {
			warnClobberCapReached(params.deps, params.configPath, existing.length);
			if (!rotateOldestClobberedSiblingsSync(params.deps, existing)) return null;
		}
		for (let attempt = 0; attempt < CONFIG_CLOBBER_SNAPSHOT_LIMIT; attempt++) {
			const targetPath = buildClobberedTargetPath(params.configPath, params.observedAt, attempt);
			try {
				params.deps.fs.writeFileSync(targetPath, params.raw, {
					encoding: "utf-8",
					mode: 384,
					flag: "wx"
				});
				return targetPath;
			} catch (error) {
				if (!isFsErrorCode(error, "EEXIST")) return null;
			}
		}
		return null;
	} finally {
		try {
			params.deps.fs.rmdirSync(paths.lockPath);
		} catch {}
	}
}
//#endregion
//#region src/config/io.observe-recovery.ts
function formatConfigPermissionHardeningWarning(params) {
	const detail = params.error instanceof Error ? params.error.message : String(params.error);
	return `Config permission hardening failed (${params.context}): ${params.configPath}: ${detail}`;
}
async function chmodConfigBestEffort(params) {
	try {
		await params.deps.fs.promises.chmod?.(params.configPath, 384);
	} catch (error) {
		params.deps.logger.warn(formatConfigPermissionHardeningWarning({
			configPath: params.configPath,
			context: params.context,
			error
		}));
	}
}
function chmodConfigBestEffortSync(params) {
	try {
		params.deps.fs.chmodSync?.(params.configPath, 384);
	} catch (error) {
		params.deps.logger.warn(formatConfigPermissionHardeningWarning({
			configPath: params.configPath,
			context: params.context,
			error
		}));
	}
}
function createRecoveryCommitEffect(params) {
	const options = {
		filePath: params.configPath,
		content: params.raw,
		dirMode: 448,
		mode: 384,
		tempPrefix: path.basename(params.configPath),
		fileSystem: params.deps.fs
	};
	return {
		sync: () => {
			replaceFileAtomicSync(options);
		},
		async: async () => {
			await replaceFileAtomic(options);
		}
	};
}
function createConfigObserveAuditAppendParams(deps, params) {
	return {
		env: deps.env,
		homedir: deps.homedir,
		record: createConfigObserveAuditRecord(params)
	};
}
function extractRestoreErrorDetails(error) {
	if (!error || typeof error !== "object") return {
		code: null,
		message: typeof error === "string" ? error : null
	};
	return {
		code: "code" in error && typeof error.code === "string" ? error.code : null,
		message: "message" in error && typeof error.message === "string" ? error.message : null
	};
}
function returnOriginalConfigRead(params) {
	return {
		raw: params.raw,
		parsed: params.parsed
	};
}
function parseBackupConfigRaw(deps, backupRaw) {
	try {
		return { parsed: deps.json5.parse(backupRaw) };
	} catch {
		return null;
	}
}
function logBackupRestoreResult(params) {
	if (params.restoredFromBackup) {
		params.deps.logger.warn(`Config auto-restored from backup: ${params.configPath} (${params.suspicious.join(", ")})`);
		return;
	}
	params.deps.logger.warn(`Config auto-restore from backup failed: ${params.configPath} (${params.suspicious.join(", ")}${params.restoreErrorMessage ? `; ${params.restoreErrorMessage}` : ""})`);
}
function createBackupRestoreAuditAppendParams(params) {
	return createConfigObserveAuditAppendParams(params.deps, {
		configPath: params.configPath,
		valid: params.restoredFromBackup,
		current: params.current,
		suspicious: params.suspicious,
		lastKnownGood: params.entry.lastKnownGood,
		backup: params.backup,
		clobberedPath: params.clobberedPath,
		restoredFromBackup: params.restoredFromBackup,
		restoredBackupPath: params.backupPath,
		restoreErrorCode: params.restoreErrorDetails.code,
		restoreErrorMessage: params.restoreErrorDetails.message
	});
}
function resolveSuspiciousSignature(current, suspicious) {
	return `${current.hash}:${suspicious.join(",")}`;
}
function isRecoverableConfigReadSuspiciousReason(reason) {
	return reason === "missing-meta-vs-last-good" || reason === "gateway-mode-missing-vs-last-good" || reason === "update-channel-only-root" || reason.startsWith("size-drop-vs-last-good:");
}
function resolveConfigReadRecoveryContext(params) {
	const suspicious = resolveConfigObserveSuspiciousReasons({
		bytes: params.current.bytes,
		hasMeta: params.current.hasMeta,
		gatewayMode: params.current.gatewayMode,
		parsed: params.parsed,
		lastKnownGood: params.backupBaseline
	});
	if (!suspicious.some(isRecoverableConfigReadSuspiciousReason)) return null;
	const suspiciousSignature = resolveSuspiciousSignature(params.current, suspicious);
	if (params.entry.lastObservedSuspiciousSignature === suspiciousSignature) return null;
	return {
		suspicious,
		suspiciousSignature
	};
}
function resolveLastKnownGoodConfigPath(configPath) {
	return `${configPath}.last-good`;
}
function isSensitiveConfigPath(pathLabel) {
	return /(^|\.)(api[-_]?key|auth|bearer|credential|password|private[-_]?key|secret|token)(\.|$)/i.test(pathLabel);
}
function collectPollutedSecretPlaceholders(value, pathLabel = "", output = []) {
	if (typeof value === "string") {
		const trimmed = value.trim();
		if (trimmed === "***" || trimmed === "[redacted]") {
			output.push(pathLabel || "<root>");
			return output;
		}
		if (isSensitiveConfigPath(pathLabel) && (trimmed.includes("...") || trimmed.includes("…"))) output.push(pathLabel || "<root>");
		return output;
	}
	if (Array.isArray(value)) {
		value.forEach((item, index) => collectPollutedSecretPlaceholders(item, `${pathLabel}[${index}]`, output));
		return output;
	}
	if (isRecord(value)) for (const [key, child] of Object.entries(value)) collectPollutedSecretPlaceholders(child, pathLabel ? `${pathLabel}.${key}` : key, output);
	return output;
}
async function maybeRecoverSuspiciousConfigRead(params) {
	const recovery = recoverSuspiciousConfigRead(params);
	let step = recovery.next();
	while (!step.done) try {
		step = recovery.next(await step.value.async());
	} catch (error) {
		step = recovery.throw(error);
	}
	return step.value;
}
function maybeRecoverSuspiciousConfigReadSync(params) {
	const recovery = recoverSuspiciousConfigRead(params);
	let step = recovery.next();
	while (!step.done) try {
		step = recovery.next(step.value.sync());
	} catch (error) {
		step = recovery.throw(error);
	}
	return step.value;
}
function createConfigRecoveryStatEffect(deps, configPath) {
	return {
		sync: () => {
			try {
				return deps.fs.statSync(configPath, { throwIfNoEntry: false }) ?? null;
			} catch {
				return null;
			}
		},
		async: () => deps.fs.promises.stat(configPath).catch(() => null)
	};
}
function createConfigBackupReadEffect(deps, backupPath) {
	return {
		sync: () => {
			try {
				return deps.fs.readFileSync(backupPath, "utf-8");
			} catch {
				return null;
			}
		},
		async: () => deps.fs.promises.readFile(backupPath, "utf-8").catch(() => null)
	};
}
function* recoverSuspiciousConfigRead(params) {
	const { deps, configPath, raw, parsed } = params;
	const stat = yield createConfigRecoveryStatEffect(deps, configPath);
	const now = (/* @__PURE__ */ new Date()).toISOString();
	const current = createConfigHealthFingerprint({
		raw,
		parsed,
		stat,
		observedAt: now
	});
	const healthState = readConfigHealthStateFromStore(deps);
	const entry = readConfigHealthEntry(healthState, configPath);
	const backupPath = `${configPath}.bak`;
	const recoveryContext = resolveConfigReadRecoveryContext({
		current,
		parsed,
		entry,
		backupBaseline: entry.lastKnownGood ?? (yield {
			sync: () => readConfigFingerprintForPathSync(deps, backupPath),
			async: () => readConfigFingerprintForPath(deps, backupPath)
		}) ?? void 0
	});
	if (!recoveryContext) return returnOriginalConfigRead(params);
	const { suspicious, suspiciousSignature } = recoveryContext;
	const backupRaw = yield createConfigBackupReadEffect(deps, backupPath);
	if (!backupRaw) return returnOriginalConfigRead(params);
	const backupParse = parseBackupConfigRaw(deps, backupRaw);
	if (!backupParse) return returnOriginalConfigRead(params);
	const backupCandidate = {
		raw: backupRaw,
		parsed: backupParse.parsed
	};
	const prepared = yield {
		sync: () => params.prepareBackup(backupCandidate),
		async: () => params.prepareBackup(backupCandidate)
	};
	if (!prepared.ok) return returnOriginalConfigRead(params);
	const preparedCandidate = prepared.candidate;
	const backupStat = yield createConfigRecoveryStatEffect(deps, backupPath);
	const backup = createConfigHealthFingerprint({
		raw: backupRaw,
		parsed: backupParse.parsed,
		stat: backupStat
	});
	if (!backup.gatewayMode) return returnOriginalConfigRead(params);
	if (params.allowBackupRecovery) {
		if (!(yield {
			sync: () => true,
			async: () => params.allowBackupRecovery?.() ?? true
		})) return returnOriginalConfigRead(params);
	}
	const snapshotParams = {
		deps,
		configPath,
		raw,
		observedAt: now
	};
	const clobberedPath = yield {
		sync: () => persistBoundedClobberedConfigSnapshotSync(snapshotParams),
		async: () => persistBoundedClobberedConfigSnapshot(snapshotParams)
	};
	let restoredFromBackup = false;
	let restoreError;
	try {
		if (preparedCandidate.raw !== backupRaw) warnIfJSON5CommentsWillBeStripped({
			raw: backupRaw,
			filePath: configPath,
			warn: (message) => deps.logger.warn(message)
		});
		yield createRecoveryCommitEffect({
			deps,
			configPath,
			raw: preparedCandidate.raw
		});
		const chmodParams = {
			deps,
			configPath,
			context: "backup restore"
		};
		yield {
			sync: () => chmodConfigBestEffortSync(chmodParams),
			async: () => chmodConfigBestEffort(chmodParams)
		};
		restoredFromBackup = true;
	} catch (error) {
		restoreError = error;
	}
	const restoreErrorDetails = restoredFromBackup ? {
		code: null,
		message: null
	} : extractRestoreErrorDetails(restoreError);
	logBackupRestoreResult({
		deps,
		configPath,
		suspicious,
		restoredFromBackup,
		restoreErrorMessage: restoreErrorDetails.message
	});
	const audit = createBackupRestoreAuditAppendParams({
		deps,
		configPath,
		restoredFromBackup,
		current,
		suspicious,
		entry,
		backup,
		clobberedPath,
		backupPath,
		restoreErrorDetails
	});
	yield {
		sync: () => appendConfigAuditRecordSync(audit),
		async: () => appendConfigAuditRecord(audit)
	};
	if (restoredFromBackup) writeConfigHealthStateToStore(deps, updateConfigHealthEntry(healthState, configPath, {
		...entry,
		lastObservedSuspiciousSignature: suspiciousSignature
	}));
	return preparedCandidate;
}
async function promoteConfigSnapshotToLastKnownGoodCore(params) {
	const { deps, snapshot } = params;
	if (!snapshot.exists || !snapshot.valid || typeof snapshot.raw !== "string") return false;
	const polluted = collectPollutedSecretPlaceholders(snapshot.parsed);
	if (polluted.length > 0) {
		params.logger?.warn(`Config last-known-good promotion skipped: redacted secret placeholder at ${polluted[0]}`);
		return false;
	}
	const stat = await deps.fs.promises.stat(snapshot.path).catch(() => null);
	const now = (/* @__PURE__ */ new Date()).toISOString();
	const current = createConfigHealthFingerprint({
		hash: resolveConfigSnapshotHash(snapshot) ?? void 0,
		raw: snapshot.raw,
		parsed: snapshot.parsed,
		resolved: snapshot.resolved,
		stat,
		observedAt: now
	});
	const lastGoodPath = resolveLastKnownGoodConfigPath(snapshot.path);
	await deps.fs.promises.writeFile(lastGoodPath, snapshot.raw, {
		encoding: "utf-8",
		mode: 384
	});
	await chmodConfigBestEffort({
		deps,
		configPath: lastGoodPath,
		context: "last-known-good promotion"
	});
	const healthState = readConfigHealthStateFromStore(deps);
	const entry = readConfigHealthEntry(healthState, snapshot.path);
	writeConfigHealthStateToStore(deps, updateConfigHealthEntry(healthState, snapshot.path, {
		...entry,
		lastKnownGood: current,
		lastPromotedGood: current,
		lastObservedSuspiciousSignature: null
	}));
	return true;
}
async function recoverConfigFromLastKnownGoodCore(params) {
	const { deps, snapshot } = params;
	if (!snapshot.exists || typeof snapshot.raw !== "string") return false;
	if (!shouldAttemptLastKnownGoodRecovery(snapshot)) {
		if (isPluginLocalInvalidConfigSnapshot(snapshot)) deps.logger.warn(`Config last-known-good recovery skipped: invalidity is scoped to stale plugin config (${params.reason})`);
		return false;
	}
	const healthState = readConfigHealthStateFromStore(deps);
	const entry = readConfigHealthEntry(healthState, snapshot.path);
	const promoted = entry.lastPromotedGood;
	if (!promoted?.hash) return false;
	const lastGoodPath = resolveLastKnownGoodConfigPath(snapshot.path);
	const backupRaw = await deps.fs.promises.readFile(lastGoodPath, "utf-8").catch(() => null);
	if (!backupRaw || hashConfigRaw(backupRaw) !== promoted.hash) return false;
	let backupParsed;
	try {
		backupParsed = deps.json5.parse(backupRaw);
	} catch {
		return false;
	}
	const originalCandidate = {
		raw: backupRaw,
		parsed: backupParsed
	};
	const prepared = params.prepareCandidate(originalCandidate);
	if (!prepared.ok) {
		deps.logger.warn(`Config last-known-good recovery skipped: ${prepared.reason} (${params.reason})`);
		return false;
	}
	const recoveryCandidate = prepared.candidate;
	const polluted = collectPollutedSecretPlaceholders(recoveryCandidate.parsed);
	if (polluted.length > 0) {
		deps.logger.warn(`Config last-known-good recovery skipped: redacted secret placeholder at ${polluted[0]}`);
		return false;
	}
	const now = (/* @__PURE__ */ new Date()).toISOString();
	const stat = await deps.fs.promises.stat(snapshot.path).catch(() => null);
	const current = createConfigHealthFingerprint({
		hash: resolveConfigSnapshotHash(snapshot) ?? void 0,
		raw: snapshot.raw,
		parsed: snapshot.parsed,
		resolved: snapshot.resolved,
		stat,
		observedAt: now
	});
	const clobberedPath = await preserveConfigSnapshotAsClobberedCore({
		deps,
		snapshot,
		observedAt: now
	});
	if (recoveryCandidate.raw !== backupRaw) warnIfJSON5CommentsWillBeStripped({
		raw: backupRaw,
		filePath: snapshot.path,
		warn: (message) => deps.logger.warn(message)
	});
	await createRecoveryCommitEffect({
		deps,
		configPath: snapshot.path,
		raw: recoveryCandidate.raw
	}).async();
	await chmodConfigBestEffort({
		deps,
		configPath: snapshot.path,
		context: "last-known-good recovery"
	});
	const issueSummary = formatConfigIssueSummary([...snapshot.issues, ...snapshot.legacyIssues]);
	deps.logger.warn(`Config auto-restored from last-known-good: ${snapshot.path} (${params.reason})${issueSummary ? `; Rejected validation details: ${issueSummary}.` : ""}`);
	await appendConfigAuditRecord(createConfigObserveAuditAppendParams(deps, {
		configPath: snapshot.path,
		valid: snapshot.valid,
		current,
		suspicious: [params.reason],
		lastKnownGood: promoted,
		backup: promoted,
		clobberedPath,
		restoredFromBackup: true,
		restoredBackupPath: lastGoodPath
	}));
	writeConfigHealthStateToStore(deps, updateConfigHealthEntry(healthState, snapshot.path, {
		...entry,
		lastKnownGood: promoted,
		lastPromotedGood: promoted,
		lastObservedSuspiciousSignature: null
	}));
	return true;
}
async function preserveConfigSnapshotAsClobberedCore(params) {
	if (!params.snapshot.exists || typeof params.snapshot.raw !== "string") return null;
	return await persistBoundedClobberedConfigSnapshot({
		deps: params.deps,
		configPath: params.snapshot.path,
		raw: params.snapshot.raw,
		observedAt: params.observedAt ?? (/* @__PURE__ */ new Date()).toISOString()
	});
}
//#endregion
//#region src/config/io.snapshot-shared.ts
function createConfigFileSnapshot(params) {
	const sourceConfigBeforeMigrations = params.sourceConfigBeforeMigrations ? asResolvedSourceConfig(params.sourceConfigBeforeMigrations) : void 0;
	const sourceConfig = asResolvedSourceConfig(params.sourceConfig);
	const runtimeConfig = asRuntimeConfig(params.runtimeConfig);
	if (params.resolutionFacts !== void 0) {
		setConfigResolutionFacts(sourceConfigBeforeMigrations, params.resolutionFacts);
		setConfigResolutionFacts(sourceConfig, params.resolutionFacts);
		setConfigResolutionFacts(runtimeConfig, params.resolutionFacts);
	}
	return {
		path: params.path,
		includedPaths: [...params.includedPaths ?? []],
		...params.includeProvenance ? { includeProvenance: params.includeProvenance.map((entry) => ({
			...entry,
			path: [...entry.path],
			...entry.targetPaths ? { targetPaths: [...entry.targetPaths] } : {}
		})) } : {},
		...params.agentRosterIncludeOwned !== void 0 ? { agentRosterIncludeOwned: params.agentRosterIncludeOwned } : {},
		...params.bindingsIncludeOwned !== void 0 ? { bindingsIncludeOwned: params.bindingsIncludeOwned } : {},
		exists: params.exists,
		raw: params.raw,
		parsed: params.parsed,
		...sourceConfigBeforeMigrations ? { sourceConfigBeforeMigrations } : {},
		sourceConfig,
		resolved: sourceConfig,
		valid: params.valid,
		runtimeConfig,
		config: runtimeConfig,
		hash: params.hash,
		...params.readError ? { readError: params.readError } : {},
		issues: params.issues,
		warnings: params.warnings,
		legacyIssues: params.legacyIssues
	};
}
async function finalizeReadConfigSnapshotInternalResult(deps, result, options) {
	if (deps.observe && options?.observe !== false) await observeConfigSnapshot(deps, result.snapshot);
	return result;
}
async function collectInvalidConfigLegacyIssues(raw, sourceRaw) {
	if (!raw || typeof raw !== "object") return [];
	const { findDoctorLegacyConfigIssues } = await import("./legacy-config-issues-DagKaXFj.js");
	return findDoctorLegacyConfigIssues(raw, sourceRaw);
}
//#endregion
//#region src/config/io.load.ts
function loadConfigFromContext(context, options = {}) {
	const { deps, configPath, pathResolution } = context;
	let envBeforeRead;
	try {
		maybeLoadDotEnvForConfig(deps.env);
		envBeforeRead = snapshotEnv(deps.env);
		if (!deps.fs.existsSync(configPath)) {
			loggedConfigWarningFingerprints.delete(configPath);
			const config = coerceConfig(migratePersistedImplicitMainRoster({}).config);
			const metadata = context.createValidationPluginMetadataSnapshotLoader({
				effectiveConfigRaw: config,
				env: deps.env
			});
			return context.finalizeLoadedRuntimeConfig(materializeRuntimeConfig(config, {
				...pathResolution,
				...context.options.pluginValidation === "core-only" ? { manifestRegistry: { plugins: [] } } : { loadManifestRegistry: () => metadata.load(config).manifestRegistry }
			}));
		}
		const raw = deps.fs.readFileSync(configPath, "utf-8");
		const parsed = deps.json5.parse(raw);
		const readResolution = resolveConfigForRead(resolveConfigIncludesForRead(parsed, configPath, deps), deps.env, deps.lowerPrecedenceEnv);
		const contextBudgetMigration = migrateLegacyContextBudgetConfig(readResolution.resolvedConfigRaw);
		const rosterMigration = migratePersistedImplicitMainRoster(contextBudgetMigration.config, {
			env: deps.env,
			homedir: deps.homedir
		});
		const effectiveConfigRaw = rosterMigration.config;
		const validationConfigRaw = effectiveConfigRaw;
		const snapshotRaw = raw;
		const snapshotParsed = parsed;
		const hash = hashConfigRaw(snapshotRaw);
		for (const warning of readResolution.envWarnings) deps.logger.warn(`Config (${configPath}): missing env var "${warning.varName}" at ${warning.configPath} - feature using this value will be unavailable`);
		for (const diagnostic of [
			...contextBudgetMigration.changes.map(({ message }) => message),
			...contextBudgetMigration.warnings.map(({ message }) => message),
			...rosterMigration.diagnostics
		]) deps.logger.warn(`Config (${configPath}): ${diagnostic}`);
		warnOnConfigMiskeys(validationConfigRaw, deps.logger);
		if (typeof validationConfigRaw === "object" && validationConfigRaw !== null) {
			const duplicates = findDuplicateAgentDirs(validationConfigRaw, pathResolution);
			if (duplicates.length > 0) throw new DuplicateAgentDirError(duplicates);
		}
		const pluginMetadata = context.createValidationPluginMetadataSnapshotLoader({
			effectiveConfigRaw,
			env: deps.env
		});
		const validated = validateConfigObjectWithPlugins(validationConfigRaw, {
			...pathResolution,
			pluginValidation: context.options.pluginValidation,
			loadPluginMetadataSnapshot: pluginMetadata.load,
			sourceRaw: snapshotParsed,
			preservedLegacyRootKeys: context.options.preservedLegacyRootKeys
		});
		if (!validated.ok) {
			context.observeLoadConfigSnapshot(createConfigFileSnapshot({
				path: configPath,
				exists: true,
				raw: snapshotRaw,
				parsed: snapshotParsed,
				sourceConfig: coerceConfig(effectiveConfigRaw),
				valid: false,
				runtimeConfig: coerceConfig(effectiveConfigRaw),
				hash,
				issues: validated.issues,
				warnings: validated.warnings,
				resolutionFacts: readResolution.resolutionFacts,
				legacyIssues: []
			}));
			throwInvalidConfig({
				configPath,
				issues: validated.issues,
				logger: deps.logger,
				loggedConfigPaths: loggedInvalidConfigs
			});
		}
		if (context.options.pluginValidation !== "skip") logConfigWarningsOnce({
			configPath,
			warnings: validated.warnings,
			logger: deps.logger
		});
		if (!deps.suppressFutureVersionWarning) warnIfConfigFromFuture(validated.config, deps.logger);
		if (deps.observe && !options.skipSuspiciousRecovery && !containsConfigIncludeDirective(parsed)) {
			if (maybeRecoverSuspiciousConfigReadSync({
				deps,
				configPath,
				raw,
				parsed,
				prepareBackup: context.prepareRecoveryBackupCandidate
			}).raw !== raw) {
				restoreEnvChangesIfUnchanged({
					env: deps.env,
					before: envBeforeRead,
					after: snapshotEnv(deps.env)
				});
				return loadConfigFromContext(context, { skipSuspiciousRecovery: true });
			}
		}
		const cfg = materializeRuntimeConfig(validated.config, {
			...pathResolution,
			manifestRegistry: pluginMetadata.getManifestRegistry()
		});
		context.observeLoadConfigSnapshot(createConfigFileSnapshot({
			path: configPath,
			exists: true,
			raw: snapshotRaw,
			parsed: snapshotParsed,
			sourceConfig: coerceConfig(effectiveConfigRaw),
			valid: true,
			runtimeConfig: cfg,
			hash,
			issues: [],
			warnings: validated.warnings,
			resolutionFacts: readResolution.resolutionFacts,
			legacyIssues: []
		}));
		return context.finalizeLoadedRuntimeConfig(cfg);
	} catch (error) {
		if (envBeforeRead) restoreEnvChangesIfUnchanged({
			env: deps.env,
			before: envBeforeRead,
			after: snapshotEnv(deps.env)
		});
		if (error instanceof DuplicateAgentDirError) {
			deps.logger.error(error.message);
			throw error;
		}
		if (error?.code === "INVALID_CONFIG") throw error;
		deps.logger.error(`Failed to read config at ${configPath}: ${formatErrorMessage(error)}`);
		throw error;
	}
}
//#endregion
//#region src/config/io.recovery.ts
function findJsonRootSuffix(raw, json5) {
	if (/^\s*(?:\{|\[)/.test(raw)) return null;
	let offset = 0;
	while (offset < raw.length) {
		const nextNewline = raw.indexOf("\n", offset);
		const lineEnd = nextNewline === -1 ? raw.length : nextNewline + 1;
		const line = raw.slice(offset, lineEnd);
		if (/^\s*(?:\{|\[)/.test(line)) {
			const candidate = raw.slice(offset);
			const parsed = parseConfigJson5(candidate, json5);
			return parsed.ok ? {
				raw: candidate,
				parsed: parsed.parsed
			} : null;
		}
		offset = lineEnd;
	}
	return null;
}
function warnOnConfigPermissionHardeningFailure(params) {
	const message = params.error instanceof Error ? params.error.message : String(params.error);
	params.context.deps.logger.warn(`Config permission hardening failed (${params.detail}): ${params.context.configPath}: ${message}`);
}
async function persistPrefixedConfigRecovery(params) {
	const { context } = params;
	const observedAt = (/* @__PURE__ */ new Date()).toISOString();
	const clobberedPath = await persistBoundedClobberedConfigSnapshot({
		deps: context.deps,
		configPath: context.configPath,
		raw: params.originalRaw,
		observedAt
	});
	await context.deps.fs.promises.writeFile(context.configPath, params.recoveredRaw, {
		encoding: "utf-8",
		mode: 384
	});
	await context.deps.fs.promises.chmod?.(context.configPath, 384).catch((error) => {
		warnOnConfigPermissionHardeningFailure({
			context,
			detail: "prefix recovery",
			error
		});
	});
	context.deps.logger.warn(`Config auto-stripped non-JSON prefix: ${context.configPath}` + (clobberedPath ? ` (original saved as ${clobberedPath})` : ""));
}
async function recoverConfigFromJsonRootSuffixWithContext(context, snapshot) {
	if (!snapshot.exists || snapshot.valid || typeof snapshot.raw !== "string") return false;
	const suffixRecovery = findJsonRootSuffix(snapshot.raw, context.deps.json5);
	if (!suffixRecovery) return false;
	let resolved;
	try {
		resolved = resolveConfigIncludesForRead(suffixRecovery.parsed, context.configPath, context.deps);
	} catch {
		return false;
	}
	const resolution = resolveConfigForRead(resolved, context.deps.env, context.deps.lowerPrecedenceEnv);
	if (!validateConfigObjectWithPlugins(resolution.resolvedConfigRaw, {
		...context.pathResolution,
		sourceRaw: suffixRecovery.parsed
	}).ok) return false;
	await persistPrefixedConfigRecovery({
		context,
		originalRaw: snapshot.raw,
		recoveredRaw: suffixRecovery.raw
	});
	return true;
}
//#endregion
//#region src/config/io.snapshot.ts
function listResolvedIncludePaths(includeFilePathsForWatch) {
	return [...includeFilePathsForWatch].toSorted();
}
async function readConfigFileSnapshotInternal(context, options = {}) {
	const { deps, configPath, pathResolution } = context;
	maybeLoadDotEnvForConfig(deps.env);
	const envBeforeRead = snapshotEnv(deps.env);
	if (!deps.fs.existsSync(configPath)) {
		const migrated = migratePersistedImplicitMainRoster({});
		const config = coerceConfig(migrated.config);
		const metadata = context.createValidationPluginMetadataSnapshotLoader({
			effectiveConfigRaw: config,
			env: deps.env,
			allowCurrentPluginMetadata: options.allowCurrentPluginMetadata
		});
		const coreOnly = context.options.pluginValidation === "core-only";
		const legacyIssues = [];
		return await finalizeReadConfigSnapshotInternalResult(deps, {
			snapshot: createConfigFileSnapshot({
				path: configPath,
				exists: false,
				raw: null,
				parsed: {},
				sourceConfig: config,
				valid: true,
				runtimeConfig: materializeRuntimeConfig(config, {
					...pathResolution,
					...coreOnly ? { manifestRegistry: { plugins: [] } } : { loadManifestRegistry: () => metadata.load(config).manifestRegistry }
				}),
				hash: hashConfigRaw(null),
				issues: [],
				warnings: [],
				legacyIssues
			}),
			pluginMetadataSnapshot: metadata.getSnapshot()
		});
	}
	let fallbackRaw = null;
	let fallbackParsed = {};
	let fallbackSourceConfig = {};
	let fallbackHash = hashConfigRaw(null);
	let fallbackEnvSnapshotForRestore;
	const includeFileHashesForWrite = {};
	const includeFileTargetsForWrite = {};
	const includeFilePathsForWatch = /* @__PURE__ */ new Set();
	const includeProvenance = [];
	let agentRosterIncludeOwned = false;
	let bindingsIncludeOwned = false;
	try {
		const raw = await deps.measure("config.snapshot.read.file", () => deps.fs.readFileSync(configPath, "utf-8"));
		const rawHash = await deps.measure("config.snapshot.read.hash", () => hashConfigRaw(raw));
		fallbackRaw = raw;
		fallbackHash = rawHash;
		const parsedRes = await deps.measure("config.snapshot.read.parse", () => parseConfigJson5(raw, deps.json5));
		if (!parsedRes.ok) return await finalizeReadConfigSnapshotInternalResult(deps, { snapshot: createConfigFileSnapshot({
			path: configPath,
			includedPaths: listResolvedIncludePaths(includeFilePathsForWatch),
			exists: true,
			raw,
			parsed: {},
			sourceConfig: {},
			valid: false,
			runtimeConfig: {},
			hash: rawHash,
			issues: [{
				path: "",
				message: `JSON5 parse failed: ${parsedRes.error}`
			}],
			warnings: [],
			legacyIssues: []
		}) });
		const effectiveParsed = parsedRes.parsed;
		fallbackParsed = effectiveParsed;
		fallbackSourceConfig = coerceConfig(effectiveParsed);
		let resolved;
		try {
			resolved = await deps.measure("config.snapshot.read.includes", () => resolveConfigIncludesForRead(effectiveParsed, configPath, deps, includeFileHashesForWrite, includeFileTargetsForWrite, includeFilePathsForWatch, (event) => {
				const { value: _value, ...ownership } = event;
				includeProvenance.push(ownership);
				agentRosterIncludeOwned ||= includeContributionOwnsAgentRoster(event);
				bindingsIncludeOwned ||= includeContributionOwnsBindings(event);
			}));
		} catch (error) {
			const message = error instanceof ConfigIncludeError ? error.message : `Include resolution failed: ${String(error)}`;
			return await finalizeReadConfigSnapshotInternalResult(deps, {
				snapshot: createConfigFileSnapshot({
					path: configPath,
					includedPaths: listResolvedIncludePaths(includeFilePathsForWatch),
					exists: true,
					raw,
					parsed: effectiveParsed,
					sourceConfig: coerceConfig(effectiveParsed),
					valid: false,
					runtimeConfig: coerceConfig(effectiveParsed),
					hash: rawHash,
					issues: [{
						path: "",
						message
					}],
					warnings: [],
					legacyIssues: []
				}),
				includeFileHashesForWrite,
				includeFileTargetsForWrite
			});
		}
		const readResolution = await deps.measure("config.snapshot.read.env", () => resolveConfigForRead(resolved, deps.env, deps.lowerPrecedenceEnv));
		fallbackEnvSnapshotForRestore = readResolution.envSnapshotForRestore;
		const envVarWarnings = readResolution.envWarnings.map((warning) => ({
			path: warning.configPath,
			message: `Missing env var "${warning.varName}" - feature using this value will be unavailable`
		}));
		const contextBudgetMigration = migrateLegacyContextBudgetConfig(readResolution.resolvedConfigRaw);
		const rosterMigration = migratePersistedImplicitMainRoster(contextBudgetMigration.config, {
			env: deps.env,
			homedir: deps.homedir
		});
		envVarWarnings.push(...contextBudgetMigration.changes, ...contextBudgetMigration.warnings, ...rosterMigration.diagnostics.map((message) => ({
			path: "agents.entries",
			message
		})));
		const effectiveConfigRaw = rosterMigration.config;
		const validationConfigRaw = effectiveConfigRaw;
		const snapshotRaw = raw;
		const snapshotParsed = effectiveParsed;
		const snapshotHash = rawHash;
		fallbackSourceConfig = coerceConfig(effectiveConfigRaw);
		const pluginMetadata = context.createValidationPluginMetadataSnapshotLoader({
			effectiveConfigRaw,
			env: deps.env,
			allowCurrentPluginMetadata: options.allowCurrentPluginMetadata
		});
		const validated = await deps.measure("config.snapshot.read.validate", () => validateConfigObjectWithPlugins(validationConfigRaw, {
			...pathResolution,
			pluginValidation: context.options.pluginValidation,
			loadPluginMetadataSnapshot: pluginMetadata.load,
			sourceRaw: effectiveParsed,
			preservedLegacyRootKeys: context.options.preservedLegacyRootKeys
		}));
		if (!validated.ok) {
			const availableSnapshot = pluginMetadata.getSnapshot();
			const collect = () => context.options.pluginValidation === "core-only" ? findLegacyConfigIssues(effectiveConfigRaw, effectiveParsed) : collectInvalidConfigLegacyIssues(effectiveConfigRaw, effectiveParsed);
			const legacyIssues = await deps.measure("config.snapshot.read.legacy-issues", () => availableSnapshot ? withPluginMetadataSnapshotScope(availableSnapshot, collect, {
				config: coerceConfig(effectiveConfigRaw),
				env: deps.env
			}) : collect());
			restoreEnvChangesIfUnchanged({
				env: deps.env,
				before: envBeforeRead,
				after: snapshotEnv(deps.env)
			});
			return await finalizeReadConfigSnapshotInternalResult(deps, {
				snapshot: createConfigFileSnapshot({
					path: configPath,
					includedPaths: listResolvedIncludePaths(includeFilePathsForWatch),
					exists: true,
					raw: snapshotRaw,
					parsed: snapshotParsed,
					includeProvenance,
					agentRosterIncludeOwned,
					bindingsIncludeOwned,
					sourceConfigBeforeMigrations: coerceConfig(readResolution.resolvedConfigRaw),
					sourceConfig: coerceConfig(effectiveConfigRaw),
					valid: false,
					runtimeConfig: coerceConfig(effectiveConfigRaw),
					hash: snapshotHash,
					issues: validated.issues,
					warnings: [...validated.warnings, ...envVarWarnings],
					resolutionFacts: readResolution.resolutionFacts,
					legacyIssues
				}),
				envSnapshotForRestore: readResolution.envSnapshotForRestore,
				includeFileHashesForWrite,
				includeFileTargetsForWrite
			});
		}
		if (!deps.suppressFutureVersionWarning) warnIfConfigFromFuture(validated.config, deps.logger);
		let callerRejectedSuspiciousRecovery = false;
		if (options.recoverSuspicious === true && deps.observe && !options.skipSuspiciousRecovery && !containsConfigIncludeDirective(effectiveParsed)) {
			const allowSuspiciousRecovery = options.allowSuspiciousRecovery;
			let recoveryCandidate = null;
			if ((await deps.measure("config.snapshot.read.recover-suspicious", () => maybeRecoverSuspiciousConfigRead({
				deps,
				configPath,
				raw,
				parsed: effectiveParsed,
				prepareBackup: (backup) => {
					const prepared = context.prepareRecoveryBackupCandidate(backup);
					recoveryCandidate = prepared.ok ? prepared.candidate.config ?? null : null;
					return prepared;
				},
				...allowSuspiciousRecovery ? { allowBackupRecovery: async () => {
					const allowed = recoveryCandidate !== null && await allowSuspiciousRecovery(recoveryCandidate, validated.config);
					callerRejectedSuspiciousRecovery = !allowed;
					return allowed;
				} } : {}
			}))).raw !== raw) {
				restoreEnvChangesIfUnchanged({
					env: deps.env,
					before: envBeforeRead,
					after: snapshotEnv(deps.env)
				});
				return await readConfigFileSnapshotInternal(context, {
					allowCurrentPluginMetadata: options.allowCurrentPluginMetadata,
					recoverSuspicious: options.recoverSuspicious,
					skipSuspiciousRecovery: true
				});
			}
		}
		const snapshotConfig = await deps.measure("config.snapshot.read.materialize", () => materializeRuntimeConfig(validated.config, {
			...pathResolution,
			manifestRegistry: pluginMetadata.getSnapshot()?.manifestRegistry ?? (context.options.pluginValidation === "core-only" ? { plugins: [] } : void 0)
		}));
		return await deps.measure("config.snapshot.read.observe", () => finalizeReadConfigSnapshotInternalResult(deps, {
			snapshot: createConfigFileSnapshot({
				path: configPath,
				includedPaths: listResolvedIncludePaths(includeFilePathsForWatch),
				exists: true,
				raw: snapshotRaw,
				parsed: snapshotParsed,
				includeProvenance,
				agentRosterIncludeOwned,
				bindingsIncludeOwned,
				sourceConfigBeforeMigrations: coerceConfig(readResolution.resolvedConfigRaw),
				sourceConfig: coerceConfig(effectiveConfigRaw),
				valid: true,
				runtimeConfig: snapshotConfig,
				hash: snapshotHash,
				issues: [],
				warnings: [...validated.warnings, ...envVarWarnings],
				resolutionFacts: readResolution.resolutionFacts,
				legacyIssues: []
			}),
			envSnapshotForRestore: readResolution.envSnapshotForRestore,
			includeFileHashesForWrite,
			includeFileTargetsForWrite,
			pluginMetadataSnapshot: pluginMetadata.getSnapshot()
		}, { observe: !callerRejectedSuspiciousRecovery }));
	} catch (error) {
		const nodeError = error;
		let message;
		if (nodeError?.code === "EACCES") {
			const uid = process.getuid?.();
			const uidHint = typeof uid === "number" ? String(uid) : "$(id -u)";
			message = [
				`read failed: ${String(error)}`,
				"",
				"Config file is not readable by the current process. If running in a container",
				"or 1-click deployment, fix ownership with:",
				`  chown ${uidHint} "${configPath}"`,
				"Then restart the gateway."
			].join("\n");
			deps.logger.error(message);
		} else message = `read failed: ${String(error)}`;
		return await finalizeReadConfigSnapshotInternalResult(deps, {
			snapshot: createConfigFileSnapshot({
				path: configPath,
				includedPaths: listResolvedIncludePaths(includeFilePathsForWatch),
				exists: true,
				raw: fallbackRaw,
				parsed: fallbackParsed,
				sourceConfig: fallbackSourceConfig,
				valid: false,
				runtimeConfig: fallbackSourceConfig,
				hash: fallbackHash,
				...fallbackRaw === null ? { readError: { code: nodeError?.code ?? null } } : {},
				issues: [{
					path: "",
					message
				}],
				warnings: [],
				legacyIssues: []
			}),
			envSnapshotForRestore: fallbackEnvSnapshotForRestore,
			includeFileHashesForWrite,
			includeFileTargetsForWrite
		});
	}
}
async function readConfigFileSnapshotFromContext(context, options = {}) {
	return (await readConfigFileSnapshotInternal(context, {
		recoverSuspicious: options.recoverSuspicious === true,
		allowSuspiciousRecovery: options.allowSuspiciousRecovery
	})).snapshot;
}
async function readConfigFileSnapshotWithPluginMetadataFromContext(context, options = {}) {
	const result = await readConfigFileSnapshotInternal(context, {
		allowCurrentPluginMetadata: options.allowCurrentPluginMetadata,
		recoverSuspicious: options.recoverSuspicious === true,
		allowSuspiciousRecovery: options.allowSuspiciousRecovery
	});
	let pluginMetadataSnapshot = result.pluginMetadataSnapshot;
	if (!pluginMetadataSnapshot && result.snapshot.valid) {
		const pluginMetadata = context.createValidationPluginMetadataSnapshotLoader({
			effectiveConfigRaw: result.snapshot.sourceConfig,
			env: context.deps.env,
			allowCurrentPluginMetadata: options.allowCurrentPluginMetadata
		});
		pluginMetadata.load(result.snapshot.sourceConfig);
		pluginMetadataSnapshot = pluginMetadata.getSnapshot();
	}
	return {
		snapshot: result.snapshot,
		...pluginMetadataSnapshot ? { pluginMetadataSnapshot } : {}
	};
}
async function readConfigFileSnapshotForWriteFromContext(context) {
	const assertConfigPathForWrite = () => {
		if (resolveConfigPathForDeps(context.deps) !== context.configPath) throw new ConfigMutationConflictError("config path changed since last load", { retryable: false });
	};
	assertConfigPathForWrite();
	const result = await readConfigFileSnapshotInternal(context);
	assertConfigPathForWrite();
	return {
		snapshot: result.snapshot,
		writeOptions: {
			assertConfigPathForWrite,
			basePluginMetadataSnapshot: result.pluginMetadataSnapshot,
			envSnapshotForRestore: result.envSnapshotForRestore,
			expectedConfigPath: context.configPath,
			ownedConfigPathForWrite: context.configPath,
			includeFileHashesForWrite: result.includeFileHashesForWrite,
			includeFileTargetsForWrite: result.includeFileTargetsForWrite,
			unsetPaths: resolveManagedUnsetPathsForWrite(void 0)
		}
	};
}
async function readBestEffortConfigSnapshotFromContext(context) {
	const result = await readConfigFileSnapshotInternal(context);
	if (!result.snapshot.valid) return {
		config: result.snapshot.config,
		sourceConfig: result.snapshot.sourceConfig,
		configDiagnostics: {
			path: result.snapshot.path,
			issues: result.snapshot.issues
		}
	};
	return {
		config: context.finalizeLoadedRuntimeConfig(result.snapshot.config),
		sourceConfig: result.snapshot.sourceConfig,
		configDiagnostics: null
	};
}
async function readSourceConfigBestEffortFromContext(context) {
	const { deps, configPath } = context;
	maybeLoadDotEnvForConfig(deps.env);
	if (!deps.fs.existsSync(configPath)) return {};
	try {
		const raw = deps.fs.readFileSync(configPath, "utf-8");
		const parsed = parseConfigJson5(raw, deps.json5);
		if (!parsed.ok) {
			deps.logger.warn(`Config (${configPath}): best-effort read ignored unparseable config: ${parsed.error}`);
			return {};
		}
		let resolved;
		try {
			resolved = resolveConfigIncludesForRead(parsed.parsed, configPath, deps);
		} catch (err) {
			deps.logger.warn(`Config (${configPath}): best-effort read skipped $include resolution: ${formatErrorMessage(err)}`);
			return coerceConfig(parsed.parsed);
		}
		const resolution = resolveConfigForRead(resolved, deps.env, deps.lowerPrecedenceEnv);
		return coerceConfig(resolution.resolvedConfigRaw);
	} catch (err) {
		deps.logger.warn(`Config (${configPath}): best-effort read failed: ${formatErrorMessage(err)}`);
		return {};
	}
}
//#endregion
//#region src/config/io.factory.ts
function createConfigIO(options = {}) {
	const context = createConfigIoContext(options);
	const readInternal = () => readConfigFileSnapshotInternal(context);
	return {
		configPath: context.configPath,
		env: context.deps.env,
		logger: context.deps.logger,
		loadConfig: (loadOptions) => loadConfigFromContext(context, loadOptions),
		readBestEffortConfig: async () => (await readBestEffortConfigSnapshotFromContext(context)).config,
		readBestEffortConfigSnapshot: () => readBestEffortConfigSnapshotFromContext(context),
		readSourceConfigBestEffort: () => readSourceConfigBestEffortFromContext(context),
		readConfigFileSnapshot: (readOptions = {}) => readConfigFileSnapshotFromContext(context, readOptions),
		readConfigFileSnapshotWithPluginMetadata: (readOptions = {}) => readConfigFileSnapshotWithPluginMetadataFromContext(context, readOptions),
		readConfigFileSnapshotForWrite: () => readConfigFileSnapshotForWriteFromContext(context),
		promoteConfigSnapshotToLastKnownGood: (snapshot) => promoteConfigSnapshotToLastKnownGoodCore({
			deps: context.deps,
			snapshot,
			logger: context.deps.logger
		}),
		recoverConfigFromLastKnownGood: (params) => recoverConfigFromLastKnownGoodCore({
			deps: context.deps,
			snapshot: params.snapshot,
			reason: params.reason,
			prepareCandidate: context.prepareRecoveryBackupCandidate
		}),
		recoverConfigFromJsonRootSuffix: (snapshot) => recoverConfigFromJsonRootSuffixWithContext(context, snapshot),
		writeConfigFile: async (config, writeOptions = {}) => {
			const { writeConfigFileFromContext } = await import("./io.write-BnSFTfNH.js");
			return writeConfigFileFromContext(context, config, writeOptions, readInternal);
		}
	};
}
//#endregion
//#region src/config/runtime-write-application.ts
const runtimeConfigWriteApplications = /* @__PURE__ */ new WeakMap();
/** Creates a single-owner receipt for one persisted config write. */
function createRuntimeConfigWriteApplication(runTransaction) {
	let claimed = false;
	const result = createDeferredCore();
	return {
		result: result.promise,
		get claimed() {
			return claimed;
		},
		claim: () => {
			if (claimed) return null;
			claimed = true;
			const claim = {
				settle: (status) => {
					delete claim.runTransaction;
					result.resolve(status);
				},
				...runTransaction ? { runTransaction } : {}
			};
			return claim;
		}
	};
}
/** Attaches a private application receipt without changing the config notification contract. */
function attachRuntimeConfigWriteApplication(target, application) {
	if (application) runtimeConfigWriteApplications.set(target, application);
	return target;
}
/** Copies a private application receipt when rebuilding an internal write carrier. */
function copyRuntimeConfigWriteApplication(source, target) {
	return attachRuntimeConfigWriteApplication(target, source ? runtimeConfigWriteApplications.get(source) : void 0);
}
/** Returns the private application receipt attached to a write or notification. */
function getRuntimeConfigWriteApplication(target) {
	return runtimeConfigWriteApplications.get(target);
}
//#endregion
//#region src/config/io.runtime.ts
function clearConfigCache() {}
function registerConfigWriteListener(listener, options = {}) {
	const unregisterOwner = options.ownsRuntimeActivationFor ? registerManagedRuntimeConfigWriteOwner(options.ownsRuntimeActivationFor, options.preCommitRuntimePreflight) : void 0;
	const unregisterListener = registerRuntimeConfigWriteListener((event) => {
		const { preparedCandidate: _preparedCandidate, preparedCandidatesByOwner: _preparedCandidatesByOwner, ...baseEvent } = event;
		const preparedCandidate = unregisterOwner ? event.preparedCandidatesByOwner?.get(unregisterOwner.ownerId) : void 0;
		listener(copyRuntimeConfigWriteApplication(event, {
			...baseEvent,
			...preparedCandidate ? { preparedCandidate } : {}
		}));
	});
	return () => {
		unregisterListener();
		unregisterOwner?.();
	};
}
function loadConfig(options) {
	const loadFresh = () => createConfigIO({
		...options?.skipPluginValidation ? { pluginValidation: "skip" } : {},
		...options?.skipShellEnvFallback ? { shellEnvFallback: "defer" } : {}
	}).loadConfig();
	return options?.pin === false ? loadFresh() : loadPinnedRuntimeConfig(loadFresh);
}
function getRuntimeConfig(options) {
	return loadConfig(options);
}
async function readBestEffortConfig(options) {
	return await createConfigIO({
		...options?.isolateEnv ? { env: cloneEnvWithPlatformSemantics(process.env) } : {},
		...options?.observe === false ? { observe: false } : {},
		pluginValidation: options?.pluginValidation ?? (options?.skipPluginValidation ? "skip" : void 0)
	}).readBestEffortConfig();
}
async function readBestEffortConfigSnapshot(options) {
	return await createConfigIO({
		...options?.observe === false ? { observe: false } : {},
		...options?.skipPluginValidation ? { pluginValidation: "skip" } : {}
	}).readBestEffortConfigSnapshot();
}
async function readSourceConfigBestEffort() {
	return await createConfigIO().readSourceConfigBestEffort();
}
async function readConfigFileSnapshot(options = {}) {
	const pluginValidation = options.pluginValidation ?? (options.skipPluginValidation ? "skip" : void 0);
	return await createConfigIO({
		...options.measure ? { measure: options.measure } : {},
		...options.observe === false ? { observe: false } : {},
		...options.isolateEnv ? { env: cloneEnvWithPlatformSemantics(process.env) } : {},
		...options.lowerPrecedenceEnv ? { lowerPrecedenceEnv: options.lowerPrecedenceEnv } : {},
		...pluginValidation ? { pluginValidation } : {},
		...options.suppressFutureVersionWarning ? { suppressFutureVersionWarning: true } : {},
		...options.preservedLegacyRootKeys ? { preservedLegacyRootKeys: options.preservedLegacyRootKeys } : {}
	}).readConfigFileSnapshot({
		recoverSuspicious: options.recoverSuspicious === true,
		allowSuspiciousRecovery: options.allowSuspiciousRecovery
	});
}
async function readConfigFileSnapshotWithPluginMetadata(options) {
	return await createConfigIO({
		...options?.measure ? { measure: options.measure } : {},
		...options?.observe === false ? { observe: false } : {},
		...options?.isolateEnv ? { env: cloneEnvWithPlatformSemantics(process.env) } : {},
		...options?.lowerPrecedenceEnv ? { lowerPrecedenceEnv: options.lowerPrecedenceEnv } : {},
		...options?.skipPluginValidation ? { pluginValidation: "skip" } : {}
	}).readConfigFileSnapshotWithPluginMetadata({
		allowCurrentPluginMetadata: options?.allowCurrentPluginMetadata,
		recoverSuspicious: options?.recoverSuspicious === true,
		allowSuspiciousRecovery: options?.allowSuspiciousRecovery
	});
}
async function promoteConfigSnapshotToLastKnownGood(snapshot) {
	return await createConfigIO().promoteConfigSnapshotToLastKnownGood(snapshot);
}
async function recoverConfigFromLastKnownGood(params) {
	return await createConfigIO().recoverConfigFromLastKnownGood(params);
}
async function recoverConfigFromJsonRootSuffix(snapshot) {
	return await createConfigIO().recoverConfigFromJsonRootSuffix(snapshot);
}
async function readSourceConfigSnapshot() {
	return await readConfigFileSnapshot();
}
async function readConfigFileSnapshotForRuntimeTransaction(activeSourceConfig) {
	return await createConfigIO({ env: createConfigRuntimeEnvBase(activeSourceConfig, process.env, { preservedKeys: GATEWAY_CONFIG_SELECTION_ENV_KEYS }) }).readConfigFileSnapshot();
}
async function readConfigFileSnapshotForWrite(options) {
	const readOptions = options?.skipPluginValidation ? { pluginValidation: "skip" } : {};
	for (let attempt = 0; attempt < 3; attempt += 1) try {
		const processIo = createConfigIO(readOptions);
		const result = await (hasManagedRuntimeConfigWriteOwner(processIo.configPath) ? createConfigIO({
			...readOptions,
			env: createManagedRuntimeEnvBase()
		}) : processIo).readConfigFileSnapshotForWrite();
		result.writeOptions.assertConfigPathForWrite?.();
		return result;
	} catch (error) {
		if (!(error instanceof ConfigMutationConflictError) || error.retryable || attempt === 2) throw error;
	}
	throw new Error("unreachable");
}
async function readSourceConfigSnapshotForWrite() {
	return await readConfigFileSnapshotForWrite();
}
function pruneUnauthoredRuntimeDeletions(patch, source, candidate) {
	if (!isRecord(patch) || source !== void 0 && !isRecord(source) || isRecord(candidate) && Object.keys(candidate).length === 0) return;
	const sourceRecord = isRecord(source) ? source : void 0;
	const candidateRecord = isRecord(candidate) ? candidate : void 0;
	for (const [key, value] of Object.entries(patch)) {
		const sourceValue = sourceRecord && Object.hasOwn(sourceRecord, key) ? sourceRecord[key] : void 0;
		if (value === null && sourceValue === void 0) {
			delete patch[key];
			continue;
		}
		if (!isRecord(value) || Object.keys(value).length === 0) continue;
		pruneUnauthoredRuntimeDeletions(value, sourceValue, candidateRecord && Object.hasOwn(candidateRecord, key) ? candidateRecord[key] : void 0);
		if (Object.keys(value).length === 0) delete patch[key];
	}
}
async function writeConfigFile(cfg, options = {}) {
	options.assertConfigPathForWrite?.();
	const ioOptions = {
		...options.ownedConfigPathForWrite ? { configPath: options.ownedConfigPathForWrite } : {},
		...options.skipPluginValidation ? { pluginValidation: "skip" } : {},
		...options.preservedLegacyRootKeys ? { preservedLegacyRootKeys: options.preservedLegacyRootKeys } : {}
	};
	const processIo = createConfigIO(ioOptions);
	const deferRuntimeActivation = hasManagedRuntimeConfigWriteOwner(processIo.configPath);
	const io = deferRuntimeActivation ? createConfigIO({
		...ioOptions,
		env: createManagedRuntimeEnvBase()
	}) : processIo;
	assertConfigWriteAllowedInCurrentMode({ configPath: io.configPath });
	let nextCfg = cfg;
	const runtimeConfigSnapshot = getRuntimeConfigSnapshot();
	const runtimeConfigSourceSnapshot = getRuntimeConfigSourceSnapshot();
	const hadRuntimeSnapshot = Boolean(runtimeConfigSnapshot);
	const hadBothSnapshots = Boolean(runtimeConfigSnapshot && runtimeConfigSourceSnapshot);
	if (hadBothSnapshots) {
		const runtimePatch = createMergePatch(runtimeConfigSnapshot, cfg);
		pruneUnauthoredRuntimeDeletions(runtimePatch, runtimeConfigSourceSnapshot, cfg);
		nextCfg = coerceConfig(applyMergePatch(runtimeConfigSourceSnapshot, runtimePatch));
	}
	const baseSnapshotRead = options.baseSnapshot ? {
		snapshot: options.baseSnapshot,
		pluginMetadataSnapshot: options.basePluginMetadataSnapshot
	} : await io.readConfigFileSnapshotWithPluginMetadata();
	const baseSnapshot = baseSnapshotRead.snapshot;
	if (deferRuntimeActivation) replaceEnvSnapshot(io.env, createManagedRuntimeEnvBase());
	let runtimePreflightResult;
	let managedPreparedCandidates = /* @__PURE__ */ new Map();
	const writeResult = await io.writeConfigFile(nextCfg, {
		baseSnapshot,
		basePluginMetadataSnapshot: baseSnapshotRead.pluginMetadataSnapshot,
		assertConfigPathForWrite: options.assertConfigPathForWrite,
		envSnapshotForRestore: resolveWriteEnvSnapshotForPath({
			actualConfigPath: io.configPath,
			expectedConfigPath: options.expectedConfigPath,
			envSnapshotForRestore: options.envSnapshotForRestore
		}),
		unsetPaths: resolveManagedUnsetPathsForWrite(options.unsetPaths),
		explicitSetPaths: options.explicitSetPaths,
		explicitSetValueSource: options.explicitSetPaths ? options.explicitSetValueSource ?? cfg : void 0,
		persistCanonicalAgentRoster: options.persistCanonicalAgentRoster,
		allowedAgentRosterRemovals: options.allowedAgentRosterRemovals,
		allowIncludeAncestorExplicitSetPaths: options.allowIncludeAncestorExplicitSetPaths,
		afterWrite: options.afterWrite,
		allowDestructiveWrite: options.allowDestructiveWrite,
		allowConfigSizeDrop: options.allowConfigSizeDrop,
		skipRuntimeSnapshotRefresh: options.skipRuntimeSnapshotRefresh,
		skipOutputLogs: options.skipOutputLogs,
		skipPluginValidation: options.skipPluginValidation,
		preservedLegacyRootKeys: options.preservedLegacyRootKeys,
		lastTouchedVersionOverride: options.lastTouchedVersionOverride,
		beforeCommit: options.beforeCommit,
		preCommitRuntimePreflight: async (sourceConfig) => {
			nextCfg = sourceConfig;
			if (deferRuntimeActivation) managedPreparedCandidates = await preflightManagedRuntimeConfigWrite(io.configPath, sourceConfig, options.runtimeRefresh);
			else runtimePreflightResult = await preflightRuntimeSnapshotWrite({
				nextSourceConfig: sourceConfig,
				refreshOptions: options.runtimeRefresh,
				formatRefreshError: (error) => formatErrorMessage(error),
				createRefreshError: (detail, cause) => new ConfigRuntimeRefreshError(`Config write blocked before committing ${io.configPath}: active SecretRef resolution failed: ${detail}`, { cause })
			});
			await options.preCommitRuntimePreflight?.(sourceConfig);
		}
	});
	if (options.skipRuntimeSnapshotRefresh && !hadRuntimeSnapshot && !getRuntimeConfigSnapshotRefreshHandler()) return writeResult;
	if (deferRuntimeActivation) replaceEnvSnapshot(io.env, createManagedRuntimeEnvBase());
	return await finalizeCommittedConfigWrite({
		io,
		options,
		nextCfg,
		writeResult,
		baseSnapshot,
		hadRuntimeSnapshot,
		hadBothSnapshots,
		deferRuntimeActivation,
		runtimePreflightResult,
		managedPreparedCandidates
	});
}
async function finalizeCommittedConfigWrite(params) {
	const { io, options, writeResult, baseSnapshot, deferRuntimeActivation, managedPreparedCandidates } = params;
	let canonicalSourceConfig = params.nextCfg;
	let canonicalRuntimeConfig = params.nextCfg;
	let envBeforeCanonicalRead = snapshotEnv(io.env);
	let envAfterCanonicalRead;
	let canonicalReadFailure = null;
	try {
		let stableEnvGeneration = !deferRuntimeActivation;
		for (let attempt = 0; attempt < 3; attempt += 1) {
			const baseline = resolveManagedRuntimeEnvBaseline();
			if (deferRuntimeActivation) {
				replaceEnvSnapshot(io.env, createConfigRuntimeEnvBase(baseline.sourceConfig, process.env, { preservedKeys: GATEWAY_CONFIG_SELECTION_ENV_KEYS }));
				envBeforeCanonicalRead = snapshotEnv(io.env);
			}
			const freshSnapshot = await io.readConfigFileSnapshot();
			if (freshSnapshot.exists && freshSnapshot.valid) {
				canonicalSourceConfig = freshSnapshot.sourceConfig;
				canonicalRuntimeConfig = freshSnapshot.config;
			} else {
				const issueSummary = formatConfigIssueSummary(freshSnapshot.issues);
				io.logger.warn(`Config (${io.configPath}): canonical reread after write was ${freshSnapshot.exists ? "invalid" : "missing"}; runtime keeps the written config${issueSummary ? `: ${issueSummary}` : ""}`);
			}
			if (!deferRuntimeActivation || resolveManagedRuntimeEnvBaseline().generation === baseline.generation) {
				stableEnvGeneration = true;
				break;
			}
		}
		if (!stableEnvGeneration) canonicalReadFailure = new ConfigRuntimeRefreshError(`Config was written to ${io.configPath}, but the active config environment changed during every canonical reread`);
	} catch (error) {
		canonicalReadFailure = new ConfigRuntimeRefreshError(`Config was written to ${io.configPath}, but the canonical reread failed: ${formatErrorMessage(error)}`, { cause: error });
	} finally {
		envAfterCanonicalRead = snapshotEnv(io.env);
	}
	const notifyCommittedWrite = () => {
		const currentRuntimeConfig = getRuntimeConfigSnapshot();
		const notificationRuntimeConfig = deferRuntimeActivation ? canonicalRuntimeConfig : currentRuntimeConfig;
		if (!notificationRuntimeConfig) return;
		const notificationPreparedCandidates = new Map([...managedPreparedCandidates].map(([ownerId, candidate]) => [ownerId, {
			...candidate,
			runtimeConfig: candidate.reapplyRuntimeOverlays?.(canonicalRuntimeConfig) ?? candidate.runtimeConfig,
			compareConfig: candidate.reapplyCompareOverlays?.(canonicalSourceConfig) ?? candidate.compareConfig
		}]));
		notifyRuntimeConfigWriteListeners(attachRuntimeConfigWriteApplication(createRuntimeConfigWriteNotification({
			configPath: io.configPath,
			sourceConfig: canonicalSourceConfig,
			runtimeConfig: notificationRuntimeConfig,
			persistedHash: writeResult.persistedHash,
			afterWrite: options.afterWrite,
			runtimeRefresh: options.runtimeRefresh,
			...notificationPreparedCandidates.size > 0 ? { preparedCandidatesByOwner: notificationPreparedCandidates } : {}
		}), getRuntimeConfigWriteApplication(options)));
	};
	try {
		if (canonicalReadFailure) throw canonicalReadFailure;
		options.assertConfigPathForWrite?.();
		await finalizeRuntimeSnapshotWrite({
			nextSourceConfig: canonicalSourceConfig,
			refreshOptions: options.runtimeRefresh,
			hadRuntimeSnapshot: params.hadRuntimeSnapshot,
			hadBothSnapshots: params.hadBothSnapshots,
			loadFreshConfig: () => io.loadConfig(),
			notifyCommittedWrite,
			formatRefreshError: (error) => formatErrorMessage(error),
			preflightResult: params.runtimePreflightResult,
			deferRuntimeActivation,
			createRefreshError: (detail, cause) => new ConfigRuntimeRefreshError(`Config was written to ${io.configPath}, but runtime snapshot refresh failed: ${detail}`, { cause })
		});
	} catch (error) {
		try {
			if (await rollbackConfigFileWriteIfUnchanged({
				configPath: io.configPath,
				previousSnapshot: baseSnapshot,
				committedHash: writeResult.persistedHash,
				fsModule: fs
			})) {
				restoreEnvChangesIfUnchanged({
					env: io.env,
					before: envBeforeCanonicalRead,
					after: envAfterCanonicalRead
				});
				writeResult[configWritePostCommitRollback]?.();
			}
		} catch (rollbackError) {
			throw new ConfigRuntimeRefreshError(`${formatErrorMessage(error)} Rollback failed: ${formatErrorMessage(rollbackError)}`, { cause: error });
		}
		throw error;
	}
	return writeResult;
}
//#endregion
export { applyChannelDoctorCompatibilityMigrations as A, applyConfigOverrides as C, setConfigOverride as D, resetConfigOverrides as E, resolveOwnerPromptNumbers as F, containsAuthoredInclude as M, isSingleTopLevelIncludeMigration as N, unsetConfigOverride as O, resolveOwnerDisplaySetting as P, createConfigIO as S, getConfigOverrides as T, writeConfigFile as _, readBestEffortConfig as a, createRuntimeConfigWriteApplication as b, readConfigFileSnapshotForRuntimeTransaction as c, readSourceConfigBestEffort as d, readSourceConfigSnapshot as f, registerConfigWriteListener as g, recoverConfigFromLastKnownGood as h, promoteConfigSnapshotToLastKnownGood as i, classifyOtelGrpcMigrationOwnership as j, applyLegacyDoctorMigrations as k, readConfigFileSnapshotForWrite as l, recoverConfigFromJsonRootSuffix as m, getRuntimeConfig as n, readBestEffortConfigSnapshot as o, readSourceConfigSnapshotForWrite as p, loadConfig as r, readConfigFileSnapshot as s, clearConfigCache as t, readConfigFileSnapshotWithPluginMetadata as u, attachRuntimeConfigWriteApplication as v, captureConfigOverrideApplier as w, getRuntimeConfigWriteApplication as x, copyRuntimeConfigWriteApplication as y };