import {
  parseYAML
} from "./chunk-NRIZR3A7.js";
import {
  ENV_VARS,
  LUMENFLOW_PATHS,
  STRING_LITERALS,
  getProjectRoot,
  toKebab
} from "./chunk-DWMLTXKQ.js";
import {
  WORKSPACE_CONFIG_FILE_NAME,
  WORKSPACE_V2_KEYS,
  WU_STATUS,
  asRecord,
  findProjectRoot,
  getConfig,
  resolveWUStatus
} from "./chunk-V6OJGLBA.js";
import {
  ErrorCodes,
  createError
} from "./chunk-RXRKBBSM.js";
import {
  __require
} from "./chunk-3RG5ZIWI.js";

// ../core/dist/lane-lock.js
import { openSync, closeSync, writeFileSync, readFileSync as readFileSync2, unlinkSync, existsSync as existsSync2, mkdirSync } from "fs";
import path2 from "path";

// ../core/dist/lane-checker.js
import { existsSync, readFileSync } from "fs";
import path from "path";

// ../core/dist/constants/backlog-patterns.js
var IN_PROGRESS_HEADERS = ["## in progress", "## \u{1F527} in progress"];
var WU_LINK_PATTERN = /\[([A-Z]+-\d+)\s*—\s*[^\]]+\]\([^)]+\)/gi;
function isInProgressHeader(line) {
  const normalized = line.trim().toLowerCase();
  return IN_PROGRESS_HEADERS.some((header) => normalized === header || normalized.startsWith(header));
}

