import { t as __exportAll } from "./rolldown-runtime-Cbj13DAv.js";
import { Gu as resolveDefaultAgentId, Pf as normalizePluginsConfig, Wu as resolveAgentWorkspaceDir, Xt as loadConfig, p as getActivePluginRegistry } from "./env-Dlz8aQHP.js";
import { B as colorize, C as shortenHomeInString, H as theme, I as setVerbose, V as isRich, w as shortenHomePath } from "./agent-paths-DUHGyU1s.js";
import { A as defaultRuntime, Ct as resolveStateDir, _ as resolveSessionTranscriptsDirForAgent, x as formatErrorMessage } from "./entry.js";
import { n as resolveMemoryBackendConfig, t as getMemorySearchManager } from "./memory-BpNgGSAl.js";
import { c as normalizeExtraMemoryPaths, s as listMemoryFiles } from "./internal-BdgFqK0w.js";
import { n as resolveHookConfig } from "./config-DfviqDy5.js";
import { t as formatDocsLink } from "./links-CPltkiov.js";
import { r as withManager } from "./cli-utils-XevKf-tr.js";
import { t as formatHelpExamples } from "./help-format-D7mxVfC9.js";
import { n as withProgress, r as withProgressTotals } from "./progress-BhMUiH4f.js";
import os from "node:os";
import path from "node:path";
import fs from "node:fs";
import fs$1 from "node:fs/promises";
import crypto from "node:crypto";

//#region src/memory/repair-execution-policy.ts
const EXECUTABLE_ACTIONS$1 = new Set([
	"create_file",
	"create_directory",
	"rebuild_index"
]);
const ALLOWED_SURFACES = new Set(["cli", "dashboard-admin"]);
const TARGET_REQUIRED_ACTIONS = new Set([
	"create_file",
	"create_directory",
	"rebuild_index"
]);
function createMemoryRepairPreviewFingerprint(preview) {
	const stable = {
		agentId: preview.agentId,
		dryRun: preview.dryRun,
		proposals: preview.proposals.map((proposal) => ({
			id: proposal.id,
			area: proposal.area,
			sourceCode: proposal.sourceCode,
			action: proposal.action,
			targetPath: proposal.targetPath ?? null,
			supported: proposal.supported,
			blockReason: proposal.blockReason ?? null
		}))
	};
	return crypto.createHash("sha256").update(JSON.stringify(stable)).digest("hex");
}
function evaluateMemoryRepairExecutionPolicy(input) {
	const previewFingerprint = createMemoryRepairPreviewFingerprint(input.preview);
	const globalReasons = collectGlobalDenyReasons(input, previewFingerprint);
	const selected = selectProposals(input.preview, input.proposalIds);
	const allowed = [];
	const blocked = [];
	for (const selection of selected) {
		if (!selection.proposal) {
			blocked.push({
				id: selection.id,
				reasons: [...globalReasons, "proposal not found in preview"]
			});
			continue;
		}
		const proposalReasons = collectProposalDenyReasons(selection.proposal, input.allowedRoots);
		const reasons = [...globalReasons, ...proposalReasons];
		if (reasons.length > 0) {
			blocked.push({
				id: selection.proposal.id,
				action: selection.proposal.action,
				reasons
			});
			continue;
		}
		allowed.push({
			id: selection.proposal.id,
			action: selection.proposal.action,
			...selection.proposal.targetPath ? { targetPath: path.resolve(selection.proposal.targetPath) } : {}
		});
	}
	return {
		ok: allowed.length > 0 && blocked.length === 0 && globalReasons.length === 0,
		previewFingerprint,
		allowed,
		blocked,
		reasons: globalReasons
	};
}
function collectGlobalDenyReasons(input, previewFingerprint) {
	const reasons = [];
	if (!ALLOWED_SURFACES.has(input.surface)) reasons.push("memory repair execution is unavailable from this surface");
	if (input.operatorScope !== "operator.admin") reasons.push("memory repair execution requires operator.admin");
	if (input.confirmation === "none") reasons.push("memory repair execution requires explicit confirmation");
	if (input.plan.backup !== "planned") reasons.push("memory repair execution requires a backup plan");
	if (input.plan.audit !== "planned") reasons.push("memory repair execution requires an audit record plan");
	if (input.plan.rollback === "none") reasons.push("memory repair execution requires a rollback or manual recovery plan");
	if (!input.allowedRoots.length) reasons.push("memory repair execution requires allowed workspace/state roots");
	if (input.acceptedPreviewFingerprint !== previewFingerprint) reasons.push("memory repair preview fingerprint was not accepted");
	return reasons;
}
function collectProposalDenyReasons(proposal, allowedRoots) {
	const reasons = [];
	if (!proposal.supported) reasons.push(proposal.blockReason ?? "proposal is not supported by repair preview");
	if (!EXECUTABLE_ACTIONS$1.has(proposal.action)) reasons.push("proposal action is review-only and cannot be executed automatically");
	if (TARGET_REQUIRED_ACTIONS.has(proposal.action) && !proposal.targetPath) reasons.push("proposal action requires a target path");
	if (proposal.targetPath) {
		if (proposal.targetPath.startsWith("[redacted:")) reasons.push("proposal target path is redacted");
		else if (!isPathWithinAnyRoot$1(proposal.targetPath, allowedRoots)) reasons.push("proposal target path is outside allowed roots");
	}
	return reasons;
}
function selectProposals(preview, proposalIds) {
	if (!proposalIds?.length) return preview.proposals.map((proposal) => ({
		id: proposal.id,
		proposal
	}));
	const byId = new Map(preview.proposals.map((proposal) => [proposal.id, proposal]));
	return proposalIds.map((id) => ({
		id,
		proposal: byId.get(id)
	}));
}
function isPathWithinAnyRoot$1(candidate, roots) {
	const resolvedCandidate = path.resolve(candidate);
	return roots.some((root) => {
		const resolvedRoot = path.resolve(root);
		const relative = path.relative(resolvedRoot, resolvedCandidate);
		return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
	});
}

//#endregion
//#region src/memory/repair-audit-plan.ts
const EXECUTION_ID_PATTERN = /^[A-Za-z0-9._-]{8,128}$/;
function createMemoryRepairAuditPlan(input) {
	const reasons = collectAuditPlanDenyReasons(input);
	if (reasons.length > 0) return {
		ok: false,
		reasons
	};
	const normalizedExecutionId = input.executionId.trim();
	const allowedRoots = input.policyInput.allowedRoots.map((root) => path.resolve(root));
	const backupRoot = path.resolve(input.backupRoot);
	const auditRoot = path.resolve(input.auditRoot);
	const selectedProposalIds = input.policyDecision.allowed.map((entry) => entry.id);
	const snapshotRoot = backupRoot;
	const entries = input.policyDecision.allowed.map((entry) => {
		if (!entry.targetPath) throw new Error(`memory repair proposal ${entry.id} target path missing after validation`);
		const targetPath = path.resolve(entry.targetPath);
		const snapshotPath = path.join(snapshotRoot, `${normalizedExecutionId}-${sanitizePathSegment(entry.id)}.snapshot`);
		return {
			proposalId: entry.id,
			action: entry.action,
			targetPath,
			snapshotPath,
			strategy: "snapshot-target-before-write"
		};
	});
	const plan = {
		schemaVersion: 1,
		kind: "doctor.memory.repair.execution.audit-plan",
		executionId: normalizedExecutionId,
		createdAt: input.createdAt,
		agentId: input.policyInput.preview.agentId,
		surface: input.policyInput.surface,
		operatorScope: input.policyInput.operatorScope,
		confirmation: input.policyInput.confirmation,
		previewFingerprint: input.policyDecision.previewFingerprint,
		acceptedPreviewFingerprint: input.policyInput.acceptedPreviewFingerprint ?? "",
		selectedProposalIds,
		allowedRoots,
		dryRun: true,
		noWritePerformed: true,
		transcriptAccess: "none",
		bodyAccess: "none",
		backup: {
			required: true,
			root: backupRoot,
			manifestPath: path.join(snapshotRoot, `${normalizedExecutionId}.manifest.json`),
			entries
		},
		audit: {
			required: true,
			root: auditRoot,
			recordPath: path.join(auditRoot, `${normalizedExecutionId}.jsonl`),
			event: "planned"
		},
		rollback: {
			required: true,
			mode: input.policyInput.plan.rollback,
			entries: entries.map((entry) => ({
				proposalId: entry.proposalId,
				action: entry.action,
				targetPath: entry.targetPath,
				snapshotPath: entry.snapshotPath,
				strategy: "restore-or-remove-to-prewrite-state"
			}))
		}
	};
	return {
		ok: true,
		plan,
		fingerprint: createMemoryRepairAuditPlanFingerprint(plan),
		reasons: []
	};
}
function createMemoryRepairAuditPlanFingerprint(plan) {
	return crypto.createHash("sha256").update(JSON.stringify(plan)).digest("hex");
}
function collectAuditPlanDenyReasons(input) {
	const reasons = [];
	const executionId = input.executionId.trim();
	if (!EXECUTION_ID_PATTERN.test(executionId)) reasons.push("memory repair audit plan requires a safe execution id");
	if (!isIsoDateTime$1(input.createdAt)) reasons.push("memory repair audit plan requires an ISO createdAt timestamp");
	if (!input.policyDecision.ok) reasons.push("memory repair audit plan requires an admitted execution policy decision");
	if (input.policyDecision.blocked.length > 0) reasons.push("memory repair audit plan cannot include blocked proposals");
	if (input.policyDecision.allowed.length === 0) reasons.push("memory repair audit plan requires at least one allowed proposal");
	const previewFingerprint = createMemoryRepairPreviewFingerprint(input.policyInput.preview);
	if (input.policyDecision.previewFingerprint !== previewFingerprint) reasons.push("memory repair audit plan preview fingerprint is stale");
	if (input.policyInput.acceptedPreviewFingerprint !== previewFingerprint) reasons.push("memory repair audit plan requires the accepted preview fingerprint");
	if (input.policyInput.plan.backup !== "planned") reasons.push("memory repair audit plan requires a planned backup");
	if (input.policyInput.plan.audit !== "planned") reasons.push("memory repair audit plan requires a planned audit record");
	if (input.policyInput.plan.rollback === "none") reasons.push("memory repair audit plan requires a rollback or manual recovery mode");
	const allowedRoots = input.policyInput.allowedRoots;
	if (!isSafePlannedPath(input.backupRoot, allowedRoots)) reasons.push("memory repair backup root must stay inside allowed roots");
	if (!isSafePlannedPath(input.auditRoot, allowedRoots)) reasons.push("memory repair audit root must stay inside allowed roots");
	for (const entry of input.policyDecision.allowed) {
		if (!entry.targetPath) {
			reasons.push(`memory repair proposal ${entry.id} requires a target path for audit planning`);
			continue;
		}
		if (!isSafePlannedPath(entry.targetPath, allowedRoots)) reasons.push(`memory repair proposal ${entry.id} target path must stay inside allowed roots`);
	}
	return Array.from(new Set(reasons));
}
function isIsoDateTime$1(value) {
	const parsed = Date.parse(value);
	return Number.isFinite(parsed) && new Date(parsed).toISOString() === value;
}
function isSafePlannedPath(candidate, roots) {
	if (!candidate || candidate.startsWith("[redacted:")) return false;
	const resolvedCandidate = path.resolve(candidate);
	return roots.some((root) => {
		const resolvedRoot = path.resolve(root);
		const relative = path.relative(resolvedRoot, resolvedCandidate);
		return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
	});
}
function sanitizePathSegment(value) {
	return value.replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 96) || "proposal";
}

