import {
  findInitiative,
  getInitiativeWUs
} from "./chunk-MZ7RKIX4.js";
import {
  buildDependencyGraph,
  buildDependencyGraphAsync,
  validateGraph
} from "./chunk-YHO3HS5X.js";
import {
  SpawnStrategyFactory
} from "./chunk-2GXVIN57.js";
import {
  generateTaskInvocation
} from "./chunk-6W5XHWYV.js";
import {
  parseYAML
} from "./chunk-NRIZR3A7.js";
import {
  WU_PATHS
} from "./chunk-6HO4GWJE.js";
import {
  STRING_LITERALS
} from "./chunk-DWMLTXKQ.js";
import {
  WU_STATUS
} from "./chunk-V6OJGLBA.js";
import {
  ErrorCodes,
  createError
} from "./chunk-RXRKBBSM.js";

// ../initiatives/dist/orchestrator/shared.js
import { existsSync } from "fs";
import { join } from "path";
var WAVE_MANIFEST_DIR = ".lumenflow/artifacts/waves";
var STAMPS_DIR = ".lumenflow/stamps";
var LOG_PREFIX = "[orchestrate:initiative]";
var DEFAULT_DEFERRED_REASON = "waiting for dependencies";
function hasStamp(wuId) {
  const stampPath = join(STAMPS_DIR, `${wuId}.done`);
  return existsSync(stampPath);
}
function getAllDependencies(doc) {
  const blockedBy = doc.blocked_by ?? [];
  const dependencies = doc.dependencies ?? [];
  const allDeps = /* @__PURE__ */ new Set([...blockedBy, ...dependencies]);
  return Array.from(allDeps);
}

// ../initiatives/dist/orchestrator/lane-policy.js
function getLockPolicyForLane(lane, laneConfigs) {
  if (!laneConfigs) {
    return "all";
  }
  const config = laneConfigs[lane];
  if (!config || !config.lock_policy) {
    return "all";
  }
  return config.lock_policy;
}
function getLaneAvailability(wus, options = {}) {
  const { laneConfigs = {} } = options;
  const result = {};
  const wusByLane = /* @__PURE__ */ new Map();
  for (const wu of wus) {
    const lane = wu.doc.lane;
    if (lane) {
      const laneWUs = wusByLane.get(lane);
      if (laneWUs) {
        laneWUs.push(wu);
      } else {
        wusByLane.set(lane, [wu]);
      }
    }
  }
  for (const [lane, laneWUs] of wusByLane) {
    const policy = getLockPolicyForLane(lane, laneConfigs);
    let inProgressCount = 0;
    let blockedCount = 0;
    let occupiedBy;
    for (const wu of laneWUs) {
      const status = wu.doc.status ?? "unknown";
      if (status === WU_STATUS.IN_PROGRESS) {
        inProgressCount++;
        if (!occupiedBy) {
          occupiedBy = wu.id;
        }
      } else if (status === WU_STATUS.BLOCKED) {
        blockedCount++;
        if (policy === "all" && !occupiedBy) {
          occupiedBy = wu.id;
        }
      }
    }
    let available;
    if (policy === "none") {
      available = true;
      occupiedBy = void 0;
    } else if (policy === "active") {
      available = inProgressCount === 0;
      if (available) {
        occupiedBy = void 0;
      }
    } else {
      available = inProgressCount === 0 && blockedCount === 0;
    }
    result[lane] = {
      available,
      policy,
      occupiedBy,
      blockedCount,
      inProgressCount
    };
  }
  return result;
}

