import { execFile } from "node:child_process";
import { BUILTIN_RUN_COMMAND_MANIFEST } from "../contracts/builtin-run-command-manifest.js";
export const POLICY_TRACE_SCHEMA_VERSION = 1;
/** Maintainer doc (repo-relative) linked from policy denial output for `workspace-kit run`. */
export const POLICY_APPROVAL_HUMAN_DOC = "docs/maintainers/POLICY-APPROVAL.md";
/** Maintainer doc: tier table + copy-paste patterns for agents (Tier A/B `run` vs CLI env approval). */
export const AGENT_CLI_MAP_HUMAN_DOC = "docs/maintainers/AGENT-CLI-MAP.md";
/** Table: env vs JSON approval lanes (POLICY-APPROVAL). */
export const POLICY_APPROVAL_TWO_LANES_DOC = `${POLICY_APPROVAL_HUMAN_DOC}#two-approval-surfaces-do-not-mix-them-up`;
/** Canonical “what counts as approval” for `workspace-kit run` (chat/env lane mismatch). */
export const POLICY_APPROVAL_RUN_CANONICAL_DOC = `${POLICY_APPROVAL_HUMAN_DOC}#canonical-what-counts-as-approval-for-workspace-kit-run`;
/** When operators set WORKSPACE_KIT_POLICY_APPROVAL but invoke a sensitive `workspace-kit run` without JSON policyApproval. */
export const POLICY_RUN_ENV_LANE_MISMATCH_DETAIL = "WORKSPACE_KIT_POLICY_APPROVAL is not read for workspace-kit run; pass policyApproval inside the third JSON argument (or use a session grant / interactive approval per POLICY-APPROVAL).";
function buildBuiltinCommandToOperation() {
    const out = {};
    for (const row of BUILTIN_RUN_COMMAND_MANIFEST) {
        if (row.policyOperationId) {
            out[row.name] = row.policyOperationId;
        }
    }
    return out;
}
const COMMAND_TO_OPERATION = buildBuiltinCommandToOperation();
/** Shipped `workspace-kit run` sensitivity: single manifest-derived map (see `builtin-run-command-manifest.json`). */
const COMMAND_POLICY_SENSITIVITY = new Map(BUILTIN_RUN_COMMAND_MANIFEST.map((r) => [r.name, r.policySensitivity]));
export function getPolicySensitivityForBuiltinCommand(commandName) {
    return COMMAND_POLICY_SENSITIVITY.get(commandName);
}
export function getOperationIdForCommand(commandName) {
    return COMMAND_TO_OPERATION[commandName];
}
export function getExtraSensitiveModuleCommandsFromEffective(effective) {
    const policy = effective.policy;
    if (!policy || typeof policy !== "object" || Array.isArray(policy)) {
        return [];
    }
    const raw = policy.extraSensitiveModuleCommands;
    if (!Array.isArray(raw)) {
        return [];
    }
    return raw.filter((x) => typeof x === "string" && x.trim().length > 0);
}
/** Resolve operation id for tracing, including config-declared sensitive module commands. */
export function resolvePolicyOperationIdForCommand(commandName, effective) {
    const builtin = getOperationIdForCommand(commandName);
    if (builtin)
        return builtin;
    if (getExtraSensitiveModuleCommandsFromEffective(effective).includes(commandName)) {
        return "policy.dynamic-sensitive";
    }
    return undefined;
}
/**
 * Sensitive per shipped manifest `policySensitivity`.
 * `sensitive-with-dryrun` is waived when:
 * - `options.dryRun === true` (documentation generators), or
 * - `draft-plan-artifact` with `persist === false` (validate-only / Tier C).
 * - `review-plan-artifact` with `recordReview !== true` (findings-only / Tier C).
 * - `finalize-plan-to-phase` with `dryRun !== false` (preview / Tier C; default dryRun is true).
 */