//#endregion
//#region src/memory/repair-execution-request-contract.ts
const DOCTOR_MEMORY_REPAIR_EXECUTION_METHOD = "doctor.memory.repair.execute";
function evaluateMemoryRepairExecutionRequest(request) {
	const previewFingerprint = createMemoryRepairPreviewFingerprint(request.preview);
	const requestReasons = collectRequestContractDenyReasons(request);
	if (requestReasons.length > 0) return deniedResponse({
		request,
		stage: "request",
		previewFingerprint,
		reasons: requestReasons
	});
	const policyInput = {
		preview: request.preview,
		proposalIds: request.proposalIds,
		acceptedPreviewFingerprint: request.acceptedPreviewFingerprint,
		surface: request.surface,
		operatorScope: request.operatorScope,
		confirmation: request.confirmation,
		plan: request.plan,
		allowedRoots: request.allowedRoots
	};
	const policy = evaluateMemoryRepairExecutionPolicy(policyInput);
	if (!policy.ok) return deniedResponse({
		request,
		stage: "policy",
		previewFingerprint,
		reasons: flattenPolicyReasons(policy),
		policy
	});
	const auditPlan = createMemoryRepairAuditPlan({
		executionId: request.executionId,
		createdAt: request.createdAt,
		policyInput,
		policyDecision: policy,
		backupRoot: request.backupRoot,
		auditRoot: request.auditRoot
	});
	if (!auditPlan.ok || !auditPlan.plan || !auditPlan.fingerprint) return deniedResponse({
		request,
		stage: "audit-plan",
		previewFingerprint,
		reasons: auditPlan.reasons,
		policy
	});
	return {
		schemaVersion: 1,
		kind: "doctor.memory.repair.execution.response",
		method: DOCTOR_MEMORY_REPAIR_EXECUTION_METHOD,
		dryRun: true,
		noWritePerformed: true,
		executionId: request.executionId,
		createdAt: request.createdAt,
		agentId: request.preview.agentId,
		status: "admitted",
		stage: "admitted",
		previewFingerprint,
		selectedProposalIds: policy.allowed.map((entry) => entry.id),
		reasons: [],
		policy,
		auditPlan: auditPlan.plan,
		auditPlanFingerprint: auditPlan.fingerprint
	};
}
function collectRequestContractDenyReasons(request) {
	const reasons = [];
	if (request.schemaVersion !== 1) reasons.push("memory repair execution request schema version is unsupported");
	if (request.kind !== "doctor.memory.repair.execution.request") reasons.push("memory repair execution request kind is unsupported");
	if (request.method !== DOCTOR_MEMORY_REPAIR_EXECUTION_METHOD) reasons.push("memory repair execution request method is unsupported");
	if (!request.dryRun) reasons.push("memory repair execution request contract must be evaluated as a pre-execution dry run");
	if (!Array.isArray(request.proposalIds) || request.proposalIds.length === 0) reasons.push("memory repair execution request requires explicit proposal ids");
	return reasons;
}
function deniedResponse(params) {
	return {
		schemaVersion: 1,
		kind: "doctor.memory.repair.execution.response",
		method: DOCTOR_MEMORY_REPAIR_EXECUTION_METHOD,
		dryRun: true,
		noWritePerformed: true,
		executionId: params.request.executionId,
		createdAt: params.request.createdAt,
		agentId: params.request.preview.agentId,
		status: "denied",
		stage: params.stage,
		previewFingerprint: params.previewFingerprint,
		selectedProposalIds: params.policy?.allowed.map((entry) => entry.id) ?? params.request.proposalIds,
		reasons: params.reasons,
		...params.policy ? { policy: params.policy } : {}
	};
}
function flattenPolicyReasons(policy) {
	return Array.from(new Set([...policy.reasons, ...policy.blocked.flatMap((entry) => entry.reasons)]));
}

//#endregion
//#region src/memory/repair-executor-fs-safety-contract.ts
const UNSAFE_NODE_KINDS = new Set([
	"symlink",
	"fifo",
	"socket",
	"block-device",
	"char-device",
	"unknown"
]);
function evaluateMemoryRepairFsSafety(input) {
	const stateByPath = new Map(input.pathStates.map((state) => [normalizePathKey(state.path), state]));
	const checkedPaths = collectPlannedFsPaths(input.auditPlan).map((planned) => evaluatePlannedPath({
		planned,
		state: stateByPath.get(normalizePathKey(planned.path)),
		allowedRoots: input.auditPlan.allowedRoots
	}));
	const auditReasons = collectAuditPlanFsDenyReasons(input.auditPlan);
	const reasons = Array.from(new Set([...auditReasons, ...checkedPaths.flatMap((entry) => entry.reasons)]));
	return {
		ok: reasons.length === 0,
		safeToOpen: reasons.length === 0,
		dryRun: true,
		noWritePerformed: true,
		checkedPaths,
		reasons
	};
}
function collectPlannedFsPaths(auditPlan) {
	const paths = [
		{
			role: "backup-root",
			path: auditPlan.backup.root,
			expectation: "directory"
		},
		{
			role: "backup-manifest",
			path: auditPlan.backup.manifestPath,
			expectation: "new-file"
		},
		{
			role: "audit-root",
			path: auditPlan.audit.root,
			expectation: "directory"
		},
		{
			role: "audit-record",
			path: auditPlan.audit.recordPath,
			expectation: "new-file"
		}
	];
	for (const entry of auditPlan.backup.entries) {
		paths.push({
			role: "target",
			path: entry.targetPath,
			expectation: "target",
			action: entry.action
		});
		paths.push({
			role: "snapshot",
			path: entry.snapshotPath,
			expectation: "new-file",
			action: entry.action
		});
	}
	return dedupePlannedPaths(paths);
}
function evaluatePlannedPath(params) {
	const reasons = [];
	const { planned, state, allowedRoots } = params;
	if (!isAbsoluteSafePath(planned.path)) reasons.push(`${planned.role} path must be absolute and non-redacted`);
	if (!isPathWithinAnyRoot(planned.path, allowedRoots)) reasons.push(`${planned.role} path is outside allowed roots`);
	if (!state) {
		reasons.push(`${planned.role} path requires read-only file-system metadata`);
		return {
			role: planned.role,
			path: path.resolve(planned.path),
			...planned.action ? { action: planned.action } : {},
			ok: false,
			reasons
		};
	}
	reasons.push(...collectNodeDenyReasons(state, planned.role, allowedRoots));
	reasons.push(...collectExpectationDenyReasons(planned, state, allowedRoots));
	return {
		role: planned.role,
		path: path.resolve(planned.path),
		...planned.action ? { action: planned.action } : {},
		ok: reasons.length === 0,
		reasons: Array.from(new Set(reasons))
	};
}
function collectAuditPlanFsDenyReasons(auditPlan) {
	const reasons = [];
	if (!auditPlan.dryRun || !auditPlan.noWritePerformed) reasons.push("memory repair fs safety contract requires pre-execution dry-run input");
	if (auditPlan.transcriptAccess !== "none" || auditPlan.bodyAccess !== "none") reasons.push("memory repair fs safety requires no transcript or body access");
	if (!auditPlan.allowedRoots.length) reasons.push("memory repair fs safety requires allowed roots");
	return reasons;
}
function collectExpectationDenyReasons(planned, state, allowedRoots) {
	switch (planned.expectation) {
		case "directory": return collectDirectoryExpectationDenyReasons(planned, state, allowedRoots);
		case "new-file": return collectNewFileExpectationDenyReasons(planned, state, allowedRoots);
		case "target": return collectTargetExpectationDenyReasons(planned, state, allowedRoots);
	}
}
function collectDirectoryExpectationDenyReasons(planned, state, allowedRoots) {
	if (state.kind === "directory") return [];
	if (state.kind === "missing") return collectMissingPathParentDenyReasons(planned.role, state, allowedRoots);
	return [`${planned.role} path must be a directory or safely creatable directory`];
}
function collectNewFileExpectationDenyReasons(planned, state, allowedRoots) {
	if (state.kind !== "missing") return [`${planned.role} output path must not already exist`];
	return collectMissingPathParentDenyReasons(planned.role, state, allowedRoots);
}
function collectTargetExpectationDenyReasons(planned, state, allowedRoots) {
	switch (planned.action) {
		case "create_directory":
			if (state.kind === "directory") return [];
			if (state.kind === "missing") return collectMissingPathParentDenyReasons(planned.role, state, allowedRoots);
			return ["target path must be a directory or safely creatable directory"];
		case "create_file":
		case "rebuild_index":
			if (state.kind === "file") return [];
			if (state.kind === "missing") return collectMissingPathParentDenyReasons(planned.role, state, allowedRoots);
			return ["target path must be a file or safely creatable file"];
		default: return ["target action is not executable by the fs safety contract"];
	}
}
function collectNodeDenyReasons(state, role, allowedRoots) {
	const reasons = [];
	if (!isAbsoluteSafePath(state.path)) reasons.push(`${role} metadata path must be absolute and non-redacted`);
	if (UNSAFE_NODE_KINDS.has(state.kind)) reasons.push(`${role} path has unsafe file type: ${state.kind}`);
	if (state.kind === "file" && typeof state.linkCount === "number" && state.linkCount > 1) reasons.push(`${role} path has multiple hard links`);
	if (state.realPath && !isPathWithinAnyRoot(state.realPath, allowedRoots)) reasons.push(`${role} real path is outside allowed roots`);
	return reasons;
}
function collectMissingPathParentDenyReasons(role, state, allowedRoots) {
	const reasons = [];
	if (!state.parent) return [`${role} missing path requires parent metadata`];
	if (!isAbsoluteSafePath(state.parent.path)) reasons.push(`${role} parent path must be absolute and non-redacted`);
	if (state.parent.kind !== "directory") reasons.push(`${role} parent must be an existing directory`);
	if (UNSAFE_NODE_KINDS.has(state.parent.kind)) reasons.push(`${role} parent has unsafe file type: ${state.parent.kind}`);
	if (state.parent.realPath && !isPathWithinAnyRoot(state.parent.realPath, allowedRoots)) reasons.push(`${role} parent real path is outside allowed roots`);
	if (!isPathWithinAnyRoot(state.parent.path, allowedRoots)) reasons.push(`${role} parent path is outside allowed roots`);
	return reasons;
}
function dedupePlannedPaths(paths) {
	const seen = /* @__PURE__ */ new Set();
	const deduped = [];
	for (const entry of paths) {
		const key = `${entry.role}:${normalizePathKey(entry.path)}:${entry.action ?? ""}`;
		if (seen.has(key)) continue;
		seen.add(key);
		deduped.push(entry);
	}
	return deduped;
}
function normalizePathKey(value) {
	return path.resolve(value);
}
function isAbsoluteSafePath(value) {
	return Boolean(value) && path.isAbsolute(value) && !value.startsWith("[redacted:");
}
function isPathWithinAnyRoot(candidate, roots) {
	if (!isAbsoluteSafePath(candidate)) return false;
	const resolvedCandidate = path.resolve(candidate);
	return roots.some((root) => {
		if (!isAbsoluteSafePath(root)) return false;
		const resolvedRoot = path.resolve(root);
		const relative = path.relative(resolvedRoot, resolvedCandidate);
		return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
	});
}

//#endregion
//#region src/memory/repair-executor-gate.ts
function evaluateMemoryRepairExecutorGate(input) {
	const reasons = collectExecutorGateDenyReasons(input);
	return {
		ok: reasons.length === 0,
		kind: "doctor.memory.repair.executor.gate",
		executionId: input.response.executionId,
		agentId: input.response.agentId,
		noWritePerformed: true,
		selectedProposalIds: input.response.selectedProposalIds,
		reasons
	};
}
function collectExecutorGateDenyReasons(input) {
	const reasons = [];
	const { gate, response } = input;
	if (!gate.enabled) reasons.push("memory repair executor gate is disabled");
	if (!gate.writeExecutorRegistered) reasons.push("memory repair write executor is not registered");
	if (!gate.gatewayHandlerRegistered) reasons.push("memory repair gateway handler is not registered");
	if (!gate.cliCommandRegistered && !gate.dashboardActionRegistered) reasons.push("memory repair requires an explicitly registered operator surface");
	if (!gate.allowWrites) reasons.push("memory repair write mode is disabled");
	if (input.operatorScope !== "operator.admin") reasons.push("memory repair executor requires operator.admin");
	if (input.confirmation === "none") reasons.push("memory repair executor requires explicit confirmation");
	if (response.status !== "admitted") reasons.push("memory repair preflight response was not admitted");
	if (!response.dryRun || !response.noWritePerformed) reasons.push("memory repair executor gate requires a dry-run preflight response");
	if (response.selectedProposalIds.length === 0) reasons.push("memory repair executor requires selected proposal ids");
	if (!response.auditPlan || !response.auditPlanFingerprint) reasons.push("memory repair executor requires an accepted audit plan");
	else if (input.acceptedAuditPlanFingerprint !== response.auditPlanFingerprint) reasons.push("memory repair audit plan fingerprint was not accepted");
	return reasons;
}

