import { r as cloneOrRefreshRepoState } from "./src-DDJn_-JW.mjs";
import { i as sumBlockLockMetrics, o as readBlockConfig, t as collectPathSnapshot } from "./metrics-DMk3mFyO.mjs";
import { t as normalizeGithubUpstreamSource } from "./git-source-CDrBBD6o.mjs";
import { existsSync } from "node:fs";
import path from "node:path";
import { cp, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
import { parse, stringify } from "yaml";
//#region src/lib/block-lock.ts
const BLOCK_LOCK_FILE = "block-lock.yaml";
const CURRENT_BLOCK_LOCK_VERSION = 1;
const contentSections = [
	"agents",
	"commands",
	"plugins",
	"references",
	"rules",
	"skills"
];
function getBlockLockPath(blockRoot) {
	return path.join(blockRoot, BLOCK_LOCK_FILE);
}
async function readBlockLock(blockRoot, blockName) {
	const lockPath = getBlockLockPath(blockRoot);
	if (!existsSync(lockPath)) return createEmptyBlockLock(blockName);
	return normalizeBlockLock(parse(await readFile(lockPath, "utf8")), blockName);
}
async function writeBlockLock(blockRoot, lock) {
	await writeFile(getBlockLockPath(blockRoot), stringify(normalizeBlockLock(lock, lock.block), { singleQuote: true }), "utf8");
}
function createEmptyBlockLock(blockName) {
	return normalizeBlockLock({
		block: blockName,
		upstreams: {},
		version: CURRENT_BLOCK_LOCK_VERSION
	}, blockName);
}
function normalizeBlockLock(lock, blockName) {
	const content = Object.fromEntries(contentSections.map((section) => [section, sortRecord(lock?.[section])]));
	const upstreams = sortRecord(lock?.upstreams);
	const contentSummary = sumContentEntries(content);
	const upstreamSummary = sumBlockLockMetrics(Object.values(upstreams));
	return {
		version: CURRENT_BLOCK_LOCK_VERSION,
		block: typeof lock?.block === "string" && lock.block.length > 0 ? lock.block : blockName,
		summary: {
			...sumBlockLockMetrics([contentSummary, upstreamSummary]),
			content: contentSummary,
			upstream: upstreamSummary
		},
		agents: content.agents,
		commands: content.commands,
		plugins: content.plugins,
		references: content.references,
		rules: content.rules,
		skills: content.skills,
		upstreams
	};
}
function sumContentEntries(content) {
	return sumBlockLockMetrics(contentSections.flatMap((section) => Object.values(content[section] ?? {})));
}
function sortRecord(record) {
	return Object.fromEntries(Object.entries(record ?? {}).sort(([left], [right]) => left.localeCompare(right)));
}
//#endregion
//#region src/lib/block-upstreams.ts
const UPSTREAM_EXCLUDED_DIRECTORY_NAMES = new Set([".git", "node_modules"]);
const blockItemKinds = [
	"agents",
	"commands",
	"plugins",
	"references",
	"rules",
	"skills"
];
async function syncBlockUpstreams(blockRoot, upstreamKey) {
	const config = readBlockConfig(path.join(blockRoot, "block.yaml"));
	const upstreams = config.upstreams ?? {};
	const selected = upstreamKey ? { [upstreamKey]: upstreams[upstreamKey] } : upstreams;
	if (upstreamKey && !upstreams[upstreamKey]) throw new Error(`Unknown block upstream: ${upstreamKey}`);
	const lock = await readBlockLock(blockRoot, config.name);
	await pruneUndeclaredUpstreams(blockRoot, Object.keys(upstreams), lock);
	const fetched = [];
	for (const [key, upstream] of Object.entries(selected)) {
		if (!upstream) continue;
		const entry = upstream.source === "github" ? await fetchGithubUpstream(blockRoot, key, upstream) : await fetchWebUpstream(blockRoot, key, upstream);
		lock.upstreams[key] = mergeUpstreamLockEntry(lock.upstreams[key], entry);
		fetched.push(key);
	}
	await writeBlockLockFromCurrentState(blockRoot, config, lock);
	return {
		blockName: config.name,
		fetched,
		lockPath: getBlockLockPath(blockRoot)
	};
}
async function applyBlockUpstreamItem(blockRoot, kind, itemName) {
	const config = readBlockConfig(path.join(blockRoot, "block.yaml"));
	const item = config[kind]?.[itemName];
	if (!item) throw new Error(`Unknown block ${kind.slice(0, -1)} item: ${itemName}`);
	const refs = getItemUpstreamTargets(item);
	if (Object.keys(refs).length === 0) throw new Error(`Block ${kind.slice(0, -1)} item has no upstreams: ${itemName}`);
	if (item.mode === "derived") {
		await syncBlockUpstreams(blockRoot);
		return {
			applied: [],
			blockName: config.name,
			item: itemName,
			kind,
			mode: item.mode,
			skipped: Object.keys(refs).map((key) => path.join("upstreams", key))
		};
	}
	if (item.mode !== "vendored") throw new Error(`Only vendored items can be applied from upstreams: ${kind}.${itemName}`);
	const applied = [];
	for (const [key, relativeTarget] of Object.entries(refs)) {
		const sourcePath = path.join(blockRoot, "upstreams", key);
		if (!existsSync(sourcePath)) throw new Error(`Missing upstream snapshot: ${path.relative(blockRoot, sourcePath)}. Run sync first.`);
		const targetPath = resolveItemTargetPath(blockRoot, kind, itemName, relativeTarget);
		await rm(targetPath, {
			recursive: true,
			force: true
		});
		await mkdir(path.dirname(targetPath), { recursive: true });
		await cp(sourcePath, targetPath, { recursive: true });
		applied.push(path.relative(blockRoot, targetPath).split("\\").join("/"));
	}
	await writeBlockLockFromCurrentState(blockRoot, config);
	return {
		applied,
		blockName: config.name,
		item: itemName,
		kind,
		mode: item.mode,
		skipped: []
	};
}
async function checkBlockLockState(blockRoot) {
	const config = readBlockConfig(path.join(blockRoot, "block.yaml"));
	const failures = [];
	const lockPath = getBlockLockPath(blockRoot);
	const upstreamKeys = new Set(Object.keys(config.upstreams ?? {}));
	if (!existsSync(lockPath)) {
		pushBlockLockFailure(failures, "$.block-lock", "block-lock.yaml not found");
		return failures;
	}
	const lock = await readBlockLock(blockRoot, config.name);
	await validateDeclaredUpstreamEntries(failures, blockRoot, config, lock, upstreamKeys);
	validateUndeclaredUpstreamEntries(failures, lock, upstreamKeys);
	for (const kind of blockItemKinds) await validateBlockContentKind(failures, blockRoot, config, lock, kind, upstreamKeys);
	return failures;
}
async function validateDeclaredUpstreamEntries(failures, blockRoot, config, lock, upstreamKeys) {
	for (const key of upstreamKeys) {
		if (!existsSync(path.join(blockRoot, "upstreams", key))) {
			pushBlockLockFailure(failures, `$.upstreams.${key}`, `upstream snapshot not found: upstreams/${key}`);
			continue;
		}
		const entry = lock.upstreams[key];
		if (!entry) {
			pushBlockLockFailure(failures, `$.upstreams.${key}`, `block-lock.yaml missing upstream entry: ${key}`);
			continue;
		}
		failures.push(...await validateUpstreamLockEntry(blockRoot, key, config.upstreams?.[key], entry));
	}
}
function validateUndeclaredUpstreamEntries(failures, lock, upstreamKeys) {
	for (const key of Object.keys(lock.upstreams)) {
		if (upstreamKeys.has(key)) continue;
		pushBlockLockFailure(failures, `$.upstreams.${key}`, `block-lock.yaml has undeclared upstream entry: ${key}`);
	}
}
async function validateBlockContentKind(failures, blockRoot, config, lock, kind, upstreamKeys) {
	const expectedKeys = /* @__PURE__ */ new Set();
	for (const [itemName, item] of Object.entries(config[kind] ?? {})) {
		const lockKey = createBlockContentLockKey(config.name, kind, itemName);
		expectedKeys.add(lockKey);
		validateReferencedUpstreams(failures, kind, itemName, item, upstreamKeys);
		await validateBlockContentEntry(failures, blockRoot, lock, kind, itemName, item, lockKey);
	}
	for (const key of Object.keys(lock[kind])) {
		if (expectedKeys.has(key)) continue;
		pushBlockLockFailure(failures, `$.${kind}`, `block-lock.yaml has undeclared content entry: ${key}`);
	}
}
function validateReferencedUpstreams(failures, kind, itemName, item, upstreamKeys) {
	for (const upstreamName of Object.keys(getItemUpstreamTargets(item))) {
		if (upstreamKeys.has(upstreamName)) continue;
		pushBlockLockFailure(failures, `$.${kind}.${itemName}.upstreams.${upstreamName}`, `upstream reference not declared: ${upstreamName}`);
	}
}
async function validateBlockContentEntry(failures, blockRoot, lock, kind, itemName, item, lockKey) {
	const currentEntry = lock[kind][lockKey];
	if (!currentEntry) {
		pushBlockLockFailure(failures, `$.${kind}.${itemName}`, `block-lock.yaml missing content entry: ${lockKey}`);
		return;
	}
	try {
		if (!contentLockEntriesMatch(currentEntry, {
			...await createContentLockEntry(blockRoot, kind, itemName, item),
			updatedAt: currentEntry.updatedAt
		})) pushBlockLockFailure(failures, `$.${kind}.${itemName}`, `block-lock.yaml content entry is out of date: ${lockKey}`);
	} catch (error) {
		pushBlockLockFailure(failures, `$.${kind}.${itemName}`, error instanceof Error ? error.message : "failed to collect content provenance");
	}
}
function pushBlockLockFailure(failures, path, message) {
	failures.push({
		path,
		message
	});
}
async function pruneUndeclaredUpstreams(blockRoot, declaredUpstreamKeys, lock) {
	const declaredKeys = new Set(declaredUpstreamKeys);
	const upstreamsRoot = path.join(blockRoot, "upstreams");
	if (existsSync(upstreamsRoot)) for (const entry of await readdir(upstreamsRoot, { withFileTypes: true })) {
		if (!entry.isDirectory() || declaredKeys.has(entry.name)) continue;
		await rm(path.join(upstreamsRoot, entry.name), {
			recursive: true,
			force: true
		});
	}
	for (const key of Object.keys(lock.upstreams)) {
		if (declaredKeys.has(key)) continue;
		delete lock.upstreams[key];
	}
}
async function syncContentLockEntries(blockRoot, config, lock) {
	for (const kind of blockItemKinds) {
		const entries = {};
		for (const [itemName, item] of Object.entries(config[kind] ?? {})) {
			const lockKey = createBlockContentLockKey(config.name, kind, itemName);
			const nextEntry = await createContentLockEntry(blockRoot, kind, itemName, item);
			entries[lockKey] = mergeContentLockEntry(lock[kind][lockKey], nextEntry);
		}
		lock[kind] = entries;
	}
}
async function writeBlockLockFromCurrentState(blockRoot, config, currentLock) {
	const lock = currentLock ?? await readBlockLock(blockRoot, config.name);
	await syncContentLockEntries(blockRoot, config, lock);
	await writeBlockLock(blockRoot, normalizeBlockLock(lock, config.name));
}
async function validateUpstreamLockEntry(blockRoot, key, upstream, entry) {
	const failures = [];
	const expectedLocal = path.join("upstreams", key).split("\\").join("/");
	const snapshot = await collectPathSnapshot(path.join(blockRoot, "upstreams", key));
	if (entry.local !== expectedLocal) failures.push({
		path: `$.upstreams.${key}`,
		message: `block-lock.yaml local path mismatch: expected ${expectedLocal}`
	});
	if (entry.hash !== snapshot.hash || entry.chars !== snapshot.chars || entry.lines !== snapshot.lines || entry.tokens !== snapshot.tokens) failures.push({
		path: `$.upstreams.${key}`,
		message: `block-lock.yaml upstream entry is out of date: ${key}`
	});
	if (!upstream || entry.source !== upstream.source) {
		failures.push({
			path: `$.upstreams.${key}`,
			message: `block-lock.yaml source mismatch: ${key}`
		});
		return failures;
	}
	if (upstream.source === "github" && entry.source === "github") {
		if (entry.repo !== upstream.repo || entry.ref !== upstream.ref || entry.path !== upstream.path || !sameRecord(mapGithubPaths(entry.paths), upstream.paths)) failures.push({
			path: `$.upstreams.${key}`,
			message: `block-lock.yaml GitHub upstream metadata is out of date: ${key}`
		});
	} else if (upstream.source === "web" && entry.source === "web" && (entry.url !== upstream.url || !sameRecord(mapWebUrls(entry.urls), upstream.urls))) failures.push({
		path: `$.upstreams.${key}`,
		message: `block-lock.yaml web upstream metadata is out of date: ${key}`
	});
	return failures;
}
function mapGithubPaths(paths) {
	if (!paths) return;
	return Object.fromEntries(Object.entries(paths).map(([key, value]) => [key, value.path]));
}
function mapWebUrls(urls) {
	if (!urls) return;
	return Object.fromEntries(Object.entries(urls).map(([key, value]) => [key, value.url]));
}
function sameRecord(left, right) {
	return stableSerialize(left ?? {}) === stableSerialize(right ?? {});
}
function stableSerialize(value) {
	if (Array.isArray(value)) return `[${value.map((item) => stableSerialize(item)).join(",")}]`;
	if (value && typeof value === "object") return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableSerialize(item)}`).join(",")}}`;
	return JSON.stringify(value);
}
async function fetchGithubUpstream(blockRoot, key, upstream) {
	const targetRoot = path.join(blockRoot, "upstreams", key);
	await resetDirectory(targetRoot);
	const source = normalizeGithubUpstreamSource(upstream);
	const repo = await cloneOrRefreshRepoState(source.url, source.ref, { paths: upstream.path ? [upstream.path] : Object.values(upstream.paths ?? {}) });
	if (upstream.path) {
		const result = await copyCachedGithubPath(repo.repoPath, upstream.path, targetRoot);
		return {
			...await collectPathSnapshot(targetRoot),
			commit: repo.headSha,
			kind: result.kind,
			local: path.relative(blockRoot, targetRoot).split("\\").join("/"),
			modifiedAt: repo.modifiedAt,
			path: upstream.path,
			ref: upstream.ref,
			repo: upstream.repo,
			source: "github"
		};
	}
	const copyPlans = await planGithubUpstreamCopies(repo.repoPath, targetRoot, upstream.paths ?? {});
	validateGithubUpstreamCopyPlans(targetRoot, copyPlans);
	const paths = {};
	for (const copyPlan of copyPlans) {
		await materializeGithubUpstreamCopy(copyPlan, repo.repoPath);
		const snapshot = await collectPathSnapshot(copyPlan.targetPath);
		paths[copyPlan.target] = {
			...snapshot,
			kind: copyPlan.kind,
			local: path.relative(blockRoot, copyPlan.targetPath).split("\\").join("/"),
			path: copyPlan.sourcePath
		};
	}
	return {
		...await collectPathSnapshot(targetRoot),
		commit: repo.headSha,
		local: path.relative(blockRoot, targetRoot).split("\\").join("/"),
		modifiedAt: repo.modifiedAt,
		paths,
		ref: upstream.ref,
		repo: upstream.repo,
		source: "github"
	};
}
async function fetchWebUpstream(blockRoot, key, upstream) {
	const targetRoot = path.join(blockRoot, "upstreams", key);
	await resetDirectory(targetRoot);
	if (upstream.url) {
		await writeFile(path.join(targetRoot, "content.md"), await fetchWebMarkdown(upstream.url), "utf8");
		return {
			...await collectPathSnapshot(targetRoot),
			local: path.relative(blockRoot, targetRoot).split("\\").join("/"),
			source: "web",
			url: upstream.url
		};
	}
	const urls = {};
	for (const [urlKey, sourceUrl] of Object.entries(upstream.urls ?? {})) {
		const targetPath = path.join(targetRoot, `${urlKey}.md`);
		await writeFile(targetPath, await fetchWebMarkdown(sourceUrl), "utf8");
		urls[urlKey] = {
			...await collectPathSnapshot(targetPath),
			local: path.relative(blockRoot, targetPath).split("\\").join("/"),
			url: sourceUrl
		};
	}
	return {
		...await collectPathSnapshot(targetRoot),
		local: path.relative(blockRoot, targetRoot).split("\\").join("/"),
		source: "web",
		urls
	};
}
async function copyCachedGithubPath(repoPath, sourcePath, targetPath) {
	const absoluteSourcePath = resolveGithubSourceAbsolutePath(repoPath, sourcePath);
	if (!existsSync(absoluteSourcePath)) throw new Error(`Failed to materialize git upstream path: ${sourcePath}`);
	if ((await import("node:fs/promises").then((module) => module.stat(absoluteSourcePath))).isDirectory()) {
		await mkdir(targetPath, { recursive: true });
		await copyFilteredDirectory(absoluteSourcePath, targetPath);
		return { kind: "folder" };
	}
	await mkdir(targetPath, { recursive: true });
	await cp(absoluteSourcePath, path.join(targetPath, path.basename(absoluteSourcePath)), {
		force: true,
		recursive: true
	});
	return { kind: "file" };
}
async function planGithubUpstreamCopies(repoPath, targetRoot, paths) {
	const plans = [];
	for (const [target, sourcePath] of Object.entries(paths)) {
		const absoluteSourcePath = resolveGithubSourceAbsolutePath(repoPath, sourcePath);
		if (!existsSync(absoluteSourcePath)) throw new Error(`Failed to materialize git upstream path: ${sourcePath}`);
		const stats = await import("node:fs/promises").then((module) => module.stat(absoluteSourcePath));
		plans.push({
			kind: stats.isDirectory() ? "folder" : "file",
			sourcePath,
			target,
			targetPath: target === "." ? targetRoot : path.join(targetRoot, target)
		});
	}
	return plans;
}
function validateGithubUpstreamCopyPlans(targetRoot, plans) {
	const seenExact = /* @__PURE__ */ new Map();
	const seenCaseFolded = /* @__PURE__ */ new Map();
	const normalizedPlans = plans.map((plan) => {
		const resolvedTargetPath = path.resolve(plan.targetPath);
		const relativeTargetPath = path.relative(targetRoot, resolvedTargetPath);
		if (relativeTargetPath.startsWith("..") || path.isAbsolute(relativeTargetPath)) throw new Error(`Invalid git upstream target path: ${plan.target}`);
		if (plan.kind === "file" && plan.target === ".") throw new Error(`Git upstream file sources require an explicit file target: ${plan.sourcePath}`);
		const exactConflict = seenExact.get(resolvedTargetPath);
		if (exactConflict) throw new Error(`Conflicting git upstream target paths: ${exactConflict} and ${plan.target}`);
		seenExact.set(resolvedTargetPath, plan.target);
		const caseFoldedTargetPath = resolvedTargetPath.toLowerCase();
		const caseConflict = seenCaseFolded.get(caseFoldedTargetPath);
		if (caseConflict) throw new Error(`Conflicting git upstream target paths: ${caseConflict} and ${plan.target}`);
		seenCaseFolded.set(caseFoldedTargetPath, plan.target);
		return {
			...plan,
			resolvedTargetPath
		};
	});
	for (let index = 0; index < normalizedPlans.length; index += 1) {
		const current = normalizedPlans[index];
		for (let compareIndex = index + 1; compareIndex < normalizedPlans.length; compareIndex += 1) {
			const compared = normalizedPlans[compareIndex];
			const currentPrefix = `${current.resolvedTargetPath}${path.sep}`;
			const comparedPrefix = `${compared.resolvedTargetPath}${path.sep}`;
			if (current.resolvedTargetPath.startsWith(comparedPrefix) || compared.resolvedTargetPath.startsWith(currentPrefix)) throw new Error(`Overlapping git upstream target paths: ${current.target} and ${compared.target}`);
		}
	}
}
async function materializeGithubUpstreamCopy(plan, repoPath) {
	const absoluteSourcePath = resolveGithubSourceAbsolutePath(repoPath, plan.sourcePath);
	await rm(plan.targetPath, {
		recursive: true,
		force: true
	});
	if (plan.kind === "folder") {
		await mkdir(plan.targetPath, { recursive: true });
		await copyFilteredDirectory(absoluteSourcePath, plan.targetPath);
		return;
	}
	await mkdir(path.dirname(plan.targetPath), { recursive: true });
	await cp(absoluteSourcePath, plan.targetPath, {
		force: true,
		recursive: true
	});
}
function resolveGithubSourceAbsolutePath(repoPath, sourcePath) {
	const normalizedPath = sourcePath === "." ? "" : path.posix.normalize(sourcePath);
	return normalizedPath.length === 0 ? repoPath : path.join(repoPath, normalizedPath);
}
async function copyFilteredDirectory(sourcePath, targetPath) {
	await mkdir(targetPath, { recursive: true });
	const entries = await readdir(sourcePath, { withFileTypes: true });
	await Promise.all(entries.map(async (entry) => {
		if (entry.isDirectory() && UPSTREAM_EXCLUDED_DIRECTORY_NAMES.has(entry.name)) return;
		const sourceEntry = path.join(sourcePath, entry.name);
		const targetEntry = path.join(targetPath, entry.name);
		if (entry.isDirectory()) {
			await copyFilteredDirectory(sourceEntry, targetEntry);
			return;
		}
		await cp(sourceEntry, targetEntry, {
			force: true,
			recursive: true
		});
	}));
}
async function fetchWebMarkdown(url) {
	const response = await fetch(url);
	if (!response.ok) throw new Error(`Failed to fetch web upstream ${url}: ${response.status} ${response.statusText}`);
	const raw = await response.text();
	const markdown = looksLikeHtml(raw) ? htmlToMarkdown(raw) : raw;
	return markdown.endsWith("\n") ? markdown : `${markdown}\n`;
}
function looksLikeHtml(value) {
	return /<html[\s>]|<body[\s>]|<main[\s>]|<article[\s>]/i.test(value);
}
function htmlToMarkdown(value) {
	return value.replace(/<script[\s\S]*?<\/script>/gi, "").replace(/<style[\s\S]*?<\/style>/gi, "").replace(/<h1[^>]*>([\s\S]*?)<\/h1>/gi, "# $1\n\n").replace(/<h2[^>]*>([\s\S]*?)<\/h2>/gi, "## $1\n\n").replace(/<h3[^>]*>([\s\S]*?)<\/h3>/gi, "### $1\n\n").replace(/<p[^>]*>([\s\S]*?)<\/p>/gi, "$1\n\n").replace(/<li[^>]*>([\s\S]*?)<\/li>/gi, "- $1\n").replace(/<[^>]+>/g, "").replace(/&nbsp;/g, " ").replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/\n{3,}/g, "\n\n").trim();
}
async function resetDirectory(directoryPath) {
	await rm(directoryPath, {
		recursive: true,
		force: true
	});
	await mkdir(directoryPath, { recursive: true });
}
function getItemUpstreamTargets(item) {
	if (item.upstream) return { [item.upstream]: "." };
	return item.upstreams ?? {};
}
function resolveItemTargetPath(blockRoot, kind, itemName, relativeTarget) {
	const itemRoot = resolveItemRootPath(blockRoot, kind, itemName);
	if (relativeTarget === ".") return itemRoot;
	return path.join(itemRoot, relativeTarget);
}
function resolveItemRootPath(blockRoot, kind, itemName) {
	const contentRoot = path.join(blockRoot, "content");
	switch (kind) {
		case "agents": return path.join(contentRoot, "agents", `${itemName}.md`);
		case "commands": return path.join(contentRoot, "commands", `${itemName}.md`);
		case "plugins": return existsSync(path.join(contentRoot, "plugins", itemName)) ? path.join(contentRoot, "plugins", itemName) : path.join(contentRoot, "plugins", `${itemName}.ts`);
		case "references": return existsSync(path.join(contentRoot, "references", itemName, "content.md")) ? path.join(contentRoot, "references", itemName) : path.join(contentRoot, "references", `${itemName}.md`);
		case "rules": return path.join(contentRoot, "rules", `${itemName}.md`);
		case "skills": return path.join(contentRoot, "skills", itemName);
		default: return path.join(contentRoot, kind, itemName);
	}
}
function resolveItemSnapshotPath(blockRoot, kind, itemName) {
	const itemRoot = resolveItemRootPath(blockRoot, kind, itemName);
	if (kind === "skills") {
		const skillPath = path.join(itemRoot, "SKILL.md");
		return existsSync(skillPath) ? skillPath : itemRoot;
	}
	return itemRoot;
}
async function createContentLockEntry(blockRoot, kind, itemName, item) {
	const snapshotPath = resolveItemSnapshotPath(blockRoot, kind, itemName);
	return {
		...await collectPathSnapshot(snapshotPath),
		mode: item.mode,
		path: path.relative(blockRoot, snapshotPath).split("\\").join("/"),
		...item.upstream ? { upstream: item.upstream } : {},
		...item.upstreams ? { upstreams: item.upstreams } : {}
	};
}
function createBlockContentLockKey(blockName, kind, itemName) {
	return `anvil:${blockName}/${kind}/${itemName}`;
}
function contentLockEntriesMatch(current, expected) {
	return current.chars === expected.chars && current.hash === expected.hash && current.lines === expected.lines && current.mode === expected.mode && current.path === expected.path && current.tokens === expected.tokens && current.upstream === expected.upstream && sameRecord(current.upstreams, expected.upstreams);
}
function mergeContentLockEntry(current, next) {
	const updatedAt = current && contentLockEntriesMatch(current, {
		...next,
		updatedAt: current.updatedAt
	}) ? current.updatedAt : (/* @__PURE__ */ new Date()).toISOString();
	return {
		...next,
		updatedAt
	};
}
function mergeUpstreamLockEntry(current, next) {
	const updatedAt = current && upstreamLockEntriesMatch(current, {
		...next,
		updatedAt: current.updatedAt
	}) ? current.updatedAt : (/* @__PURE__ */ new Date()).toISOString();
	return {
		...next,
		updatedAt
	};
}
function upstreamLockEntriesMatch(current, expected) {
	if (current.chars !== expected.chars || current.hash !== expected.hash || current.lines !== expected.lines || current.local !== expected.local || current.modifiedAt !== expected.modifiedAt || current.source !== expected.source || current.tokens !== expected.tokens) return false;
	if (current.source === "github" && expected.source === "github") return current.commit === expected.commit && current.kind === expected.kind && current.path === expected.path && sameRecord(current.paths, expected.paths) && current.ref === expected.ref && current.repo === expected.repo;
	if (current.source === "web" && expected.source === "web") return current.url === expected.url && sameRecord(current.urls, expected.urls);
	return false;
}
//#endregion
export { checkBlockLockState as n, syncBlockUpstreams as r, applyBlockUpstreamItem as t };

//# sourceMappingURL=block-upstreams-CV5bdDNL.mjs.map