/** * Project ticket file format — parse and edit one `-.md` file * (specs/2026-09-28-project-tickets.md §2). * * The file is owned by humans as much as by Crewly: people edit the body * freely, add frontmatter keys, write comments. So the writer here never * re-renders a file. It edits in place: * - frontmatter: only the keys in {@link OWNED_TICKET_FIELDS} are set, through * the `yaml` Document API, so unknown keys, key order and comments survive; * when no owned key changes, the frontmatter bytes are kept as they were; * - body: lines are appended to the `## Log` section, and the Description / * Acceptance sections are replaced only when a caller explicitly asks. * Everything else is preserved byte-for-byte. * * @module services/project-tickets/ticket-file */ import { type ProjectTicketCriterion, type ProjectTicketFields } from '../../types/project-ticket.types.js'; /** Ticket ids: `-` */ export declare const TICKET_ID_RE: RegExp; /** A successfully parsed ticket file. */ export interface ParsedTicketFile { /** The owned fields, validated and normalised */ fields: ProjectTicketFields; /** Frontmatter keys the service does not own */ extra: Record; /** Everything after the closing `---` line, verbatim */ body: string; /** Text of the Description section (trimmed) */ description: string; /** Acceptance criteria */ acceptance: ProjectTicketCriterion[]; /** Log lines (without the leading `- `) */ log: string[]; } /** Parse outcome: a ticket, or why the file is not one. */ export type ParseTicketResult = { ok: true; file: ParsedTicketFile; } | { ok: false; error: string; }; /** Changes applied by {@link applyTicketChanges}. */ export interface TicketChanges { /** Owned frontmatter fields to set */ fields?: Partial; /** Replace the Description section content */ description?: string; /** Replace the Acceptance criteria section content */ acceptance?: ProjectTicketCriterion[]; /** Lines to append to the Log section (without `- `) */ logLines?: string[]; } /** Content of a brand-new ticket file. */ export interface NewTicketContent { fields: ProjectTicketFields; description: string; acceptance: ProjectTicketCriterion[]; logLines: string[]; } /** * Render acceptance criteria as checkbox lines. * * @param criteria - Criteria * @param eol - Line ending * @returns Section content */ export declare function renderCriteria(criteria: readonly ProjectTicketCriterion[], eol?: string): string; /** * Parse a ticket file. Never throws: an unreadable file comes back as * `{ ok: false, error }` so callers can skip it with a warning. * * @param content - Whole file content * @returns The parsed ticket, or the reason it is not one * * @example * ```typescript * const r = parseTicketFile(await fs.readFile(p, 'utf8')); * if (r.ok) console.log(r.file.fields.status); * ``` */ export declare function parseTicketFile(content: string): ParseTicketResult; /** * Apply changes to a ticket file, touching only owned frontmatter keys and * the sections asked for. * * @param content - Current file content * @param changes - What to change * @returns New file content (identical to `content` when nothing changes) * @throws When the file has no parseable frontmatter mapping * * @example * ```typescript * const next = applyTicketChanges(text, { fields: { status: 'ready' }, logLines: ['… · owner · ready'] }); * ``` */ export declare function applyTicketChanges(content: string, changes: TicketChanges): string; /** * Render a brand-new ticket file. * * @param content - Fields, description, criteria and the first log lines * @returns File content */ export declare function renderNewTicketFile(content: NewTicketContent): string; /** * A file-name slug for a title (`Export as CSV!` → `export-as-csv`). * * @param title - Ticket title * @returns Slug (never empty) */ export declare function slugifyTitle(title: string): string; /** * Format one Log line: ` · · `. * * @param actor - Who did it (`owner`, a session name, `system`) * @param message - What happened * @param at - Timestamp (defaults to now) * @returns The line (without `- `) */ export declare function formatLogLine(actor: string, message: string, at?: string): string; //# sourceMappingURL=ticket-file.d.ts.map