//#endregion
//#region src/memory/repair-executor-lock-contract.ts
function evaluateMemoryRepairExecutionLockAdmission(input) {
	const requestReasons = collectLockAdmissionDenyReasons(input);
	const workspaceKey = input.workspaceKey ?? createMemoryRepairWorkspaceKey(input.response);
	if (requestReasons.length > 0) return deniedLockDecision(workspaceKey, requestReasons);
	const nowMs = Date.parse(input.now);
	const existingLocks = input.existingLocks ?? [];
	if (existingLocks.find((lock) => lock.executionId === input.response.executionId && !lockMatchesResponse(lock, input.response, workspaceKey))) return deniedLockDecision(workspaceKey, ["memory repair execution id was already used for a different repair plan"]);
	const sameExecutionLocks = existingLocks.filter((lock) => lockMatchesResponse(lock, input.response, workspaceKey));
	const activeSameExecution = sameExecutionLocks.find((lock) => lock.status === "active");
	if (activeSameExecution && !isExpiredLock(activeSameExecution, nowMs)) return {
		ok: true,
		canAcquire: false,
		idempotent: true,
		status: "idempotent-active",
		workspaceKey,
		record: activeSameExecution,
		reasons: []
	};
	const completedSameExecution = sameExecutionLocks.find((lock) => lock.status === "completed");
	if (completedSameExecution) return {
		ok: true,
		canAcquire: false,
		idempotent: true,
		status: "idempotent-completed",
		workspaceKey,
		record: completedSameExecution,
		reasons: []
	};
	if (sameExecutionLocks.find((lock) => lock.status === "failed" || lock.status === "abandoned")) return deniedLockDecision(workspaceKey, ["memory repair execution id already has a failed or abandoned terminal state"]);
	if (existingLocks.find((lock) => lock.workspaceKey === workspaceKey && lock.executionId !== input.response.executionId && lock.status === "active" && !isExpiredLock(lock, nowMs))) return deniedLockDecision(workspaceKey, ["another memory repair execution is active for this workspace"]);
	const expiresAt = new Date(nowMs + input.ttlMs).toISOString();
	return {
		ok: true,
		canAcquire: true,
		idempotent: false,
		status: "admitted",
		workspaceKey,
		record: {
			schemaVersion: 1,
			kind: "doctor.memory.repair.execution.lock",
			dryRun: true,
			noWritePerformed: true,
			agentId: input.response.agentId,
			workspaceKey,
			executionId: input.response.executionId,
			previewFingerprint: input.response.previewFingerprint,
			auditPlanFingerprint: input.response.auditPlanFingerprint ?? "",
			selectedProposalIds: input.response.selectedProposalIds,
			surface: input.response.auditPlan?.surface ?? "cli",
			operatorScope: input.response.auditPlan?.operatorScope ?? "operator.admin",
			status: "active",
			acquiredAt: input.now,
			expiresAt
		},
		reasons: []
	};
}
function createMemoryRepairWorkspaceKey(response) {
	const stable = {
		agentId: response.agentId,
		allowedRoots: response.auditPlan?.allowedRoots ?? []
	};
	const hash = crypto.createHash("sha256").update(JSON.stringify(stable)).digest("hex");
	return `${response.agentId}:${hash.slice(0, 24)}`;
}
function collectLockAdmissionDenyReasons(input) {
	const reasons = [];
	if (input.response.status !== "admitted" || input.response.stage !== "admitted") reasons.push("memory repair lock requires an admitted execution response");
	if (!input.response.dryRun || !input.response.noWritePerformed) reasons.push("memory repair lock contract requires pre-execution dry-run input");
	if (!input.response.auditPlan || !input.response.auditPlanFingerprint) reasons.push("memory repair lock requires an audit plan and fingerprint");
	if (!input.response.selectedProposalIds.length) reasons.push("memory repair lock requires selected proposal ids");
	if (!isIsoDateTime(input.now)) reasons.push("memory repair lock requires an ISO now timestamp");
	if (!Number.isFinite(input.ttlMs) || input.ttlMs <= 0) reasons.push("memory repair lock requires a positive ttlMs");
	for (const lock of input.existingLocks ?? []) if (lock.status === "active" && !isIsoDateTime(lock.expiresAt)) reasons.push("active memory repair lock has invalid expiry");
	return Array.from(new Set(reasons));
}
function lockMatchesResponse(lock, response, workspaceKey) {
	return lock.executionId === response.executionId && lock.workspaceKey === workspaceKey && lock.agentId === response.agentId && lock.previewFingerprint === response.previewFingerprint && lock.auditPlanFingerprint === response.auditPlanFingerprint && arraysEqual(lock.selectedProposalIds, response.selectedProposalIds);
}
function isExpiredLock(lock, nowMs) {
	return Date.parse(lock.expiresAt) <= nowMs;
}
function deniedLockDecision(workspaceKey, reasons) {
	return {
		ok: false,
		canAcquire: false,
		idempotent: false,
		status: "denied",
		...workspaceKey ? { workspaceKey } : {},
		reasons: Array.from(new Set(reasons))
	};
}
function isIsoDateTime(value) {
	const parsed = Date.parse(value);
	return Number.isFinite(parsed) && new Date(parsed).toISOString() === value;
}
function arraysEqual(left, right) {
	return left.length === right.length && left.every((entry, index) => entry === right[index]);
}

