import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { repoRoot } from "./core.mjs"; const orchExecutableName = process.platform === "win32" ? "orch.exe" : "orch"; export const defaultDbPath = path.join(repoRoot, ".artifacts", "orch", "coord.db"); export const defaultWorkspaceRoot = path.join(repoRoot, ".artifacts", "orch", "worktrees"); export const defaultTaskBodyRoot = path.join(repoRoot, ".artifacts", "orch", "task-bodies"); export const legacyOrchBinPath = path.join( os.homedir(), ".codex", "skills", "orch", "assets", orchExecutableName ); function searchPathForExecutable(pathValue, existsSync = fs.existsSync) { if (!pathValue) { return null; } for (const entry of pathValue.split(path.delimiter)) { if (!entry) { continue; } const candidate = path.join(entry, orchExecutableName); if (existsSync(candidate)) { return candidate; } } return null; } export function resolveOrchBinary({ env = process.env, existsSync = fs.existsSync } = {}) { const checkedPaths = []; const explicitPath = env.CADENCE_UI_ORCH_BIN ? path.resolve(env.CADENCE_UI_ORCH_BIN) : null; if (explicitPath) { checkedPaths.push(explicitPath); if (existsSync(explicitPath)) { return { binaryPath: explicitPath, checkedPaths, source: "CADENCE_UI_ORCH_BIN" }; } } const pathMatch = searchPathForExecutable(env.PATH ?? "", existsSync); if (pathMatch) { checkedPaths.push(pathMatch); return { binaryPath: pathMatch, checkedPaths, source: "PATH" }; } checkedPaths.push(legacyOrchBinPath); if (existsSync(legacyOrchBinPath)) { return { binaryPath: legacyOrchBinPath, checkedPaths, source: "legacy" }; } return { binaryPath: null, checkedPaths, source: null }; } function parseTaskToken(token) { const [taskIdPart, dependencyPart] = token.split("->").map((value) => value.trim()); return { dependsOn: dependencyPart ? dependencyPart .split(",") .map((value) => value.trim()) .filter(Boolean) : [], id: taskIdPart }; } export function parsePlanTaskSketch(markdown) { const lines = markdown.split(/\r?\n/); const planTitle = lines .find((line) => line.startsWith("# ")) ?.slice(2) .trim() ?? "Execution Plan"; const tasks = []; let inTaskSketch = false; for (const line of lines) { if (line.startsWith("## ")) { if (inTaskSketch) { break; } inTaskSketch = line.trim() === "## Orchestration Task Sketch"; continue; } if (!inTaskSketch) { continue; } const match = line.match(/^\s*-\s+(?:`([^`]+)`|([^:]+)):\s+(.+)$/); if (!match) { continue; } const taskToken = (match[1] ?? match[2]).trim(); const taskTitle = match[3].trim(); const task = parseTaskToken(taskToken); tasks.push({ ...task, title: taskTitle }); } return { planTitle, tasks }; } export function readPlanFile(planFile) { const absolutePath = path.isAbsolute(planFile) ? planFile : path.join(repoRoot, planFile); const markdown = fs.readFileSync(absolutePath, "utf8"); const parsed = parsePlanTaskSketch(markdown); return { ...parsed, absolutePath, relativePath: path.relative(repoRoot, absolutePath) }; } export function renderTaskBody({ plan, task }) { return `# ${task.id} — ${task.title} - Source plan: \`${plan.relativePath}\` - Plan title: ${plan.planTitle} - Task id: ${task.id} - Dependencies: ${task.dependsOn.length > 0 ? task.dependsOn.join(", ") : "none"} ## Execution Notes - Read the source execution plan before editing. - Keep this task scoped to the work implied by the task title and dependencies. - Run the narrowest useful harness suites first, then report what broader validation remains. - Return any shared integration follow-up instead of editing unrelated surfaces opportunistically. `; } function sanitizeSegment(value) { return value.replace(/[^a-zA-Z0-9._-]+/g, "-"); } export function writeTaskBodyFile({ bodyRoot = defaultTaskBodyRoot, plan, runId, task }) { const runDir = path.join(bodyRoot, sanitizeSegment(runId)); const outputPath = path.join(runDir, `${sanitizeSegment(task.id)}.md`); fs.mkdirSync(runDir, { recursive: true }); fs.writeFileSync(outputPath, `${renderTaskBody({ plan, task })}\n`, "utf8"); return outputPath; }