import type { ExtractedPlan, PlanTask } from "./types.js"; const CHECKBOX = /^\s*(?:[-*]|\d+[.)])\s+\[( |x|X|~|-)\]\s+(.+)$/; const NUMBERED = /^\s*(\d+)[.)]\s+(.+)$/; const BULLET = /^\s*[-*]\s+(.+)$/; const DONE_MARKER = /\[DONE:(\d+)\]/g; export function extractPlanTasks(text: string): ExtractedPlan { const tasks: PlanTask[] = []; for (const line of text.split(/\r?\n/)) { const checkbox = CHECKBOX.exec(line); if (checkbox) { tasks.push({ index: tasks.length + 1, text: cleanTask(checkbox[2] ?? ""), status: checkbox[1]?.toLowerCase() === "x" ? "done" : "pending" }); continue; } const numbered = NUMBERED.exec(line); if (numbered) { tasks.push({ index: tasks.length + 1, text: cleanTask(numbered[2] ?? ""), status: "pending" }); continue; } const bullet = BULLET.exec(line); if (bullet && looksLikeTask(bullet[1] ?? "")) { tasks.push({ index: tasks.length + 1, text: cleanTask(bullet[1] ?? ""), status: "pending" }); } } for (const match of text.matchAll(DONE_MARKER)) { const idx = Number(match[1]); const task = tasks[idx - 1]; if (Number.isInteger(idx) && task) task.status = "done"; } return { tasks, raw: text }; } function looksLikeTask(text: string): boolean { return /^(read|write|create|implement|add|update|run|verify|test|fix|port|build|document|audit|connect|review)\b/i.test(text.trim()); } function cleanTask(text: string): string { return text.replace(DONE_MARKER, "").trim(); } export function applyDoneMarker(tasks: PlanTask[], markerText: string): PlanTask[] { const result = tasks.map((task) => ({ ...task })); for (const match of markerText.matchAll(DONE_MARKER)) { const idx = Number(match[1]); const task = result[idx - 1]; if (Number.isInteger(idx) && task) task.status = "done"; } return result; }