// ../initiatives/dist/orchestrator/execution-planning.js
async function buildExecutionPlanAsync(wus) {
  const { readyWUs, skipped, skippedWithReasons, deferred, doneStatuses, allWuMap, allWuIds } = categoriseWUs(wus);
  if (readyWUs.length === 0) {
    return { waves: [], skipped, skippedWithReasons, deferred };
  }
  const wuMap = new Map(readyWUs.map((wu) => [wu.id, wu]));
  const wuIds = new Set(wuMap.keys());
  const graph = await buildDependencyGraphAsync();
  validateCycles(graph, wuIds);
  const deferredIds = processDeferrals(readyWUs, allWuMap, allWuIds, doneStatuses, deferred);
  const schedulableWUs = readyWUs.filter((wu) => !deferredIds.has(wu.id));
  const schedulableMap = new Map(schedulableWUs.map((wu) => [wu.id, wu]));
  const schedulableIds = new Set(schedulableMap.keys());
  if (schedulableIds.size === 0) {
    return { waves: [], skipped, skippedWithReasons, deferred };
  }
  const waves = buildWaves(schedulableMap, schedulableIds, skipped, wus, allWuIds);
  return { waves, skipped, skippedWithReasons, deferred };
}
function buildExecutionPlanWithLockPolicy(wus, options = {}) {
  const { laneConfigs = {} } = options;
  const { readyWUs, skipped, skippedWithReasons, deferred, doneStatuses, allWuMap, allWuIds } = categoriseWUs(wus);
  if (readyWUs.length === 0) {
    return { waves: [], skipped, skippedWithReasons, deferred };
  }
  const wuMap = new Map(readyWUs.map((wu) => [wu.id, wu]));
  const wuIds = new Set(wuMap.keys());
  const graph = buildDependencyGraph();
  validateCycles(graph, wuIds);
  const deferredIds = processDeferrals(readyWUs, allWuMap, allWuIds, doneStatuses, deferred);
  const schedulableWUs = readyWUs.filter((wu) => !deferredIds.has(wu.id));
  const schedulableMap = new Map(schedulableWUs.map((wu) => [wu.id, wu]));
  const schedulableIds = new Set(schedulableMap.keys());
  if (schedulableIds.size === 0) {
    return { waves: [], skipped, skippedWithReasons, deferred };
  }
  const lanesOccupiedByInProgress = /* @__PURE__ */ new Set();
  const lanesOccupiedByBlocked = /* @__PURE__ */ new Set();
  for (const wu of wus) {
    const status = wu.doc.status ?? "unknown";
    const lane = wu.doc.lane;
    if (lane) {
      if (status === WU_STATUS.IN_PROGRESS) {
        lanesOccupiedByInProgress.add(lane);
      } else if (status === WU_STATUS.BLOCKED) {
        lanesOccupiedByBlocked.add(lane);
      }
    }
  }
  const waves = [];
  const remaining = new Set(schedulableIds);
  const completed = new Set(skipped);
  addStampedExternalDeps(wus, allWuIds, completed);
  while (remaining.size > 0) {
    const wave = [];
    const lanesInWave = /* @__PURE__ */ new Set();
    const deferredToNextWave = [];
    for (const id of remaining) {
      const wu = schedulableMap.get(id);
      if (!wu)
        continue;
      const blockers = getAllDependencies(wu.doc);
      const allBlockersDone = blockers.every((blockerId) => completed.has(blockerId));
      if (allBlockersDone) {
        const lane = wu.doc.lane ?? "";
        const policy = getLockPolicyForLane(lane, laneConfigs);
        if (policy !== "none" && lanesInWave.has(lane)) {
          deferredToNextWave.push(wu);
          continue;
        }
        let laneBlocked = false;
        if (policy === "active") {
          laneBlocked = lanesOccupiedByInProgress.has(lane);
        } else if (policy === "all") {
          laneBlocked = lanesOccupiedByInProgress.has(lane) || lanesOccupiedByBlocked.has(lane);
        }
        if (laneBlocked) {
          deferredToNextWave.push(wu);
        } else {
          wave.push(wu);
          lanesInWave.add(lane);
        }
      }
    }
    if (wave.length === 0 && remaining.size > 0 && deferredToNextWave.length === 0) {
      const stuckIds = Array.from(remaining);
      throw createError(ErrorCodes.VALIDATION_ERROR, `Circular or unresolvable dependencies detected. Stuck WUs: ${stuckIds.join(", ")}`, { stuckIds });
    }
    if (wave.length > 0) {
      waves.push(wave);
      for (const wu of wave) {
        remaining.delete(wu.id);
        completed.add(wu.id);
      }
    }
    if (wave.length === 0 && deferredToNextWave.length > 0) {
      const processedLanes = /* @__PURE__ */ new Set();
      for (const wu of deferredToNextWave) {
        const lane = wu.doc.lane ?? "";
        if (!processedLanes.has(lane)) {
          wave.push(wu);
          processedLanes.add(lane);
        }
      }
      if (wave.length > 0) {
        waves.push(wave);
        for (const wu of wave) {
          remaining.delete(wu.id);
          completed.add(wu.id);
        }
      }
    }
  }
  return { waves, skipped, skippedWithReasons, deferred };
}
function categoriseWUs(wus) {
  const skipped = [];
  const skippedWithReasons = [];
  const deferred = [];
  const doneStatuses = /* @__PURE__ */ new Set([WU_STATUS.DONE, WU_STATUS.COMPLETED]);
  for (const wu of wus) {
    const status = wu.doc.status ?? "unknown";
    if (doneStatuses.has(status)) {
      skipped.push(wu.id);
    } else if (status !== WU_STATUS.READY) {
      skippedWithReasons.push({ id: wu.id, reason: `status: ${status}` });
    }
  }
  const readyWUs = wus.filter((wu) => wu.doc.status === WU_STATUS.READY);
  const allWuMap = new Map(wus.map((wu) => [wu.id, wu]));
  const allWuIds = new Set(allWuMap.keys());
  return { readyWUs, skipped, skippedWithReasons, deferred, doneStatuses, allWuMap, allWuIds };
}
function validateCycles(graph, wuIds) {
  const { cycles } = validateGraph(graph);
  const relevantCycles = cycles.filter((cycle) => cycle.some((id) => wuIds.has(id)));
  if (relevantCycles.length > 0) {
    const cycleStr = relevantCycles.map((c) => c.join(" \u2192 ")).join("; ");
    throw createError(ErrorCodes.VALIDATION_ERROR, `Circular dependencies detected: ${cycleStr}`, {
      cycles: relevantCycles
    });
  }
}
function processDeferrals(readyWUs, allWuMap, allWuIds, doneStatuses, deferred) {
  const deferredIds = /* @__PURE__ */ new Set();
  const deferredReasons = /* @__PURE__ */ new Map();
  const deferredBlockers = /* @__PURE__ */ new Map();
  const addDeferredEntry = (wuId, blockers, reason) => {
    deferredIds.add(wuId);
    if (!deferredReasons.has(wuId)) {
      deferredReasons.set(wuId, /* @__PURE__ */ new Set());
    }
    if (!deferredBlockers.has(wuId)) {
      deferredBlockers.set(wuId, /* @__PURE__ */ new Set());
    }
    const reasonSet = deferredReasons.get(wuId);
    const blockerSet = deferredBlockers.get(wuId);
    for (const blockerId of blockers) {
      blockerSet.add(blockerId);
    }
    reasonSet.add(reason);
  };
  for (const wu of readyWUs) {
    const blockers = getAllDependencies(wu.doc);
    const externalBlockers = blockers.filter((blockerId) => !allWuIds.has(blockerId));
    const internalBlockers = blockers.filter((blockerId) => allWuIds.has(blockerId));
    if (externalBlockers.length > 0) {
      const unstampedBlockers = externalBlockers.filter((blockerId) => !hasStamp(blockerId));
      if (unstampedBlockers.length > 0) {
        addDeferredEntry(wu.id, unstampedBlockers, `waiting for external: ${unstampedBlockers.join(", ")}`);
      }
    }
    if (internalBlockers.length > 0) {
      const nonReadyInternal = internalBlockers.filter((blockerId) => {
        const blocker = allWuMap.get(blockerId);
        const status = blocker?.doc?.status ?? "unknown";
        if (status === WU_STATUS.READY) {
          return false;
        }
        return !doneStatuses.has(status);
      });
      if (nonReadyInternal.length > 0) {
        const details = nonReadyInternal.map((blockerId) => {
          const status = allWuMap.get(blockerId)?.doc?.status ?? "unknown";
          return `${blockerId} (status: ${status})`;
        });
        addDeferredEntry(wu.id, nonReadyInternal, `waiting for internal: ${details.join(", ")}`);
      }
    }
  }
  let hasNewDeferral = true;
  while (hasNewDeferral) {
    hasNewDeferral = false;
    for (const wu of readyWUs) {
      if (deferredIds.has(wu.id)) {
        continue;
      }
      const blockers = getAllDependencies(wu.doc);
      const deferredInternal = blockers.filter((blockerId) => allWuIds.has(blockerId) && deferredIds.has(blockerId));
      if (deferredInternal.length > 0) {
        const details = deferredInternal.map((blockerId) => {
          const status = allWuMap.get(blockerId)?.doc?.status ?? "unknown";
          return `${blockerId} (status: ${status})`;
        });
        addDeferredEntry(wu.id, deferredInternal, `waiting for internal: ${details.join(", ")}`);
        hasNewDeferral = true;
      }
    }
  }
  for (const wu of readyWUs) {
    if (deferredIds.has(wu.id)) {
      const blockerSet = deferredBlockers.get(wu.id) || /* @__PURE__ */ new Set();
      const reasonSet = deferredReasons.get(wu.id) || /* @__PURE__ */ new Set();
      deferred.push({
        id: wu.id,
        blockedBy: Array.from(blockerSet),
        reason: reasonSet.size > 0 ? Array.from(reasonSet).join("; ") : DEFAULT_DEFERRED_REASON
      });
    }
  }
  return deferredIds;
}
function addStampedExternalDeps(wus, allWuIds, completed) {
  for (const wu of wus) {
    const blockers = getAllDependencies(wu.doc);
    for (const blockerId of blockers) {
      if (!allWuIds.has(blockerId) && hasStamp(blockerId)) {
        completed.add(blockerId);
      }
    }
  }
}
function buildWaves(schedulableMap, schedulableIds, skipped, allWUs, allWuIds) {
  const waves = [];
  const remaining = new Set(schedulableIds);
  const completed = new Set(skipped);
  addStampedExternalDeps(allWUs, allWuIds, completed);
  while (remaining.size > 0) {
    const wave = [];
    const lanesInWave = /* @__PURE__ */ new Set();
    const deferredToNextWave = [];
    for (const id of remaining) {
      const wu = schedulableMap.get(id);
      const blockers = getAllDependencies(wu.doc);
      const allBlockersDone = blockers.every((blockerId) => completed.has(blockerId));
      if (allBlockersDone) {
        const lane = wu.doc.lane;
        if (lanesInWave.has(lane)) {
          deferredToNextWave.push(wu);
        } else {
          wave.push(wu);
          lanesInWave.add(lane);
        }
      }
    }
    if (wave.length === 0 && remaining.size > 0 && deferredToNextWave.length === 0) {
      const stuckIds = Array.from(remaining);
      throw createError(ErrorCodes.VALIDATION_ERROR, `Circular or unresolvable dependencies detected. Stuck WUs: ${stuckIds.join(", ")}`, { stuckIds });
    }
    waves.push(wave);
    for (const wu of wave) {
      remaining.delete(wu.id);
      completed.add(wu.id);
    }
  }
  return waves;
}