//#endregion
//#region src/memory/inventory.ts
const MAX_MARKDOWN_FILE_COUNT = 1e3;
const SESSION_MEMORY_FILENAME_RE = /^(\d{4}-\d{2}-\d{2}-\d{4})(?:-(\d+))?\.md$/;
async function buildMemoryInventory(params) {
	const { cfg, agentId, providerStatus } = params;
	const workspaceDir = path.resolve(resolveAgentWorkspaceDir(cfg, agentId));
	const stateDir = path.resolve(resolveStateDir(process.env));
	const roots = [workspaceDir, stateDir];
	const resolved = resolveMemoryBackendConfig({
		cfg,
		agentId
	});
	const qmdDir = path.join(stateDir, "agents", agentId, "qmd");
	const qmdIndexPath = path.join(qmdDir, "xdg-cache", "qmd", "index.sqlite");
	const memoryDir = path.join(workspaceDir, "memory");
	const hookConfig = resolveHookConfig(cfg, "session-memory");
	const activePlugin = resolveActiveMemoryPlugin(cfg);
	const workspaceStatus = await summarizePath(workspaceDir, roots);
	const memoryRootSpecs = [
		{
			id: "MEMORY.md",
			path: path.join(workspaceDir, "MEMORY.md")
		},
		{
			id: "memory.md",
			path: path.join(workspaceDir, "memory.md")
		},
		{
			id: "memory-dir",
			path: memoryDir
		}
	];
	const memoryRoots = await Promise.all(memoryRootSpecs.map(async (entry) => ({
		id: entry.id,
		...await summarizePath(entry.path, roots)
	})));
	const memoryDirStatus = await summarizePath(memoryDir, roots);
	const filenameDiagnostics = memoryDirStatus.exists && memoryDirStatus.kind === "directory" ? await summarizeSessionMemoryFilenameDiagnostics(memoryDir) : void 0;
	const extraPaths = providerStatus?.extraPaths?.length ? await Promise.all(providerStatus.extraPaths.map((entry) => summarizePath(entry, roots))) : void 0;
	const qmd = resolved.qmd ? {
		enabled: true,
		command: resolved.qmd.command,
		searchMode: resolved.qmd.searchMode,
		index: await summarizePath(providerStatus?.dbPath ?? qmdIndexPath, roots),
		collections: await Promise.all(resolved.qmd.collections.map(async (collection) => ({
			name: collection.name,
			pattern: collection.pattern,
			collectionKind: collection.kind,
			...await summarizePath(collection.path, roots)
		}))),
		sessions: {
			enabled: resolved.qmd.sessions.enabled,
			...resolved.qmd.sessions.retentionDays ? { retentionDays: resolved.qmd.sessions.retentionDays } : {},
			exportDir: await summarizePath(resolved.qmd.sessions.exportDir ?? path.join(qmdDir, "sessions"), roots)
		},
		mcporter: resolved.qmd.mcporter
	} : { enabled: false };
	return {
		agentId,
		workspace: {
			path: displayPath(workspaceDir, roots).path,
			exists: workspaceStatus.exists,
			memoryRoots
		},
		backend: {
			configured: resolved.backend,
			...providerStatus?.backend ? { active: providerStatus.backend } : {},
			citations: resolved.citations,
			...providerStatus?.provider ? { provider: providerStatus.provider } : {},
			...providerStatus?.model ? { model: providerStatus.model } : {},
			...providerStatus?.requestedProvider ? { requestedProvider: providerStatus.requestedProvider } : {},
			...typeof providerStatus?.files === "number" ? { files: providerStatus.files } : {},
			...typeof providerStatus?.chunks === "number" ? { chunks: providerStatus.chunks } : {},
			...typeof providerStatus?.dirty === "boolean" ? { dirty: providerStatus.dirty } : {},
			...providerStatus?.dbPath ? { db: await summarizePath(providerStatus.dbPath, roots) } : {},
			...providerStatus?.sources ? { sources: providerStatus.sources } : {},
			...providerStatus?.sourceCounts ? { sourceCounts: providerStatus.sourceCounts } : {},
			...extraPaths ? { extraPaths } : {},
			...params.providerError ? { error: params.providerError } : {}
		},
		qmd,
		sessionMemory: {
			hookConfigured: Boolean(hookConfig),
			enabled: cfg.hooks?.internal?.enabled === true && hookConfig?.enabled === true,
			...typeof hookConfig?.messages === "number" ? { messages: hookConfig.messages } : {},
			...typeof hookConfig?.llmSlug === "boolean" ? { llmSlug: hookConfig.llmSlug } : {},
			memoryDir: memoryDirStatus,
			...filenameDiagnostics ? { filenameDiagnostics } : {}
		},
		memoryPlugin: activePlugin
	};
}
function validateMemoryInventory(inventory) {
	const findings = [];
	const push = (finding) => findings.push(finding);
	if (!inventory.workspace.exists) push({
		severity: "error",
		code: "workspace.missing",
		area: "workspace",
		message: "Agent workspace does not exist.",
		path: inventory.workspace.path
	});
	const canonicalMemoryExists = inventory.workspace.memoryRoots.some((root) => root.id === "MEMORY.md" && root.exists && root.kind === "file");
	for (const root of inventory.workspace.memoryRoots) {
		if (root.id === "memory.md" && !root.exists && canonicalMemoryExists) continue;
		validatePathStatus({
			status: root,
			area: "workspace",
			codePrefix: `workspace.${root.id}`,
			label: `Workspace memory root ${root.id}`,
			expectedKind: root.id === "memory-dir" ? "directory" : "file",
			missingSeverity: "info",
			push
		});
	}
	const memoryMarkdownFiles = inventory.workspace.memoryRoots.reduce((sum, root) => sum + (root.markdownFiles ?? 0), 0);
	if (inventory.workspace.exists && memoryMarkdownFiles === 0) push({
		severity: "warn",
		code: "workspace.memory.empty",
		area: "workspace",
		message: "No markdown memory files were found in the default workspace memory roots.",
		path: inventory.workspace.path
	});
	if (inventory.backend.error) push({
		severity: "error",
		code: "backend.status.unavailable",
		area: "backend",
		message: inventory.backend.error
	});
	if (inventory.backend.configured !== inventory.backend.active && inventory.backend.active) push({
		severity: "warn",
		code: "backend.active.differs",
		area: "backend",
		message: `Configured memory backend is ${inventory.backend.configured}, but active backend reports ${inventory.backend.active}.`
	});
	validatePathStatus({
		status: inventory.backend.db,
		area: "backend",
		codePrefix: "backend.db",
		label: "Memory backend database",
		expectedKind: "file",
		missingSeverity: inventory.backend.configured === "builtin" ? "warn" : "info",
		push
	});
	for (const [index, extraPath] of inventory.backend.extraPaths?.entries() ?? []) validatePathStatus({
		status: extraPath,
		area: "backend",
		codePrefix: `backend.extraPath.${index}`,
		label: `Memory extra path ${index + 1}`,
		expectedKind: "any",
		missingSeverity: "warn",
		push
	});
	if (inventory.qmd.enabled) {
		validatePathStatus({
			status: inventory.qmd.index,
			area: "qmd",
			codePrefix: "qmd.index",
			label: "QMD index",
			expectedKind: "file",
			missingSeverity: "warn",
			push
		});
		for (const collection of inventory.qmd.collections ?? []) validatePathStatus({
			status: collection,
			area: "qmd",
			codePrefix: `qmd.collection.${collection.name}`,
			label: `QMD collection ${collection.name}`,
			expectedKind: "directory",
			missingSeverity: "warn",
			push
		});
		if (inventory.qmd.sessions?.enabled) validatePathStatus({
			status: inventory.qmd.sessions.exportDir,
			area: "qmd",
			codePrefix: "qmd.sessions.exportDir",
			label: "QMD session export directory",
			expectedKind: "directory",
			missingSeverity: "warn",
			push
		});
	} else if (inventory.backend.configured === "qmd") push({
		severity: "error",
		code: "qmd.config.unresolved",
		area: "qmd",
		message: "QMD is configured but no QMD inventory was resolved."
	});
	if (inventory.sessionMemory.enabled) validatePathStatus({
		status: inventory.sessionMemory.memoryDir,
		area: "session-memory",
		codePrefix: "sessionMemory.memoryDir",
		label: "Session-memory output directory",
		expectedKind: "directory",
		missingSeverity: "warn",
		push
	});
	else if (inventory.sessionMemory.hookConfigured) push({
		severity: "info",
		code: "sessionMemory.disabled",
		area: "session-memory",
		message: "Session-memory hook is configured but not enabled."
	});
	if (!inventory.memoryPlugin.registryLoaded) push({
		severity: "warn",
		code: "plugin.registry.unloaded",
		area: "plugin",
		message: "Plugin registry is not loaded; active memory plugin state may be incomplete."
	});
	else if (!inventory.memoryPlugin.enabled) {
		const intentionalNone = inventory.memoryPlugin.configuredSlot === null;
		push({
			severity: intentionalNone ? "info" : "warn",
			code: intentionalNone ? "plugin.memory.disabled" : "plugin.memory.unavailable",
			area: "plugin",
			message: inventory.memoryPlugin.reason ?? "Active memory plugin is not loaded."
		});
	}
	const errors = findings.filter((finding) => finding.severity === "error").length;
	const warnings = findings.filter((finding) => finding.severity === "warn").length;
	const info = findings.filter((finding) => finding.severity === "info").length;
	return {
		agentId: inventory.agentId,
		ok: errors === 0,
		summary: {
			errors,
			warnings,
			info
		},
		findings
	};
}
function previewMemoryInventoryRepair(inventory) {
	const validation = validateMemoryInventory(inventory);
	const proposals = validation.findings.map((finding, index) => previewProposalForFinding(finding, index));
	const supported = proposals.filter((proposal) => proposal.supported).length;
	const blocked = proposals.length - supported;
	return {
		agentId: inventory.agentId,
		dryRun: true,
		ok: validation.ok,
		validation: validation.summary,
		summary: {
			proposals: proposals.length,
			supported,
			blocked
		},
		proposals
	};
}
function previewProposalForFinding(finding, index) {
	const base = {
		id: `memory-repair-preview-${index + 1}`,
		area: finding.area,
		sourceCode: finding.code,
		severity: finding.severity,
		dryRun: true,
		wouldMutate: true,
		requiresOperatorWrite: true
	};
	if (finding.code.endsWith(".outside_roots")) return {
		...base,
		action: "manual_review",
		description: "Review the configured path; automatic repair is not previewed for paths outside the workspace/state roots.",
		...finding.path ? { targetPath: finding.path } : {},
		supported: false,
		blockReason: "outside allowed roots"
	};
	if (finding.code.endsWith(".inaccessible")) return {
		...base,
		action: "manual_review",
		description: "Inspect permissions or ownership for this memory artifact path before attempting repair.",
		...finding.path ? { targetPath: finding.path } : {},
		supported: false,
		blockReason: "path inaccessible"
	};
	if (finding.code.endsWith(".symlink")) return {
		...base,
		action: "manual_review",
		description: "Review the symlink target manually; the repair preview will not follow or rewrite symlinks.",
		...finding.path ? { targetPath: finding.path } : {},
		supported: false,
		blockReason: "symlink target not inspected"
	};
	if (finding.code.endsWith(".invalid_kind")) return {
		...base,
		action: "manual_review",
		description: "Review this artifact path manually because it has the wrong filesystem kind for its memory role.",
		...finding.path ? { targetPath: finding.path } : {},
		supported: false,
		blockReason: "invalid artifact kind"
	};
	if (finding.code === "workspace.missing") return {
		...base,
		action: "create_directory",
		description: "Would create the agent workspace directory before memory artifacts are repaired.",
		...finding.path ? { targetPath: finding.path } : {},
		supported: true
	};
	if (finding.code === "workspace.MEMORY.md.missing" || finding.code === "workspace.memory.md.missing") return {
		...base,
		action: "create_file",
		description: "Would create an empty workspace memory markdown file.",
		...finding.path ? { targetPath: finding.path } : {},
		supported: true
	};
	if (finding.code === "workspace.memory-dir.missing" || finding.code.startsWith("qmd.collection.") || finding.code === "qmd.sessions.exportDir.missing" || finding.code === "sessionMemory.memoryDir.missing") return {
		...base,
		action: "create_directory",
		description: "Would create the missing memory artifact directory.",
		...finding.path ? { targetPath: finding.path } : {},
		supported: true
	};
	if (finding.code === "qmd.index.missing") return {
		...base,
		action: "rebuild_index",
		description: "Would rebuild or initialize the QMD index using configured memory sources; no source content is read by this preview.",
		...finding.path ? { targetPath: finding.path } : {},
		supported: true
	};
	if (finding.code === "workspace.memory.empty") return {
		...base,
		action: "seed_memory",
		description: "Would suggest adding a starter memory note; the preview does not generate or write memory content.",
		...finding.path ? { targetPath: finding.path } : {},
		supported: false,
		blockReason: "requires user-authored memory content"
	};
	if (finding.code.startsWith("backend.")) return {
		...base,
		action: finding.code === "backend.active.differs" ? "review_config" : "review_backend",
		description: "Would review backend configuration and health before any memory repair is attempted.",
		...finding.path ? { targetPath: finding.path } : {},
		supported: false,
		blockReason: "backend repair requires a dedicated admin flow"
	};
	if (finding.code.startsWith("plugin.")) return {
		...base,
		action: "review_plugin",
		description: "Would review memory plugin configuration and runtime state.",
		supported: false,
		blockReason: "plugin repair requires plugin admin approval"
	};
	if (finding.code === "sessionMemory.disabled" || finding.code === "qmd.config.unresolved") return {
		...base,
		action: "review_config",
		description: "Would review memory configuration; this preview does not mutate config.",
		...finding.path ? { targetPath: finding.path } : {},
		supported: false,
		blockReason: "config mutation is not part of memory repair preview"
	};
	return {
		...base,
		action: "manual_review",
		description: "Would require manual review before a memory repair plan can be created.",
		...finding.path ? { targetPath: finding.path } : {},
		supported: false,
		blockReason: "no safe preview mapping for validation finding"
	};
}
function validatePathStatus(params) {
	const { status } = params;
	if (!status) return;
	if (status.redacted) {
		params.push({
			severity: "warn",
			code: `${params.codePrefix}.outside_roots`,
			area: params.area,
			message: `${params.label} is outside the configured workspace/state roots and was redacted.`,
			path: status.path
		});
		return;
	}
	if (status.kind === "error") {
		params.push({
			severity: "error",
			code: `${params.codePrefix}.inaccessible`,
			area: params.area,
			message: `${params.label} could not be inspected${status.error ? `: ${status.error}` : "."}`,
			path: status.path
		});
		return;
	}
	if (!status.exists || status.kind === "missing") {
		params.push({
			severity: params.missingSeverity,
			code: `${params.codePrefix}.missing`,
			area: params.area,
			message: `${params.label} is missing.`,
			path: status.path
		});
		return;
	}
	if (status.kind === "symlink") {
		params.push({
			severity: "warn",
			code: `${params.codePrefix}.symlink`,
			area: params.area,
			message: `${params.label} is a symlink and was not followed by validation.`,
			path: status.path
		});
		return;
	}
	if (params.expectedKind !== "any" && status.kind !== params.expectedKind) params.push({
		severity: "error",
		code: `${params.codePrefix}.invalid_kind`,
		area: params.area,
		message: `${params.label} should be a ${params.expectedKind}, but is ${status.kind}.`,
		path: status.path
	});
}
function resolveActiveMemoryPlugin(cfg) {
	const normalized = normalizePluginsConfig(cfg.plugins);
	const slot = normalized.slots.memory ?? null;
	const registry = getActivePluginRegistry();
	const active = slot ? registry?.plugins.find((plugin) => plugin.id === slot) : void 0;
	return {
		configuredSlot: slot,
		enabled: normalized.enabled && Boolean(slot) && active?.enabled === true && active.status === "loaded",
		registryLoaded: Boolean(registry),
		...active ? { active: {
			id: active.id,
			name: active.name,
			...active.kind ? { kind: active.kind } : {},
			origin: active.origin,
			status: active.status,
			enabled: active.enabled,
			toolNames: active.toolNames,
			...active.error ? { error: active.error } : {}
		} } : {},
		...resolveMemoryPluginReason({
			normalizedEnabled: normalized.enabled,
			slot,
			active
		})
	};
}
function resolveMemoryPluginReason(params) {
	if (!params.normalizedEnabled) return { reason: "plugins disabled" };
	if (!params.slot) return { reason: "plugins.slots.memory=\"none\"" };
	if (!params.active) return { reason: "active plugin registry has no selected memory plugin" };
	if (!params.active.enabled) return { reason: params.active.error ?? "selected memory plugin disabled" };
	if (params.active.status !== "loaded") return { reason: params.active.error ?? `selected memory plugin ${params.active.status}` };
	return {};
}
async function summarizePath(absPath, allowedRoots) {
	const display = displayPath(absPath, allowedRoots);
	try {
		const stat = await fs$1.lstat(absPath);
		if (stat.isSymbolicLink()) return {
			...display,
			exists: true,
			kind: "symlink"
		};
		if (stat.isFile()) return {
			...display,
			exists: true,
			kind: "file",
			markdownFiles: absPath.toLowerCase().endsWith(".md") ? 1 : 0
		};
		if (stat.isDirectory()) {
			const counted = await countMarkdownFiles(absPath);
			return {
				...display,
				exists: true,
				kind: "directory",
				markdownFiles: counted.count,
				...counted.truncated ? { truncated: true } : {}
			};
		}
		return {
			...display,
			exists: true,
			kind: "other"
		};
	} catch (err) {
		if (isMissingPathError(err)) return {
			...display,
			exists: false,
			kind: "missing"
		};
		return {
			...display,
			exists: false,
			kind: "error",
			error: formatFsError$1(err)
		};
	}
}
async function summarizeSessionMemoryFilenameDiagnostics(memoryDir) {
	let entries;
	try {
		entries = await fs$1.readdir(memoryDir, { withFileTypes: true });
	} catch (err) {
		return {
			checked: true,
			status: "unavailable",
			groups: [],
			error: formatFsError$1(err)
		};
	}
	const grouped = /* @__PURE__ */ new Map();
	let matched = 0;
	let truncated = false;
	for (const entry of entries.toSorted((left, right) => left.name.localeCompare(right.name))) {
		if (!entry.isFile()) continue;
		const match = SESSION_MEMORY_FILENAME_RE.exec(entry.name);
		if (!match) continue;
		const [, stem, suffixRaw] = match;
		if (!stem) continue;
		const suffix = suffixRaw ? Number(suffixRaw) : 0;
		if (!Number.isSafeInteger(suffix) || suffix < 0) continue;
		const files = grouped.get(stem) ?? [];
		files.push({
			name: entry.name,
			suffix
		});
		grouped.set(stem, files);
		matched += 1;
		if (matched >= MAX_MARKDOWN_FILE_COUNT) {
			truncated = true;
			break;
		}
	}
	const groups = [...grouped.entries()].map(([stem, files]) => ({
		stem,
		state: files.some((file) => file.suffix === 0) ? "collision-suffixed" : "suffix-gap",
		files: files.toSorted((left, right) => left.suffix - right.suffix || left.name.localeCompare(right.name))
	})).filter((group) => group.files.length > 1 || group.files.some((file) => file.suffix > 0)).toSorted((left, right) => left.stem.localeCompare(right.stem));
	return {
		checked: true,
		status: groups.length ? "suffixes-present" : truncated ? "truncated" : "none",
		groups,
		...truncated ? { truncated: true } : {}
	};
}
async function countMarkdownFiles(root) {
	let count = 0;
	const stack = [root];
	while (stack.length > 0) {
		const current = stack.pop();
		let entries;
		try {
			entries = await fs$1.readdir(current, { withFileTypes: true });
		} catch {
			continue;
		}
		for (const entry of entries) {
			if (entry.isSymbolicLink()) continue;
			const child = path.join(current, entry.name);
			if (entry.isDirectory()) {
				stack.push(child);
				continue;
			}
			if (entry.isFile() && entry.name.toLowerCase().endsWith(".md")) {
				count += 1;
				if (count >= MAX_MARKDOWN_FILE_COUNT) return {
					count,
					truncated: true
				};
			}
		}
	}
	return {
		count,
		truncated: false
	};
}
function displayPath(absPath, allowedRoots) {
	const resolved = path.resolve(absPath);
	if (allowedRoots.some((root) => isWithinRoot(resolved, root))) return { path: resolved };
	return {
		path: `[redacted:${path.basename(resolved) || "path"}]`,
		redacted: true
	};
}
function isWithinRoot(candidate, root) {
	const resolvedRoot = path.resolve(root);
	const relative = path.relative(resolvedRoot, candidate);
	return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
}
function isMissingPathError(err) {
	return Boolean(err && typeof err === "object" && err.code === "ENOENT");
}
function formatFsError$1(err) {
	if (err && typeof err === "object" && typeof err.code === "string") return err.code;
	return err instanceof Error ? err.name : "error";
}