export function isSensitiveModuleCommand(commandName, args) {
    const sens = COMMAND_POLICY_SENSITIVITY.get(commandName);
    if (!sens || sens === "non-sensitive") {
        return false;
    }
    if (sens === "sensitive-with-dryrun") {
        if (commandName === "draft-plan-artifact" && args.persist === false) {
            return false;
        }
        if (commandName === "review-plan-artifact" && args.recordReview !== true) {
            return false;
        }
        if (commandName === "finalize-plan-to-phase" && args.dryRun !== false) {
            return false;
        }
        const options = typeof args.options === "object" && args.options !== null
            ? args.options
            : {};
        if (options.dryRun === true) {
            return false;
        }
    }
    return true;
}
export function parsePolicyApprovalFromEnv(env) {
    const raw = env.WORKSPACE_KIT_POLICY_APPROVAL?.trim();
    if (!raw)
        return undefined;
    try {
        const o = JSON.parse(raw);
        if (o.confirmed !== true)
            return undefined;
        const rationale = typeof o.rationale === "string" ? o.rationale.trim() : "";
        if (!rationale)
            return undefined;
        return { confirmed: true, rationale };
    }
    catch {
        return undefined;
    }
}
export function parsePolicyApproval(args) {
    const raw = args.policyApproval;
    if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
        return undefined;
    }
    const o = raw;
    const confirmed = o.confirmed === true;
    const rationale = typeof o.rationale === "string" ? o.rationale.trim() : "";
    if (!confirmed || rationale.length === 0) {
        return undefined;
    }
    const scopeRaw = o.scope;
    const scope = scopeRaw === "session" || scopeRaw === "once" ? scopeRaw : undefined;
    return { confirmed, rationale, ...(scope ? { scope } : {}) };
}
export function resolveActor(_workspacePath, args, env) {
    if (typeof args.actor === "string" && args.actor.trim().length > 0) {
        return args.actor.trim();
    }
    const fromEnv = env.WORKSPACE_KIT_ACTOR?.trim();
    if (fromEnv)
        return fromEnv;
    return "unknown";
}
function runGitConfigValue(workspacePath, key, timeoutMs) {
    return new Promise((resolve) => {
        execFile("git", ["config", key], {
            cwd: workspacePath,
            encoding: "utf8",
            timeout: timeoutMs,
            windowsHide: true
        }, (error, stdout) => {
            if (error) {
                resolve(undefined);
                return;
            }
            const trimmed = stdout.trim();
            resolve(trimmed.length > 0 ? trimmed : undefined);
        });
    });
}
/**
 * Actor precedence:
 * 1) command args.actor
 * 2) WORKSPACE_KIT_ACTOR
 * 3) bounded git user.email/user.name lookup (unless WORKSPACE_KIT_ACTOR_GIT_LOOKUP=off)
 * 4) "unknown"
 */
export async function resolveActorWithFallback(workspacePath, args, env) {
    const explicit = resolveActor(workspacePath, args, env);
    if (explicit !== "unknown") {
        return explicit;
    }
    if (env.WORKSPACE_KIT_ACTOR_GIT_LOOKUP?.trim().toLowerCase() === "off") {
        return "unknown";
    }
    const timeoutMs = 300;
    const email = await runGitConfigValue(workspacePath, "user.email", timeoutMs);
    if (email)
        return email;
    const name = await runGitConfigValue(workspacePath, "user.name", timeoutMs);
    if (name)
        return name;
    return "unknown";
}
/** Policy sensitivity from built-in map plus `policy.extraSensitiveModuleCommands` on effective config. */
export function isSensitiveModuleCommandForEffective(commandName, args, effective) {
    if (isSensitiveModuleCommand(commandName, args)) {
        return true;
    }
    return getExtraSensitiveModuleCommandsFromEffective(effective).includes(commandName);
}
export async function appendPolicyTrace(workspacePath, record, effectiveConfig) {
    const { appendPolicyTraceRow, importPolicyTracesJsonlIfNeeded, openKitPolicyTraceDatabase } = await import("./state/kit-policy-traces-sqlite.js");
    const db = openKitPolicyTraceDatabase(workspacePath, effectiveConfig);
    try {
        importPolicyTracesJsonlIfNeeded(db, workspacePath);
        appendPolicyTraceRow(db, record);
    }
    finally {
        db.close();
    }
}