// ../initiatives/dist/orchestrator/checkpoint.js
import { existsSync as existsSync2, mkdirSync, writeFileSync, readFileSync, readdirSync } from "fs";
import { join as join2 } from "path";
var MANIFEST_WU_STATUS = "queued";
var CHECKPOINT_AUTO_THRESHOLDS = {
  /** Auto-enable checkpoint mode if pending WU count exceeds this (>3 = 4+) */
  WU_COUNT: 3,
  /** Auto-enable checkpoint mode if wave count exceeds this (>2 = 3+) */
  WAVE_COUNT: 2
};
function filterByDependencyStamps(candidates) {
  const spawnable = [];
  const blocked = [];
  const blockingDeps = /* @__PURE__ */ new Set();
  for (const wu of candidates) {
    const deps = getAllDependencies(wu.doc);
    const unmetDeps = deps.filter((depId) => !hasStamp(depId));
    if (unmetDeps.length === 0) {
      spawnable.push(wu);
    } else {
      blocked.push(wu);
      for (const depId of unmetDeps) {
        blockingDeps.add(depId);
      }
    }
  }
  let waitingMessage = "";
  if (spawnable.length === 0 && blockingDeps.size > 0) {
    const depsArray = Array.from(blockingDeps);
    waitingMessage = `Waiting for ${depsArray.join(", ")} to complete. No WUs can spawn until ${depsArray.length === 1 ? "this dependency has" : "these dependencies have"} a stamp.`;
  }
  return {
    spawnable,
    blocked,
    blockingDeps: Array.from(blockingDeps),
    waitingMessage
  };
}
async function shouldAutoEnableCheckpointAsync(wus) {
  const pendingWUs = wus.filter((wu) => wu.doc.status !== WU_STATUS.DONE);
  const pendingCount = pendingWUs.length;
  if (pendingCount > CHECKPOINT_AUTO_THRESHOLDS.WU_COUNT) {
    return {
      autoEnabled: true,
      reason: `${pendingCount} pending WUs exceeds threshold (>${CHECKPOINT_AUTO_THRESHOLDS.WU_COUNT})`,
      pendingCount,
      waveCount: -1
      // Not computed (early return)
    };
  }
  if (pendingCount === 0) {
    return {
      autoEnabled: false,
      reason: "No pending WUs",
      pendingCount: 0,
      waveCount: 0
    };
  }
  const plan = await buildExecutionPlanAsync(wus);
  const waveCount = plan.waves.length;
  if (waveCount > CHECKPOINT_AUTO_THRESHOLDS.WAVE_COUNT) {
    return {
      autoEnabled: true,
      reason: `${waveCount} waves exceeds threshold (>${CHECKPOINT_AUTO_THRESHOLDS.WAVE_COUNT})`,
      pendingCount,
      waveCount
    };
  }
  return {
    autoEnabled: false,
    reason: `${pendingCount} pending WUs and ${waveCount} waves within thresholds`,
    pendingCount,
    waveCount
  };
}
async function resolveCheckpointModeAsync(options, wus) {
  const { checkpointPerWave = false, noCheckpoint = false, dryRun = false } = options;
  if (checkpointPerWave) {
    return {
      enabled: true,
      source: "explicit",
      reason: "Enabled via -c/--checkpoint-per-wave flag"
    };
  }
  if (noCheckpoint) {
    return {
      enabled: false,
      source: "override",
      reason: "Disabled via --no-checkpoint flag"
    };
  }
  if (dryRun) {
    return {
      enabled: false,
      source: "dryrun",
      reason: "Disabled in dry-run mode (preview uses polling mode)"
    };
  }
  const autoResult = await shouldAutoEnableCheckpointAsync(wus);
  return {
    enabled: autoResult.autoEnabled,
    source: "auto",
    reason: autoResult.reason
  };
}
function validateCheckpointFlags(options) {
  if (options.checkpointPerWave && options.dryRun) {
    throw createError(ErrorCodes.VALIDATION_ERROR, "Cannot combine --checkpoint-per-wave (-c) with --dry-run (-d). Checkpoint mode writes manifests and spawns agents.", { flags: { checkpointPerWave: true, dryRun: true } });
  }
  if (options.checkpointPerWave && options.noCheckpoint) {
    throw createError(ErrorCodes.VALIDATION_ERROR, "Cannot combine --checkpoint-per-wave (-c) with --no-checkpoint. These flags are mutually exclusive.", { flags: { checkpointPerWave: true, noCheckpoint: true } });
  }
}
function buildCheckpointWave(initRef, options = {}) {
  const { dryRun = false } = options;
  const initData = findInitiative(initRef);
  if (!initData) {
    throw createError(ErrorCodes.INIT_NOT_FOUND, `Initiative '${initRef}' not found.`, { initRef });
  }
  const initId = initData.id;
  const wus = getInitiativeWUs(initRef);
  const readyCandidates = wus.filter((wu) => {
    if (wu.doc.status !== WU_STATUS.READY) {
      return false;
    }
    if (hasStamp(wu.id)) {
      return false;
    }
    return true;
  });
  if (readyCandidates.length === 0) {
    return null;
  }
  const depResult = filterByDependencyStamps(readyCandidates);
  if (depResult.spawnable.length === 0) {
    return {
      initiative: initId,
      wave: -1,
      wus: [],
      manifestPath: null,
      blockedBy: depResult.blockingDeps,
      waitingMessage: depResult.waitingMessage
    };
  }
  const selectedWUs = [];
  const usedLanes = /* @__PURE__ */ new Set();
  for (const wu of depResult.spawnable) {
    const lane = wu.doc.lane;
    if (!usedLanes.has(lane)) {
      selectedWUs.push(wu);
      usedLanes.add(lane);
    }
  }
  const waveNum = getNextWaveNumber(initId);
  const manifest = {
    initiative: initId,
    wave: waveNum,
    created_at: (/* @__PURE__ */ new Date()).toISOString(),
    wus: selectedWUs.map((wu) => ({
      id: wu.id,
      lane: wu.doc.lane,
      status: MANIFEST_WU_STATUS
    })),
    lane_validation: "pass",
    done_criteria: "All stamps exist in .lumenflow/stamps/"
  };
  const manifestPath = join2(WAVE_MANIFEST_DIR, `${initId}-wave-${waveNum}.json`);
  if (!dryRun) {
    if (!existsSync2(WAVE_MANIFEST_DIR)) {
      mkdirSync(WAVE_MANIFEST_DIR, { recursive: true });
    }
    writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), "utf8");
  }
  return {
    initiative: initId,
    wave: waveNum,
    wus: manifest.wus,
    manifestPath
  };
}
function getExistingWaveManifests(initId) {
  if (!existsSync2(WAVE_MANIFEST_DIR)) {
    return [];
  }
  const files = readdirSync(WAVE_MANIFEST_DIR);
  const pattern = new RegExp(`^${initId}-wave-(\\d+)\\.json$`);
  const manifests = [];
  for (const file of files) {
    const match = file.match(pattern);
    if (match) {
      try {
        const content = readFileSync(join2(WAVE_MANIFEST_DIR, file), "utf8");
        const manifest = JSON.parse(content);
        manifests.push(manifest);
      } catch {
      }
    }
  }
  return manifests.sort((a, b) => a.wave - b.wave);
}
function getNextWaveNumber(initId) {
  const manifests = getExistingWaveManifests(initId);
  if (manifests.length === 0) {
    return 0;
  }
  const maxWave = Math.max(...manifests.map((m) => m.wave));
  return maxWave + 1;
}