//#endregion
//#region src/memory/repair-executor.ts
const LOCK_TTL_MS = 5 * 6e4;
const EXECUTABLE_ACTIONS = new Set(["create_file", "create_directory"]);
async function executeMemoryRepair(input) {
	const createdAt = (input.now ?? /* @__PURE__ */ new Date()).toISOString();
	const executionId = normalizeExecutionId(input.executionId, input.agentId);
	const { preview, allowedRoots, stateDir } = await buildExecutionPreview(input);
	const previewFingerprint = createMemoryRepairPreviewFingerprint(preview);
	const acceptedPreviewFingerprint = input.acceptCurrentPreview ? previewFingerprint : input.acceptedPreviewFingerprint;
	const response = evaluateMemoryRepairExecutionRequest({
		schemaVersion: 1,
		kind: "doctor.memory.repair.execution.request",
		method: DOCTOR_MEMORY_REPAIR_EXECUTION_METHOD,
		dryRun: true,
		executionId,
		createdAt,
		preview,
		proposalIds: input.proposalIds,
		acceptedPreviewFingerprint: acceptedPreviewFingerprint ?? "",
		surface: input.surface,
		operatorScope: "operator.admin",
		confirmation: input.confirmation,
		plan: {
			backup: "planned",
			audit: "planned",
			rollback: "manual"
		},
		allowedRoots,
		backupRoot: stateDir,
		auditRoot: stateDir
	});
	if (response.status !== "admitted" || !response.auditPlan || !response.auditPlanFingerprint) return deniedResult({
		response,
		previewFingerprint,
		reasons: response.reasons,
		executionId,
		agentId: preview.agentId
	});
	const acceptedAuditPlanFingerprint = input.acceptCurrentAuditPlan ? response.auditPlanFingerprint : input.acceptedAuditPlanFingerprint;
	const gate = evaluateMemoryRepairExecutorGate({
		response,
		gate: {
			enabled: true,
			writeExecutorRegistered: true,
			gatewayHandlerRegistered: true,
			cliCommandRegistered: input.surface === "cli",
			dashboardActionRegistered: input.surface === "dashboard-admin",
			allowWrites: input.allowWrites
		},
		operatorScope: "operator.admin",
		confirmation: input.confirmation,
		acceptedAuditPlanFingerprint
	});
	if (!gate.ok) return deniedResult({
		response,
		previewFingerprint,
		reasons: gate.reasons,
		executionId,
		agentId: preview.agentId
	});
	const unsupportedActions = response.auditPlan.backup.entries.filter((entry) => !EXECUTABLE_ACTIONS.has(entry.action));
	if (unsupportedActions.length > 0) return deniedResult({
		response,
		previewFingerprint,
		reasons: unsupportedActions.map((entry) => `memory repair action ${entry.action} is not implemented by the write executor`),
		executionId,
		agentId: preview.agentId
	});
	const lockAdmission = evaluateMemoryRepairExecutionLockAdmission({
		response,
		now: createdAt,
		ttlMs: LOCK_TTL_MS,
		existingLocks: await readExistingLocks(stateDir)
	});
	if (!lockAdmission.ok || !lockAdmission.record) return deniedResult({
		response,
		previewFingerprint,
		reasons: lockAdmission.reasons,
		executionId,
		agentId: preview.agentId
	});
	if (!lockAdmission.canAcquire) return {
		...baseResult(response, previewFingerprint),
		status: "idempotent",
		noWritePerformed: true,
		lockPath: lockPathFor(stateDir, response.executionId),
		summary: emptySummary(response.selectedProposalIds.length),
		rollback: {
			attempted: false,
			status: "not-needed",
			reasons: []
		},
		steps: [{
			proposalId: "__lock__",
			action: "manual_review",
			stage: "lock",
			status: "skipped",
			message: `memory repair execution is ${lockAdmission.status}`
		}],
		reasons: []
	};
	const lockPath = lockPathFor(stateDir, response.executionId);
	const steps = [];
	let lockRecord = lockAdmission.record;
	try {
		await writeJsonFileExclusive(lockPath, lockRecord);
	} catch (err) {
		return deniedResult({
			response,
			previewFingerprint,
			reasons: [`memory repair lock could not be acquired: ${formatFsError(err)}`],
			executionId,
			agentId: preview.agentId
		});
	}
	const fsSafety = await evaluateCurrentFsSafety(response);
	if (!fsSafety.ok || !fsSafety.safeToOpen) {
		await finishLock(lockPath, lockRecord, "failed");
		return deniedResult({
			response,
			previewFingerprint,
			reasons: fsSafety.reasons,
			executionId,
			agentId: preview.agentId,
			lockPath,
			fsSafety
		});
	}
	const snapshots = [];
	try {
		for (const entry of response.auditPlan.backup.entries) {
			snapshots.push(await backupTarget(entry));
			steps.push({
				proposalId: entry.proposalId,
				action: entry.action,
				stage: "backup",
				status: "succeeded",
				targetPath: entry.targetPath,
				snapshotPath: entry.snapshotPath
			});
		}
		await writeJsonFileExclusive(response.auditPlan.backup.manifestPath, {
			schemaVersion: 1,
			kind: "doctor.memory.repair.execution.backup-manifest",
			executionId: response.executionId,
			agentId: response.agentId,
			createdAt,
			auditPlanFingerprint: response.auditPlanFingerprint,
			snapshots
		});
		await writeAuditRecord(response.auditPlan.audit.recordPath, {
			event: "started",
			response,
			auditPlanFingerprint: response.auditPlanFingerprint,
			fsSafety
		});
		for (const entry of response.auditPlan.backup.entries) {
			const snapshot = snapshots.find((item) => item.proposalId === entry.proposalId);
			if (!snapshot) throw new Error(`missing backup snapshot for ${entry.proposalId}`);
			const writeStep = await writeTarget(entry.action, entry.proposalId, entry.targetPath);
			snapshot.wroteTarget = writeStep.status === "succeeded" && writeStep.message !== "already present";
			steps.push(writeStep);
			if (writeStep.status === "failed") break;
		}
		const result = buildExecutionResult({
			response,
			previewFingerprint,
			steps,
			rollback: steps.some((step) => step.stage === "write" && step.status === "failed") ? await rollbackSnapshots(snapshots, steps) : void 0,
			lockPath
		});
		await writeAuditRecord(response.auditPlan.audit.recordPath, {
			event: "finished",
			result
		});
		lockRecord = {
			...lockRecord,
			status: result.status === "success" ? "completed" : "failed"
		};
		await finishLock(lockPath, lockRecord, lockRecord.status);
		return result;
	} catch (err) {
		const rollback = await rollbackSnapshots(snapshots, steps);
		steps.push({
			proposalId: "__executor__",
			action: "manual_review",
			stage: "write",
			status: "failed",
			message: formatFsError(err)
		});
		const result = buildExecutionResult({
			response,
			previewFingerprint,
			steps,
			rollback,
			lockPath,
			extraReasons: [formatFsError(err)]
		});
		await writeAuditRecord(response.auditPlan.audit.recordPath, {
			event: "failed",
			result
		}).catch(() => {});
		await finishLock(lockPath, lockRecord, "failed");
		return result;
	}
}
async function buildExecutionPreview(input) {
	const stateDir = path.resolve(resolveStateDir(input.env ?? process.env));
	const workspaceDir = path.resolve(resolveAgentWorkspaceDir(input.cfg, input.agentId));
	let providerStatus;
	let providerError;
	const { manager, error } = await getMemorySearchManager({
		cfg: input.cfg,
		agentId: input.agentId,
		purpose: "status"
	});
	providerError = error;
	if (manager) try {
		providerStatus = manager.status();
	} catch (err) {
		providerError = `memory status failed: ${formatFsError(err)}`;
	} finally {
		await manager.close?.().catch(() => {});
	}
	return {
		preview: previewMemoryInventoryRepair(await buildMemoryInventory({
			cfg: input.cfg,
			agentId: input.agentId,
			...providerStatus ? { providerStatus } : {},
			...providerError ? { providerError } : {}
		})),
		allowedRoots: [workspaceDir, stateDir],
		stateDir
	};
}
function baseResult(response, previewFingerprint) {
	return {
		schemaVersion: 1,
		kind: "doctor.memory.repair.execution.result",
		method: DOCTOR_MEMORY_REPAIR_EXECUTION_METHOD,
		dryRun: false,
		noWritePerformed: false,
		executionId: response.executionId,
		agentId: response.agentId,
		previewFingerprint,
		...response.auditPlanFingerprint ? { auditPlanFingerprint: response.auditPlanFingerprint } : {},
		selectedProposalIds: response.selectedProposalIds,
		...response.auditPlan?.backup.manifestPath ? { backupManifestPath: response.auditPlan.backup.manifestPath } : {},
		...response.auditPlan?.audit.recordPath ? { auditRecordPath: response.auditPlan.audit.recordPath } : {}
	};
}
function deniedResult(params) {
	const selected = params.response?.selectedProposalIds ?? [];
	return {
		schemaVersion: 1,
		kind: "doctor.memory.repair.execution.result",
		method: DOCTOR_MEMORY_REPAIR_EXECUTION_METHOD,
		dryRun: false,
		noWritePerformed: true,
		executionId: params.executionId,
		agentId: params.agentId,
		status: "denied",
		previewFingerprint: params.previewFingerprint,
		...params.response?.auditPlanFingerprint ? { auditPlanFingerprint: params.response.auditPlanFingerprint } : {},
		selectedProposalIds: selected,
		...params.response?.auditPlan?.backup.manifestPath ? { backupManifestPath: params.response.auditPlan.backup.manifestPath } : {},
		...params.response?.auditPlan?.audit.recordPath ? { auditRecordPath: params.response.auditPlan.audit.recordPath } : {},
		...params.lockPath ? { lockPath: params.lockPath } : {},
		summary: emptySummary(selected.length),
		rollback: {
			attempted: false,
			status: "not-needed",
			reasons: []
		},
		steps: params.fsSafety ? params.fsSafety.checkedPaths.map((entry) => ({
			proposalId: "__fs_safety__",
			action: entry.action ?? "manual_review",
			stage: "fs-safety",
			status: entry.ok ? "succeeded" : "failed",
			targetPath: entry.path,
			message: entry.reasons.join("; ")
		})) : [],
		reasons: Array.from(new Set(params.reasons))
	};
}
function buildExecutionResult(params) {
	const failed = params.steps.filter((step) => step.status === "failed").length;
	const writeSucceeded = params.steps.filter((step) => step.stage === "write" && step.status === "succeeded").length;
	const backupSucceeded = params.steps.filter((step) => step.stage === "backup" && step.status === "succeeded").length;
	const skipped = params.steps.filter((step) => step.status === "skipped").length;
	const status = failed === 0 && writeSucceeded === params.response.selectedProposalIds.length ? "success" : writeSucceeded > 0 ? "partial-write" : "failure";
	const reasons = [...params.steps.filter((step) => step.status === "failed").map((step) => step.message ?? ""), ...params.extraReasons ?? []].filter(Boolean);
	const noWritePerformed = writeSucceeded === 0;
	return {
		...baseResult(params.response, params.previewFingerprint),
		status,
		noWritePerformed,
		lockPath: params.lockPath,
		summary: {
			selected: params.response.selectedProposalIds.length,
			backupSucceeded,
			writeSucceeded,
			failed,
			skipped
		},
		rollback: params.rollback ?? {
			attempted: false,
			status: "not-needed",
			reasons: []
		},
		steps: params.steps,
		reasons: Array.from(new Set(reasons))
	};
}
function emptySummary(selected) {
	return {
		selected,
		backupSucceeded: 0,
		writeSucceeded: 0,
		failed: 0,
		skipped: 0
	};
}
async function evaluateCurrentFsSafety(response) {
	if (!response.auditPlan) return {
		ok: false,
		safeToOpen: false,
		dryRun: true,
		noWritePerformed: true,
		checkedPaths: [],
		reasons: ["memory repair fs safety requires an audit plan"]
	};
	return evaluateMemoryRepairFsSafety({
		auditPlan: response.auditPlan,
		pathStates: await collectFsPathStates(response.auditPlan)
	});
}
async function collectFsPathStates(auditPlan) {
	const paths = new Set([
		auditPlan.backup.root,
		auditPlan.backup.manifestPath,
		auditPlan.audit.root,
		auditPlan.audit.recordPath
	]);
	for (const entry of auditPlan.backup.entries) {
		paths.add(entry.targetPath);
		paths.add(entry.snapshotPath);
	}
	return await Promise.all(Array.from(paths).map((entry) => inspectPath(entry)));
}
async function inspectPath(pathname) {
	try {
		const stat = await fs$1.lstat(pathname);
		return {
			path: pathname,
			kind: kindFromStats(stat),
			...stat.isSymbolicLink() ? {} : { realPath: await fs$1.realpath(pathname).catch(() => pathname) },
			...stat.isFile() ? { linkCount: stat.nlink } : {}
		};
	} catch (err) {
		if (err.code !== "ENOENT") return {
			path: pathname,
			kind: "unknown",
			parent: await inspectNode(path.dirname(pathname))
		};
		return {
			path: pathname,
			kind: "missing",
			parent: await inspectNode(path.dirname(pathname))
		};
	}
}
async function inspectNode(pathname) {
	try {
		const stat = await fs$1.lstat(pathname);
		return {
			path: pathname,
			kind: kindFromStats(stat),
			...stat.isSymbolicLink() ? {} : { realPath: await fs$1.realpath(pathname).catch(() => pathname) },
			...stat.isFile() ? { linkCount: stat.nlink } : {}
		};
	} catch {
		return {
			path: pathname,
			kind: "missing"
		};
	}
}
function kindFromStats(stat) {
	if (stat.isFile()) return "file";
	if (stat.isDirectory()) return "directory";
	if (stat.isSymbolicLink()) return "symlink";
	if (stat.isFIFO()) return "fifo";
	if (stat.isSocket()) return "socket";
	if (stat.isBlockDevice()) return "block-device";
	if (stat.isCharacterDevice()) return "char-device";
	return "unknown";
}
async function backupTarget(entry) {
	const beforeState = await inspectPath(entry.targetPath);
	if (beforeState.kind === "file") {
		await fs$1.copyFile(entry.targetPath, entry.snapshotPath, fs.constants.COPYFILE_EXCL);
		return {
			proposalId: entry.proposalId,
			action: entry.action,
			targetPath: entry.targetPath,
			snapshotPath: entry.snapshotPath,
			before: "file",
			wroteTarget: false
		};
	}
	const before = beforeState.kind === "directory" ? "directory" : "missing";
	await writeJsonFileExclusive(entry.snapshotPath, {
		kind: "doctor.memory.repair.execution.snapshot-marker",
		proposalId: entry.proposalId,
		targetPath: entry.targetPath,
		before
	});
	return {
		proposalId: entry.proposalId,
		action: entry.action,
		targetPath: entry.targetPath,
		snapshotPath: entry.snapshotPath,
		before,
		wroteTarget: false
	};
}
async function writeTarget(action, proposalId, targetPath) {
	try {
		const state = await inspectPath(targetPath);
		if (action === "create_file") {
			if (state.kind === "file") return {
				proposalId,
				action,
				stage: "write",
				status: "succeeded",
				targetPath,
				message: "already present"
			};
			if (state.kind !== "missing") return {
				proposalId,
				action,
				stage: "write",
				status: "failed",
				targetPath,
				message: `target is ${state.kind}`
			};
			await fs$1.writeFile(targetPath, "", {
				flag: "wx",
				mode: 384
			});
			return {
				proposalId,
				action,
				stage: "write",
				status: "succeeded",
				targetPath
			};
		}
		if (action === "create_directory") {
			if (state.kind === "directory") return {
				proposalId,
				action,
				stage: "write",
				status: "succeeded",
				targetPath,
				message: "already present"
			};
			if (state.kind !== "missing") return {
				proposalId,
				action,
				stage: "write",
				status: "failed",
				targetPath,
				message: `target is ${state.kind}`
			};
			await fs$1.mkdir(targetPath, {
				recursive: false,
				mode: 448
			});
			return {
				proposalId,
				action,
				stage: "write",
				status: "succeeded",
				targetPath
			};
		}
		return {
			proposalId,
			action,
			stage: "write",
			status: "failed",
			targetPath,
			message: `action ${action} is not implemented by memory repair executor`
		};
	} catch (err) {
		return {
			proposalId,
			action,
			stage: "write",
			status: "failed",
			targetPath,
			message: formatFsError(err),
			errorCode: err.code
		};
	}
}
async function rollbackSnapshots(snapshots, steps) {
	const wrote = snapshots.filter((snapshot) => snapshot.wroteTarget);
	if (wrote.length === 0) return {
		attempted: false,
		status: "not-needed",
		reasons: []
	};
	const reasons = [];
	for (const snapshot of wrote.toReversed()) try {
		if (snapshot.before === "missing") if (snapshot.action === "create_directory") await fs$1.rmdir(snapshot.targetPath);
		else await fs$1.unlink(snapshot.targetPath);
		else if (snapshot.before === "file") await fs$1.copyFile(snapshot.snapshotPath, snapshot.targetPath);
		steps.push({
			proposalId: snapshot.proposalId,
			action: snapshot.action,
			stage: "rollback",
			status: "succeeded",
			targetPath: snapshot.targetPath,
			snapshotPath: snapshot.snapshotPath
		});
	} catch (err) {
		reasons.push(`rollback failed for ${snapshot.proposalId}: ${formatFsError(err)}`);
		steps.push({
			proposalId: snapshot.proposalId,
			action: snapshot.action,
			stage: "rollback",
			status: "failed",
			targetPath: snapshot.targetPath,
			snapshotPath: snapshot.snapshotPath,
			message: formatFsError(err),
			errorCode: err.code
		});
	}
	return {
		attempted: true,
		status: reasons.length === 0 ? "completed" : "failed",
		reasons
	};
}
async function readExistingLocks(stateDir) {
	let entries;
	try {
		entries = await fs$1.readdir(stateDir);
	} catch {
		return [];
	}
	const locks = [];
	for (const entry of entries) {
		if (!entry.startsWith("memory-repair-") || !entry.endsWith(".lock.json")) continue;
		try {
			const parsed = JSON.parse(await fs$1.readFile(path.join(stateDir, entry), "utf8"));
			if (parsed?.kind === "doctor.memory.repair.execution.lock") locks.push(parsed);
		} catch {
			continue;
		}
	}
	return locks;
}
async function finishLock(lockPath, record, status) {
	await fs$1.writeFile(lockPath, `${JSON.stringify({
		...record,
		status,
		finishedAt: (/* @__PURE__ */ new Date()).toISOString()
	}, null, 2)}\n`, { mode: 384 });
}
async function writeAuditRecord(pathname, payload) {
	await fs$1.appendFile(pathname, `${JSON.stringify(payload)}\n`, { mode: 384 });
}
async function writeJsonFileExclusive(pathname, payload) {
	await fs$1.writeFile(pathname, `${JSON.stringify(payload, null, 2)}\n`, {
		flag: "wx",
		mode: 384
	});
}
function lockPathFor(stateDir, executionId) {
	return path.join(stateDir, `memory-repair-${executionId}.lock.json`);
}
function normalizeExecutionId(value, agentId) {
	const trimmed = value?.trim();
	if (trimmed && /^[A-Za-z0-9._-]{8,128}$/.test(trimmed)) return trimmed;
	const suffix = crypto.randomBytes(4).toString("hex");
	return `repair-${agentId.replace(/[^A-Za-z0-9._-]/g, "_")}-${Date.now()}-${suffix}`.slice(0, 128);
}
function formatFsError(err) {
	if (err instanceof Error) return err.message;
	return String(err);
}