// ../core/dist/lane-checker.js
var ACTIVE_COUNTED_STATUSES_ALL = /* @__PURE__ */ new Set([WU_STATUS.IN_PROGRESS, WU_STATUS.BLOCKED]);
var ACTIVE_COUNTED_STATUSES_PROGRESS_ONLY = /* @__PURE__ */ new Set([WU_STATUS.IN_PROGRESS]);
var PREFIX = "[lane-checker]";
var SOFTWARE_DELIVERY_KEY = WORKSPACE_V2_KEYS.SOFTWARE_DELIVERY;
var LANE_DEFINITIONS_HINT = `${WORKSPACE_CONFIG_FILE_NAME} (${SOFTWARE_DELIVERY_KEY}.lanes.definitions)`;
var NO_ITEMS_MARKER = "No items currently in progress";
function extractParent(lane) {
  const trimmed = lane.trim();
  const colonIndex = trimmed.indexOf(":");
  if (colonIndex === -1) {
    return trimmed;
  }
  return trimmed.substring(0, colonIndex).trim();
}
function countChar(str, char) {
  let count = 0;
  for (const c of str) {
    if (c === char)
      count++;
  }
  return count;
}
var LANE_SEPARATOR = ":";
var SPACE = " ";
function validateColonFormat(lane, trimmed, colonIndex) {
  if (colonIndex > 0 && trimmed[colonIndex - 1] === SPACE) {
    throw createError(ErrorCodes.INVALID_LANE, `Invalid lane format: "${lane}" has space before colon. Expected format: "Parent: Subdomain" (space AFTER colon only)`, { lane });
  }
  if (colonIndex + 1 >= trimmed.length || trimmed[colonIndex + 1] !== SPACE) {
    throw createError(ErrorCodes.INVALID_LANE, `Invalid lane format: "${lane}" is missing space after colon. Expected format: "Parent: Subdomain"`, { lane });
  }
}
function validateSubLaneFormat(lane, trimmed, colonIndex, configPath) {
  validateColonFormat(lane, trimmed, colonIndex);
  const parent = trimmed.substring(0, colonIndex).trim();
  const subdomain = trimmed.substring(colonIndex + LANE_SEPARATOR.length + SPACE.length).trim();
  if (!isValidParentLane(parent, configPath)) {
    throw createError(ErrorCodes.INVALID_LANE, `Unknown parent lane: "${parent}". Check ${LANE_DEFINITIONS_HINT} for valid lanes.`, { parent, lane });
  }
  validateSubLaneInWorkspaceDefinitions(parent, subdomain, lane, configPath);
  return { valid: true, parent, error: null };
}
function validateSubLaneInWorkspaceDefinitions(parent, subdomain, lane, configPath) {
  const validSubLanes = getConfiguredSubLanesForParent(parent, configPath);
  if (validSubLanes.length === 0) {
    throw createError(ErrorCodes.INVALID_LANE, `Parent lane "${parent}" does not support sub-lanes in ${LANE_DEFINITIONS_HINT}. Use parent-only format "${parent}" or add "${parent}: <sublane>" to workspace.yaml.`, { parent, lane });
  }
  if (!validSubLanes.includes(subdomain)) {
    throw createError(ErrorCodes.INVALID_LANE, `Unknown sub-lane: "${subdomain}" for parent lane "${parent}".

Valid sub-lanes in ${LANE_DEFINITIONS_HINT}: ${validSubLanes.join(", ")}`, { parent, subdomain, validSubLanes });
  }
}
function validateParentOnlyFormat(trimmed, configPath, strict) {
  if (!isValidParentLane(trimmed, configPath)) {
    throw createError(ErrorCodes.INVALID_LANE, `Unknown parent lane: "${trimmed}". Check ${LANE_DEFINITIONS_HINT} for valid lanes.`, { lane: trimmed });
  }
  const validSubLanes = getConfiguredSubLanesForParent(trimmed, configPath);
  if (validSubLanes.length > 0) {
    const message = `Parent-only lane "${trimmed}" blocked. Sub-lane required. Valid: ${validSubLanes.join(", ")}. Format: "${trimmed}: <sublane>"`;
    if (strict) {
      throw createError(ErrorCodes.INVALID_LANE, message, { lane: trimmed, validSubLanes });
    }
    console.warn(`${PREFIX} \u26A0\uFE0F  ${message}`);
  }
  return { valid: true, parent: trimmed, error: null };
}
function validateLaneFormat(lane, configPath = null, options = {}) {
  const { strict = true } = options;
  const trimmed = lane.trim();
  const colonCount = countChar(trimmed, LANE_SEPARATOR);
  if (colonCount > 1) {
    throw createError(ErrorCodes.INVALID_LANE, `Invalid lane format: "${lane}" contains multiple colons. Expected format: "Parent: Subdomain" or "Parent"`, { lane });
  }
  const colonIndex = trimmed.indexOf(LANE_SEPARATOR);
  const isSubLaneFormat = colonIndex !== -1;
  if (isSubLaneFormat) {
    return validateSubLaneFormat(lane, trimmed, colonIndex, configPath);
  }
  return validateParentOnlyFormat(trimmed, configPath, strict);
}
function extractLanesForParentCheck(config) {
  const allLanes = [];
  const parentLanes = /* @__PURE__ */ new Set();
  if (!config.lanes) {
    return { allLanes, parentLanes };
  }
  if (Array.isArray(config.lanes)) {
    allLanes.push(...config.lanes.map((l) => l.name));
    return { allLanes, parentLanes };
  }
  if (config.lanes.definitions) {
    for (const lane of config.lanes.definitions) {
      allLanes.push(lane.name);
      const extracted = extractParent(lane.name);
      parentLanes.add(extracted.toLowerCase().trim());
    }
  }
  if (config.lanes.engineering) {
    allLanes.push(...config.lanes.engineering.map((l) => l.name));
  }
  if (config.lanes.business) {
    allLanes.push(...config.lanes.business.map((l) => l.name));
  }
  return { allLanes, parentLanes };
}
function resolveConfigPath(configPath) {
  if (configPath) {
    return configPath;
  }
  const projectRoot = findProjectRoot();
  return path.join(projectRoot, WORKSPACE_CONFIG_FILE_NAME);
}
function readConfigFromPath(configPath) {
  if (!existsSync(configPath)) {
    return null;
  }
  try {
    const configContent = readFileSync(configPath, { encoding: "utf-8" });
    const parsed = parseYAML(configContent);
    const workspace = asRecord(parsed);
    if (!workspace) {
      return null;
    }
    const softwareDelivery = asRecord(workspace[SOFTWARE_DELIVERY_KEY]);
    if (!softwareDelivery) {
      return null;
    }
    return softwareDelivery;
  } catch {
    return null;
  }
}
function readRuntimeConfig(projectRoot) {
  const workspacePath = path.join(projectRoot, WORKSPACE_CONFIG_FILE_NAME);
  if (!existsSync(workspacePath)) {
    return { kind: "missing", config: null };
  }
  try {
    const config = getConfig({
      projectRoot,
      reload: true,
      strictWorkspace: true
    });
    return { kind: "ok", config: { lanes: config.lanes } };
  } catch {
    return { kind: "invalid", config: null };
  }
}
function loadLanesConfig(configPath) {
  const resolvedConfigPath = resolveConfigPath(configPath);
  let config;
  if (configPath !== null) {
    config = readConfigFromPath(resolvedConfigPath);
  } else {
    const result = readRuntimeConfig(findProjectRoot());
    if (result.kind === "invalid") {
      throw createError(ErrorCodes.CONFIG_ERROR, `workspace.yaml exists but failed validation: ${resolvedConfigPath}

The control_plane section may have an incompatible schema.
Run: pnpm lumenflow:doctor  to diagnose config issues.`, { path: resolvedConfigPath });
    }
    config = result.config;
  }
  if (!config) {
    throw createError(ErrorCodes.FILE_NOT_FOUND, `Config file not found: ${resolvedConfigPath}`, {
      path: resolvedConfigPath
    });
  }
  return { config, resolvedConfigPath };
}
function getConfiguredSubLanesForParent(parent, configPath = null) {
  const { config } = loadLanesConfig(configPath);
  const { allLanes } = extractLanesForParentCheck(config);
  const normalizedParent = parent.toLowerCase().trim();
  const subLanes = /* @__PURE__ */ new Set();
  for (const laneName of allLanes) {
    const trimmedLane = laneName.trim();
    const colonIndex = trimmedLane.indexOf(LANE_SEPARATOR);
    if (colonIndex === -1) {
      continue;
    }
    const laneParent = trimmedLane.substring(0, colonIndex).trim().toLowerCase();
    if (laneParent !== normalizedParent) {
      continue;
    }
    const subLane = trimmedLane.substring(colonIndex + 1).trim();
    if (subLane.length > 0) {
      subLanes.add(subLane);
    }
  }
  return [...subLanes];
}
function isValidParentLane(parent, configPath = null) {
  const { config } = loadLanesConfig(configPath);
  const { allLanes, parentLanes } = extractLanesForParentCheck(config);
  const normalizedParent = parent.toLowerCase().trim();
  if (parentLanes.size > 0) {
    return parentLanes.has(normalizedParent);
  }
  return allLanes.some((lane) => lane.toLowerCase().trim() === normalizedParent);
}
var DEFAULT_WIP_LIMIT = 1;
function getWipLimitForLane(lane, options = {}) {
  const config = options.configPath ? readConfigFromPath(options.configPath) : readRuntimeConfig(findProjectRoot()).config;
  if (!config?.lanes) {
    return DEFAULT_WIP_LIMIT;
  }
  const normalizedLane = lane.toLowerCase().trim();
  const allLanes = extractAllLanesFromConfig(config);
  const matchingLane = allLanes.find((l) => l.name.toLowerCase().trim() === normalizedLane);
  return matchingLane?.wip_limit ?? DEFAULT_WIP_LIMIT;
}
var DEFAULT_LOCK_POLICY = "all";
function getLockPolicyForLane(lane, options = {}) {
  const config = options.configPath ? readConfigFromPath(options.configPath) : readRuntimeConfig(findProjectRoot()).config;
  if (!config?.lanes) {
    return DEFAULT_LOCK_POLICY;
  }
  const normalizedLane = lane.toLowerCase().trim();
  const allLanes = extractAllLanesFromConfig(config);
  const matchingLane = allLanes.find((l) => l.name.toLowerCase().trim() === normalizedLane);
  const policy = matchingLane?.lock_policy;
  return policy === "all" || policy === "active" || policy === "none" ? policy : DEFAULT_LOCK_POLICY;
}
var SECTION_HEADING_PREFIX = "## ";
function createEmptyLaneResult(wipLimit) {
  return {
    free: true,
    occupiedBy: null,
    error: null,
    inProgressWUs: [],
    wipLimit,
    currentCount: 0
  };
}
function extractInProgressSection(lines) {
  const inProgressIdx = lines.findIndex((l) => isInProgressHeader(l));
  if (inProgressIdx === -1) {
    return { section: "", error: 'Could not find "## In Progress" section in status.md' };
  }
  let endIdx = lines.slice(inProgressIdx + 1).findIndex((l) => l.startsWith(SECTION_HEADING_PREFIX));
  if (endIdx === -1) {
    endIdx = lines.length - inProgressIdx - 1;
  } else {
    endIdx = inProgressIdx + 1 + endIdx;
  }
  const section = lines.slice(inProgressIdx + 1, endIdx).join(STRING_LITERALS.NEWLINE);
  return { section, error: null };
}
var BLOCKED_HEADERS = ["## blocked", "## \u26D4 blocked"];
function isBlockedHeader(line) {
  const normalized = line.trim().toLowerCase();
  return BLOCKED_HEADERS.some((header) => normalized === header || normalized.startsWith(header));
}
function extractBlockedSection(lines) {
  const blockedIdx = lines.findIndex((l) => isBlockedHeader(l));
  if (blockedIdx === -1) {
    return { section: "" };
  }
  let endIdx = lines.slice(blockedIdx + 1).findIndex((l) => l.startsWith(SECTION_HEADING_PREFIX));
  if (endIdx === -1) {
    endIdx = lines.length - blockedIdx - 1;
  } else {
    endIdx = blockedIdx + 1 + endIdx;
  }
  const section = lines.slice(blockedIdx + 1, endIdx).join(STRING_LITERALS.NEWLINE);
  return { section };
}
function checkWuLaneMatch(activeWuid, wuid, wuDir, targetLane, allowedStatuses) {
  if (activeWuid === wuid) {
    return null;
  }
  const wuPath = path.join(wuDir, `${activeWuid}.yaml`);
  if (!existsSync(wuPath)) {
    console.warn(`${PREFIX} Warning: ${activeWuid} referenced in status.md but ${wuPath} not found`);
    return null;
  }
  try {
    const wuContent = readFileSync(wuPath, { encoding: "utf-8" });
    const wuDoc = parseYAML(wuContent);
    if (!wuDoc || !wuDoc.lane) {
      console.warn(`${PREFIX} Warning: ${activeWuid} has no lane field`);
      return null;
    }
    const activeLane = wuDoc.lane.toString().trim().toLowerCase();
    const resolvedStatus = resolveWUStatus(wuDoc.status);
    if (activeLane === targetLane && allowedStatuses.has(resolvedStatus)) {
      return activeWuid;
    }
  } catch (e) {
    const errMessage = e instanceof Error ? e.message : String(e);
    console.warn(`${PREFIX} Warning: Failed to parse ${activeWuid} YAML: ${errMessage}`);
  }
  return null;
}
function collectInProgressWUsForLane(matches, wuid, wuDir, targetLane, allowedStatuses) {
  const inProgressWUs = [];
  for (const match of matches) {
    const activeWuid = match[1];
    if (!activeWuid) {
      continue;
    }
    const matchedWu = checkWuLaneMatch(activeWuid, wuid, wuDir, targetLane, allowedStatuses);
    if (matchedWu) {
      inProgressWUs.push(matchedWu);
    }
  }
  return inProgressWUs;
}
function extractWUsFromSection(section, wuid, wuDir, targetLane, allowedStatuses) {
  if (!section || section.includes(NO_ITEMS_MARKER)) {
    return [];
  }
  WU_LINK_PATTERN.lastIndex = 0;
  const matches = [...section.matchAll(WU_LINK_PATTERN)];
  if (matches.length === 0) {
    return [];
  }
  return collectInProgressWUsForLane(matches, wuid, wuDir, targetLane, allowedStatuses);
}
function checkLaneFree(statusPath, lane, wuid, options = {}) {
  try {
    const wipLimit = getWipLimitForLane(lane, { configPath: options.configPath });
    const lockPolicy = getLockPolicyForLane(lane, { configPath: options.configPath });
    if (lockPolicy === "none") {
      return createEmptyLaneResult(wipLimit);
    }
    if (!existsSync(statusPath)) {
      return { free: false, occupiedBy: null, error: `status.md not found: ${statusPath}` };
    }
    const content = readFileSync(statusPath, { encoding: "utf-8" });
    const lines = content.split(/\r?\n/);
    const { section: inProgressSection, error } = extractInProgressSection(lines);
    if (error) {
      return { free: false, occupiedBy: null, error };
    }
    const resolvedStatusPath = path.resolve(statusPath);
    const projectRoot = findProjectRoot(path.dirname(resolvedStatusPath));
    const wuDir = path.join(projectRoot, getConfig({ projectRoot }).directories.wuDir);
    const targetLane = lane.toString().trim().toLowerCase();
    const inProgressAllowedStatuses = lockPolicy === "all" ? ACTIVE_COUNTED_STATUSES_ALL : ACTIVE_COUNTED_STATUSES_PROGRESS_ONLY;
    const inProgressWUs = extractWUsFromSection(inProgressSection, wuid, wuDir, targetLane, inProgressAllowedStatuses);
    let blockedWUs = [];
    if (lockPolicy === "all") {
      const { section: blockedSection } = extractBlockedSection(lines);
      blockedWUs = extractWUsFromSection(blockedSection, wuid, wuDir, targetLane, ACTIVE_COUNTED_STATUSES_ALL);
    }
    const allCountedWUs = [...inProgressWUs, ...blockedWUs];
    const currentCount = allCountedWUs.length;
    const isFree = currentCount < wipLimit;
    return {
      free: isFree,
      occupiedBy: isFree ? null : allCountedWUs[0] || null,
      error: null,
      inProgressWUs: allCountedWUs,
      // Include all counted WUs for visibility
      wipLimit,
      currentCount
    };
  } catch (error) {
    const errMessage = error instanceof Error ? error.message : String(error);
    return { free: false, occupiedBy: null, error: `Unexpected error: ${errMessage}` };
  }
}
var NO_JUSTIFICATION_REQUIRED = {
  valid: true,
  warning: null,
  requiresJustification: false
};
function extractAllLanesFromConfig(config) {
  if (!config.lanes) {
    return [];
  }
  if (Array.isArray(config.lanes)) {
    return config.lanes;
  }
  const allLanes = [];
  if (config.lanes.definitions) {
    allLanes.push(...config.lanes.definitions);
  }
  if (config.lanes.engineering) {
    allLanes.push(...config.lanes.engineering);
  }
  if (config.lanes.business) {
    allLanes.push(...config.lanes.business);
  }
  return allLanes;
}
function checkWipJustification(lane, options = {}) {
  const config = options.configPath ? readConfigFromPath(options.configPath) : readRuntimeConfig(findProjectRoot()).config;
  if (!config) {
    return NO_JUSTIFICATION_REQUIRED;
  }
  const allLanes = extractAllLanesFromConfig(config);
  if (allLanes.length === 0) {
    return NO_JUSTIFICATION_REQUIRED;
  }
  const normalizedLane = lane.toLowerCase().trim();
  const matchingLane = allLanes.find((l) => l.name.toLowerCase().trim() === normalizedLane);
  if (!matchingLane) {
    return NO_JUSTIFICATION_REQUIRED;
  }
  const wipLimit = matchingLane.wip_limit ?? DEFAULT_WIP_LIMIT;
  if (wipLimit <= 1) {
    return NO_JUSTIFICATION_REQUIRED;
  }
  const justification = matchingLane.wip_justification;
  if (justification && justification.trim().length > 0) {
    return {
      valid: true,
      warning: null,
      requiresJustification: false,
      justification: justification.trim()
    };
  }
  const warning = `Lane "${lane}" has WIP limit of ${wipLimit} but no wip_justification. Philosophy: If you need WIP > 1, you need better lanes, not higher limits. Add wip_justification under ${LANE_DEFINITIONS_HINT} to suppress this warning.`;
  return {
    valid: true,
    warning,
    requiresJustification: true
  };
}