// ../initiatives/dist/orchestrator/formatting.js
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
var BANNER_SEPARATOR = "==============================================================================";
var ANTML_NS = "antml:";
var XML_PATTERNS = {
  FUNCTION_CALLS_OPEN: `<${ANTML_NS}function_calls>`,
  FUNCTION_CALLS_CLOSE: `</${ANTML_NS}function_calls>`,
  INVOKE_OPEN: `<${ANTML_NS}invoke`,
  INVOKE_CLOSE: `</${ANTML_NS}invoke>`
};
function formatExecutionPlan(initiative, plan) {
  const lines = [];
  lines.push(`Initiative: ${initiative.id} \u2014 ${initiative.title}`);
  lines.push("");
  if (plan.skipped.length > 0) {
    lines.push(`Skipped (already done): ${plan.skipped.join(", ")}`);
    lines.push("");
  }
  if (plan.skippedWithReasons && plan.skippedWithReasons.length > 0) {
    lines.push("Skipped (not ready):");
    for (const entry of plan.skippedWithReasons) {
      lines.push(`  - ${entry.id}: ${entry.reason}`);
    }
    lines.push("");
  }
  if (plan.deferred && plan.deferred.length > 0) {
    lines.push("Deferred (waiting for dependencies):");
    for (const entry of plan.deferred) {
      lines.push(`  - ${entry.id}: ${entry.reason}`);
      if (entry.blockedBy && entry.blockedBy.length > 0) {
        lines.push(`      blocked by: ${entry.blockedBy.join(", ")}`);
      }
    }
    lines.push("");
  }
  if (plan.waves.length === 0) {
    const hasPending = plan.deferred.length > 0 || plan.skippedWithReasons && plan.skippedWithReasons.length > 0;
    if (hasPending) {
      const pendingCount = plan.deferred.length + (plan.skippedWithReasons ? plan.skippedWithReasons.length : 0);
      lines.push(`${pendingCount} WU(s) still pending but none are unblocked.`);
    } else {
      lines.push("All WUs are complete.");
    }
    return lines.join(STRING_LITERALS.NEWLINE);
  }
  lines.push(`Execution Plan: ${plan.waves.length} wave(s)`);
  lines.push("");
  const allWUs = plan.waves.flat();
  const bottleneckWUs = getBottleneckWUs(allWUs);
  if (bottleneckWUs.length > 0) {
    lines.push("Bottleneck WUs (prioritise these for fastest unblocking):");
    for (const bottleneck of bottleneckWUs) {
      lines.push(`  - ${bottleneck.id}: ${bottleneck.title} [blocks ${bottleneck.blocksCount} WU${bottleneck.blocksCount !== 1 ? "s" : ""}]`);
    }
    lines.push("");
  }
  for (let i = 0; i < plan.waves.length; i++) {
    const wave = plan.waves[i];
    lines.push(`Wave ${i} (${wave.length} WU${wave.length !== 1 ? "s" : ""} in parallel):`);
    for (const wu of wave) {
      const blockers = getAllDependencies(wu.doc);
      const blockerStr = blockers.length > 0 ? ` [blocked by: ${blockers.join(", ")}]` : "";
      const isBottleneck = bottleneckWUs.some((b) => b.id === wu.id);
      const bottleneckMarker = isBottleneck ? " *BOTTLENECK*" : "";
      lines.push(`  - ${wu.id}: ${wu.doc.title}${blockerStr}${bottleneckMarker}`);
    }
    lines.push("");
  }
  if (plan.waves.length > 1) {
    lines.push("Coordination Guidance:");
    lines.push("  - Poll mem:inbox between waves: pnpm mem:inbox --since 10m");
    lines.push("  - Check for bug discoveries from sub-agents");
    lines.push("  - Review signals before proceeding to next wave");
    lines.push("");
  }
  return lines.join(STRING_LITERALS.NEWLINE);
}
function calculateProgress(wus) {
  const stats = {
    total: wus.length,
    done: 0,
    active: 0,
    pending: 0,
    blocked: 0,
    percentage: 0
  };
  for (const { doc } of wus) {
    switch (doc.status) {
      case WU_STATUS.DONE:
        stats.done++;
        break;
      case WU_STATUS.IN_PROGRESS:
        stats.active++;
        break;
      case WU_STATUS.BLOCKED:
        stats.blocked++;
        break;
      case WU_STATUS.READY:
        stats.pending++;
        break;
      default:
        break;
    }
  }
  stats.percentage = stats.total > 0 ? Math.round(stats.done / stats.total * 100) : 0;
  return stats;
}
function formatProgress(progress) {
  const bar = createProgressBar(progress.percentage);
  return [
    `Progress: ${bar} ${progress.percentage}%`,
    `  Done: ${progress.done}/${progress.total}`,
    `  Active: ${progress.active}`,
    `  Pending: ${progress.pending}`,
    `  Blocked: ${progress.blocked}`
  ].join(STRING_LITERALS.NEWLINE);
}
function createProgressBar(percentage, width = 20) {
  const filled = Math.round(percentage / 100 * width);
  const empty = width - filled;
  return `[${"\u2588".repeat(filled)}${"\u2591".repeat(empty)}]`;
}
function getBottleneckWUs(wus, limit = 5) {
  const blocksCounts = /* @__PURE__ */ new Map();
  for (const wu of wus) {
    blocksCounts.set(wu.id, 0);
  }
  for (const wu of wus) {
    const blockers = getAllDependencies(wu.doc);
    for (const blockerId of blockers) {
      if (blocksCounts.has(blockerId)) {
        blocksCounts.set(blockerId, blocksCounts.get(blockerId) + 1);
      }
    }
  }
  const bottlenecks = [];
  for (const wu of wus) {
    const blocksCount = blocksCounts.get(wu.id);
    if (blocksCount !== void 0 && blocksCount > 0) {
      bottlenecks.push({
        id: wu.id,
        title: wu.doc.title ?? wu.id,
        blocksCount
      });
    }
  }
  bottlenecks.sort((a, b) => b.blocksCount - a.blocksCount);
  return bottlenecks.slice(0, limit);
}
function formatCheckpointOutput(waveData) {
  const lines = [];
  const isDryRun = waveData.dryRun === true;
  if (waveData.blockedBy && waveData.blockedBy.length > 0) {
    lines.push(`Waiting for dependencies to complete:`);
    for (const depId of waveData.blockedBy) {
      lines.push(`  - ${depId}`);
    }
    lines.push("");
    lines.push(waveData.waitingMessage || "No WUs can spawn until dependencies have stamps.");
    lines.push("");
    lines.push("Check dependency progress with:");
    lines.push(`  pnpm mem:inbox --since 10m`);
    lines.push(`  pnpm orchestrate:initiative -i ${waveData.initiative} -c`);
    return lines.join(STRING_LITERALS.NEWLINE);
  }
  if (isDryRun) {
    lines.push("[DRY-RUN PREVIEW] Checkpoint mode output (no manifest written)");
    lines.push("");
  }
  lines.push(`Wave ${waveData.wave} manifest: ${waveData.manifestPath}`);
  lines.push(`WUs in this wave: ${waveData.wus.length}`);
  for (const wu of waveData.wus) {
    lines.push(`  - ${wu.id} (${wu.lane})`);
  }
  lines.push("");
  lines.push(BANNER_SEPARATOR);
  lines.push("ACTION REQUIRED: Agents have NOT been spawned yet.");
  lines.push("");
  lines.push("To spawn agents, copy the XML below and invoke the Task tool.");
  lines.push("The output below is documentation only - it will NOT execute automatically.");
  lines.push(BANNER_SEPARATOR);
  lines.push("");
  lines.push("```xml");
  const xmlLines = [];
  xmlLines.push(XML_PATTERNS.FUNCTION_CALLS_OPEN);
  for (const wu of waveData.wus) {
    try {
      const fullInvocation = generateEmbeddedSpawnPrompt(wu.id);
      const startIdx = fullInvocation.indexOf(XML_PATTERNS.INVOKE_OPEN);
      const endIdx = fullInvocation.indexOf(XML_PATTERNS.INVOKE_CLOSE);
      if (startIdx !== -1 && endIdx !== -1) {
        const invokeBlock = fullInvocation.substring(startIdx, endIdx + XML_PATTERNS.INVOKE_CLOSE.length);
        xmlLines.push(invokeBlock);
      }
    } catch {
      xmlLines.push(`<!-- Could not generate Task invocation for ${wu.id} -->`);
    }
  }
  xmlLines.push(XML_PATTERNS.FUNCTION_CALLS_CLOSE);
  lines.push(xmlLines.join(STRING_LITERALS.NEWLINE));
  lines.push("```");
  lines.push("");
  lines.push("Resume with:");
  lines.push(`  pnpm mem:ready --wu WU-ORCHESTRATOR`);
  lines.push(`  pnpm orchestrate:initiative -i ${waveData.initiative} -c`);
  return lines.join(STRING_LITERALS.NEWLINE);
}
function generateEmbeddedSpawnPrompt(wuId) {
  const wuPath = WU_PATHS.WU(wuId);
  if (!existsSync3(wuPath)) {
    throw createError(ErrorCodes.WU_NOT_FOUND, `WU file not found: ${wuPath}`, {
      wuId,
      path: wuPath
    });
  }
  const text = readFileSync2(wuPath, "utf8");
  const doc = parseYAML(text);
  return generateTaskInvocation(doc, wuId, SpawnStrategyFactory.create("claude-code"));
}
function formatExecutionPlanWithEmbeddedSpawns(plan) {
  const lines = [];
  if (plan.waves.length === 0) {
    const hasPending = plan.deferred.length > 0 || plan.skippedWithReasons && plan.skippedWithReasons.length > 0;
    if (hasPending) {
      const pendingCount = plan.deferred.length + (plan.skippedWithReasons ? plan.skippedWithReasons.length : 0);
      return `${pendingCount} WU(s) still pending but none are unblocked.`;
    }
    return "All WUs are complete.";
  }
  for (let waveIndex = 0; waveIndex < plan.waves.length; waveIndex++) {
    const wave = plan.waves[waveIndex];
    lines.push(`## Wave ${waveIndex} (${wave.length} WU${wave.length !== 1 ? "s" : ""} in parallel)`);
    lines.push("");
    lines.push(BANNER_SEPARATOR);
    lines.push("ACTION REQUIRED: Agents have NOT been spawned yet.");
    lines.push("");
    lines.push("To spawn agents, copy the XML below and invoke the Task tool.");
    lines.push("The output below is documentation only - it will NOT execute automatically.");
    lines.push(BANNER_SEPARATOR);
    lines.push("");
    lines.push("```xml");
    const xmlLines = [];
    const openTag = "<antml:function_calls>";
    const closeTag = "</antml:function_calls>";
    xmlLines.push(openTag);
    for (const wu of wave) {
      const fullInvocation = generateTaskInvocation(wu.doc, wu.id, SpawnStrategyFactory.create("claude-code"));
      const startPattern = "<antml:invoke";
      const endPattern = "</antml:invoke>";
      const startIdx = fullInvocation.indexOf(startPattern);
      const endIdx = fullInvocation.indexOf(endPattern);
      if (startIdx !== -1 && endIdx !== -1) {
        let invokeBlock = fullInvocation.substring(startIdx, endIdx + endPattern.length);
        if (!invokeBlock.includes("run_in_background")) {
          const paramOpen = '<antml:parameter name="';
          const paramClose = "</antml:parameter>";
          const invokeTag = '<antml:invoke name="Task">';
          invokeBlock = invokeBlock.replace(invokeTag, `${invokeTag}
${paramOpen}run_in_background">true${paramClose}`);
        }
        xmlLines.push(invokeBlock);
      }
    }
    xmlLines.push(closeTag);
    lines.push(xmlLines.join(STRING_LITERALS.NEWLINE));
    lines.push("```");
    lines.push("");
    if (waveIndex < plan.waves.length - 1) {
      lines.push(`After all Wave ${waveIndex} agents complete, proceed to Wave ${waveIndex + 1}.`);
      lines.push("Before next wave: pnpm mem:inbox --since 10m (check for bug discoveries)");
      lines.push("");
    }
  }
  return lines.join(STRING_LITERALS.NEWLINE);
}

