/** Bounded, no-follow local project reads shared by localhost UI probes. */
import { realpath } from "node:fs/promises";
import { readProjectText } from "../health/read-only-fs.js";
import { isJsonObject } from "../sync/json-path.js";
import { deepMerge } from "../utils/index.js";
/**
 * Read one project-relative text file through deterministic Health confinement.
 * @param projectRoot - Project root, canonicalized before the read
 * @param relativePath - Strict project-relative path
 * @returns Bounded UTF-8 text, or undefined when absent
 */
export async function readConfinedProjectText(projectRoot, relativePath) {
    const root = await realpath(projectRoot);
    return await readProjectText(root, relativePath);
}
/**
 * Read and parse one confined JSON file.
 * @param projectRoot - Project root
 * @param relativePath - Strict project-relative JSON path
 * @returns Parsed JSON, or undefined when absent
 */
export async function readConfinedProjectJson(projectRoot, relativePath) {
    const text = await readConfinedProjectText(projectRoot, relativePath);
    return text === undefined ? undefined : JSON.parse(text);
}
/**
 * Read committed-plus-local Lisa config without following unsafe files.
 * @param projectRoot - Project root
 * @returns Merged config with the local overlay winning per key
 */
export async function readConfinedMergedConfig(projectRoot) {
    const [committed, local] = await Promise.all([
        readConfinedProjectJson(projectRoot, ".lisa.config.json"),
        readConfinedProjectJson(projectRoot, ".lisa.config.local.json"),
    ]);
    return deepMerge(isJsonObject(committed) ? committed : {}, isJsonObject(local) ? local : {});
}
//# sourceMappingURL=ui-confined-project-read.js.map