//#endregion
//#region src/cli/memory-cli.ts
var memory_cli_exports = /* @__PURE__ */ __exportAll({
	registerMemoryCli: () => registerMemoryCli,
	runMemoryDoctorStatus: () => runMemoryDoctorStatus,
	runMemoryRepairExecute: () => runMemoryRepairExecute,
	runMemoryStatus: () => runMemoryStatus
});
function formatSourceLabel(source, workspaceDir, agentId) {
	if (source === "memory") return shortenHomeInString(`memory (MEMORY.md + ${path.join(workspaceDir, "memory")}${path.sep}*.md)`);
	if (source === "sessions") {
		const stateDir = resolveStateDir(process.env, os.homedir);
		return shortenHomeInString(`sessions (${path.join(stateDir, "agents", agentId, "sessions")}${path.sep}*.jsonl)`);
	}
	return source;
}
function resolveAgent(cfg, agent) {
	const trimmed = agent?.trim();
	if (trimmed) return trimmed;
	return resolveDefaultAgentId(cfg);
}
function resolveAgentIds(cfg, agent) {
	const trimmed = agent?.trim();
	if (trimmed) return [trimmed];
	const list = cfg.agents?.list ?? [];
	if (list.length > 0) return list.map((entry) => entry.id).filter(Boolean);
	return [resolveDefaultAgentId(cfg)];
}
function formatExtraPaths(workspaceDir, extraPaths) {
	return normalizeExtraMemoryPaths(workspaceDir, extraPaths).map((entry) => shortenHomePath(entry));
}
async function withMemoryManagerForAgent(params) {
	const managerParams = {
		cfg: params.cfg,
		agentId: params.agentId
	};
	if (params.purpose) managerParams.purpose = params.purpose;
	await withManager({
		getManager: () => getMemorySearchManager(managerParams),
		onMissing: (error) => defaultRuntime.log(error ?? "Memory search disabled."),
		onCloseError: (err) => defaultRuntime.error(`Memory manager close failed: ${formatErrorMessage(err)}`),
		close: async (manager) => {
			await manager.close?.();
		},
		run: params.run
	});
}
async function checkReadableFile(pathname) {
	try {
		await fs$1.access(pathname, fs.constants.R_OK);
		return { exists: true };
	} catch (err) {
		const code = err.code;
		if (code === "ENOENT") return { exists: false };
		return {
			exists: true,
			issue: `${shortenHomePath(pathname)} not readable (${code ?? "error"})`
		};
	}
}
async function scanSessionFiles(agentId) {
	const issues = [];
	const sessionsDir = resolveSessionTranscriptsDirForAgent(agentId);
	try {
		return {
			source: "sessions",
			totalFiles: (await fs$1.readdir(sessionsDir, { withFileTypes: true })).filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).length,
			issues
		};
	} catch (err) {
		const code = err.code;
		if (code === "ENOENT") {
			issues.push(`sessions directory missing (${shortenHomePath(sessionsDir)})`);
			return {
				source: "sessions",
				totalFiles: 0,
				issues
			};
		}
		issues.push(`sessions directory not accessible (${shortenHomePath(sessionsDir)}): ${code ?? "error"}`);
		return {
			source: "sessions",
			totalFiles: null,
			issues
		};
	}
}
async function scanMemoryFiles(workspaceDir, extraPaths = []) {
	const issues = [];
	const memoryFile = path.join(workspaceDir, "MEMORY.md");
	const altMemoryFile = path.join(workspaceDir, "memory.md");
	const memoryDir = path.join(workspaceDir, "memory");
	const primary = await checkReadableFile(memoryFile);
	const alt = await checkReadableFile(altMemoryFile);
	if (primary.issue) issues.push(primary.issue);
	if (alt.issue) issues.push(alt.issue);
	const resolvedExtraPaths = normalizeExtraMemoryPaths(workspaceDir, extraPaths);
	for (const extraPath of resolvedExtraPaths) try {
		if ((await fs$1.lstat(extraPath)).isSymbolicLink()) continue;
		const extraCheck = await checkReadableFile(extraPath);
		if (extraCheck.issue) issues.push(extraCheck.issue);
	} catch (err) {
		const code = err.code;
		if (code === "ENOENT") issues.push(`additional memory path missing (${shortenHomePath(extraPath)})`);
		else issues.push(`additional memory path not accessible (${shortenHomePath(extraPath)}): ${code ?? "error"}`);
	}
	let dirReadable = null;
	try {
		await fs$1.access(memoryDir, fs.constants.R_OK);
		dirReadable = true;
	} catch (err) {
		const code = err.code;
		if (code === "ENOENT") {
			issues.push(`memory directory missing (${shortenHomePath(memoryDir)})`);
			dirReadable = false;
		} else {
			issues.push(`memory directory not accessible (${shortenHomePath(memoryDir)}): ${code ?? "error"}`);
			dirReadable = null;
		}
	}
	let listed = [];
	let listedOk = false;
	try {
		listed = await listMemoryFiles(workspaceDir, resolvedExtraPaths);
		listedOk = true;
	} catch (err) {
		const code = err.code;
		if (dirReadable !== null) {
			issues.push(`memory directory scan failed (${shortenHomePath(memoryDir)}): ${code ?? "error"}`);
			dirReadable = null;
		}
	}
	let totalFiles = 0;
	if (dirReadable === null) totalFiles = null;
	else {
		const files = new Set(listedOk ? listed : []);
		if (!listedOk) {
			if (primary.exists) files.add(memoryFile);
			if (alt.exists) files.add(altMemoryFile);
		}
		totalFiles = files.size;
	}
	if ((totalFiles ?? 0) === 0 && issues.length === 0) issues.push(`no memory files found in ${shortenHomePath(workspaceDir)}`);
	return {
		source: "memory",
		totalFiles,
		issues
	};
}
async function summarizeQmdIndexArtifact(manager) {
	const status = manager.status?.();
	if (!status || status.backend !== "qmd") return null;
	const dbPath = status.dbPath?.trim();
	if (!dbPath) return null;
	let stat;
	try {
		stat = await fs$1.stat(dbPath);
	} catch (err) {
		const code = err.code;
		if (code === "ENOENT") throw new Error(`QMD index file not found: ${shortenHomePath(dbPath)}`, { cause: err });
		throw new Error(`QMD index file check failed: ${shortenHomePath(dbPath)} (${code ?? "error"})`, { cause: err });
	}
	if (!stat.isFile() || stat.size <= 0) throw new Error(`QMD index file is empty: ${shortenHomePath(dbPath)}`);
	return `QMD index: ${shortenHomePath(dbPath)} (${stat.size} bytes)`;
}
async function scanMemorySources(params) {
	const scans = [];
	const extraPaths = params.extraPaths ?? [];
	for (const source of params.sources) {
		if (source === "memory") scans.push(await scanMemoryFiles(params.workspaceDir, extraPaths));
		if (source === "sessions") scans.push(await scanSessionFiles(params.agentId));
	}
	const issues = scans.flatMap((scan) => scan.issues);
	const totals = scans.map((scan) => scan.totalFiles);
	const numericTotals = totals.filter((total) => total !== null);
	return {
		sources: scans,
		totalFiles: totals.some((total) => total === null) ? null : numericTotals.reduce((sum, total) => sum + total, 0),
		issues
	};
}
async function buildMemoryDoctorReport(params) {
	let providerStatus;
	let providerError;
	const { manager, error } = await getMemorySearchManager({
		cfg: params.cfg,
		agentId: params.agentId,
		purpose: "status"
	});
	providerError = error;
	if (manager) try {
		providerStatus = manager.status();
	} catch (err) {
		providerError = `memory status failed: ${formatErrorMessage(err)}`;
	} finally {
		await manager.close?.().catch(() => {});
	}
	const inventory = await buildMemoryInventory({
		cfg: params.cfg,
		agentId: params.agentId,
		...providerStatus ? { providerStatus } : {},
		...providerError ? { providerError } : {}
	});
	const validation = validateMemoryInventory(inventory);
	const repairPreview = previewMemoryInventoryRepair(inventory);
	return {
		agentId: params.agentId,
		inventory,
		validation,
		repairPreview
	};
}
function formatSummaryCount(count, singular, plural = `${singular}s`) {
	return `${count} ${count === 1 ? singular : plural}`;
}
function formatPathState(status) {
	if (!status) return "not configured";
	const state = status.exists ? status.kind : "missing";
	const suffix = typeof status.markdownFiles === "number" ? `, ${formatSummaryCount(status.markdownFiles, "markdown file")}` : "";
	return `${shortenHomePath(status.path)} (${state}${suffix})`;
}
function formatSessionMemoryFilenameDiagnostics(diagnostics) {
	if (!diagnostics) return "";
	if (diagnostics.status === "unavailable") return ` · filename diagnostics unavailable${diagnostics.error ? ` (${diagnostics.error})` : ""}`;
	if (diagnostics.status === "suffixes-present") {
		const fileCount = diagnostics.groups.reduce((sum, group) => sum + group.files.length, 0);
		return ` · filename diagnostics suffixes present (${formatSummaryCount(diagnostics.groups.length, "group")}, ${formatSummaryCount(fileCount, "file")})`;
	}
	if (diagnostics.status === "truncated") return " · filename diagnostics checked truncated";
	return " · filename diagnostics clean";
}
function formatMemoryPluginState(plugin) {
	if (plugin.enabled && plugin.active) return `${plugin.active.name} (${plugin.active.id})`;
	return plugin.reason ?? "not enabled";
}
function formatFindingLine(finding) {
	const pathSuffix = finding.path ? ` · ${shortenHomePath(finding.path)}` : "";
	return `[${finding.severity}] ${finding.code} · ${finding.message}${pathSuffix}`;
}
function formatMemoryDoctorReport(report) {
	const rich = isRich();
	const heading = (text) => colorize(rich, theme.heading, text);
	const muted = (text) => colorize(rich, theme.muted, text);
	const info = (text) => colorize(rich, theme.info, text);
	const success = (text) => colorize(rich, theme.success, text);
	const warn = (text) => colorize(rich, theme.warn, text);
	const accent = (text) => colorize(rich, theme.accent, text);
	const label = (text) => muted(`${text}:`);
	const { inventory, validation, repairPreview } = report;
	const status = validation.ok ? success("pass") : warn("needs attention");
	const validationSummary = [
		formatSummaryCount(validation.summary.errors, "error"),
		formatSummaryCount(validation.summary.warnings, "warning"),
		formatSummaryCount(validation.summary.info, "info")
	].join(", ");
	const proposalSummary = [
		formatSummaryCount(repairPreview.summary.proposals, "dry-run proposal"),
		formatSummaryCount(repairPreview.summary.supported, "supported", "supported"),
		formatSummaryCount(repairPreview.summary.blocked, "blocked", "blocked")
	].join(", ");
	const workspaceState = inventory.workspace.exists ? "present" : "missing";
	const backendState = [
		inventory.backend.configured,
		inventory.backend.active ? `active ${inventory.backend.active}` : null,
		inventory.backend.provider ? `provider ${inventory.backend.provider}` : null,
		inventory.backend.model ? `model ${inventory.backend.model}` : null
	].filter(Boolean).join(" · ");
	const sessionMemoryState = inventory.sessionMemory.enabled ? `enabled · ${formatPathState(inventory.sessionMemory.memoryDir)}` : inventory.sessionMemory.hookConfigured ? `configured but disabled · ${formatPathState(inventory.sessionMemory.memoryDir)}` : `disabled · ${formatPathState(inventory.sessionMemory.memoryDir)}`;
	const sessionMemoryDiagnostics = formatSessionMemoryFilenameDiagnostics(inventory.sessionMemory.filenameDiagnostics);
	const lines = [
		`${heading("Memory Doctor")} ${muted(`(${report.agentId})`)}`,
		`${label("Status")} ${status}`,
		`${label("Workspace")} ${info(`${shortenHomePath(inventory.workspace.path)} (${workspaceState})`)}`,
		`${label("Backend")} ${info(backendState || inventory.backend.configured)}`,
		`${label("Workspace roots")} ${inventory.workspace.memoryRoots.map((root) => `${root.id}=${formatPathState(root)}`).join("; ")}`,
		`${label("QMD")} ${inventory.qmd.enabled ? info(`enabled${inventory.qmd.index ? ` · index ${formatPathState(inventory.qmd.index)}` : ""}`) : muted("disabled")}`,
		`${label("Session memory")} ${inventory.sessionMemory.enabled ? info(`${sessionMemoryState}${sessionMemoryDiagnostics}`) : muted(`${sessionMemoryState}${sessionMemoryDiagnostics}`)}`,
		`${label("Memory plugin")} ${info(formatMemoryPluginState(inventory.memoryPlugin))}`,
		`${label("Validation")} ${validation.ok ? success(validationSummary) : warn(validationSummary)}`,
		`${label("Repair preview")} ${info(proposalSummary)}`
	];
	if (inventory.backend.error) lines.push(`${label("Backend error")} ${warn(inventory.backend.error)}`);
	if (validation.findings.length) {
		lines.push(label("Findings"));
		for (const finding of validation.findings) {
			const color = finding.severity === "error" ? warn : finding.severity === "warn" ? warn : muted;
			lines.push(`  ${color(formatFindingLine(finding))}`);
		}
	} else lines.push(`${label("Findings")} ${success("none")}`);
	if (repairPreview.proposals.length) {
		lines.push(label("Dry-run proposals"));
		for (const proposal of repairPreview.proposals) {
			const supported = proposal.supported ? success("supported") : warn("blocked");
			const target = proposal.targetPath ? ` · ${shortenHomePath(proposal.targetPath)}` : "";
			const block = proposal.blockReason ? ` · ${proposal.blockReason}` : "";
			lines.push(`  ${accent(proposal.action)} ${muted("·")} ${supported} ${muted("·")} ${proposal.description}${target}${block}`);
		}
	} else lines.push(`${label("Dry-run proposals")} ${success("none")}`);
	return lines.join("\n");
}
function formatMemoryRepairExecutionResult(result) {
	const rich = isRich();
	const heading = (text) => colorize(rich, theme.heading, text);
	const muted = (text) => colorize(rich, theme.muted, text);
	const info = (text) => colorize(rich, theme.info, text);
	const success = (text) => colorize(rich, theme.success, text);
	const warn = (text) => colorize(rich, theme.warn, text);
	const label = (text) => muted(`${text}:`);
	const ok = result.status === "success" || result.status === "idempotent";
	const lines = [
		`${heading("Memory Repair Execute")} ${muted(`(${result.agentId})`)}`,
		`${label("Status")} ${ok ? success(result.status) : warn(result.status)}`,
		`${label("Execution")} ${info(result.executionId)}`,
		`${label("Selected")} ${info(result.selectedProposalIds.join(", ") || "none")}`,
		`${label("Writes")} ${info(`${result.summary.writeSucceeded}/${result.summary.selected}`)}`,
		result.backupManifestPath ? `${label("Backup manifest")} ${info(shortenHomePath(result.backupManifestPath))}` : null,
		result.auditRecordPath ? `${label("Audit record")} ${info(shortenHomePath(result.auditRecordPath))}` : null
	].filter(Boolean);
	if (result.reasons.length) {
		lines.push(label("Reasons"));
		for (const reason of result.reasons) lines.push(`  ${warn(reason)}`);
	}
	if (result.steps.length) {
		lines.push(label("Steps"));
		for (const step of result.steps) {
			const state = step.status === "succeeded" ? success(step.status) : step.status === "skipped" ? muted(step.status) : warn(step.status);
			const target = step.targetPath ? ` · ${shortenHomePath(step.targetPath)}` : "";
			const message = step.message ? ` · ${step.message}` : "";
			lines.push(`  ${step.stage}/${step.proposalId} ${muted("·")} ${state}${target}${message}`);
		}
	}
	return lines.join("\n");
}
async function runMemoryDoctorStatus(opts) {
	const cfg = loadConfig();
	const agentIds = resolveAgentIds(cfg, opts.agent);
	const reports = await Promise.all(agentIds.map((agentId) => buildMemoryDoctorReport({
		cfg,
		agentId
	})));
	if (opts.json) {
		defaultRuntime.log(JSON.stringify({ reports }, null, 2));
		return;
	}
	for (const report of reports) {
		defaultRuntime.log(formatMemoryDoctorReport(report));
		defaultRuntime.log("");
	}
}
async function runMemoryRepairExecute(opts) {
	if (!opts.yes) throw new Error("memory repair execute is write-capable and requires --yes");
	const proposalIds = opts.proposalId?.map((entry) => entry.trim()).filter(Boolean) ?? [];
	if (proposalIds.length === 0) throw new Error("memory repair execute requires at least one --proposal-id");
	const cfg = loadConfig();
	const result = await executeMemoryRepair({
		cfg,
		agentId: resolveAgent(cfg, opts.agent),
		proposalIds,
		surface: "cli",
		confirmation: "cli-yes",
		allowWrites: true,
		acceptCurrentPreview: true,
		acceptCurrentAuditPlan: true,
		...opts.executionId ? { executionId: opts.executionId } : {}
	});
	if (opts.json) defaultRuntime.log(JSON.stringify(result, null, 2));
	else defaultRuntime.log(formatMemoryRepairExecutionResult(result));
	if (result.status !== "success" && result.status !== "idempotent") process.exitCode = 1;
}
async function runMemoryStatus(opts) {
	setVerbose(Boolean(opts.verbose));
	const cfg = loadConfig();
	const agentIds = resolveAgentIds(cfg, opts.agent);
	const allResults = [];
	for (const agentId of agentIds) await withMemoryManagerForAgent({
		cfg,
		agentId,
		purpose: opts.index ? "default" : "status",
		run: async (manager) => {
			const deep = Boolean(opts.deep || opts.index);
			let embeddingProbe;
			let indexError;
			const syncFn = manager.sync ? manager.sync.bind(manager) : void 0;
			if (deep) {
				await withProgress({
					label: "Checking memory…",
					total: 2
				}, async (progress) => {
					progress.setLabel("Probing vector…");
					await manager.probeVectorAvailability();
					progress.tick();
					progress.setLabel("Probing embeddings…");
					embeddingProbe = await manager.probeEmbeddingAvailability();
					progress.tick();
				});
				if (opts.index && syncFn) await withProgressTotals({
					label: "Indexing memory…",
					total: 0,
					fallback: opts.verbose ? "line" : void 0
				}, async (update, progress) => {
					try {
						await syncFn({
							reason: "cli",
							force: Boolean(opts.force),
							progress: (syncUpdate) => {
								update({
									completed: syncUpdate.completed,
									total: syncUpdate.total,
									label: syncUpdate.label
								});
								if (syncUpdate.label) progress.setLabel(syncUpdate.label);
							}
						});
					} catch (err) {
						indexError = formatErrorMessage(err);
						defaultRuntime.error(`Memory index failed: ${indexError}`);
						process.exitCode = 1;
					}
				});
				else if (opts.index && !syncFn) defaultRuntime.log("Memory backend does not support manual reindex.");
			} else await manager.probeVectorAvailability();
			const status = manager.status();
			const sources = status.sources?.length ? status.sources : ["memory"];
			const workspaceDir = status.workspaceDir;
			const scan = workspaceDir ? await scanMemorySources({
				workspaceDir,
				agentId,
				sources,
				extraPaths: status.extraPaths
			}) : void 0;
			allResults.push({
				agentId,
				status,
				embeddingProbe,
				indexError,
				scan
			});
		}
	});
	if (opts.json) {
		defaultRuntime.log(JSON.stringify(allResults, null, 2));
		return;
	}
	const rich = isRich();
	const heading = (text) => colorize(rich, theme.heading, text);
	const muted = (text) => colorize(rich, theme.muted, text);
	const info = (text) => colorize(rich, theme.info, text);
	const success = (text) => colorize(rich, theme.success, text);
	const warn = (text) => colorize(rich, theme.warn, text);
	const accent = (text) => colorize(rich, theme.accent, text);
	const label = (text) => muted(`${text}:`);
	for (const result of allResults) {
		const { agentId, status, embeddingProbe, indexError, scan } = result;
		const filesIndexed = status.files ?? 0;
		const chunksIndexed = status.chunks ?? 0;
		const totalFiles = scan?.totalFiles ?? null;
		const indexedLabel = totalFiles === null ? `${filesIndexed}/? files · ${chunksIndexed} chunks` : `${filesIndexed}/${totalFiles} files · ${chunksIndexed} chunks`;
		if (opts.index) {
			const line = indexError ? `Memory index failed: ${indexError}` : "Memory index complete.";
			defaultRuntime.log(line);
		}
		const requestedProvider = status.requestedProvider ?? status.provider;
		const modelLabel = status.model ?? status.provider;
		const storePath = status.dbPath ? shortenHomePath(status.dbPath) : "<unknown>";
		const workspacePath = status.workspaceDir ? shortenHomePath(status.workspaceDir) : "<unknown>";
		const sourceList = status.sources?.length ? status.sources.join(", ") : null;
		const extraPaths = status.workspaceDir ? formatExtraPaths(status.workspaceDir, status.extraPaths ?? []) : [];
		const lines = [
			`${heading("Memory Search")} ${muted(`(${agentId})`)}`,
			`${label("Provider")} ${info(status.provider)} ${muted(`(requested: ${requestedProvider})`)}`,
			`${label("Model")} ${info(modelLabel)}`,
			sourceList ? `${label("Sources")} ${info(sourceList)}` : null,
			extraPaths.length ? `${label("Extra paths")} ${info(extraPaths.join(", "))}` : null,
			`${label("Indexed")} ${success(indexedLabel)}`,
			`${label("Dirty")} ${status.dirty ? warn("yes") : muted("no")}`,
			`${label("Store")} ${info(storePath)}`,
			`${label("Workspace")} ${info(workspacePath)}`
		].filter(Boolean);
		if (embeddingProbe) {
			const state = embeddingProbe.ok ? "ready" : "unavailable";
			const stateColor = embeddingProbe.ok ? theme.success : theme.warn;
			lines.push(`${label("Embeddings")} ${colorize(rich, stateColor, state)}`);
			if (embeddingProbe.error) lines.push(`${label("Embeddings error")} ${warn(embeddingProbe.error)}`);
		}
		if (status.sourceCounts?.length) {
			lines.push(label("By source"));
			for (const entry of status.sourceCounts) {
				const total = scan?.sources?.find((scanEntry) => scanEntry.source === entry.source)?.totalFiles;
				const counts = total === null ? `${entry.files}/? files · ${entry.chunks} chunks` : `${entry.files}/${total} files · ${entry.chunks} chunks`;
				lines.push(`  ${accent(entry.source)} ${muted("·")} ${muted(counts)}`);
			}
		}
		if (status.fallback) lines.push(`${label("Fallback")} ${warn(status.fallback.from)}`);
		if (status.vector) {
			const vectorState = status.vector.enabled ? status.vector.available === void 0 ? "unknown" : status.vector.available ? "ready" : "unavailable" : "disabled";
			const vectorColor = vectorState === "ready" ? theme.success : vectorState === "unavailable" ? theme.warn : theme.muted;
			lines.push(`${label("Vector")} ${colorize(rich, vectorColor, vectorState)}`);
			if (status.vector.dims) lines.push(`${label("Vector dims")} ${info(String(status.vector.dims))}`);
			if (status.vector.extensionPath) lines.push(`${label("Vector path")} ${info(shortenHomePath(status.vector.extensionPath))}`);
			if (status.vector.loadError) lines.push(`${label("Vector error")} ${warn(status.vector.loadError)}`);
		}
		if (status.fts) {
			const ftsState = status.fts.enabled ? status.fts.available ? "ready" : "unavailable" : "disabled";
			const ftsColor = ftsState === "ready" ? theme.success : ftsState === "unavailable" ? theme.warn : theme.muted;
			lines.push(`${label("FTS")} ${colorize(rich, ftsColor, ftsState)}`);
			if (status.fts.error) lines.push(`${label("FTS error")} ${warn(status.fts.error)}`);
		}
		if (status.cache) {
			const cacheState = status.cache.enabled ? "enabled" : "disabled";
			const cacheColor = status.cache.enabled ? theme.success : theme.muted;
			const suffix = status.cache.enabled && typeof status.cache.entries === "number" ? ` (${status.cache.entries} entries)` : "";
			lines.push(`${label("Embedding cache")} ${colorize(rich, cacheColor, cacheState)}${suffix}`);
			if (status.cache.enabled && typeof status.cache.maxEntries === "number") lines.push(`${label("Cache cap")} ${info(String(status.cache.maxEntries))}`);
		}
		if (status.batch) {
			const batchState = status.batch.enabled ? "enabled" : "disabled";
			const batchColor = status.batch.enabled ? theme.success : theme.warn;
			const batchSuffix = ` (failures ${status.batch.failures}/${status.batch.limit})`;
			lines.push(`${label("Batch")} ${colorize(rich, batchColor, batchState)}${muted(batchSuffix)}`);
			if (status.batch.lastError) lines.push(`${label("Batch error")} ${warn(status.batch.lastError)}`);
		}
		if (status.fallback?.reason) lines.push(muted(status.fallback.reason));
		if (indexError) lines.push(`${label("Index error")} ${warn(indexError)}`);
		if (scan?.issues.length) {
			lines.push(label("Issues"));
			for (const issue of scan.issues) lines.push(`  ${warn(issue)}`);
		}
		defaultRuntime.log(lines.join("\n"));
		defaultRuntime.log("");
	}
}
function registerMemoryCli(program) {
	const memory = program.command("memory").description("Search, inspect, and reindex memory files").addHelpText("after", () => `\n${theme.heading("Examples:")}\n${formatHelpExamples([
		["fased memory status", "Show index and provider status."],
		["fased memory doctor", "Show read-only memory doctor diagnostics."],
		["fased memory repair execute --proposal-id memory-repair-preview-1 --yes", "Execute a selected Memory Doctor repair proposal."],
		["fased memory index --force", "Force a full reindex."],
		["fased memory search --query \"deployment notes\"", "Search indexed memory entries."],
		["fased memory status --json", "Output machine-readable JSON."]
	])}\n\n${theme.muted("Docs:")} ${formatDocsLink("/cli/memory", "docs.fased.ai/cli/memory")}\n`);
	memory.command("status").description("Show memory search index status").option("--agent <id>", "Agent id (default: default agent)").option("--json", "Print JSON").option("--deep", "Probe embedding provider availability").option("--index", "Reindex if dirty (implies --deep)").option("--verbose", "Verbose logging", false).action(async (opts) => {
		await runMemoryStatus(opts);
	});
	memory.command("doctor").description("Show read-only memory doctor diagnostics").option("--agent <id>", "Agent id (default: all configured agents)").option("--json", "Print JSON").action(async (opts) => {
		await runMemoryDoctorStatus(opts);
	});
	const collectProposalId = (value, previous = []) => [...previous, value];
	memory.command("repair").description("Execute gated Memory Doctor repairs").command("execute").description("Execute selected Memory Doctor repair proposals with backup and audit").option("--agent <id>", "Agent id (default: default agent)").option("--proposal-id <id>", "Proposal id to execute; repeat for multiple proposals", collectProposalId, []).option("--execution-id <id>", "Safe execution id for idempotency/audit records").option("--yes", "Confirm write-capable memory repair execution", false).option("--json", "Print JSON").action(async (opts) => {
		await runMemoryRepairExecute(opts);
	});
	memory.command("index").description("Reindex memory files").option("--agent <id>", "Agent id (default: default agent)").option("--force", "Force full reindex", false).option("--verbose", "Verbose logging", false).action(async (opts) => {
		setVerbose(Boolean(opts.verbose));
		const cfg = loadConfig();
		const agentIds = resolveAgentIds(cfg, opts.agent);
		for (const agentId of agentIds) await withMemoryManagerForAgent({
			cfg,
			agentId,
			run: async (manager) => {
				try {
					const syncFn = manager.sync ? manager.sync.bind(manager) : void 0;
					if (opts.verbose) {
						const status = manager.status();
						const rich = isRich();
						const heading = (text) => colorize(rich, theme.heading, text);
						const muted = (text) => colorize(rich, theme.muted, text);
						const info = (text) => colorize(rich, theme.info, text);
						const warn = (text) => colorize(rich, theme.warn, text);
						const label = (text) => muted(`${text}:`);
						const sourceLabels = (status.sources ?? []).map((source) => formatSourceLabel(source, status.workspaceDir ?? "", agentId));
						const extraPaths = status.workspaceDir ? formatExtraPaths(status.workspaceDir, status.extraPaths ?? []) : [];
						const requestedProvider = status.requestedProvider ?? status.provider;
						const modelLabel = status.model ?? status.provider;
						const lines = [
							`${heading("Memory Index")} ${muted(`(${agentId})`)}`,
							`${label("Provider")} ${info(status.provider)} ${muted(`(requested: ${requestedProvider})`)}`,
							`${label("Model")} ${info(modelLabel)}`,
							sourceLabels.length ? `${label("Sources")} ${info(sourceLabels.join(", "))}` : null,
							extraPaths.length ? `${label("Extra paths")} ${info(extraPaths.join(", "))}` : null
						].filter(Boolean);
						if (status.fallback) lines.push(`${label("Fallback")} ${warn(status.fallback.from)}`);
						defaultRuntime.log(lines.join("\n"));
						defaultRuntime.log("");
					}
					const startedAt = Date.now();
					let lastLabel = "Indexing memory…";
					let lastCompleted = 0;
					let lastTotal = 0;
					const formatElapsed = () => {
						const elapsedMs = Math.max(0, Date.now() - startedAt);
						const seconds = Math.floor(elapsedMs / 1e3);
						const minutes = Math.floor(seconds / 60);
						const remainingSeconds = seconds % 60;
						return `${minutes}:${String(remainingSeconds).padStart(2, "0")}`;
					};
					const formatEta = () => {
						if (lastTotal <= 0 || lastCompleted <= 0) return null;
						const elapsedMs = Math.max(1, Date.now() - startedAt);
						const rate = lastCompleted / elapsedMs;
						if (!Number.isFinite(rate) || rate <= 0) return null;
						const remainingMs = Math.max(0, (lastTotal - lastCompleted) / rate);
						const seconds = Math.floor(remainingMs / 1e3);
						const minutes = Math.floor(seconds / 60);
						const remainingSeconds = seconds % 60;
						return `${minutes}:${String(remainingSeconds).padStart(2, "0")}`;
					};
					const buildLabel = () => {
						const elapsed = formatElapsed();
						const eta = formatEta();
						return eta ? `${lastLabel} · elapsed ${elapsed} · eta ${eta}` : `${lastLabel} · elapsed ${elapsed}`;
					};
					if (!syncFn) {
						defaultRuntime.log("Memory backend does not support manual reindex.");
						return;
					}
					await withProgressTotals({
						label: "Indexing memory…",
						total: 0,
						fallback: opts.verbose ? "line" : void 0
					}, async (update, progress) => {
						const interval = setInterval(() => {
							progress.setLabel(buildLabel());
						}, 1e3);
						try {
							await syncFn({
								reason: "cli",
								force: Boolean(opts.force),
								progress: (syncUpdate) => {
									if (syncUpdate.label) lastLabel = syncUpdate.label;
									lastCompleted = syncUpdate.completed;
									lastTotal = syncUpdate.total;
									update({
										completed: syncUpdate.completed,
										total: syncUpdate.total,
										label: buildLabel()
									});
									progress.setLabel(buildLabel());
								}
							});
						} finally {
							clearInterval(interval);
						}
					});
					const qmdIndexSummary = await summarizeQmdIndexArtifact(manager);
					if (qmdIndexSummary) defaultRuntime.log(qmdIndexSummary);
					defaultRuntime.log(`Memory index updated (${agentId}).`);
				} catch (err) {
					const message = formatErrorMessage(err);
					defaultRuntime.error(`Memory index failed (${agentId}): ${message}`);
					process.exitCode = 1;
				}
			}
		});
	});
	memory.command("search").description("Search memory files").argument("[query]", "Search query").option("--query <text>", "Search query (alternative to positional argument)").option("--agent <id>", "Agent id (default: default agent)").option("--max-results <n>", "Max results", (value) => Number(value)).option("--min-score <n>", "Minimum score", (value) => Number(value)).option("--json", "Print JSON").action(async (queryArg, opts) => {
		const query = opts.query ?? queryArg;
		if (!query) {
			defaultRuntime.error("Missing search query. Provide a positional query or use --query <text>.");
			process.exitCode = 1;
			return;
		}
		const cfg = loadConfig();
		await withMemoryManagerForAgent({
			cfg,
			agentId: resolveAgent(cfg, opts.agent),
			run: async (manager) => {
				let results;
				try {
					results = await manager.search(query, {
						maxResults: opts.maxResults,
						minScore: opts.minScore
					});
				} catch (err) {
					const message = formatErrorMessage(err);
					defaultRuntime.error(`Memory search failed: ${message}`);
					process.exitCode = 1;
					return;
				}
				if (opts.json) {
					defaultRuntime.log(JSON.stringify({ results }, null, 2));
					return;
				}
				if (results.length === 0) {
					defaultRuntime.log("No matches.");
					return;
				}
				const rich = isRich();
				const lines = [];
				for (const result of results) {
					lines.push(`${colorize(rich, theme.success, result.score.toFixed(3))} ${colorize(rich, theme.accent, `${shortenHomePath(result.path)}:${result.startLine}-${result.endLine}`)}`);
					lines.push(colorize(rich, theme.muted, result.snippet));
					lines.push("");
				}
				defaultRuntime.log(lines.join("\n").trim());
			}
		});
	});
}

//#endregion
export { previewMemoryInventoryRepair as a, buildMemoryInventory as i, registerMemoryCli as n, validateMemoryInventory as o, executeMemoryRepair as r, memory_cli_exports as t };