// ../initiatives/dist/orchestrator/initiative-loading.js
function loadInitiativeWUs(initRef) {
  const initiative = findInitiative(initRef);
  if (!initiative) {
    throw createError(ErrorCodes.INIT_NOT_FOUND, `Initiative '${initRef}' not found. Check the ID or slug.`, { initRef });
  }
  const wus = getInitiativeWUs(initRef);
  return {
    initiative: initiative.doc,
    wus
  };
}
function loadMultipleInitiatives(initRefs) {
  const allWUs = [];
  const seenIds = /* @__PURE__ */ new Set();
  for (const ref of initRefs) {
    const { wus } = loadInitiativeWUs(ref);
    for (const wu of wus) {
      if (!seenIds.has(wu.id)) {
        seenIds.add(wu.id);
        allWUs.push(wu);
      }
    }
  }
  return allWUs;
}

// ../initiatives/dist/orchestrator/scope-advisory.js
var SCOPE_ADVISORY_THRESHOLDS = {
  /**
   * WU-to-unique-file ratio above which the initiative is flagged as over-granular.
   * A ratio of 2.0 means there are twice as many WUs as unique files.
   */
  OVER_GRANULAR_RATIO: 2,
  /**
   * Percentage of WUs that share the same code path before flagging overlap.
   * 0.5 = 50% of WUs touch at least one common file.
   */
  OVERLAP_PERCENTAGE: 0.5,
  /**
   * Percentage of WUs in a single lane before flagging lane concentration.
   * 0.7 = 70% of WUs are in the same lane.
   */
  LANE_CONCENTRATION_PERCENTAGE: 0.7,
  /**
   * Minimum number of WUs required before lane concentration check fires.
   * Small initiatives (< 4 WUs) naturally have high lane concentration.
   */
  MIN_WUS_FOR_LANE_CHECK: 4
};
function analyseScopeShape(wus) {
  const advisories = [];
  if (wus.length <= 1) {
    return { advisories, clean: true };
  }
  const overGranularAdvisory = detectOverGranular(wus);
  if (overGranularAdvisory) {
    advisories.push(overGranularAdvisory);
  }
  const overlapAdvisory = detectOverlapConcentration(wus);
  if (overlapAdvisory) {
    advisories.push(overlapAdvisory);
  }
  const laneAdvisory = detectLaneConcentration(wus);
  if (laneAdvisory) {
    advisories.push(laneAdvisory);
  }
  return {
    advisories,
    clean: advisories.length === 0
  };
}
function formatScopeAdvisory(result) {
  if (result.clean) {
    return "";
  }
  const lines = [];
  lines.push("Scope Advisory:");
  for (const advisory of result.advisories) {
    lines.push(`  [${advisory.severity}] ${advisory.type}: ${advisory.detail}`);
    lines.push(`    -> ${advisory.suggestion}`);
  }
  return lines.join("\n");
}
function collectCodePaths(wus) {
  const uniqueFiles = /* @__PURE__ */ new Set();
  const fileToWuCount = /* @__PURE__ */ new Map();
  let wusWithPaths = 0;
  for (const wu of wus) {
    const paths = wu.doc.code_paths;
    if (!paths || paths.length === 0) {
      continue;
    }
    wusWithPaths++;
    for (const p of paths) {
      uniqueFiles.add(p);
      fileToWuCount.set(p, (fileToWuCount.get(p) ?? 0) + 1);
    }
  }
  return { uniqueFiles, wusWithPaths, fileToWuCount };
}
function detectOverGranular(wus) {
  const { uniqueFiles, wusWithPaths } = collectCodePaths(wus);
  if (uniqueFiles.size === 0 || wusWithPaths === 0) {
    return null;
  }
  const ratio = wusWithPaths / uniqueFiles.size;
  if (ratio > SCOPE_ADVISORY_THRESHOLDS.OVER_GRANULAR_RATIO) {
    return {
      type: "over-granular",
      severity: "warning",
      detail: `${wusWithPaths} WUs touch only ${uniqueFiles.size} unique files (ratio: ${ratio.toFixed(1)})`,
      suggestion: "Consider merging related WUs to reduce context-switching overhead."
    };
  }
  return null;
}
function detectOverlapConcentration(wus) {
  const { wusWithPaths, fileToWuCount } = collectCodePaths(wus);
  if (wusWithPaths < 2) {
    return null;
  }
  const threshold = SCOPE_ADVISORY_THRESHOLDS.OVERLAP_PERCENTAGE;
  for (const [filePath, count] of fileToWuCount) {
    const percentage = count / wusWithPaths;
    if (percentage > threshold) {
      return {
        type: "overlap-heavy",
        severity: "warning",
        detail: `${count} of ${wusWithPaths} WUs (${Math.round(percentage * 100)}%) touch ${filePath}`,
        suggestion: "High overlap suggests these WUs could be consolidated or the shared file should be split first."
      };
    }
  }
  return null;
}
function detectLaneConcentration(wus) {
  if (wus.length < SCOPE_ADVISORY_THRESHOLDS.MIN_WUS_FOR_LANE_CHECK) {
    return null;
  }
  const laneCounts = /* @__PURE__ */ new Map();
  for (const wu of wus) {
    const lane = wu.doc.lane ?? "unknown";
    laneCounts.set(lane, (laneCounts.get(lane) ?? 0) + 1);
  }
  const threshold = SCOPE_ADVISORY_THRESHOLDS.LANE_CONCENTRATION_PERCENTAGE;
  for (const [lane, count] of laneCounts) {
    const percentage = count / wus.length;
    if (percentage > threshold) {
      return {
        type: "lane-heavy",
        severity: "warning",
        detail: `${count} of ${wus.length} WUs (${Math.round(percentage * 100)}%) are in lane "${lane}"`,
        suggestion: "Lane concentration creates a serialisation bottleneck. Consider splitting work across lanes or increasing WIP limits for this lane."
      };
    }
  }
  return null;
}