// ../core/dist/lane-lock.js
var LOG_PREFIX = "[lane-lock]";
var LOCKS_DIR = LUMENFLOW_PATHS.LOCKS_DIR;
var DEFAULT_STALE_LOCK_THRESHOLD_HOURS = 2;
function getStaleThresholdMs() {
  const envValue = process.env[ENV_VARS.STALE_LOCK_THRESHOLD_HOURS];
  if (envValue) {
    const hours = parseFloat(envValue);
    if (!Number.isNaN(hours) && hours > 0) {
      return hours * 60 * 60 * 1e3;
    }
  }
  return DEFAULT_STALE_LOCK_THRESHOLD_HOURS * 60 * 60 * 1e3;
}
function getLocksDir(baseDir = null) {
  const projectRoot = baseDir || getProjectRoot(import.meta.url);
  return path2.join(projectRoot, LOCKS_DIR);
}
function getLockFilePath(lane, baseDir = null) {
  const laneKebab = toKebab(lane);
  const locksDir = getLocksDir(baseDir);
  return path2.join(locksDir, `${laneKebab}.lock`);
}
function ensureLocksDir(baseDir = null) {
  const locksDir = getLocksDir(baseDir);
  if (!existsSync2(locksDir)) {
    mkdirSync(locksDir, { recursive: true });
  }
}
function isLockStale(metadata) {
  if (!metadata || !metadata.timestamp) {
    return true;
  }
  const lockTime = new Date(metadata.timestamp).getTime();
  const now = Date.now();
  return now - lockTime > getStaleThresholdMs();
}
function isZombieLock(metadata) {
  if (!metadata || typeof metadata.pid !== "number") {
    return true;
  }
  try {
    process.kill(metadata.pid, 0);
    return false;
  } catch {
    return true;
  }
}
function readLockMetadata(lockPath) {
  try {
    if (!existsSync2(lockPath)) {
      return null;
    }
    const content = readFileSync2(lockPath, { encoding: "utf-8" });
    return JSON.parse(content);
  } catch {
    return null;
  }
}
function acquireLaneLock(lane, wuId, options = {}) {
  const { agentSession = null, baseDir = null } = options;
  const lockPolicy = getLockPolicyForLane(lane);
  if (lockPolicy === "none") {
    console.log(`${LOG_PREFIX} Skipping lock acquisition for "${lane}" (lock_policy=none)`);
    return {
      acquired: true,
      error: null,
      existingLock: null,
      isStale: false,
      skipped: true
    };
  }
  try {
    ensureLocksDir(baseDir);
    const lockPath = getLockFilePath(lane, baseDir);
    const metadata = {
      wuId,
      timestamp: (/* @__PURE__ */ new Date()).toISOString(),
      agentSession,
      pid: process.pid,
      lane
    };
    try {
      const fd = openSync(lockPath, "wx");
      writeFileSync(lockPath, JSON.stringify(metadata, null, 2), { encoding: "utf-8" });
      closeSync(fd);
      console.log(`${LOG_PREFIX} Acquired lane lock for "${lane}" (${wuId})`);
      return {
        acquired: true,
        error: null,
        existingLock: null,
        isStale: false
      };
    } catch (err) {
      if (err.code === "EEXIST") {
        const existingLock = readLockMetadata(lockPath);
        const stale = existingLock ? isLockStale(existingLock) : true;
        const zombie = existingLock ? isZombieLock(existingLock) : true;
        if (existingLock && existingLock.wuId === wuId) {
          console.log(`${LOG_PREFIX} Lock already held by same WU (${wuId})`);
          return {
            acquired: true,
            // Allow re-claim of same WU
            error: null,
            existingLock,
            isStale: stale
          };
        }
        if (zombie && stale) {
          console.warn(`${LOG_PREFIX} Detected stale zombie lock for "${lane}" (PID ${existingLock?.pid} not running, lock age > threshold)`);
          console.warn(`${LOG_PREFIX}    Previous owner: ${existingLock?.wuId}`);
          console.warn(`${LOG_PREFIX}    Lock timestamp: ${existingLock?.timestamp}`);
          console.warn(`${LOG_PREFIX}    Auto-clearing stale zombie lock...`);
          try {
            unlinkSync(lockPath);
          } catch {
          }
          return acquireLaneLock(lane, wuId, options);
        }
        return {
          acquired: false,
          error: existingLock ? `Lane "${lane}" is locked by ${existingLock.wuId} (since ${existingLock.timestamp})` : `Lane "${lane}" has an invalid lock file`,
          existingLock,
          isStale: stale
        };
      }
      throw err;
    }
  } catch (err) {
    const errMessage = err instanceof Error ? err.message : String(err);
    return {
      acquired: false,
      error: `Failed to acquire lane lock: ${errMessage}`,
      existingLock: null,
      isStale: false
    };
  }
}
function releaseLaneLock(lane, options = {}) {
  const { wuId = null, baseDir = null, force = false } = options;
  try {
    const lockPath = getLockFilePath(lane, baseDir);
    if (!existsSync2(lockPath)) {
      return {
        released: true,
        error: null,
        notFound: true
      };
    }
    if (wuId && !force) {
      const existingLock = readLockMetadata(lockPath);
      if (existingLock && existingLock.wuId !== wuId) {
        return {
          released: false,
          error: `Cannot release lock: owned by ${existingLock.wuId}, not ${wuId}`,
          notFound: false
        };
      }
    }
    unlinkSync(lockPath);
    console.log(`${LOG_PREFIX} Released lane lock for "${lane}"`);
    return {
      released: true,
      error: null,
      notFound: false
    };
  } catch (err) {
    const errMessage = err instanceof Error ? err.message : String(err);
    return {
      released: false,
      error: `Failed to release lane lock: ${errMessage}`,
      notFound: false
    };
  }
}
function checkLaneLock(lane, options = {}) {
  const { baseDir = null } = options;
  const lockPath = getLockFilePath(lane, baseDir);
  const metadata = readLockMetadata(lockPath);
  if (!metadata) {
    return {
      locked: false,
      metadata: null,
      isStale: false
    };
  }
  return {
    locked: true,
    metadata,
    isStale: isLockStale(metadata)
  };
}
function forceRemoveStaleLock(lane, options = {}) {
  const { baseDir = null } = options;
  const lockPath = getLockFilePath(lane, baseDir);
  const existingLock = readLockMetadata(lockPath);
  if (!existingLock) {
    return {
      released: true,
      error: null,
      notFound: true
    };
  }
  if (!isLockStale(existingLock)) {
    return {
      released: false,
      error: `Cannot force-remove: lock is not stale (${existingLock.wuId} since ${existingLock.timestamp})`,
      notFound: false
    };
  }
  console.warn(`${LOG_PREFIX} \u26A0\uFE0F  Force-removing stale lock for "${lane}"`);
  console.warn(`${LOG_PREFIX}    Previous owner: ${existingLock.wuId}`);
  console.warn(`${LOG_PREFIX}    Lock timestamp: ${existingLock.timestamp}`);
  return releaseLaneLock(lane, { baseDir, force: true });
}
function getAllLaneLocks(options = {}) {
  const { baseDir = null } = options;
  const locksDir = getLocksDir(baseDir);
  const locks = /* @__PURE__ */ new Map();
  if (!existsSync2(locksDir)) {
    return locks;
  }
  try {
    const files = __require("fs").readdirSync(locksDir);
    for (const file of files) {
      if (!file.endsWith(".lock"))
        continue;
      const lockPath = path2.join(locksDir, file);
      const metadata = readLockMetadata(lockPath);
      if (metadata && metadata.lane) {
        locks.set(metadata.lane, metadata);
      }
    }
  } catch {
  }
  return locks;
}
function auditedUnlock(lane, options) {
  const { reason, baseDir = null, force = false } = options;
  if (!reason) {
    return {
      released: false,
      error: 'Reason is required for audited unlock. Use --reason "<text>"',
      notFound: false
    };
  }
  const lockPath = getLockFilePath(lane, baseDir);
  const existingLock = readLockMetadata(lockPath);
  if (!existingLock) {
    return {
      released: true,
      error: null,
      notFound: true,
      reason
    };
  }
  const stale = isLockStale(existingLock);
  const zombie = isZombieLock(existingLock);
  const safeToRemove = stale || zombie;
  if (!safeToRemove && !force) {
    return {
      released: false,
      error: `Cannot unlock active lock for "${lane}" (${existingLock.wuId}).
Lock is recent (${existingLock.timestamp}) and PID ${existingLock.pid} is running.
Use --force to override (emergency only).`,
      notFound: false,
      previousLock: existingLock
    };
  }
  const unlockType = force ? "FORCED" : zombie ? "ZOMBIE" : "STALE";
  console.log(`${LOG_PREFIX} Audited unlock (${unlockType}) for "${lane}"`);
  console.log(`${LOG_PREFIX}    Previous owner: ${existingLock.wuId}`);
  console.log(`${LOG_PREFIX}    Lock timestamp: ${existingLock.timestamp}`);
  console.log(`${LOG_PREFIX}    Lock PID: ${existingLock.pid}`);
  console.log(`${LOG_PREFIX}    Reason: ${reason}`);
  if (force && !safeToRemove) {
    console.warn(`${LOG_PREFIX}    \u26A0\uFE0F  WARNING: Forced unlock of active lock!`);
  }
  const releaseResult = releaseLaneLock(lane, { baseDir, force: true });
  return {
    ...releaseResult,
    reason,
    forced: force && !safeToRemove,
    previousLock: existingLock
  };
}

export {
  extractParent,
  validateLaneFormat,
  getWipLimitForLane,
  getLockPolicyForLane,
  checkLaneFree,
  checkWipJustification,
  getStaleThresholdMs,
  getLocksDir,
  getLockFilePath,
  isLockStale,
  isZombieLock,
  readLockMetadata,
  acquireLaneLock,
  releaseLaneLock,
  checkLaneLock,
  forceRemoveStaleLock,
  getAllLaneLocks,
  auditedUnlock
};
