UNPKG

framework

Version:

The (AI) Framework: turnkey, zero-config AI orchestration that wraps a coding-agent CLI (Claude Code) as a black box and takes you from an idea to a running app. Vite for AI.

51 lines 2.38 kB
import { basename } from 'node:path'; import { readDocs } from './docs.js'; // A markdown list item (`-`, `*`, or `1.`), any leading indent. Same rule as the sweep's // `parseTodoEntries` (todo-loop.ts), deliberately: the queue's readers must agree on what an // entry is, or the card says "Nothing queued" while the sweep drains the same file (#1296). const LIST_ITEM = /^\s*(?:[-*]|\d+\.)\s+(.*\S)\s*$/; // A GitHub-style task checkbox at the start of an item's text: `[ ]` open, `[x]` done. const CHECKBOX = /^\[([ xX])\]\s*(.*)$/; /** * Parse the queue entries out of a TODO doc; headings, prose and blank lines are ignored. * * Every list item is an entry, open unless its checkbox is checked — the sweep's semantics * (#1296). Triage agents write the ticket-link (#1164) style (`- [Title](tickets/x.md) — ...`) with no * checkbox, and the old checkbox-only regex read that whole queue as empty. */ export function parseTodoItems(content) { const items = []; for (const line of content.split('\n')) { const item = LIST_ITEM.exec(line); if (!item) continue; const task = CHECKBOX.exec(item[1]); if (task) { if (task[2].trim()) items.push({ text: task[2].trim(), done: task[1] !== ' ' }); } else { items.push({ text: item[1], done: false }); } } return items; } /** * Roll up the open TODO queue across the given projects, most-open first. Reads each * project's surfaced TODO docs (the `TODO*` half of {@link readDocs}) and parses their * checklist items. `read` is injectable so this is unit-testable off disk. Projects with * no TODO doc or no checklist items are omitted; a read failure just skips that project. */ export async function collectQueue(projects, read = readDocs) { const queues = []; for (const project of projects) { const docs = await read(project.path).catch(() => []); const items = docs.filter(d => basename(d.name).startsWith('TODO')).flatMap(d => parseTodoItems(d.content)); if (items.length === 0) continue; const open = items.filter(i => !i.done).length; queues.push({ projectId: project.id, projectName: project.name, open, total: items.length, items }); } return queues.sort((a, b) => b.open - a.open); } //# sourceMappingURL=queue.js.map