// ../initiatives/dist/orchestrator/spawn-status.js
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";

// ../initiatives/dist/lane-config-resolver.js
var LANE_SECTION_KEYS = ["definitions", "engineering", "business"];
function isRecord(value) {
  return typeof value === "object" && value !== null;
}
function isLaneConfigContainer(config) {
  return isRecord(config);
}
function isLaneDefinition(value) {
  return isRecord(value);
}
function collectLaneDefinitions(value, target) {
  if (!Array.isArray(value)) {
    return;
  }
  for (const entry of value) {
    if (isLaneDefinition(entry)) {
      target.push(entry);
    }
  }
}
function extractLaneDefinitions(config) {
  if (!isLaneConfigContainer(config)) {
    return [];
  }
  const lanes = config.lanes;
  if (!lanes) {
    return [];
  }
  if (Array.isArray(lanes)) {
    const flat = [];
    collectLaneDefinitions(lanes, flat);
    return flat;
  }
  if (!isRecord(lanes)) {
    return [];
  }
  const grouped = [];
  for (const key of LANE_SECTION_KEYS) {
    collectLaneDefinitions(lanes[key], grouped);
  }
  return grouped;
}
function isLockPolicy(value) {
  return value === "all" || value === "active" || value === "none";
}
function resolveLaneConfigsFromConfig(config) {
  const result = {};
  const laneDefinitions = extractLaneDefinitions(config);
  for (const lane of laneDefinitions) {
    if (!lane.name || typeof lane.name !== "string") {
      continue;
    }
    const entry = {};
    if (isLockPolicy(lane.lock_policy)) {
      entry.lock_policy = lane.lock_policy;
    }
    if (typeof lane.wip_limit === "number") {
      entry.wip_limit = lane.wip_limit;
    }
    result[lane.name] = entry;
  }
  return result;
}

export {
  LOG_PREFIX,
  getLaneAvailability,
  buildExecutionPlanWithLockPolicy,
  resolveCheckpointModeAsync,
  validateCheckpointFlags,
  buildCheckpointWave,
  formatExecutionPlan,
  calculateProgress,
  formatProgress,
  formatCheckpointOutput,
  formatExecutionPlanWithEmbeddedSpawns,
  loadInitiativeWUs,
  loadMultipleInitiatives,
  analyseScopeShape,
  formatScopeAdvisory,
  resolveLaneConfigsFromConfig
};
