markform 0.0.1 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli-9fvFySww.mjs","names":["result: Record<string, unknown>","OUTPUT_FORMATS: OutputFormat[]","formatState","formatConsoleReport","lines: string[]","parsedJson: unknown","result","formatFieldValue","lines: string[]","plainValues: Record<string, unknown>","result: Record<string, unknown>","EXAMPLE_DEFINITIONS: ExampleDefinition[]","candidate","version","items","values: Record<string, \"todo\" | \"done\">","values: Record<string, \"yes\" | \"no\" | \"unfilled\">","values: Record<string, \"todo\" | \"done\" | \"incomplete\" | \"active\" | \"na\">","patches: Patch[]","options: { value: string; label: string; hint?: string }[]","harnessConfig: Partial<HarnessConfig>","patches: Patch[]","example","content: string","format: ExportFormat","output: ExportOutput","lines: string[]","targetRoles: string[]","fillMode: FillMode","durationMs","outputPath","formMarkdown","harnessConfig: Partial<HarnessConfig>","agent: Agent","mockPath: string | undefined","systemPrompt: string | undefined","transcript: SessionTranscript","formatState","formatPriority","formatSeverity","formatConsoleReport","lines: string[]","targetRoles: string[] | undefined","lines: string[]","command: string","result: Record<string, string | string[]>","patches: Patch[]","values: Record<string, \"done\" | \"todo\">","values: Record<string, string>","chunks: Buffer[]","inputHtml: string","lines: string[]"],"sources":["../src/cli/lib/naming.ts","../src/cli/lib/shared.ts","../src/cli/commands/apply.ts","../src/cli/commands/dump.ts","../src/cli/lib/exportHelpers.ts","../src/cli/examples/exampleRegistry.ts","../src/cli/lib/versioning.ts","../src/cli/lib/interactivePrompts.ts","../src/cli/commands/examples.ts","../src/cli/commands/export.ts","../src/cli/commands/fill.ts","../src/cli/commands/inspect.ts","../src/cli/commands/models.ts","../src/cli/commands/serve.ts","../src/cli/commands/render.ts","../src/cli/commands/validate.ts","../src/cli/cli.ts"],"sourcesContent":["/**\n * Naming convention utilities for JSON/YAML output.\n *\n * Converts between camelCase (TypeScript internal) and snake_case (JSON/YAML output).\n */\n\n/**\n * Convert a camelCase string to snake_case.\n *\n * @example\n * toSnakeCase(\"fieldCount\") // \"field_count\"\n * toSnakeCase(\"parentFieldId\") // \"parent_field_id\"\n * toSnakeCase(\"already_snake\") // \"already_snake\"\n */\nexport function toSnakeCase(str: string): string {\n return str.replace(/([A-Z])/g, \"_$1\").toLowerCase();\n}\n\n/**\n * Convert a snake_case string to camelCase.\n *\n * @example\n * toCamelCase(\"field_count\") // \"fieldCount\"\n * toCamelCase(\"parent_field_id\") // \"parentFieldId\"\n * toCamelCase(\"alreadyCamel\") // \"alreadyCamel\"\n */\nexport function toCamelCase(str: string): string {\n return str.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase());\n}\n\n/**\n * Recursively convert all object keys from camelCase to snake_case.\n *\n * Handles nested objects and arrays. Primitives are returned unchanged.\n */\nexport function convertKeysToSnakeCase(obj: unknown): unknown {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(convertKeysToSnakeCase);\n }\n\n if (typeof obj === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n const snakeKey = toSnakeCase(key);\n result[snakeKey] = convertKeysToSnakeCase(value);\n }\n return result;\n }\n\n return obj;\n}\n\n/**\n * Recursively convert all object keys from snake_case to camelCase.\n *\n * Handles nested objects and arrays. Primitives are returned unchanged.\n */\nexport function convertKeysToCamelCase(obj: unknown): unknown {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(convertKeysToCamelCase);\n }\n\n if (typeof obj === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n const camelKey = toCamelCase(key);\n result[camelKey] = convertKeysToCamelCase(value);\n }\n return result;\n }\n\n return obj;\n}\n","/**\n * Shared CLI utilities for command context, debug, and dry-run helpers.\n */\n\nimport type { Command } from \"commander\";\n\nimport { relative } from \"node:path\";\n\nimport pc from \"picocolors\";\nimport YAML from \"yaml\";\n\nimport { convertKeysToSnakeCase } from \"./naming.js\";\nimport type { CommandContext, OutputFormat } from \"./cliTypes.js\";\n\n// Re-export types for backwards compatibility\nexport type { CommandContext, OutputFormat } from \"./cliTypes.js\";\n\n/**\n * Valid format options for Commander choice validation.\n */\nexport const OUTPUT_FORMATS: OutputFormat[] = [\n \"console\",\n \"plaintext\",\n \"yaml\",\n \"json\",\n \"markform\",\n \"markdown\",\n];\n\n/**\n * Extract command context from Commander options.\n */\nexport function getCommandContext(command: Command): CommandContext {\n const opts = command.optsWithGlobals<{\n dryRun?: boolean;\n verbose?: boolean;\n quiet?: boolean;\n format?: OutputFormat;\n }>();\n return {\n dryRun: opts.dryRun ?? false,\n verbose: opts.verbose ?? false,\n quiet: opts.quiet ?? false,\n format: opts.format ?? \"console\",\n };\n}\n\n/**\n * Check if output should use colors.\n * Returns true for console format when stdout is a TTY.\n */\nexport function shouldUseColors(ctx: CommandContext): boolean {\n if (ctx.format === \"plaintext\" || ctx.format === \"yaml\" || ctx.format === \"json\") {\n return false;\n }\n // console format: use colors if stdout is a TTY and NO_COLOR is not set\n return process.stdout.isTTY && !process.env.NO_COLOR;\n}\n\n/**\n * Format structured data according to output format.\n *\n * JSON and YAML outputs are converted to snake_case keys for consistency.\n */\nexport function formatOutput(\n ctx: CommandContext,\n data: unknown,\n consoleFormatter?: (data: unknown, useColors: boolean) => string\n): string {\n switch (ctx.format) {\n case \"json\":\n return JSON.stringify(convertKeysToSnakeCase(data), null, 2);\n case \"yaml\":\n return YAML.stringify(convertKeysToSnakeCase(data));\n case \"plaintext\":\n case \"console\":\n default:\n if (consoleFormatter) {\n return consoleFormatter(data, shouldUseColors(ctx));\n }\n // Default: use YAML for readable console output\n return YAML.stringify(convertKeysToSnakeCase(data));\n }\n}\n\n/**\n * Log a dry-run message.\n */\nexport function logDryRun(message: string, details?: unknown): void {\n console.log(pc.yellow(`[DRY RUN] ${message}`));\n if (details) {\n console.log(pc.dim(JSON.stringify(details, null, 2)));\n }\n}\n\n/**\n * Log a verbose message (only shown if --verbose is set).\n */\nexport function logVerbose(ctx: CommandContext, message: string): void {\n if (ctx.verbose) {\n console.log(pc.dim(message));\n }\n}\n\n/**\n * Log an info message (hidden if --quiet is set).\n */\nexport function logInfo(ctx: CommandContext, message: string): void {\n if (!ctx.quiet) {\n console.log(message);\n }\n}\n\n/**\n * Log an error message (always shown).\n */\nexport function logError(message: string): void {\n console.error(pc.red(`Error: ${message}`));\n}\n\n/**\n * Log a success message (hidden if --quiet is set).\n */\nexport function logSuccess(ctx: CommandContext, message: string): void {\n if (!ctx.quiet) {\n console.log(pc.green(message));\n }\n}\n\n/**\n * Log a timing message (hidden if --quiet is set).\n */\nexport function logTiming(\n ctx: CommandContext,\n label: string,\n durationMs: number\n): void {\n if (!ctx.quiet) {\n const seconds = (durationMs / 1000).toFixed(1);\n console.log(pc.cyan(`⏰ ${label}: ${seconds}s`));\n }\n}\n\n/**\n * Log a warning message (hidden if --quiet is set).\n */\nexport function logWarn(ctx: CommandContext, message: string): void {\n if (!ctx.quiet) {\n console.log(pc.yellow(`⚠️ ${message}`));\n }\n}\n\n/**\n * Format a file path for display: relative to cwd, colored green.\n * If the path is within the cwd, shows as relative (e.g., \"./simple-filled1.form.md\")\n * If outside cwd, shows the absolute path.\n */\nexport function formatPath(absolutePath: string, cwd: string = process.cwd()): string {\n const relativePath = relative(cwd, absolutePath);\n // If the relative path doesn't start with \"..\", it's within cwd\n const displayPath = relativePath.startsWith(\"..\") ? absolutePath : `./${relativePath}`;\n return pc.green(displayPath);\n}\n\n/**\n * Read a file and return its contents.\n */\nexport async function readFile(filePath: string): Promise<string> {\n const { readFile: fsReadFile } = await import(\"node:fs/promises\");\n return fsReadFile(filePath, \"utf-8\");\n}\n\n/**\n * Write contents to a file.\n */\nexport async function writeFile(\n filePath: string,\n contents: string\n): Promise<void> {\n const { writeFile: fsWriteFile } = await import(\"node:fs/promises\");\n await fsWriteFile(filePath, contents, \"utf-8\");\n}\n","/**\n * Apply command - Apply patches to a form.\n *\n * Reads patches from JSON and applies them to the form,\n * outputting the modified form or a report.\n */\n\nimport type { Command } from \"commander\";\n\nimport pc from \"picocolors\";\n\nimport { applyPatches } from \"../../engine/apply.js\";\nimport { parseForm } from \"../../engine/parse.js\";\nimport { serialize } from \"../../engine/serialize.js\";\nimport type { ApplyResult, InspectIssue, ProgressState } from \"../../engine/coreTypes.js\";\nimport { PatchSchema } from \"../../engine/coreTypes.js\";\nimport {\n formatOutput,\n getCommandContext,\n logDryRun,\n logError,\n logSuccess,\n logVerbose,\n readFile,\n writeFile,\n} from \"../lib/shared.js\";\n\ninterface ApplyReport {\n apply_status: \"applied\" | \"rejected\";\n form_state: ProgressState;\n is_complete: boolean;\n structure: ApplyResult[\"structureSummary\"];\n progress: ApplyResult[\"progressSummary\"];\n issues: InspectIssue[];\n}\n\n/**\n * Format state badge for console output.\n */\nfunction formatState(state: ProgressState, useColors: boolean): string {\n const badges: Record<ProgressState, [string, (s: string) => string]> = {\n complete: [\"✓ complete\", pc.green],\n incomplete: [\"○ incomplete\", pc.yellow],\n empty: [\"◌ empty\", pc.dim],\n invalid: [\"✗ invalid\", pc.red],\n };\n const [text, colorFn] = badges[state] ?? [state, (s: string) => s];\n return useColors ? colorFn(text) : text;\n}\n\n/**\n * Format apply report for console output.\n */\nfunction formatConsoleReport(report: ApplyReport, useColors: boolean): string {\n const lines: string[] = [];\n const bold = useColors ? pc.bold : (s: string) => s;\n const dim = useColors ? pc.dim : (s: string) => s;\n const cyan = useColors ? pc.cyan : (s: string) => s;\n const green = useColors ? pc.green : (s: string) => s;\n const red = useColors ? pc.red : (s: string) => s;\n\n // Header\n lines.push(bold(cyan(\"Apply Result\")));\n lines.push(\"\");\n\n // Status\n const statusColor = report.apply_status === \"applied\" ? green : red;\n lines.push(`${bold(\"Status:\")} ${statusColor(report.apply_status)}`);\n lines.push(`${bold(\"Form State:\")} ${formatState(report.form_state, useColors)}`);\n lines.push(`${bold(\"Complete:\")} ${report.is_complete ? green(\"yes\") : dim(\"no\")}`);\n lines.push(\"\");\n\n // Progress summary\n const counts = report.progress.counts;\n lines.push(bold(\"Progress:\"));\n lines.push(` Total fields: ${counts.totalFields}`);\n lines.push(` Complete: ${counts.completeFields}`);\n lines.push(` Incomplete: ${counts.incompleteFields}`);\n lines.push(` Empty (required): ${counts.emptyRequiredFields}`);\n lines.push(\"\");\n\n // Issues\n if (report.issues.length > 0) {\n lines.push(bold(`Issues (${report.issues.length}):`));\n for (const issue of report.issues) {\n const priority = `P${issue.priority}`;\n lines.push(` ${dim(priority)} ${dim(issue.ref)}: ${issue.message}`);\n }\n } else {\n lines.push(dim(\"No issues.\"));\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Register the apply command.\n */\nexport function registerApplyCommand(program: Command): void {\n program\n .command(\"apply <file>\")\n .description(\"Apply patches to a form\")\n .option(\"--patch <json>\", \"JSON array of patches to apply\")\n .option(\"-o, --output <file>\", \"Output file (defaults to stdout)\")\n .option(\"--report\", \"Output apply result report instead of modified form\")\n .action(\n async (\n file: string,\n options: { patch?: string; output?: string; report?: boolean },\n cmd: Command\n ) => {\n const ctx = getCommandContext(cmd);\n\n try {\n // Validate patch option\n if (!options.patch) {\n logError(\"--patch option is required\");\n process.exit(1);\n }\n\n logVerbose(ctx, `Reading file: ${file}`);\n const content = await readFile(file);\n\n logVerbose(ctx, \"Parsing form...\");\n const form = parseForm(content);\n\n logVerbose(ctx, \"Parsing patches...\");\n let parsedJson: unknown;\n try {\n parsedJson = JSON.parse(options.patch) as unknown;\n } catch {\n logError(\"Invalid JSON in --patch option\");\n process.exit(1);\n }\n\n if (!Array.isArray(parsedJson)) {\n logError(\"--patch must be a JSON array\");\n process.exit(1);\n }\n const patches = parsedJson as unknown[];\n\n // Validate each patch against schema\n const validatedPatches = [];\n for (let i = 0; i < patches.length; i++) {\n const result = PatchSchema.safeParse(patches[i]);\n if (!result.success) {\n logError(\n `Invalid patch at index ${i}: ${result.error.issues[0]?.message ?? \"Unknown error\"}`\n );\n process.exit(1);\n }\n validatedPatches.push(result.data);\n }\n\n if (ctx.dryRun) {\n logDryRun(`Would apply ${validatedPatches.length} patches to ${file}`, {\n patches: validatedPatches,\n });\n return;\n }\n\n logVerbose(ctx, `Applying ${validatedPatches.length} patches...`);\n const result = applyPatches(form, validatedPatches);\n\n if (result.applyStatus === \"rejected\") {\n logError(\"Patches rejected - structural validation failed\");\n const report: ApplyReport = {\n apply_status: result.applyStatus,\n form_state: result.formState,\n is_complete: result.isComplete,\n structure: result.structureSummary,\n progress: result.progressSummary,\n issues: result.issues,\n };\n const output = formatOutput(ctx, report, (data, useColors) =>\n formatConsoleReport(data as ApplyReport, useColors)\n );\n console.error(output);\n process.exit(1);\n }\n\n // Output result\n if (options.report) {\n // Output apply result report\n const report: ApplyReport = {\n apply_status: result.applyStatus,\n form_state: result.formState,\n is_complete: result.isComplete,\n structure: result.structureSummary,\n progress: result.progressSummary,\n issues: result.issues,\n };\n\n const output = formatOutput(ctx, report, (data, useColors) =>\n formatConsoleReport(data as ApplyReport, useColors)\n );\n if (options.output) {\n await writeFile(options.output, output);\n logSuccess(ctx, `Report written to ${options.output}`);\n } else {\n console.log(output);\n }\n } else {\n // Output modified form (always markdown)\n const output = serialize(form);\n if (options.output) {\n await writeFile(options.output, output);\n logSuccess(ctx, `Modified form written to ${options.output}`);\n } else {\n console.log(output);\n }\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logError(message);\n process.exit(1);\n }\n }\n );\n}\n","/**\n * Dump command - Extract and display form values only.\n *\n * A lightweight alternative to inspect that outputs only the values map,\n * without structure, progress, or validation information.\n * Useful for quick value extraction, scripting, and integration.\n */\n\nimport type { Command } from \"commander\";\n\nimport pc from \"picocolors\";\n\nimport { parseForm } from \"../../engine/parse.js\";\nimport type { FieldValue } from \"../../engine/coreTypes.js\";\nimport {\n formatOutput,\n getCommandContext,\n logError,\n logVerbose,\n readFile,\n} from \"../lib/shared.js\";\n\n/**\n * Format a field value for console display.\n */\nfunction formatFieldValue(\n value: FieldValue | undefined,\n useColors: boolean\n): string {\n const dim = useColors ? pc.dim : (s: string) => s;\n const green = useColors ? pc.green : (s: string) => s;\n\n if (!value) {\n return dim(\"(empty)\");\n }\n\n switch (value.kind) {\n case \"string\":\n return value.value ? green(`\"${value.value}\"`) : dim(\"(empty)\");\n case \"number\":\n return value.value !== null ? green(String(value.value)) : dim(\"(empty)\");\n case \"string_list\":\n return value.items.length > 0\n ? green(`[${value.items.join(\", \")}]`)\n : dim(\"(empty)\");\n case \"single_select\":\n return value.selected ? green(value.selected) : dim(\"(none selected)\");\n case \"multi_select\":\n return value.selected.length > 0\n ? green(`[${value.selected.join(\", \")}]`)\n : dim(\"(none selected)\");\n case \"checkboxes\": {\n const entries = Object.entries(value.values);\n if (entries.length === 0) {\n return dim(\"(no entries)\");\n }\n return entries.map(([k, v]) => `${k}:${v}`).join(\", \");\n }\n default:\n return dim(\"(unknown)\");\n }\n}\n\n/**\n * Format values for console output.\n */\nfunction formatConsoleValues(\n values: Record<string, FieldValue>,\n useColors: boolean\n): string {\n const lines: string[] = [];\n const bold = useColors ? pc.bold : (s: string) => s;\n\n for (const [fieldId, value] of Object.entries(values)) {\n const valueStr = formatFieldValue(value, useColors);\n lines.push(`${bold(fieldId)}: ${valueStr}`);\n }\n\n if (lines.length === 0) {\n const dim = useColors ? pc.dim : (s: string) => s;\n lines.push(dim(\"(no values)\"));\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Convert FieldValue to a plain value for JSON/YAML serialization.\n */\nfunction toPlainValue(value: FieldValue): unknown {\n switch (value.kind) {\n case \"string\":\n return value.value ?? null;\n case \"number\":\n return value.value ?? null;\n case \"string_list\":\n return value.items;\n case \"single_select\":\n return value.selected ?? null;\n case \"multi_select\":\n return value.selected;\n case \"checkboxes\":\n return value.values;\n default:\n return null;\n }\n}\n\n/**\n * Register the dump command.\n */\nexport function registerDumpCommand(program: Command): void {\n program\n .command(\"dump <file>\")\n .description(\"Extract and display form values only (lightweight inspect)\")\n .action(async (file: string, _options: Record<string, unknown>, cmd: Command) => {\n const ctx = getCommandContext(cmd);\n\n try {\n logVerbose(ctx, `Reading file: ${file}`);\n const content = await readFile(file);\n\n logVerbose(ctx, \"Parsing form...\");\n const form = parseForm(content);\n\n // For JSON/YAML output, convert to plain values\n // For console/plaintext, use the full FieldValue objects for formatting\n const isStructured = ctx.format === \"json\" || ctx.format === \"yaml\";\n\n if (isStructured) {\n // Convert to plain values for structured output\n const plainValues: Record<string, unknown> = {};\n for (const [fieldId, value] of Object.entries(form.valuesByFieldId)) {\n plainValues[fieldId] = toPlainValue(value);\n }\n const output = formatOutput(ctx, plainValues, () => \"\");\n console.log(output);\n } else {\n // Use formatted output for console/plaintext\n const output = formatOutput(ctx, form.valuesByFieldId, (data, useColors) =>\n formatConsoleValues(data as Record<string, FieldValue>, useColors)\n );\n console.log(output);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logError(message);\n process.exit(1);\n }\n });\n}\n","/**\n * Export helpers for multi-format form output.\n *\n * Provides reusable functions for exporting forms to multiple formats:\n * - Markform format (.form.md) - canonical form with directives\n * - Raw markdown (.raw.md) - plain readable markdown\n * - YAML values (.yml) - extracted field values\n */\n\nimport { writeFileSync } from \"node:fs\";\nimport YAML from \"yaml\";\n\nimport { serialize, serializeRawMarkdown } from \"../../engine/serialize.js\";\nimport type { ParsedForm } from \"../../engine/coreTypes.js\";\nimport type { ExportResult } from \"./cliTypes.js\";\n\n// Re-export types for backwards compatibility\nexport type { ExportResult } from \"./cliTypes.js\";\n\n/**\n * Convert field values to plain values for YAML export.\n *\n * Extracts the underlying values from the typed FieldValue wrappers\n * for a cleaner YAML representation.\n */\nexport function toPlainValues(form: ParsedForm): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [fieldId, value] of Object.entries(form.valuesByFieldId)) {\n switch (value.kind) {\n case \"string\":\n result[fieldId] = value.value ?? null;\n break;\n case \"number\":\n result[fieldId] = value.value ?? null;\n break;\n case \"string_list\":\n result[fieldId] = value.items;\n break;\n case \"single_select\":\n result[fieldId] = value.selected ?? null;\n break;\n case \"multi_select\":\n result[fieldId] = value.selected;\n break;\n case \"checkboxes\":\n result[fieldId] = value.values;\n break;\n }\n }\n\n return result;\n}\n\n/**\n * Derive export paths from a base form path.\n *\n * @param basePath - Path to the .form.md file\n * @returns Object with paths for all export formats\n */\nexport function deriveExportPaths(basePath: string): ExportResult {\n return {\n formPath: basePath,\n rawPath: basePath.replace(/\\.form\\.md$/, \".raw.md\"),\n yamlPath: basePath.replace(/\\.form\\.md$/, \".yml\"),\n };\n}\n\n/**\n * Export form to multiple formats.\n *\n * Writes:\n * - Markform format (.form.md) - canonical form with directives\n * - Raw markdown (.raw.md) - plain readable markdown (no directives)\n * - YAML values (.yml) - extracted field values only\n *\n * @param form - The parsed form to export\n * @param basePath - Base path for the .form.md file (other paths are derived)\n * @returns Paths to all exported files\n */\nexport function exportMultiFormat(\n form: ParsedForm,\n basePath: string,\n): ExportResult {\n const paths = deriveExportPaths(basePath);\n\n // Export form markdown\n const formContent = serialize(form);\n writeFileSync(paths.formPath, formContent, \"utf-8\");\n\n // Export raw markdown\n const rawContent = serializeRawMarkdown(form);\n writeFileSync(paths.rawPath, rawContent, \"utf-8\");\n\n // Export YAML values\n const values = toPlainValues(form);\n const yamlContent = YAML.stringify(values);\n writeFileSync(paths.yamlPath, yamlContent, \"utf-8\");\n\n return paths;\n}\n\n/**\n * Export form to markform format only.\n *\n * Use this for commands like `markform fill` where only the canonical format\n * is needed by default. Users can generate raw/yaml via `markform export` or\n * `markform dump`. Note: The `examples` command uses exportMultiFormat() for\n * both user and agent fills.\n *\n * @param form - The parsed form to export\n * @param outputPath - Path to write the .form.md file\n */\nexport function exportFormOnly(form: ParsedForm, outputPath: string): void {\n const formContent = serialize(form);\n writeFileSync(outputPath, formContent, \"utf-8\");\n}\n","/**\n * Example form registry.\n * Provides form content from the examples directory for the examples CLI command.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport type { ExampleDefinition } from \"../lib/cliTypes.js\";\n\n// Re-export types for backwards compatibility\nexport type { ExampleDefinition } from \"../lib/cliTypes.js\";\n\n/** Example definitions without content - content is loaded lazily. */\nexport const EXAMPLE_DEFINITIONS: ExampleDefinition[] = [\n {\n id: \"simple\",\n title: \"Simple Test Form\",\n description:\n \"User and agent roles for testing full workflow. User fills required fields, agent fills optional.\",\n filename: \"simple.form.md\",\n path: \"simple/simple.form.md\",\n },\n {\n id: \"political-research\",\n title: \"Political Research\",\n description:\n \"Biographical research form with one user field (name) and agent-filled details. Uses web search.\",\n filename: \"political-research.form.md\",\n path: \"political-research/political-research.form.md\",\n },\n {\n id: \"earnings-analysis\",\n title: \"Company Quarterly Analysis\",\n description:\n \"Financial analysis with one user field (company) and agent-filled quarterly analysis sections.\",\n filename: \"earnings-analysis.form.md\",\n path: \"earnings-analysis/earnings-analysis.form.md\",\n },\n];\n\n/**\n * Get the path to the examples directory.\n * Works both during development and when installed as a package.\n */\nfunction getExamplesDir(): string {\n // Get the directory of this file\n // - Bundled mode: thisDir is /path/to/package/dist\n // - Dev mode: thisDir is /path/to/package/src/cli/examples\n const thisDir = dirname(fileURLToPath(import.meta.url));\n\n // Check if we're in the dist directory (bundled mode)\n // Use basename to check the directory name, not a substring match\n const dirName = thisDir.split(/[/\\\\]/).pop();\n if (dirName === \"dist\") {\n // Bundled: dist -> package root -> examples\n return join(dirname(thisDir), \"examples\");\n }\n\n // Development mode: src/cli/examples -> src/cli -> src -> package root -> examples\n return join(dirname(dirname(dirname(thisDir))), \"examples\");\n}\n\n/**\n * Load the content of an example form.\n * @param exampleId - The example ID (e.g., 'simple', 'political-research')\n * @returns The form content as a string\n * @throws Error if the example is not found\n */\nexport function loadExampleContent(exampleId: string): string {\n const example = EXAMPLE_DEFINITIONS.find((e) => e.id === exampleId);\n if (!example) {\n throw new Error(`Unknown example: ${exampleId}`);\n }\n\n const examplesDir = getExamplesDir();\n const filePath = join(examplesDir, example.path);\n\n try {\n return readFileSync(filePath, \"utf-8\");\n } catch (error) {\n throw new Error(\n `Failed to load example '${exampleId}' from ${filePath}: ${error}`,\n );\n }\n}\n\n/**\n * Get all example IDs.\n */\nexport function getExampleIds(): string[] {\n return EXAMPLE_DEFINITIONS.map((e) => e.id);\n}\n\n/**\n * Get an example definition by ID.\n */\nexport function getExampleById(id: string): ExampleDefinition | undefined {\n return EXAMPLE_DEFINITIONS.find((e) => e.id === id);\n}\n","/**\n * Versioned filename utilities for form output.\n *\n * Generates versioned filenames to avoid overwriting existing files.\n * Pattern: name.form.md → name-filled1.form.md → name-filled2.form.md\n */\n\nimport { existsSync } from \"node:fs\";\n\n/**\n * Version pattern that matches -filledN or _filledN before the extension.\n * Also matches legacy -vN pattern for backwards compatibility.\n */\nconst VERSION_PATTERN = /^(.+?)(?:[-_]?(?:filled|v)(\\d+))?(\\.form\\.md)$/i;\n\n/**\n * Extension pattern for fallback matching.\n */\nconst EXTENSION_PATTERN = /^(.+)(\\.form\\.md)$/i;\n\n/**\n * Parse a versioned filename into its components.\n *\n * @param filePath - Path to parse\n * @returns Parsed components or null if not a valid form file\n */\nexport function parseVersionedPath(filePath: string): {\n base: string;\n version: number | null;\n extension: string;\n} | null {\n const match = VERSION_PATTERN.exec(filePath);\n if (match) {\n const base = match[1];\n const versionStr = match[2];\n const ext = match[3];\n // The regex guarantees base and ext are defined when match succeeds\n if (base !== undefined && ext !== undefined) {\n return {\n base,\n version: versionStr ? parseInt(versionStr, 10) : null,\n extension: ext,\n };\n }\n }\n\n const extMatch = EXTENSION_PATTERN.exec(filePath);\n if (extMatch) {\n const base = extMatch[1];\n const ext = extMatch[2];\n // The regex guarantees both groups are defined when match succeeds\n if (base !== undefined && ext !== undefined) {\n return {\n base,\n version: null,\n extension: ext,\n };\n }\n }\n\n return null;\n}\n\n/**\n * Generate the next versioned filename.\n *\n * If the file has no version, adds -filled1.\n * If the file has a version, increments it.\n *\n * @param filePath - Original file path\n * @returns Next versioned filename\n */\nexport function incrementVersion(filePath: string): string {\n const parsed = parseVersionedPath(filePath);\n\n if (parsed) {\n const newVersion = parsed.version !== null ? parsed.version + 1 : 1;\n return `${parsed.base}-filled${newVersion}${parsed.extension}`;\n }\n\n // Fallback for non-.form.md files\n return `${filePath}-filled1`;\n}\n\n/**\n * Generate a versioned filename that doesn't conflict with existing files.\n *\n * Starts from the incremented version and keeps incrementing until\n * a non-existent filename is found.\n *\n * @param filePath - Original file path\n * @returns Path to a non-existent versioned file\n */\nexport function generateVersionedPath(filePath: string): string {\n const parsed = parseVersionedPath(filePath);\n\n if (!parsed) {\n // Fallback for non-.form.md files\n let candidate = `${filePath}-filled1`;\n let version = 1;\n while (existsSync(candidate)) {\n version++;\n candidate = `${filePath}-filled${version}`;\n }\n return candidate;\n }\n\n // Start from version 1 or increment existing version\n let version = parsed.version !== null ? parsed.version + 1 : 1;\n let candidate = `${parsed.base}-filled${version}${parsed.extension}`;\n\n // Find next available version\n while (existsSync(candidate)) {\n version++;\n candidate = `${parsed.base}-filled${version}${parsed.extension}`;\n }\n\n return candidate;\n}\n","/**\n * Interactive prompts module for console-based form filling.\n *\n * Uses @clack/prompts to provide a rich terminal UI for users to\n * fill form fields interactively.\n */\n\nimport * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\n\nimport { formatPath } from \"./shared.js\";\n\nimport type {\n Field,\n FieldValue,\n Patch,\n StringField,\n NumberField,\n StringListField,\n SingleSelectField,\n MultiSelectField,\n CheckboxesField,\n ParsedForm,\n InspectIssue,\n} from \"../../engine/coreTypes.js\";\n\n/**\n * Context for a field prompt including description from docs.\n */\ninterface FieldPromptContext {\n field: Field;\n currentValue: FieldValue | undefined;\n description?: string;\n index: number;\n total: number;\n}\n\n/**\n * Get field description from form docs.\n */\nfunction getFieldDescription(form: ParsedForm, fieldId: string): string | undefined {\n const doc = form.docs.find(\n (d) => d.ref === fieldId && (d.tag === \"description\" || d.tag === \"instructions\")\n );\n return doc?.bodyMarkdown;\n}\n\n/**\n * Get a field by ID from the form schema.\n */\nfunction getFieldById(form: ParsedForm, fieldId: string): Field | undefined {\n for (const group of form.schema.groups) {\n const field = group.children.find((f) => f.id === fieldId);\n if (field) {\nreturn field;\n}\n }\n return undefined;\n}\n\n/**\n * Format field label with required indicator and progress.\n */\nfunction formatFieldLabel(ctx: FieldPromptContext): string {\n const required = ctx.field.required ? pc.red(\"*\") : \"\";\n const progress = pc.dim(`(${ctx.index} of ${ctx.total})`);\n return `${ctx.field.label}${required} ${progress}`;\n}\n\n/**\n * Prompt for a string field value.\n */\nasync function promptForString(ctx: FieldPromptContext): Promise<Patch | null> {\n const field = ctx.field as StringField;\n const currentVal =\n ctx.currentValue?.kind === \"string\" ? ctx.currentValue.value : null;\n\n const result = await p.text({\n message: formatFieldLabel(ctx),\n placeholder: currentVal ?? (ctx.description ? ctx.description.slice(0, 60) : undefined),\n initialValue: currentVal ?? \"\",\n validate: (value) => {\n if (field.required && !value.trim()) {\n return \"This field is required\";\n }\n if (field.minLength && value.length < field.minLength) {\n return `Minimum ${field.minLength} characters required`;\n }\n if (field.maxLength && value.length > field.maxLength) {\n return `Maximum ${field.maxLength} characters allowed`;\n }\n if (field.pattern && !new RegExp(field.pattern).test(value)) {\n return `Must match pattern: ${field.pattern}`;\n }\n return undefined;\n },\n });\n\n if (p.isCancel(result)) {\n return null;\n }\n\n // Skip if empty and not required (user pressed Enter to skip)\n if (!result && !field.required) {\n return null;\n }\n\n return {\n op: \"set_string\",\n fieldId: field.id,\n value: result || null,\n };\n}\n\n/**\n * Prompt for a number field value.\n */\nasync function promptForNumber(ctx: FieldPromptContext): Promise<Patch | null> {\n const field = ctx.field as NumberField;\n const currentVal =\n ctx.currentValue?.kind === \"number\" ? ctx.currentValue.value : null;\n\n const result = await p.text({\n message: formatFieldLabel(ctx),\n placeholder: currentVal !== null ? String(currentVal) : undefined,\n initialValue: currentVal !== null ? String(currentVal) : \"\",\n validate: (value) => {\n if (field.required && !value.trim()) {\n return \"This field is required\";\n }\n if (!value.trim()) {\n return undefined; // Allow empty for optional\n }\n const num = Number(value);\n if (isNaN(num)) {\n return \"Please enter a valid number\";\n }\n if (field.integer && !Number.isInteger(num)) {\n return \"Please enter a whole number\";\n }\n if (field.min !== undefined && num < field.min) {\n return `Minimum value is ${field.min}`;\n }\n if (field.max !== undefined && num > field.max) {\n return `Maximum value is ${field.max}`;\n }\n return undefined;\n },\n });\n\n if (p.isCancel(result)) {\n return null;\n }\n\n // Skip if empty and not required\n if (!result && !field.required) {\n return null;\n }\n\n return {\n op: \"set_number\",\n fieldId: field.id,\n value: result ? Number(result) : null,\n };\n}\n\n/**\n * Prompt for a string list field value.\n */\nasync function promptForStringList(ctx: FieldPromptContext): Promise<Patch | null> {\n const field = ctx.field as StringListField;\n const currentItems =\n ctx.currentValue?.kind === \"string_list\" ? ctx.currentValue.items : [];\n\n const hint = ctx.description\n ? `${ctx.description.slice(0, 50)}... (one item per line)`\n : \"Enter items, one per line. Press Enter twice when done.\";\n\n const result = await p.text({\n message: formatFieldLabel(ctx),\n placeholder: hint,\n initialValue: currentItems.join(\"\\n\"),\n validate: (value) => {\n const items = value\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter(Boolean);\n if (field.required && items.length === 0) {\n return \"At least one item is required\";\n }\n if (field.minItems && items.length < field.minItems) {\n return `Minimum ${field.minItems} items required`;\n }\n if (field.maxItems && items.length > field.maxItems) {\n return `Maximum ${field.maxItems} items allowed`;\n }\n return undefined;\n },\n });\n\n if (p.isCancel(result)) {\n return null;\n }\n\n const items = (result)\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter(Boolean);\n\n // Skip if empty and not required\n if (items.length === 0 && !field.required) {\n return null;\n }\n\n return {\n op: \"set_string_list\",\n fieldId: field.id,\n items,\n };\n}\n\n/**\n * Prompt for a single-select field value.\n */\nasync function promptForSingleSelect(ctx: FieldPromptContext): Promise<Patch | null> {\n const field = ctx.field as SingleSelectField;\n const currentSelected =\n ctx.currentValue?.kind === \"single_select\" ? ctx.currentValue.selected : null;\n\n const options = field.options.map((opt) => ({\n value: opt.id,\n label: opt.label,\n }));\n\n const result = await p.select({\n message: formatFieldLabel(ctx),\n options,\n initialValue: currentSelected ?? undefined,\n });\n\n if (p.isCancel(result)) {\n return null;\n }\n\n return {\n op: \"set_single_select\",\n fieldId: field.id,\n selected: result,\n };\n}\n\n/**\n * Prompt for a multi-select field value.\n */\nasync function promptForMultiSelect(ctx: FieldPromptContext): Promise<Patch | null> {\n const field = ctx.field as MultiSelectField;\n const currentSelected =\n ctx.currentValue?.kind === \"multi_select\" ? ctx.currentValue.selected : [];\n\n const options = field.options.map((opt) => ({\n value: opt.id,\n label: opt.label,\n }));\n\n const result = await p.multiselect({\n message: formatFieldLabel(ctx),\n options,\n initialValues: currentSelected,\n required: field.required,\n });\n\n if (p.isCancel(result)) {\n return null;\n }\n\n return {\n op: \"set_multi_select\",\n fieldId: field.id,\n selected: result,\n };\n}\n\n/**\n * Prompt for a checkboxes field value.\n *\n * Behavior varies by checkboxMode:\n * - simple: multiselect to pick items marked as done\n * - multi: per-option select with 5 states\n * - explicit: per-option yes/no/skip\n */\nasync function promptForCheckboxes(ctx: FieldPromptContext): Promise<Patch | null> {\n const field = ctx.field as CheckboxesField;\n const currentValues =\n ctx.currentValue?.kind === \"checkboxes\" ? ctx.currentValue.values : {};\n\n if (field.checkboxMode === \"simple\") {\n // Simple mode: multiselect to mark items as done\n const options = field.options.map((opt) => ({\n value: opt.id,\n label: opt.label,\n }));\n\n const currentlyDone = field.options\n .filter((opt) => currentValues[opt.id] === \"done\")\n .map((opt) => opt.id);\n\n const result = await p.multiselect({\n message: formatFieldLabel(ctx),\n options,\n initialValues: currentlyDone,\n required: field.required && field.minDone !== undefined && field.minDone > 0,\n });\n\n if (p.isCancel(result)) {\n return null;\n }\n\n const selected = result;\n const values: Record<string, \"todo\" | \"done\"> = {};\n for (const opt of field.options) {\n values[opt.id] = selected.includes(opt.id) ? \"done\" : \"todo\";\n }\n\n return {\n op: \"set_checkboxes\",\n fieldId: field.id,\n values,\n };\n }\n\n if (field.checkboxMode === \"explicit\") {\n // Explicit mode: yes/no for each option\n const values: Record<string, \"yes\" | \"no\" | \"unfilled\"> = {};\n\n for (const opt of field.options) {\n const current = currentValues[opt.id];\n const result = await p.select({\n message: `${opt.label}`,\n options: [\n { value: \"yes\", label: \"Yes\" },\n { value: \"no\", label: \"No\" },\n { value: \"unfilled\", label: \"Skip\" },\n ],\n initialValue: current === \"yes\" || current === \"no\" ? current : \"unfilled\",\n });\n\n if (p.isCancel(result)) {\n return null;\n }\n\n values[opt.id] = result as \"yes\" | \"no\" | \"unfilled\";\n }\n\n return {\n op: \"set_checkboxes\",\n fieldId: field.id,\n values,\n };\n }\n\n // Multi mode: 5 states per option\n const values: Record<string, \"todo\" | \"done\" | \"incomplete\" | \"active\" | \"na\"> = {};\n\n for (const opt of field.options) {\n const current = currentValues[opt.id] as\n | \"todo\"\n | \"done\"\n | \"incomplete\"\n | \"active\"\n | \"na\"\n | undefined;\n const result = await p.select({\n message: `${opt.label}`,\n options: [\n { value: \"todo\", label: \"To do\" },\n { value: \"active\", label: \"In progress\" },\n { value: \"done\", label: \"Done\" },\n { value: \"incomplete\", label: \"Incomplete\" },\n { value: \"na\", label: \"N/A\" },\n ],\n initialValue: current ?? \"todo\",\n });\n\n if (p.isCancel(result)) {\n return null;\n }\n\n values[opt.id] = result;\n }\n\n return {\n op: \"set_checkboxes\",\n fieldId: field.id,\n values,\n };\n}\n\n/**\n * Prompt user for a single field value based on field type.\n * Returns a Patch to set the value, or null if skipped/cancelled.\n */\nexport async function promptForField(\n ctx: FieldPromptContext\n): Promise<Patch | null> {\n // Show description if available\n if (ctx.description) {\n p.note(ctx.description, pc.dim(\"Instructions\"));\n }\n\n switch (ctx.field.kind) {\n case \"string\":\n return promptForString(ctx);\n case \"number\":\n return promptForNumber(ctx);\n case \"string_list\":\n return promptForStringList(ctx);\n case \"single_select\":\n return promptForSingleSelect(ctx);\n case \"multi_select\":\n return promptForMultiSelect(ctx);\n case \"checkboxes\":\n return promptForCheckboxes(ctx);\n default:\n // Unknown field type - skip\n return null;\n }\n}\n\n/**\n * Run an interactive fill session for a list of field issues.\n * Returns patches for all filled fields.\n *\n * @param form - The parsed form\n * @param issues - The issues indicating fields to fill\n * @returns Array of patches to apply\n */\nexport async function runInteractiveFill(\n form: ParsedForm,\n issues: InspectIssue[]\n): Promise<{ patches: Patch[]; cancelled: boolean }> {\n // Filter to field-level issues only (not form/group/option)\n const fieldIssues = issues.filter((i) => i.scope === \"field\");\n\n // Deduplicate by fieldId (a field might have multiple issues)\n const seenFieldIds = new Set<string>();\n const uniqueFieldIssues = fieldIssues.filter((issue) => {\n if (seenFieldIds.has(issue.ref)) {\nreturn false;\n}\n seenFieldIds.add(issue.ref);\n return true;\n });\n\n if (uniqueFieldIssues.length === 0) {\n p.note(\"No fields to fill for the selected role.\", \"Info\");\n return { patches: [], cancelled: false };\n }\n\n const patches: Patch[] = [];\n let index = 0;\n\n for (const issue of uniqueFieldIssues) {\n const field = getFieldById(form, issue.ref);\n if (!field) {\ncontinue;\n}\n\n index++;\n const ctx: FieldPromptContext = {\n field,\n currentValue: form.valuesByFieldId[field.id],\n description: getFieldDescription(form, field.id),\n index,\n total: uniqueFieldIssues.length,\n };\n\n const patch = await promptForField(ctx);\n\n if (patch === null && p.isCancel(patch)) {\n // User cancelled (Ctrl+C)\n const shouldContinue = await p.confirm({\n message: \"Cancel and discard changes?\",\n initialValue: false,\n });\n\n if (p.isCancel(shouldContinue) || shouldContinue) {\n return { patches: [], cancelled: true };\n }\n // Continue filling - re-prompt this field\n index--;\n continue;\n }\n\n if (patch) {\n patches.push(patch);\n }\n }\n\n return { patches, cancelled: false };\n}\n\n/**\n * Show intro message for interactive fill session.\n */\nexport function showInteractiveIntro(\n formTitle: string,\n role: string,\n fieldCount: number\n): void {\n p.intro(pc.bgCyan(pc.black(\" Markform Interactive Fill \")));\n\n const lines = [\n `${pc.bold(\"Form:\")} ${formTitle}`,\n `${pc.bold(\"Role:\")} ${role}`,\n `${pc.bold(\"Fields:\")} ${fieldCount} to fill`,\n ];\n\n p.note(lines.join(\"\\n\"), \"Session Info\");\n}\n\n/**\n * Show outro message after interactive fill.\n */\nexport function showInteractiveOutro(\n patchCount: number,\n outputPath: string,\n cancelled: boolean\n): void {\n if (cancelled) {\n p.cancel(\"Interactive fill cancelled.\");\n return;\n }\n\n if (patchCount === 0) {\n p.outro(pc.yellow(\"No changes made.\"));\n return;\n }\n\n p.outro(`✓ ${patchCount} field(s) updated. Saved to ${formatPath(outputPath)}`);\n}\n","/**\n * Examples command - Scaffold and fill example forms interactively.\n *\n * Provides a complete workflow:\n * 1. Select an example form\n * 2. Scaffold it with a versioned filename\n * 3. Automatically run interactive fill for user-role fields\n * 4. Optionally run agent fill for remaining fields\n * 5. Export results in multiple formats\n */\n\nimport type { Command } from \"commander\";\n\nimport * as p from \"@clack/prompts\";\nimport { existsSync, writeFileSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport pc from \"picocolors\";\n\nimport { parseForm } from \"../../engine/parse.js\";\nimport { inspect } from \"../../engine/inspect.js\";\nimport { applyPatches } from \"../../engine/apply.js\";\nimport { exportMultiFormat } from \"../lib/exportHelpers.js\";\nimport {\n USER_ROLE,\n AGENT_ROLE,\n SUGGESTED_LLMS,\n DEFAULT_MAX_TURNS,\n DEFAULT_MAX_PATCHES_PER_TURN,\n DEFAULT_MAX_ISSUES,\n} from \"../../settings.js\";\nimport type { ParsedForm, HarnessConfig, Patch } from \"../../engine/coreTypes.js\";\nimport { createHarness } from \"../../harness/harness.js\";\nimport { createLiveAgent } from \"../../harness/liveAgent.js\";\nimport { resolveModel, getProviderInfo, type ProviderName } from \"../../harness/modelResolver.js\";\nimport {\n EXAMPLE_DEFINITIONS,\n getExampleById,\n loadExampleContent,\n} from \"../examples/exampleRegistry.js\";\nimport { formatPath, getCommandContext, logError, logTiming } from \"../lib/shared.js\";\nimport { generateVersionedPath } from \"../lib/versioning.js\";\nimport {\n runInteractiveFill,\n showInteractiveIntro,\n showInteractiveOutro,\n} from \"../lib/interactivePrompts.js\";\n\n/**\n * Print non-interactive list of examples.\n */\nfunction printExamplesList(): void {\n console.log(pc.bold(\"Available examples:\\n\"));\n for (const example of EXAMPLE_DEFINITIONS) {\n console.log(` ${pc.cyan(example.id)}`);\n console.log(` ${pc.bold(example.title)}`);\n console.log(` ${pc.dim(example.description)}`);\n console.log(` Default filename: ${example.filename}`);\n console.log(\"\");\n }\n}\n\n/**\n * Display API availability status at startup.\n */\nfunction showApiStatus(): void {\n console.log(pc.dim(\"API Status:\"));\n for (const [provider, _models] of Object.entries(SUGGESTED_LLMS)) {\n const info = getProviderInfo(provider as ProviderName);\n const hasKey = !!process.env[info.envVar];\n const status = hasKey ? pc.green(\"✓\") : pc.dim(\"○\");\n const envVar = hasKey ? pc.dim(info.envVar) : pc.yellow(info.envVar);\n console.log(` ${status} ${provider} (${envVar})`);\n }\n console.log(\"\");\n}\n\n/**\n * Build model options for the select prompt.\n */\nfunction buildModelOptions(): { value: string; label: string; hint?: string }[] {\n const options: { value: string; label: string; hint?: string }[] = [];\n\n for (const [provider, models] of Object.entries(SUGGESTED_LLMS)) {\n const info = getProviderInfo(provider as ProviderName);\n const hasKey = !!process.env[info.envVar];\n const keyStatus = hasKey ? pc.green(\"✓\") : pc.dim(\"○\");\n\n for (const model of models.slice(0, 2)) {\n // Show top 2 models per provider\n options.push({\n value: `${provider}/${model}`,\n label: `${provider}/${model}`,\n hint: `${keyStatus} ${info.envVar}`,\n });\n }\n }\n\n options.push({\n value: \"custom\",\n label: \"Enter custom model ID...\",\n hint: \"provider/model-id format\",\n });\n\n return options;\n}\n\n/**\n * Prompt user to select a model for agent fill.\n */\nasync function promptForModel(): Promise<string | null> {\n const modelOptions = buildModelOptions();\n\n const selection = await p.select({\n message: \"Select LLM model:\",\n options: modelOptions,\n });\n\n if (p.isCancel(selection)) {\n return null;\n }\n\n if (selection === \"custom\") {\n const customModel = await p.text({\n message: \"Model ID (provider/model-id):\",\n placeholder: \"anthropic/claude-sonnet-4-20250514\",\n validate: (value) => {\n if (!value.includes(\"/\")) {\n return \"Format: provider/model-id (e.g., anthropic/claude-sonnet-4-20250514)\";\n }\n return undefined;\n },\n });\n\n if (p.isCancel(customModel)) {\n return null;\n }\n\n return customModel;\n }\n\n return selection;\n}\n\n/**\n * Run the agent fill workflow.\n */\nasync function runAgentFill(\n form: ParsedForm,\n modelId: string,\n _outputPath: string,\n): Promise<{ success: boolean; turnCount: number }> {\n const spinner = p.spinner();\n\n try {\n // Resolve the model\n spinner.start(`Resolving model: ${modelId}`);\n const { model } = await resolveModel(modelId);\n spinner.stop(`Model resolved: ${modelId}`);\n\n // Create harness config\n const harnessConfig: Partial<HarnessConfig> = {\n maxTurns: DEFAULT_MAX_TURNS,\n maxPatchesPerTurn: DEFAULT_MAX_PATCHES_PER_TURN,\n maxIssues: DEFAULT_MAX_ISSUES,\n targetRoles: [AGENT_ROLE],\n fillMode: \"continue\",\n };\n\n // Create harness and agent\n const harness = createHarness(form, harnessConfig);\n const agent = createLiveAgent({ model, targetRole: AGENT_ROLE });\n\n // Run harness loop with verbose output\n console.log(\"\");\n p.log.step(pc.bold(\"Agent fill in progress...\"));\n let stepResult = harness.step();\n\n while (!stepResult.isComplete && !harness.hasReachedMaxTurns()) {\n console.log(\n pc.dim(` Turn ${stepResult.turnNumber}: ${stepResult.issues.length} issue(s) to address`)\n );\n\n // Generate patches from agent\n const patches: Patch[] = await agent.generatePatches(\n stepResult.issues,\n harness.getForm(),\n harnessConfig.maxPatchesPerTurn!\n );\n\n // Log each patch\n for (const patch of patches) {\n const fieldId = patch.fieldId;\n console.log(pc.dim(` → ${patch.op} ${fieldId}`));\n }\n\n // Apply patches\n stepResult = harness.apply(patches, stepResult.issues);\n console.log(\n pc.dim(` ${patches.length} patch(es) applied, ${stepResult.issues.length} remaining`)\n );\n\n if (!stepResult.isComplete) {\n stepResult = harness.step();\n }\n }\n\n if (stepResult.isComplete) {\n p.log.success(pc.green(`Form completed in ${harness.getTurnNumber()} turn(s)`));\n } else {\n p.log.warn(pc.yellow(`Max turns reached (${harnessConfig.maxTurns})`));\n }\n\n // Copy final form state\n Object.assign(form, harness.getForm());\n\n return {\n success: stepResult.isComplete,\n turnCount: harness.getTurnNumber(),\n };\n } catch (error) {\n spinner.stop(pc.red(\"Agent fill failed\"));\n throw error;\n }\n}\n\n/**\n * Run the interactive example scaffolding and filling flow.\n */\nasync function runInteractiveFlow(\n preselectedId?: string,\n): Promise<void> {\n const startTime = Date.now();\n\n p.intro(pc.bgCyan(pc.black(\" markform examples \")));\n\n // Show API availability status\n showApiStatus();\n\n // Step 1: Select example (or use preselected)\n let selectedId = preselectedId;\n\n if (!selectedId) {\n const selection = await p.select({\n message: \"Select an example form to scaffold:\",\n options: EXAMPLE_DEFINITIONS.map((example) => ({\n value: example.id,\n label: example.title,\n hint: example.description,\n })),\n });\n\n if (p.isCancel(selection)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n selectedId = selection;\n }\n\n const example = getExampleById(selectedId);\n if (!example) {\n p.cancel(`Unknown example: ${selectedId}`);\n process.exit(1);\n }\n\n // Step 2: Prompt for output filename (use filled naming convention)\n const defaultFilename = generateVersionedPath(example.filename);\n const filenameResult = await p.text({\n message: \"Output filename:\",\n initialValue: defaultFilename,\n validate: (value) => {\n if (!value.trim()) {\n return \"Filename is required\";\n }\n if (!value.endsWith(\".form.md\") && !value.endsWith(\".md\")) {\n return \"Filename should end with .form.md or .md\";\n }\n return undefined;\n },\n });\n\n if (p.isCancel(filenameResult)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n const filename = filenameResult;\n const outputPath = join(process.cwd(), filename);\n\n // Step 3: Check for existing file\n if (existsSync(outputPath)) {\n const overwrite = await p.confirm({\n message: `${filename} already exists. Overwrite?`,\n initialValue: false,\n });\n\n if (p.isCancel(overwrite) || !overwrite) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n }\n\n // Step 4: Load and write the example\n let content: string;\n try {\n content = loadExampleContent(selectedId);\n writeFileSync(outputPath, content, \"utf-8\");\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n p.cancel(`Failed to write file: ${message}`);\n process.exit(1);\n }\n\n p.log.success(`Created ${formatPath(outputPath)}`);\n\n // Step 5: Parse the form and run interactive fill\n const form = parseForm(content);\n const targetRoles = [USER_ROLE];\n\n // Inspect form to get issues for user role\n const inspectResult = inspect(form, { targetRoles });\n const fieldIssues = inspectResult.issues.filter((i) => i.scope === \"field\");\n const uniqueFieldIds = new Set(fieldIssues.map((i) => i.ref));\n\n if (uniqueFieldIds.size === 0) {\n p.log.info(\"No user-role fields to fill in this example.\");\n // Check if there are agent fields\n const agentInspect = inspect(form, { targetRoles: [AGENT_ROLE] });\n const agentFieldIssues = agentInspect.issues.filter((i) => i.scope === \"field\");\n\n if (agentFieldIssues.length === 0) {\n logTiming({ verbose: false, format: \"console\", dryRun: false, quiet: false }, \"Total time\", Date.now() - startTime);\n p.outro(pc.dim(\"Form scaffolded with no fields to fill.\"));\n return;\n }\n // Skip to agent fill\n } else {\n // Show interactive fill intro\n const formTitle = form.schema.title ?? form.schema.id;\n showInteractiveIntro(formTitle, targetRoles.join(\", \"), uniqueFieldIds.size);\n\n // Run interactive prompts\n const { patches, cancelled } = await runInteractiveFill(form, inspectResult.issues);\n\n if (cancelled) {\n showInteractiveOutro(0, \"\", true);\n process.exit(1);\n }\n\n // Apply patches to form\n if (patches.length > 0) {\n applyPatches(form, patches);\n }\n\n // Export filled form in all formats (examples command always exports all formats)\n const { formPath, rawPath, yamlPath } = exportMultiFormat(form, outputPath);\n\n showInteractiveOutro(patches.length, outputPath, false);\n console.log(\"\");\n p.log.success(\"Outputs:\");\n console.log(` ${formatPath(formPath)} ${pc.dim(\"(markform)\")}`);\n console.log(` ${formatPath(rawPath)} ${pc.dim(\"(plain markdown)\")}`);\n console.log(` ${formatPath(yamlPath)} ${pc.dim(\"(values as YAML)\")}`);\n\n logTiming({ verbose: false, format: \"console\", dryRun: false, quiet: false }, \"Fill time\", Date.now() - startTime);\n }\n\n // Step 6: Check for agent-role fields and prompt for agent fill\n const agentInspect = inspect(form, { targetRoles: [AGENT_ROLE] });\n const agentFieldIssues = agentInspect.issues.filter((i) => i.scope === \"field\");\n\n if (agentFieldIssues.length > 0) {\n console.log(\"\");\n p.log.info(`This form has ${agentFieldIssues.length} agent-role field(s) remaining.`);\n\n const runAgent = await p.confirm({\n message: \"Run agent fill now?\",\n initialValue: true,\n });\n\n if (p.isCancel(runAgent) || !runAgent) {\n console.log(\"\");\n console.log(pc.dim(\"You can run agent fill later with:\"));\n console.log(pc.dim(` markform fill ${formatPath(outputPath)} --agent=live --model=<provider/model>`));\n p.outro(pc.dim(\"Happy form filling!\"));\n return;\n }\n\n // Step 7: Model selection\n const modelId = await promptForModel();\n if (!modelId) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n // Step 8: Agent output filename\n const agentDefaultFilename = generateVersionedPath(outputPath);\n const agentFilenameResult = await p.text({\n message: \"Agent output filename:\",\n initialValue: basename(agentDefaultFilename),\n validate: (value) => {\n if (!value.trim()) {\n return \"Filename is required\";\n }\n return undefined;\n },\n });\n\n if (p.isCancel(agentFilenameResult)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n const agentOutputPath = join(process.cwd(), agentFilenameResult);\n\n // Step 9: Run agent fill\n const agentStartTime = Date.now();\n try {\n const { success, turnCount: _turnCount } = await runAgentFill(form, modelId, agentOutputPath);\n\n logTiming({ verbose: false, format: \"console\", dryRun: false, quiet: false }, \"Agent fill time\", Date.now() - agentStartTime);\n\n // Step 10: Multi-format export\n const { formPath, rawPath, yamlPath } = exportMultiFormat(form, agentOutputPath);\n\n console.log(\"\");\n p.log.success(\"Agent fill complete. Outputs:\");\n console.log(` ${formatPath(formPath)} ${pc.dim(\"(markform)\")}`);\n console.log(` ${formatPath(rawPath)} ${pc.dim(\"(plain markdown)\")}`);\n console.log(` ${formatPath(yamlPath)} ${pc.dim(\"(values as YAML)\")}`);\n\n if (!success) {\n p.log.warn(\"Agent did not complete all fields. You may need to run it again.\");\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n p.log.error(`Agent fill failed: ${message}`);\n console.log(\"\");\n console.log(pc.dim(\"You can try again with:\"));\n console.log(pc.dim(` markform fill ${formatPath(outputPath)} --agent=live --model=${modelId}`));\n }\n }\n\n p.outro(pc.dim(\"Happy form filling!\"));\n}\n\n/**\n * Register the examples command.\n */\nexport function registerExamplesCommand(program: Command): void {\n program\n .command(\"examples\")\n .description(\"Scaffold an example form and fill it interactively\")\n .option(\"--list\", \"List available examples without interactive selection\")\n .option(\n \"--name <example>\",\n \"Select example by ID (still prompts for filename)\"\n )\n .action(\n async (\n options: { list?: boolean; name?: string },\n cmd: Command\n ) => {\n const _ctx = getCommandContext(cmd);\n\n try {\n // --list mode: just print examples and exit\n if (options.list) {\n printExamplesList();\n return;\n }\n\n // Validate --name if provided\n if (options.name) {\n const example = getExampleById(options.name);\n if (!example) {\n logError(`Unknown example: ${options.name}`);\n console.log(\"\\nAvailable examples:\");\n for (const ex of EXAMPLE_DEFINITIONS) {\n console.log(` ${ex.id}`);\n }\n process.exit(1);\n }\n }\n\n // Run interactive flow\n await runInteractiveFlow(options.name);\n } catch (error) {\n const message =\n error instanceof Error ? error.message : String(error);\n logError(message);\n process.exit(1);\n }\n }\n );\n}\n","/**\n * Export command - Export form as markform or plain markdown or structured data.\n *\n * Default output is markform format (canonical markdown with markdoc directives).\n * With --format=markdown, outputs plain readable markdown without markdoc.\n * With --format=json or --format=yaml, outputs structured data with:\n * - schema: Form structure and field definitions\n * - values: Current field values\n * - markdown: Canonical markdown string\n */\n\nimport type { Command } from \"commander\";\n\nimport YAML from \"yaml\";\n\nimport { parseForm } from \"../../engine/parse.js\";\nimport { serialize, serializeRawMarkdown } from \"../../engine/serialize.js\";\nimport type { FieldValue, Id } from \"../../engine/coreTypes.js\";\nimport { getCommandContext, logError, logVerbose, readFile } from \"../lib/shared.js\";\n\ninterface ExportField {\n id: string;\n kind: string;\n label: string;\n required: boolean;\n options?: { id: string; label: string }[];\n}\n\ninterface ExportGroup {\n id: string;\n title?: string;\n children: ExportField[];\n}\n\ninterface ExportSchema {\n id: string;\n title?: string;\n groups: ExportGroup[];\n}\n\ninterface ExportOutput {\n schema: ExportSchema;\n values: Record<Id, FieldValue>;\n markdown: string;\n}\n\n/** Export format options */\ntype ExportFormat = \"markform\" | \"markdown\" | \"json\" | \"yaml\";\n\n/**\n * Register the export command.\n */\nexport function registerExportCommand(program: Command): void {\n program\n .command(\"export <file>\")\n .description(\n \"Export form as markform (default), markdown (readable), or json/yaml for structured data\"\n )\n .option(\"--compact\", \"Output compact JSON (no formatting, only for JSON format)\")\n .action(\n async (\n file: string,\n options: { compact?: boolean },\n cmd: Command\n ) => {\n const ctx = getCommandContext(cmd);\n\n // Determine format: map global format to export format\n // json/yaml from global --format work for export\n // console/plaintext from global map to markform (export's default)\n let format: ExportFormat = \"markform\";\n if (ctx.format === \"json\") {\n format = \"json\";\n } else if (ctx.format === \"yaml\") {\n format = \"yaml\";\n } else if (ctx.format === \"markdown\") {\n format = \"markdown\";\n } else if (ctx.format === \"markform\") {\n format = \"markform\";\n }\n // \"console\" and \"plaintext\" default to \"markform\" for export\n\n try {\n logVerbose(ctx, `Reading file: ${file}`);\n const content = await readFile(file);\n\n logVerbose(ctx, \"Parsing form...\");\n const form = parseForm(content);\n\n // For markform format, output canonical markdoc markdown\n if (format === \"markform\") {\n console.log(serialize(form));\n return;\n }\n\n // For markdown format, output plain readable markdown\n if (format === \"markdown\") {\n console.log(serializeRawMarkdown(form));\n return;\n }\n\n // For JSON/YAML, build the full structured output\n const schema: ExportSchema = {\n id: form.schema.id,\n title: form.schema.title,\n groups: form.schema.groups.map((group) => ({\n id: group.id,\n title: group.title,\n children: group.children.map((field) => ({\n id: field.id,\n kind: field.kind,\n label: field.label,\n required: field.required,\n ...(field.kind === \"single_select\" ||\n field.kind === \"multi_select\" ||\n field.kind === \"checkboxes\"\n ? {\n options: field.options.map((opt) => ({\n id: opt.id,\n label: opt.label,\n })),\n }\n : {}),\n })),\n })),\n };\n\n const output: ExportOutput = {\n schema,\n values: form.valuesByFieldId,\n markdown: serialize(form),\n };\n\n // Output in JSON or YAML format\n if (format === \"json\") {\n if (options.compact) {\n console.log(JSON.stringify(output));\n } else {\n console.log(JSON.stringify(output, null, 2));\n }\n } else {\n // YAML format\n console.log(YAML.stringify(output));\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logError(message);\n process.exit(1);\n }\n }\n );\n}\n","/**\n * Fill command - Run an agent to autonomously fill a form.\n *\n * Supports both mock mode (for testing) and live mode (with LLM agent).\n * Records session transcripts for debugging and golden tests.\n */\n\nimport type { Command } from \"commander\";\n\nimport { resolve } from \"node:path\";\n\nimport pc from \"picocolors\";\n\nimport { parseForm } from \"../../engine/parse.js\";\nimport { serialize } from \"../../engine/serialize.js\";\nimport { serializeSession } from \"../../engine/session.js\";\nimport type {\n FillMode,\n HarnessConfig,\n Patch,\n SessionFinal,\n SessionTranscript,\n} from \"../../engine/coreTypes.js\";\nimport { createHarness } from \"../../harness/harness.js\";\nimport { createLiveAgent } from \"../../harness/liveAgent.js\";\nimport { createMockAgent } from \"../../harness/mockAgent.js\";\nimport {\n DEFAULT_MAX_ISSUES,\n DEFAULT_MAX_PATCHES_PER_TURN,\n DEFAULT_MAX_TURNS,\n AGENT_ROLE,\n USER_ROLE,\n parseRolesFlag,\n} from \"../../settings.js\";\nimport type { Agent } from \"../../harness/mockAgent.js\";\nimport { resolveModel } from \"../../harness/modelResolver.js\";\nimport { formatSuggestedLlms } from \"../../settings.js\";\nimport {\n formatOutput,\n getCommandContext,\n logError,\n logInfo,\n logSuccess,\n logTiming,\n logVerbose,\n logWarn,\n readFile,\n writeFile,\n} from \"../lib/shared.js\";\nimport { generateVersionedPath } from \"../lib/versioning.js\";\nimport {\n runInteractiveFill,\n showInteractiveIntro,\n showInteractiveOutro,\n} from \"../lib/interactivePrompts.js\";\nimport { inspect } from \"../../engine/inspect.js\";\nimport { applyPatches } from \"../../engine/apply.js\";\n\n/** Supported agent types */\nconst AGENT_TYPES = [\"mock\", \"live\"] as const;\ntype AgentType = (typeof AGENT_TYPES)[number];\n\n/**\n * Format a patch value for display.\n */\nfunction formatPatchValue(patch: Patch): string {\n switch (patch.op) {\n case \"set_string\":\n return patch.value ? `\"${patch.value}\"` : \"(empty)\";\n case \"set_number\":\n return patch.value !== null ? String(patch.value) : \"(empty)\";\n case \"set_string_list\":\n return patch.items.length > 0 ? `[${patch.items.join(\", \")}]` : \"(empty)\";\n case \"set_single_select\":\n return patch.selected ?? \"(none)\";\n case \"set_multi_select\":\n return patch.selected.length > 0 ? `[${patch.selected.join(\", \")}]` : \"(none)\";\n case \"set_checkboxes\":\n return Object.entries(patch.values)\n .map(([k, v]) => `${k}:${v}`)\n .join(\", \");\n case \"clear_field\":\n return \"(cleared)\";\n }\n}\n\n/**\n * Format session transcript for console output.\n */\nfunction formatConsoleSession(\n transcript: SessionTranscript,\n useColors: boolean\n): string {\n const lines: string[] = [];\n const bold = useColors ? pc.bold : (s: string) => s;\n const dim = useColors ? pc.dim : (s: string) => s;\n const cyan = useColors ? pc.cyan : (s: string) => s;\n const green = useColors ? pc.green : (s: string) => s;\n const yellow = useColors ? pc.yellow : (s: string) => s;\n\n // Header\n lines.push(bold(cyan(\"Session Transcript\")));\n lines.push(\"\");\n\n // Session info\n lines.push(`${bold(\"Form:\")} ${transcript.form.path}`);\n lines.push(`${bold(\"Mode:\")} ${transcript.mode}`);\n lines.push(`${bold(\"Version:\")} ${transcript.sessionVersion}`);\n lines.push(\"\");\n\n // Harness config\n lines.push(bold(\"Harness Config:\"));\n lines.push(` Max turns: ${transcript.harness.maxTurns}`);\n lines.push(` Max patches/turn: ${transcript.harness.maxPatchesPerTurn}`);\n lines.push(` Max issues: ${transcript.harness.maxIssues}`);\n lines.push(\"\");\n\n // Turns summary\n lines.push(bold(`Turns (${transcript.turns.length}):`));\n for (const turn of transcript.turns) {\n const issueCount = turn.inspect.issues.length;\n const patchCount = turn.apply.patches.length;\n const afterIssues = turn.after.requiredIssueCount;\n\n lines.push(\n ` Turn ${turn.turn}: ${dim(`${issueCount} issues`)} → ${yellow(`${patchCount} patches`)} → ${afterIssues === 0 ? green(\"0 remaining\") : dim(`${afterIssues} remaining`)}`\n );\n }\n lines.push(\"\");\n\n // Final result\n const expectText = transcript.final.expectComplete\n ? green(\"✓ complete\")\n : yellow(\"○ incomplete\");\n lines.push(`${bold(\"Expected:\")} ${expectText}`);\n lines.push(`${bold(\"Completed form:\")} ${transcript.final.expectedCompletedForm}`);\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Register the fill command.\n */\nexport function registerFillCommand(program: Command): void {\n program\n .command(\"fill <file>\")\n .description(\"Run an agent to autonomously fill a form\")\n .option(\n \"--agent <type>\",\n `Agent type: ${AGENT_TYPES.join(\", \")} (default: live)`,\n \"live\"\n )\n .option(\n \"--model <id>\",\n \"Model ID for live agent (format: provider/model-id, e.g. openai/gpt-4o)\"\n )\n .option(\"--mock-source <file>\", \"Path to completed form for mock agent\")\n .option(\"--record <file>\", \"Record session transcript to file\")\n .option(\n \"--max-turns <n>\",\n `Maximum turns (default: ${DEFAULT_MAX_TURNS})`,\n String(DEFAULT_MAX_TURNS)\n )\n .option(\n \"--max-patches <n>\",\n `Maximum patches per turn (default: ${DEFAULT_MAX_PATCHES_PER_TURN})`,\n String(DEFAULT_MAX_PATCHES_PER_TURN)\n )\n .option(\n \"--max-issues <n>\",\n `Maximum issues shown per turn (default: ${DEFAULT_MAX_ISSUES})`,\n String(DEFAULT_MAX_ISSUES)\n )\n .option(\n \"--max-fields <n>\",\n \"Maximum unique fields per turn (applied before --max-issues)\"\n )\n .option(\n \"--max-groups <n>\",\n \"Maximum unique groups per turn (applied before --max-issues)\"\n )\n .option(\n \"--roles <roles>\",\n \"Target roles to fill (comma-separated, or '*' for all; default: 'agent' in agent mode, 'user' in --interactive mode)\"\n )\n .option(\n \"--mode <mode>\",\n \"Fill mode: continue (skip filled fields) or overwrite (re-fill; default: continue)\"\n )\n .option(\"-o, --output <file>\", \"Write final form to file\")\n .option(\n \"--prompt <file>\",\n \"Path to custom system prompt file (appends to default)\"\n )\n .option(\n \"--instructions <text>\",\n \"Inline system prompt (appends to default; takes precedence over --prompt)\"\n )\n .option(\n \"-i, --interactive\",\n \"Interactive mode: prompt user for field values (defaults to user role)\"\n )\n .action(\n async (\n file: string,\n options: {\n agent?: string;\n model?: string;\n mockSource?: string;\n record?: string;\n maxTurns?: string;\n maxPatches?: string;\n maxIssues?: string;\n maxFields?: string;\n maxGroups?: string;\n roles?: string;\n mode?: string;\n output?: string;\n prompt?: string;\n instructions?: string;\n interactive?: boolean;\n },\n cmd: Command\n ) => {\n const ctx = getCommandContext(cmd);\n const filePath = resolve(file);\n\n try {\n const startTime = Date.now();\n\n // Parse and validate --roles (default depends on mode)\n let targetRoles: string[];\n if (options.roles) {\n try {\n targetRoles = parseRolesFlag(options.roles);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logError(`Invalid --roles: ${message}`);\n process.exit(1);\n }\n } else {\n // Default: user role for interactive, agent role for agent mode\n targetRoles = options.interactive ? [USER_ROLE] : [AGENT_ROLE];\n }\n\n // Parse and validate --mode\n let fillMode: FillMode = \"continue\"; // Default\n if (options.mode) {\n if (options.mode !== \"continue\" && options.mode !== \"overwrite\") {\n logError(`Invalid --mode: ${options.mode}. Valid modes: continue, overwrite`);\n process.exit(1);\n }\n fillMode = options.mode;\n }\n\n logVerbose(ctx, `Reading form: ${filePath}`);\n const formContent = await readFile(filePath);\n\n logVerbose(ctx, \"Parsing form...\");\n const form = parseForm(formContent);\n\n // =====================================================================\n // INTERACTIVE MODE\n // =====================================================================\n if (options.interactive) {\n // Validate: --interactive conflicts with agent options\n if (options.agent && options.agent !== \"live\") {\n logError(\"--interactive cannot be used with --agent\");\n process.exit(1);\n }\n if (options.model) {\n logError(\"--interactive cannot be used with --model\");\n process.exit(1);\n }\n if (options.mockSource) {\n logError(\"--interactive cannot be used with --mock-source\");\n process.exit(1);\n }\n\n // Inspect form to get issues for target roles\n const inspectResult = inspect(form, { targetRoles });\n\n // Show intro\n const formTitle = form.schema.title ?? form.schema.id;\n const fieldIssues = inspectResult.issues.filter((i) => i.scope === \"field\");\n const uniqueFieldIds = new Set(fieldIssues.map((i) => i.ref));\n showInteractiveIntro(\n formTitle,\n targetRoles.join(\", \"),\n uniqueFieldIds.size\n );\n\n // Run interactive prompts\n const { patches, cancelled } = await runInteractiveFill(form, inspectResult.issues);\n\n if (cancelled) {\n showInteractiveOutro(0, \"\", true);\n process.exit(1);\n }\n\n // Apply patches to form (mutates form in place)\n if (patches.length > 0) {\n applyPatches(form, patches);\n }\n\n const durationMs = Date.now() - startTime;\n\n // Write output file\n const outputPath = options.output\n ? resolve(options.output)\n : generateVersionedPath(filePath);\n const formMarkdown = serialize(form);\n\n if (ctx.dryRun) {\n logInfo(ctx, `[DRY RUN] Would write form to: ${outputPath}`);\n } else {\n await writeFile(outputPath, formMarkdown);\n }\n\n showInteractiveOutro(patches.length, outputPath, false);\n logTiming(ctx, \"Fill time\", durationMs);\n\n // Show next step hint\n if (patches.length > 0) {\n console.log(\"\");\n console.log(pc.dim(\"Next step: fill remaining fields with agent\"));\n console.log(pc.dim(` markform fill ${outputPath} --agent=live --model=<provider/model>`));\n }\n\n process.exit(0);\n }\n\n // =====================================================================\n // AGENT MODE (mock or live)\n // =====================================================================\n\n // Validate agent type\n const agentType = (options.agent ?? \"live\") as AgentType;\n if (!AGENT_TYPES.includes(agentType)) {\n logError(\n `Invalid agent type '${options.agent}'. Valid types: ${AGENT_TYPES.join(\", \")}`\n );\n process.exit(1);\n }\n\n // Validate options based on agent type\n if (agentType === \"mock\" && !options.mockSource) {\n logError(\"--agent=mock requires --mock-source <file>\");\n process.exit(1);\n }\n\n if (agentType === \"live\" && !options.model) {\n logError(\"--agent=live requires --model <provider/model-id>\");\n console.log(\"\");\n console.log(formatSuggestedLlms());\n process.exit(1);\n }\n\n // Warn about --roles=* in non-interactive mode\n if (targetRoles.includes(\"*\")) {\n logWarn(ctx, \"Warning: Filling all roles including user-designated fields\");\n }\n\n // Parse harness config\n const harnessConfig: Partial<HarnessConfig> = {\n maxTurns: parseInt(\n options.maxTurns ?? String(DEFAULT_MAX_TURNS),\n 10\n ),\n maxPatchesPerTurn: parseInt(\n options.maxPatches ?? String(DEFAULT_MAX_PATCHES_PER_TURN),\n 10\n ),\n maxIssues: parseInt(\n options.maxIssues ?? String(DEFAULT_MAX_ISSUES),\n 10\n ),\n ...(options.maxFields && {\n maxFieldsPerTurn: parseInt(options.maxFields, 10),\n }),\n ...(options.maxGroups && {\n maxGroupsPerTurn: parseInt(options.maxGroups, 10),\n }),\n targetRoles,\n fillMode,\n };\n\n // Create harness\n const harness = createHarness(form, harnessConfig);\n\n // Create agent based on type\n let agent: Agent;\n let mockPath: string | undefined;\n\n if (agentType === \"mock\") {\n // Mock agent requires a completed form as source\n mockPath = resolve(options.mockSource!);\n logVerbose(ctx, `Reading mock source: ${mockPath}`);\n const mockContent = await readFile(mockPath);\n const mockForm = parseForm(mockContent);\n agent = createMockAgent(mockForm);\n } else {\n // Live agent uses LLM (model is required, validated above)\n const modelId = options.model!;\n logVerbose(ctx, `Resolving model: ${modelId}`);\n const { model } = await resolveModel(modelId);\n\n // Determine system prompt: --instructions > --prompt > default\n let systemPrompt: string | undefined;\n if (options.instructions) {\n systemPrompt = options.instructions;\n logVerbose(ctx, \"Using inline system prompt from --instructions\");\n } else if (options.prompt) {\n const promptPath = resolve(options.prompt);\n logVerbose(ctx, `Reading system prompt from: ${promptPath}`);\n systemPrompt = await readFile(promptPath);\n }\n\n // Pass first target role to agent (for instruction lookup)\n const primaryRole = targetRoles[0] === \"*\" ? AGENT_ROLE : targetRoles[0];\n agent = createLiveAgent({\n model,\n systemPromptAddition: systemPrompt,\n targetRole: primaryRole,\n });\n logVerbose(ctx, `Using live agent with model: ${modelId}`);\n }\n\n logInfo(ctx, pc.cyan(`Filling form: ${filePath}`));\n logInfo(ctx, `Agent: ${agentType}${options.model ? ` (${options.model})` : \"\"}`);\n logVerbose(ctx, `Max turns: ${harnessConfig.maxTurns}`);\n logVerbose(ctx, `Max patches per turn: ${harnessConfig.maxPatchesPerTurn}`);\n logVerbose(ctx, `Max issues per step: ${harnessConfig.maxIssues}`);\n logVerbose(ctx, `Target roles: ${targetRoles.includes(\"*\") ? \"*\" : targetRoles.join(\", \")}`);\n logVerbose(ctx, `Fill mode: ${fillMode}`);\n\n // Run harness loop\n let stepResult = harness.step();\n logInfo(\n ctx,\n `Turn ${pc.bold(String(stepResult.turnNumber))}: ${pc.yellow(String(stepResult.issues.length))} issues`\n );\n\n while (!stepResult.isComplete && !harness.hasReachedMaxTurns()) {\n // Generate patches from agent\n const patches = await agent.generatePatches(\n stepResult.issues,\n harness.getForm(),\n harnessConfig.maxPatchesPerTurn!\n );\n\n // Log patches - brief by default, detailed in verbose mode\n logInfo(ctx, ` → ${pc.yellow(String(patches.length))} patches`);\n for (const patch of patches) {\n const value = formatPatchValue(patch);\n logVerbose(ctx, ` ${pc.cyan(patch.fieldId)} ${pc.dim(\"=\")} ${pc.green(value)}`);\n }\n\n // Apply patches\n stepResult = harness.apply(patches, stepResult.issues);\n\n if (stepResult.isComplete) {\n logInfo(ctx, pc.green(` ✓ Complete`));\n } else {\n // Step for next turn\n stepResult = harness.step();\n logInfo(\n ctx,\n `Turn ${pc.bold(String(stepResult.turnNumber))}: ${pc.yellow(String(stepResult.issues.length))} issues`\n );\n }\n }\n\n const durationMs = Date.now() - startTime;\n\n // Check if completed\n if (stepResult.isComplete) {\n logSuccess(\n ctx,\n `Form completed in ${harness.getTurnNumber()} turn(s)`\n );\n } else if (harness.hasReachedMaxTurns()) {\n logWarn(ctx, `Max turns reached (${harnessConfig.maxTurns})`);\n }\n\n logTiming(ctx, \"Fill time\", durationMs);\n\n // Write output file\n const outputPath = options.output\n ? resolve(options.output)\n : generateVersionedPath(filePath);\n const formMarkdown = serialize(harness.getForm());\n\n if (ctx.dryRun) {\n logInfo(ctx, `[DRY RUN] Would write form to: ${outputPath}`);\n } else {\n await writeFile(outputPath, formMarkdown);\n logSuccess(ctx, `Form written to: ${outputPath}`);\n }\n\n // Build session transcript\n const transcript = buildSessionTranscript(\n filePath,\n agentType,\n mockPath,\n options.model,\n harnessConfig as HarnessConfig,\n harness.getTurns(),\n stepResult.isComplete,\n outputPath\n );\n\n // Output or record session\n if (options.record) {\n const recordPath = resolve(options.record);\n // Always use YAML for recorded files (standard format)\n const yaml = serializeSession(transcript);\n\n if (ctx.dryRun) {\n logInfo(ctx, `[DRY RUN] Would write session to: ${recordPath}`);\n console.log(yaml);\n } else {\n await writeFile(recordPath, yaml);\n logSuccess(ctx, `Session recorded to: ${recordPath}`);\n }\n } else {\n // Output to stdout in requested format\n const output = formatOutput(ctx, transcript, (data, useColors) =>\n formatConsoleSession(data as SessionTranscript, useColors)\n );\n console.log(output);\n }\n\n process.exit(stepResult.isComplete ? 0 : 1);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logError(message);\n process.exit(1);\n }\n }\n );\n}\n\n/**\n * Build a session transcript from harness execution.\n */\nfunction buildSessionTranscript(\n formPath: string,\n agentType: AgentType,\n mockPath: string | undefined,\n modelId: string | undefined,\n harnessConfig: HarnessConfig,\n turns: SessionTranscript[\"turns\"],\n expectComplete: boolean,\n outputPath: string\n): SessionTranscript {\n const final: SessionFinal = {\n expectComplete,\n // For mock mode, use the mock source as expected; otherwise use actual output\n expectedCompletedForm: agentType === \"mock\" ? (mockPath ?? outputPath) : outputPath,\n };\n\n const transcript: SessionTranscript = {\n sessionVersion: \"0.1.0\",\n mode: agentType,\n form: {\n path: formPath,\n },\n harness: harnessConfig,\n turns,\n final,\n };\n\n // Add mode-specific fields\n if (agentType === \"mock\" && mockPath) {\n transcript.mock = {\n completedMock: mockPath,\n };\n } else if (agentType === \"live\" && modelId) {\n transcript.live = {\n modelId,\n };\n }\n\n return transcript;\n}\n","/**\n * Inspect command - Display form structure, progress, and issues.\n *\n * Outputs a comprehensive report with:\n * - Form state and title\n * - Structure summary (field counts, types)\n * - Progress summary (filled/empty counts)\n * - Full form content (groups, fields, current values)\n * - Issues sorted by priority\n */\n\nimport type { Command } from \"commander\";\n\nimport pc from \"picocolors\";\n\nimport { inspect } from \"../../engine/inspect.js\";\nimport { parseForm } from \"../../engine/parse.js\";\nimport type {\n FieldValue,\n InspectIssue,\n ProgressState,\n} from \"../../engine/coreTypes.js\";\nimport { parseRolesFlag } from \"../../settings.js\";\nimport {\n formatOutput,\n getCommandContext,\n logError,\n logVerbose,\n readFile,\n} from \"../lib/shared.js\";\n\n/**\n * Format state badge for console output.\n */\nfunction formatState(state: ProgressState, useColors: boolean): string {\n const badges: Record<ProgressState, [string, (s: string) => string]> = {\n complete: [\"✓ complete\", pc.green],\n incomplete: [\"○ incomplete\", pc.yellow],\n empty: [\"◌ empty\", pc.dim],\n invalid: [\"✗ invalid\", pc.red],\n };\n const [text, colorFn] = badges[state] ?? [state, (s: string) => s];\n return useColors ? colorFn(text) : text;\n}\n\n/**\n * Format priority badge for console output.\n *\n * Priority tiers and colors:\n * - P1: bold red (critical)\n * - P2: yellow (high)\n * - P3: cyan (medium)\n * - P4: blue (low)\n * - P5: dim/gray (minimal)\n */\nfunction formatPriority(priority: number, useColors: boolean): string {\n const label = `P${priority}`;\n if (!useColors) {\n return label;\n }\n switch (priority) {\n case 1:\n return pc.red(pc.bold(label));\n case 2:\n return pc.yellow(label);\n case 3:\n return pc.cyan(label);\n case 4:\n return pc.blue(label);\n case 5:\n default:\n return pc.dim(label);\n }\n}\n\n/**\n * Format severity badge for console output.\n */\nfunction formatSeverity(\n severity: \"required\" | \"recommended\",\n useColors: boolean\n): string {\n if (!useColors) {\n return severity;\n }\n return severity === \"required\" ? pc.red(severity) : pc.yellow(severity);\n}\n\n/**\n * Format a field value for console display.\n */\nfunction formatFieldValue(\n value: FieldValue | undefined,\n useColors: boolean\n): string {\n const dim = useColors ? pc.dim : (s: string) => s;\n const green = useColors ? pc.green : (s: string) => s;\n\n if (!value) {\n return dim(\"(empty)\");\n }\n\n switch (value.kind) {\n case \"string\":\n return value.value ? green(`\"${value.value}\"`) : dim(\"(empty)\");\n case \"number\":\n return value.value !== null ? green(String(value.value)) : dim(\"(empty)\");\n case \"string_list\":\n return value.items.length > 0\n ? green(`[${value.items.map((i) => `\"${i}\"`).join(\", \")}]`)\n : dim(\"(empty)\");\n case \"single_select\":\n return value.selected ? green(value.selected) : dim(\"(none selected)\");\n case \"multi_select\":\n return value.selected.length > 0\n ? green(`[${value.selected.join(\", \")}]`)\n : dim(\"(none selected)\");\n case \"checkboxes\": {\n const entries = Object.entries(value.values);\n if (entries.length === 0) {\n return dim(\"(no entries)\");\n }\n return entries.map(([k, v]) => `${k}:${v}`).join(\", \");\n }\n default:\n return dim(\"(unknown)\");\n }\n}\n\n/** Field info for console report */\ninterface ReportField {\n id: string;\n kind: string;\n label: string;\n required: boolean;\n role: string;\n}\n\n/** Group info for console report */\ninterface ReportGroup {\n id: string;\n title?: string;\n children: ReportField[];\n}\n\n/** Report structure for console/JSON output */\ninterface InspectReport {\n title?: string;\n structure: unknown;\n progress: unknown;\n form_state: ProgressState;\n groups: ReportGroup[];\n values: Record<string, FieldValue>;\n issues: {\n ref: string;\n scope: string;\n reason: string;\n message: string;\n priority: number;\n severity: \"required\" | \"recommended\";\n blockedBy?: string;\n }[];\n}\n\n/**\n * Format inspect report for console output.\n */\nfunction formatConsoleReport(report: InspectReport, useColors: boolean): string {\n const lines: string[] = [];\n const bold = useColors ? pc.bold : (s: string) => s;\n const dim = useColors ? pc.dim : (s: string) => s;\n const cyan = useColors ? pc.cyan : (s: string) => s;\n const yellow = useColors ? pc.yellow : (s: string) => s;\n\n // Header\n lines.push(bold(cyan(\"Form Inspection Report\")));\n if (report.title) {\n lines.push(`${bold(\"Title:\")} ${report.title}`);\n }\n lines.push(\"\");\n\n // Form state\n lines.push(`${bold(\"Form State:\")} ${formatState(report.form_state, useColors)}`);\n lines.push(\"\");\n\n // Structure summary\n const structure = report.structure as {\n groupCount: number;\n fieldCount: number;\n optionCount: number;\n };\n lines.push(bold(\"Structure:\"));\n lines.push(` Groups: ${structure.groupCount}`);\n lines.push(` Fields: ${structure.fieldCount}`);\n lines.push(` Options: ${structure.optionCount}`);\n lines.push(\"\");\n\n // Progress summary\n const progress = report.progress as {\n counts: {\n totalFields: number;\n requiredFields: number;\n submittedFields: number;\n completeFields: number;\n incompleteFields: number;\n invalidFields: number;\n emptyRequiredFields: number;\n emptyOptionalFields: number;\n };\n };\n lines.push(bold(\"Progress:\"));\n lines.push(` Total fields: ${progress.counts.totalFields}`);\n lines.push(` Required: ${progress.counts.requiredFields}`);\n lines.push(` Submitted: ${progress.counts.submittedFields}`);\n lines.push(` Complete: ${progress.counts.completeFields}`);\n lines.push(` Incomplete: ${progress.counts.incompleteFields}`);\n lines.push(` Invalid: ${progress.counts.invalidFields}`);\n lines.push(` Empty (required): ${progress.counts.emptyRequiredFields}`);\n lines.push(` Empty (optional): ${progress.counts.emptyOptionalFields}`);\n lines.push(\"\");\n\n // Form content (groups and fields with values)\n lines.push(bold(\"Form Content:\"));\n for (const group of report.groups) {\n lines.push(` ${bold(group.title ?? group.id)}`);\n for (const field of group.children) {\n const reqBadge = field.required ? yellow(\"[required]\") : dim(\"[optional]\");\n const roleBadge = field.role !== \"agent\" ? cyan(`[${field.role}]`) : \"\";\n const value = report.values[field.id];\n const valueStr = formatFieldValue(value, useColors);\n lines.push(` ${field.label} ${dim(`(${field.kind})`)} ${reqBadge} ${roleBadge}`.trim());\n lines.push(` ${dim(\"→\")} ${valueStr}`);\n }\n }\n lines.push(\"\");\n\n // Issues\n if (report.issues.length > 0) {\n lines.push(bold(`Issues (${report.issues.length}):`));\n for (const issue of report.issues) {\n const priority = formatPriority(issue.priority, useColors);\n const severity = formatSeverity(issue.severity, useColors);\n const blockedInfo = issue.blockedBy\n ? ` ${dim(`(blocked by: ${issue.blockedBy})`)}`\n : \"\";\n lines.push(\n ` ${priority} (${severity}) ${dim(`[${issue.scope}]`)} ${dim(issue.ref)}: ${issue.message}${blockedInfo}`\n );\n }\n } else {\n lines.push(dim(\"No issues found.\"));\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Register the inspect command.\n */\nexport function registerInspectCommand(program: Command): void {\n program\n .command(\"inspect <file>\")\n .description(\"Inspect a form and display its structure, progress, and issues\")\n .option(\n \"--roles <roles>\",\n \"Filter issues by target roles (comma-separated, or '*' for all; default: all)\"\n )\n .action(\n async (\n file: string,\n options: { roles?: string },\n cmd: Command\n ) => {\n const ctx = getCommandContext(cmd);\n\n try {\n // Parse and validate --roles\n let targetRoles: string[] | undefined;\n if (options.roles) {\n try {\n targetRoles = parseRolesFlag(options.roles);\n // '*' means all roles - pass undefined to not filter\n if (targetRoles.includes(\"*\")) {\n targetRoles = undefined;\n }\n } catch (error) {\n const message =\n error instanceof Error ? error.message : String(error);\n logError(`Invalid --roles: ${message}`);\n process.exit(1);\n }\n }\n\n logVerbose(ctx, `Reading file: ${file}`);\n const content = await readFile(file);\n\n logVerbose(ctx, \"Parsing form...\");\n const form = parseForm(content);\n\n logVerbose(ctx, \"Running inspection...\");\n const result = inspect(form, { targetRoles });\n\n // Build the report structure\n const report: InspectReport = {\n title: form.schema.title,\n structure: result.structureSummary,\n progress: result.progressSummary,\n form_state: result.formState,\n groups: form.schema.groups.map((group) => ({\n id: group.id,\n title: group.title,\n children: group.children.map((field) => ({\n id: field.id,\n kind: field.kind,\n label: field.label,\n required: field.required,\n role: field.role,\n })),\n })),\n values: form.valuesByFieldId,\n issues: result.issues.map((issue: InspectIssue) => ({\n ref: issue.ref,\n scope: issue.scope,\n reason: issue.reason,\n message: issue.message,\n priority: issue.priority,\n severity: issue.severity,\n blockedBy: issue.blockedBy,\n })),\n };\n\n // Output in requested format\n const output = formatOutput(ctx, report, (data, useColors) =>\n formatConsoleReport(data as typeof report, useColors)\n );\n console.log(output);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logError(message);\n process.exit(1);\n }\n }\n );\n}\n","/**\n * Models command - List available AI models and providers.\n *\n * Displays supported providers, their environment variables,\n * and example models for use with the fill command.\n */\n\nimport type { Command } from \"commander\";\n\nimport pc from \"picocolors\";\n\nimport {\n getProviderInfo,\n getProviderNames,\n type ProviderName,\n} from \"../../harness/modelResolver.js\";\nimport { SUGGESTED_LLMS } from \"../../settings.js\";\nimport { formatOutput, getCommandContext, logError } from \"../lib/shared.js\";\n\n/**\n * Model info for a single provider.\n */\ninterface ProviderModelInfo {\n provider: ProviderName;\n envVar: string;\n models: string[];\n}\n\n/**\n * Get model info for all providers or a specific one.\n */\nfunction getModelInfo(providerFilter?: string): ProviderModelInfo[] {\n const providers = getProviderNames();\n\n // Validate filter if provided\n if (providerFilter && !providers.includes(providerFilter as ProviderName)) {\n throw new Error(\n `Unknown provider: \"${providerFilter}\". Available: ${providers.join(\", \")}`\n );\n }\n\n const filtered = providerFilter\n ? [providerFilter as ProviderName]\n : providers;\n\n return filtered.map((provider) => {\n const info = getProviderInfo(provider);\n return {\n provider,\n envVar: info.envVar,\n models: SUGGESTED_LLMS[provider] ?? [],\n };\n });\n}\n\n/**\n * Format model info for console output.\n */\nfunction formatConsoleOutput(\n info: ProviderModelInfo[],\n useColors: boolean\n): string {\n const lines: string[] = [];\n const bold = useColors ? pc.bold : (s: string) => s;\n const cyan = useColors ? pc.cyan : (s: string) => s;\n const dim = useColors ? pc.dim : (s: string) => s;\n const green = useColors ? pc.green : (s: string) => s;\n\n for (const { provider, envVar, models } of info) {\n lines.push(bold(cyan(`${provider}/`)));\n lines.push(` ${dim(\"env:\")} ${envVar}`);\n\n if (models.length > 0) {\n lines.push(` ${dim(\"models:\")}`);\n for (const model of models) {\n lines.push(` ${green(`${provider}/${model}`)}`);\n }\n } else {\n lines.push(` ${dim(\"(no suggested models)\")}`);\n }\n lines.push(\"\");\n }\n\n // Remove trailing empty line\n if (lines.length > 0 && lines[lines.length - 1] === \"\") {\n lines.pop();\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Register the models command.\n */\nexport function registerModelsCommand(program: Command): void {\n program\n .command(\"models\")\n .description(\"List available AI providers and example models\")\n .option(\n \"-p, --provider <name>\",\n \"Filter by provider (anthropic, openai, google, xai, deepseek)\"\n )\n .action((options: { provider?: string }, cmd: Command) => {\n const ctx = getCommandContext(cmd);\n\n try {\n const info = getModelInfo(options.provider);\n\n const output = formatOutput(ctx, info, (data, useColors) =>\n formatConsoleOutput(data as ProviderModelInfo[], useColors)\n );\n console.log(output);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logError(message);\n process.exit(1);\n }\n });\n}\n","/**\n * Serve command - Serve a form as a web page for browsing.\n *\n * Starts an HTTP server that renders the form as interactive HTML.\n */\n\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { Command } from \"commander\";\n\nimport { exec } from \"node:child_process\";\nimport { createServer } from \"node:http\";\nimport { resolve } from \"node:path\";\n\nimport pc from \"picocolors\";\n\nimport { applyPatches } from \"../../engine/apply.js\";\nimport { parseForm } from \"../../engine/parse.js\";\nimport { serialize } from \"../../engine/serialize.js\";\nimport { DEFAULT_PORT } from \"../../settings.js\";\nimport type {\n CheckboxesField,\n CheckboxesValue,\n Field,\n FieldGroup,\n FieldValue,\n MultiSelectField,\n MultiSelectValue,\n NumberField,\n Patch,\n ParsedForm,\n SingleSelectField,\n SingleSelectValue,\n StringField,\n StringListField,\n} from \"../../engine/coreTypes.js\";\nimport {\n type CommandContext,\n getCommandContext,\n logError,\n logInfo,\n logVerbose,\n readFile,\n writeFile,\n} from \"../lib/shared.js\";\nimport { generateVersionedPath } from \"../lib/versioning.js\";\n\n/**\n * Open a URL in the default browser (cross-platform).\n */\nfunction openBrowser(url: string): void {\n const platform = process.platform;\n\n let command: string;\n if (platform === \"darwin\") {\n command = `open \"${url}\"`;\n } else if (platform === \"win32\") {\n command = `start \"\" \"${url}\"`;\n } else {\n // Linux and other Unix-like systems\n command = `xdg-open \"${url}\"`;\n }\n\n exec(command, (error) => {\n if (error) {\n // Silently ignore - user can still open URL manually\n }\n });\n}\n\n/**\n * Register the serve command.\n */\nexport function registerServeCommand(program: Command): void {\n program\n .command(\"serve <file>\")\n .description(\"Serve a form as a web page for browsing\")\n .option(\"-p, --port <port>\", \"Port to serve on\", String(DEFAULT_PORT))\n .option(\"--no-open\", \"Don't open browser automatically\")\n .action(\n async (\n file: string,\n options: { port?: string; open?: boolean },\n cmd: Command\n ) => {\n const ctx = getCommandContext(cmd);\n const port = parseInt(options.port ?? String(DEFAULT_PORT), 10);\n const filePath = resolve(file);\n\n try {\n logVerbose(ctx, `Reading file: ${filePath}`);\n const content = await readFile(filePath);\n let form = parseForm(content);\n\n // Start the server\n const server = createServer(\n (req: IncomingMessage, res: ServerResponse) => {\n handleRequest(req, res, form, filePath, ctx, (updatedForm) => {\n form = updatedForm;\n }).catch((err) => {\n console.error(\"Request error:\", err);\n res.writeHead(500);\n res.end(\"Internal Server Error\");\n });\n }\n );\n\n server.listen(port, () => {\n const url = `http://localhost:${port}`;\n logInfo(ctx, pc.green(`\\n✓ Form server running at ${pc.bold(url)}\\n`));\n logInfo(ctx, pc.dim(\"Press Ctrl+C to stop\\n\"));\n\n // Open browser by default unless --no-open is specified\n if (options.open !== false) {\n openBrowser(url);\n }\n });\n\n // Handle graceful shutdown\n process.on(\"SIGINT\", () => {\n logInfo(ctx, \"\\nShutting down server...\");\n server.close();\n process.exit(0);\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logError(message);\n process.exit(1);\n }\n }\n );\n}\n\n/**\n * Handle HTTP requests.\n */\nasync function handleRequest(\n req: IncomingMessage,\n res: ServerResponse,\n form: ParsedForm,\n filePath: string,\n ctx: CommandContext,\n updateForm: (form: ParsedForm) => void\n): Promise<void> {\n const url = req.url ?? \"/\";\n\n if (req.method === \"GET\" && url === \"/\") {\n // Render the form as HTML\n const html = renderFormHtml(form);\n res.writeHead(200, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(html);\n } else if (req.method === \"POST\" && url === \"/save\") {\n // Save the form to a new versioned file\n await handleSave(req, res, form, filePath, ctx, updateForm);\n } else if (url === \"/api/form\") {\n // API endpoint for form data\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ schema: form.schema }));\n } else {\n res.writeHead(404);\n res.end(\"Not Found\");\n }\n}\n\n/**\n * Parse form body data.\n */\nfunction parseFormBody(body: string): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n const params = new URLSearchParams(body);\n\n for (const [key, value] of params) {\n const existing = result[key];\n if (existing !== undefined) {\n if (Array.isArray(existing)) {\n existing.push(value);\n } else {\n result[key] = [existing, value];\n }\n } else {\n result[key] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Convert form data to patches.\n */\nfunction formDataToPatches(\n formData: Record<string, string | string[]>,\n form: ParsedForm\n): Patch[] {\n const patches: Patch[] = [];\n const fields = form.schema.groups.flatMap((g) => g.children);\n\n for (const field of fields) {\n const fieldId = field.id;\n\n switch (field.kind) {\n case \"string\": {\n const value = formData[fieldId];\n if (typeof value === \"string\" && value.trim() !== \"\") {\n patches.push({ op: \"set_string\", fieldId, value: value.trim() });\n } else if (!value || (typeof value === \"string\" && value.trim() === \"\")) {\n patches.push({ op: \"clear_field\", fieldId });\n }\n break;\n }\n\n case \"number\": {\n const value = formData[fieldId];\n if (typeof value === \"string\" && value.trim() !== \"\") {\n const num = parseFloat(value);\n if (!isNaN(num)) {\n patches.push({ op: \"set_number\", fieldId, value: num });\n }\n } else {\n patches.push({ op: \"clear_field\", fieldId });\n }\n break;\n }\n\n case \"string_list\": {\n const value = formData[fieldId];\n if (typeof value === \"string\" && value.trim() !== \"\") {\n const items = value\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter((s) => s !== \"\");\n if (items.length > 0) {\n patches.push({ op: \"set_string_list\", fieldId, items });\n } else {\n patches.push({ op: \"clear_field\", fieldId });\n }\n } else {\n patches.push({ op: \"clear_field\", fieldId });\n }\n break;\n }\n\n case \"single_select\": {\n const value = formData[fieldId];\n if (typeof value === \"string\" && value !== \"\") {\n patches.push({ op: \"set_single_select\", fieldId, selected: value });\n } else {\n patches.push({ op: \"clear_field\", fieldId });\n }\n break;\n }\n\n case \"multi_select\": {\n const value = formData[fieldId];\n const selected = Array.isArray(value)\n ? value\n : value\n ? [value]\n : [];\n if (selected.length > 0 && selected[0] !== \"\") {\n patches.push({ op: \"set_multi_select\", fieldId, selected });\n } else {\n patches.push({ op: \"clear_field\", fieldId });\n }\n break;\n }\n\n case \"checkboxes\": {\n const mode = field.checkboxMode ?? \"multi\";\n\n if (mode === \"simple\") {\n // Simple mode: checkboxes send their value when checked\n const value = formData[fieldId];\n const checked = Array.isArray(value)\n ? value\n : value\n ? [value]\n : [];\n\n const values: Record<string, \"done\" | \"todo\"> = {};\n for (const opt of field.options) {\n values[opt.id] = checked.includes(opt.id) ? \"done\" : \"todo\";\n }\n patches.push({ op: \"set_checkboxes\", fieldId, values });\n } else {\n // Multi or explicit mode: each option has its own select\n const values: Record<string, string> = {};\n for (const opt of field.options) {\n const selectName = `${fieldId}.${opt.id}`;\n const selectValue = formData[selectName];\n if (typeof selectValue === \"string\" && selectValue !== \"\") {\n values[opt.id] = selectValue;\n }\n }\n if (Object.keys(values).length > 0) {\n patches.push({\n op: \"set_checkboxes\",\n fieldId,\n values: values as Record<\n string,\n | \"todo\"\n | \"done\"\n | \"active\"\n | \"incomplete\"\n | \"na\"\n | \"yes\"\n | \"no\"\n | \"unfilled\"\n >,\n });\n }\n }\n break;\n }\n }\n }\n\n return patches;\n}\n\n/**\n * Handle form save request.\n */\nasync function handleSave(\n req: IncomingMessage,\n res: ServerResponse,\n form: ParsedForm,\n filePath: string,\n ctx: CommandContext,\n updateForm: (form: ParsedForm) => void\n): Promise<void> {\n try {\n // Read request body\n const chunks: Buffer[] = [];\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n const body = Buffer.concat(chunks).toString(\"utf-8\");\n\n // Parse form data\n const formData = parseFormBody(body);\n\n // Convert to patches\n const patches = formDataToPatches(formData, form);\n\n // Apply patches (mutates form in place)\n applyPatches(form, patches);\n\n // Update the in-memory form reference\n updateForm(form);\n\n // Generate versioned filename\n const newPath = generateVersionedPath(filePath);\n\n // Serialize the form\n const content = serialize(form);\n\n if (ctx.dryRun) {\n logInfo(ctx, `[DRY RUN] Would save to: ${newPath}`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ success: true, path: newPath, dryRun: true }));\n return;\n }\n\n // Write the file\n await writeFile(newPath, content);\n logInfo(ctx, pc.green(`Saved to: ${newPath}`));\n\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ success: true, path: newPath }));\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ success: false, error: message }));\n }\n}\n\n/**\n * Render the form as HTML.\n * @public Exported for testing.\n */\nexport function renderFormHtml(form: ParsedForm): string {\n const { schema, valuesByFieldId } = form;\n const formTitle = schema.title ?? schema.id;\n\n const groupsHtml = schema.groups\n .map((group) => renderGroup(group, valuesByFieldId))\n .join(\"\\n\");\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${escapeHtml(formTitle)} - Markform</title>\n <style>\n * { box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n line-height: 1.6;\n max-width: 800px;\n margin: 0 auto;\n padding: 2rem;\n background: #f8f9fa;\n color: #212529;\n }\n h1 { color: #495057; border-bottom: 2px solid #dee2e6; padding-bottom: 0.5rem; }\n h2 { color: #6c757d; margin-top: 2rem; font-size: 1.25rem; }\n .group {\n background: white;\n border-radius: 8px;\n padding: 1.5rem;\n margin-bottom: 1.5rem;\n box-shadow: 0 1px 3px rgba(0,0,0,0.1);\n }\n .field {\n margin-bottom: 1.5rem;\n padding-bottom: 1rem;\n border-bottom: 1px solid #e9ecef;\n }\n .field:last-child { border-bottom: none; margin-bottom: 0; padding-bottom: 0; }\n .field-label {\n font-weight: 600;\n color: #495057;\n display: block;\n margin-bottom: 0.5rem;\n }\n .required { color: #dc3545; }\n .type-badge {\n font-size: 0.7rem;\n padding: 0.1rem 0.3rem;\n background: #e9ecef;\n border-radius: 3px;\n color: #6c757d;\n margin-left: 0.5rem;\n font-weight: normal;\n }\n input[type=\"text\"],\n input[type=\"number\"],\n textarea,\n select {\n width: 100%;\n padding: 0.5rem 0.75rem;\n font-size: 1rem;\n border: 1px solid #ced4da;\n border-radius: 4px;\n background: #fff;\n transition: border-color 0.15s ease-in-out;\n }\n input[type=\"text\"]:focus,\n input[type=\"number\"]:focus,\n textarea:focus,\n select:focus {\n outline: none;\n border-color: #80bdff;\n box-shadow: 0 0 0 0.2rem rgba(0,123,255,.25);\n }\n textarea {\n min-height: 100px;\n resize: vertical;\n }\n .checkbox-group {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n }\n .checkbox-item {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n }\n .checkbox-item input[type=\"checkbox\"] {\n width: auto;\n margin: 0;\n }\n .checkbox-item label {\n margin: 0;\n font-weight: normal;\n cursor: pointer;\n }\n .checkbox-item select {\n width: auto;\n min-width: 120px;\n }\n .option-row {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n margin-bottom: 0.5rem;\n }\n .option-row:last-child { margin-bottom: 0; }\n .option-label {\n flex: 1;\n }\n .toolbar {\n position: fixed;\n bottom: 2rem;\n right: 2rem;\n display: flex;\n gap: 0.5rem;\n }\n .btn {\n padding: 0.75rem 1.5rem;\n border: none;\n border-radius: 6px;\n font-size: 1rem;\n cursor: pointer;\n transition: all 0.2s;\n }\n .btn-primary {\n background: #0d6efd;\n color: white;\n }\n .btn-primary:hover { background: #0b5ed7; }\n .field-help {\n font-size: 0.85rem;\n color: #6c757d;\n margin-top: 0.25rem;\n }\n </style>\n</head>\n<body>\n <h1>${escapeHtml(formTitle)}</h1>\n <form method=\"POST\" action=\"/save\" id=\"markform\">\n ${groupsHtml}\n <div class=\"toolbar\">\n <button type=\"submit\" class=\"btn btn-primary\">Save</button>\n </div>\n </form>\n <script>\n document.getElementById('markform').addEventListener('submit', async (e) => {\n e.preventDefault();\n const formData = new FormData(e.target);\n const params = new URLSearchParams();\n for (const [key, value] of formData) {\n params.append(key, value);\n }\n try {\n const res = await fetch('/save', {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: params.toString()\n });\n const data = await res.json();\n if (data.success) {\n alert('Saved to: ' + data.path);\n location.reload();\n } else {\n alert('Error: ' + data.error);\n }\n } catch (err) {\n alert('Save failed: ' + err.message);\n }\n });\n </script>\n</body>\n</html>`;\n}\n\n/**\n * Render a field group as HTML.\n */\nfunction renderGroup(\n group: FieldGroup,\n values: Record<string, FieldValue>\n): string {\n const groupTitle = group.title ?? group.id;\n const fieldsHtml = group.children\n .map((field) => renderFieldHtml(field, values[field.id]))\n .join(\"\\n\");\n\n return `\n <div class=\"group\">\n <h2>${escapeHtml(groupTitle)}</h2>\n ${fieldsHtml}\n </div>`;\n}\n\n/**\n * Render a field as HTML.\n * @public Exported for testing.\n */\nexport function renderFieldHtml(field: Field, value: FieldValue | undefined): string {\n const requiredMark = field.required ? '<span class=\"required\">*</span>' : \"\";\n const typeLabel = `<span class=\"type-badge\">${field.kind}</span>`;\n\n let inputHtml: string;\n\n switch (field.kind) {\n case \"string\":\n inputHtml = renderStringInput(field, value);\n break;\n case \"number\":\n inputHtml = renderNumberInput(field, value);\n break;\n case \"string_list\":\n inputHtml = renderStringListInput(field, value);\n break;\n case \"single_select\":\n inputHtml = renderSingleSelectInput(\n field,\n value as SingleSelectValue | undefined\n );\n break;\n case \"multi_select\":\n inputHtml = renderMultiSelectInput(\n field,\n value as MultiSelectValue | undefined\n );\n break;\n case \"checkboxes\":\n inputHtml = renderCheckboxesInput(\n field,\n value as CheckboxesValue | undefined\n );\n break;\n default:\n inputHtml = '<div class=\"field-help\">(unknown field type)</div>';\n }\n\n return `\n <div class=\"field\">\n <label class=\"field-label\" for=\"field-${field.id}\">\n ${escapeHtml(field.label)} ${requiredMark} ${typeLabel}\n </label>\n ${inputHtml}\n </div>`;\n}\n\n/**\n * Render a string field as text input.\n */\nfunction renderStringInput(\n field: StringField,\n value: FieldValue | undefined\n): string {\n const currentValue =\n value?.kind === \"string\" && value.value !== null ? value.value : \"\";\n const requiredAttr = field.required ? \" required\" : \"\";\n const minLengthAttr =\n field.minLength !== undefined ? ` minlength=\"${field.minLength}\"` : \"\";\n const maxLengthAttr =\n field.maxLength !== undefined ? ` maxlength=\"${field.maxLength}\"` : \"\";\n\n return `<input type=\"text\" id=\"field-${field.id}\" name=\"${field.id}\" value=\"${escapeHtml(currentValue)}\"${requiredAttr}${minLengthAttr}${maxLengthAttr}>`;\n}\n\n/**\n * Render a number field as number input.\n */\nfunction renderNumberInput(\n field: NumberField,\n value: FieldValue | undefined\n): string {\n const currentValue =\n value?.kind === \"number\" && value.value !== null ? String(value.value) : \"\";\n const requiredAttr = field.required ? \" required\" : \"\";\n const minAttr = field.min !== undefined ? ` min=\"${field.min}\"` : \"\";\n const maxAttr = field.max !== undefined ? ` max=\"${field.max}\"` : \"\";\n const stepAttr = field.integer ? ' step=\"1\"' : \"\";\n\n return `<input type=\"number\" id=\"field-${field.id}\" name=\"${field.id}\" value=\"${escapeHtml(currentValue)}\"${requiredAttr}${minAttr}${maxAttr}${stepAttr}>`;\n}\n\n/**\n * Render a string list field as textarea.\n */\nfunction renderStringListInput(\n field: StringListField,\n value: FieldValue | undefined\n): string {\n const items =\n value?.kind === \"string_list\" ? value.items : [];\n const currentValue = items.join(\"\\n\");\n const requiredAttr = field.required ? \" required\" : \"\";\n\n return `<textarea id=\"field-${field.id}\" name=\"${field.id}\" placeholder=\"Enter one item per line\"${requiredAttr}>${escapeHtml(currentValue)}</textarea>`;\n}\n\n/**\n * Render a single-select field as select element.\n */\nfunction renderSingleSelectInput(\n field: SingleSelectField,\n value: SingleSelectValue | undefined\n): string {\n const selected = value?.selected ?? null;\n const requiredAttr = field.required ? \" required\" : \"\";\n\n const options = field.options\n .map((opt) => {\n const isSelected = selected === opt.id;\n const selectedAttr = isSelected ? \" selected\" : \"\";\n return `<option value=\"${escapeHtml(opt.id)}\"${selectedAttr}>${escapeHtml(opt.label)}</option>`;\n })\n .join(\"\\n \");\n\n return `<select id=\"field-${field.id}\" name=\"${field.id}\"${requiredAttr}>\n <option value=\"\">-- Select --</option>\n ${options}\n </select>`;\n}\n\n/**\n * Render a multi-select field as checkboxes.\n */\nfunction renderMultiSelectInput(\n field: MultiSelectField,\n value: MultiSelectValue | undefined\n): string {\n const selected = value?.selected ?? [];\n\n const checkboxes = field.options\n .map((opt) => {\n const isChecked = selected.includes(opt.id);\n const checkedAttr = isChecked ? \" checked\" : \"\";\n const checkboxId = `field-${field.id}-${opt.id}`;\n return `<div class=\"checkbox-item\">\n <input type=\"checkbox\" id=\"${checkboxId}\" name=\"${field.id}\" value=\"${escapeHtml(opt.id)}\"${checkedAttr}>\n <label for=\"${checkboxId}\">${escapeHtml(opt.label)}</label>\n </div>`;\n })\n .join(\"\\n \");\n\n return `<div class=\"checkbox-group\">\n ${checkboxes}\n </div>`;\n}\n\n/**\n * Render checkboxes field based on mode.\n */\nfunction renderCheckboxesInput(\n field: CheckboxesField,\n value: CheckboxesValue | undefined\n): string {\n const checkboxValues = value?.values ?? {};\n const mode = field.checkboxMode ?? \"multi\";\n\n if (mode === \"simple\") {\n // Simple mode: render as HTML checkboxes\n const checkboxes = field.options\n .map((opt) => {\n const state = checkboxValues[opt.id];\n const isChecked = state === \"done\";\n const checkedAttr = isChecked ? \" checked\" : \"\";\n const checkboxId = `field-${field.id}-${opt.id}`;\n return `<div class=\"checkbox-item\">\n <input type=\"checkbox\" id=\"${checkboxId}\" name=\"${field.id}\" value=\"${escapeHtml(opt.id)}\"${checkedAttr}>\n <label for=\"${checkboxId}\">${escapeHtml(opt.label)}</label>\n </div>`;\n })\n .join(\"\\n \");\n\n return `<div class=\"checkbox-group\">\n ${checkboxes}\n </div>`;\n }\n\n if (mode === \"explicit\") {\n // Explicit mode: render as select with yes/no/unfilled options\n const rows = field.options\n .map((opt) => {\n const state = checkboxValues[opt.id] ?? \"unfilled\";\n const selectId = `field-${field.id}-${opt.id}`;\n const selectName = `${field.id}.${opt.id}`;\n\n return `<div class=\"option-row\">\n <span class=\"option-label\">${escapeHtml(opt.label)}</span>\n <select id=\"${selectId}\" name=\"${selectName}\">\n <option value=\"unfilled\"${state === \"unfilled\" ? \" selected\" : \"\"}>-- Select --</option>\n <option value=\"yes\"${state === \"yes\" ? \" selected\" : \"\"}>Yes</option>\n <option value=\"no\"${state === \"no\" ? \" selected\" : \"\"}>No</option>\n </select>\n </div>`;\n })\n .join(\"\\n \");\n\n return `<div class=\"checkbox-group\">\n ${rows}\n </div>`;\n }\n\n // Multi mode: render as select with multiple state options\n const rows = field.options\n .map((opt) => {\n const state = checkboxValues[opt.id] ?? \"todo\";\n const selectId = `field-${field.id}-${opt.id}`;\n const selectName = `${field.id}.${opt.id}`;\n\n return `<div class=\"option-row\">\n <span class=\"option-label\">${escapeHtml(opt.label)}</span>\n <select id=\"${selectId}\" name=\"${selectName}\">\n <option value=\"todo\"${state === \"todo\" ? \" selected\" : \"\"}>To Do</option>\n <option value=\"active\"${state === \"active\" ? \" selected\" : \"\"}>Active</option>\n <option value=\"done\"${state === \"done\" ? \" selected\" : \"\"}>Done</option>\n <option value=\"incomplete\"${state === \"incomplete\" ? \" selected\" : \"\"}>Incomplete</option>\n <option value=\"na\"${state === \"na\" ? \" selected\" : \"\"}>N/A</option>\n </select>\n </div>`;\n })\n .join(\"\\n \");\n\n return `<div class=\"checkbox-group\">\n ${rows}\n </div>`;\n}\n\n/**\n * Escape HTML special characters.\n * @public Exported for testing.\n */\nexport function escapeHtml(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#039;\");\n}\n","/**\n * Render command - Render a form as static HTML output.\n *\n * Generates the same HTML as the serve command but writes to a file\n * instead of serving via HTTP.\n */\n\nimport type { Command } from \"commander\";\n\nimport { basename, dirname, resolve } from \"node:path\";\n\nimport pc from \"picocolors\";\n\nimport { parseForm } from \"../../engine/parse.js\";\nimport {\n getCommandContext,\n logDryRun,\n logError,\n logSuccess,\n logVerbose,\n readFile,\n writeFile,\n} from \"../lib/shared.js\";\nimport { renderFormHtml } from \"./serve.js\";\n\n/**\n * Generate default output path by replacing .form.md with .form.html.\n */\nfunction getDefaultOutputPath(inputPath: string): string {\n const dir = dirname(inputPath);\n const base = basename(inputPath);\n\n // Replace .form.md extension with .form.html\n const newBase = base.replace(/\\.form\\.md$/i, \".form.html\");\n\n if (newBase === base) {\n // No .form.md extension found, append .html\n return `${inputPath}.html`;\n }\n\n return resolve(dir, newBase);\n}\n\n/**\n * Register the render command.\n */\nexport function registerRenderCommand(program: Command): void {\n program\n .command(\"render <file>\")\n .description(\"Render a form as static HTML output\")\n .option(\"-o, --output <path>\", \"Output file path (default: same stem + .html)\")\n .action(\n async (\n file: string,\n options: { output?: string },\n cmd: Command\n ) => {\n const ctx = getCommandContext(cmd);\n const filePath = resolve(file);\n const outputPath = options.output\n ? resolve(options.output)\n : getDefaultOutputPath(filePath);\n\n try {\n logVerbose(ctx, `Reading file: ${filePath}`);\n const content = await readFile(filePath);\n\n logVerbose(ctx, \"Parsing form...\");\n const form = parseForm(content);\n\n logVerbose(ctx, \"Rendering HTML...\");\n const html = renderFormHtml(form);\n\n if (ctx.dryRun) {\n logDryRun(`Would write HTML to: ${outputPath}`);\n return;\n }\n\n await writeFile(outputPath, html);\n logSuccess(ctx, pc.green(`✓ Rendered to ${outputPath}`));\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logError(message);\n process.exit(1);\n }\n }\n );\n}\n","/**\n * Validate command - Display form summary and validation issues.\n *\n * A streamlined version of inspect that shows:\n * - Form state\n * - Structure summary (field counts, types)\n * - Progress summary (filled/empty counts)\n * - Issues sorted by priority\n *\n * Does NOT include full form content (use inspect for that).\n */\n\nimport type { Command } from \"commander\";\n\nimport pc from \"picocolors\";\n\nimport { inspect } from \"../../engine/inspect.js\";\nimport { parseForm } from \"../../engine/parse.js\";\nimport type { InspectIssue, ProgressState } from \"../../engine/coreTypes.js\";\nimport {\n formatOutput,\n getCommandContext,\n logError,\n logVerbose,\n readFile,\n} from \"../lib/shared.js\";\n\n/**\n * Format state badge for console output.\n */\nfunction formatState(state: ProgressState, useColors: boolean): string {\n const badges: Record<ProgressState, [string, (s: string) => string]> = {\n complete: [\"✓ complete\", pc.green],\n incomplete: [\"○ incomplete\", pc.yellow],\n empty: [\"◌ empty\", pc.dim],\n invalid: [\"✗ invalid\", pc.red],\n };\n const [text, colorFn] = badges[state] ?? [state, (s: string) => s];\n return useColors ? colorFn(text) : text;\n}\n\n/**\n * Format priority badge for console output.\n */\nfunction formatPriority(priority: number, useColors: boolean): string {\n const label = `P${priority}`;\n if (!useColors) {\n return label;\n }\n switch (priority) {\n case 1:\n return pc.red(pc.bold(label));\n case 2:\n return pc.yellow(label);\n case 3:\n return pc.cyan(label);\n case 4:\n return pc.blue(label);\n case 5:\n default:\n return pc.dim(label);\n }\n}\n\n/**\n * Format severity badge for console output.\n */\nfunction formatSeverity(\n severity: \"required\" | \"recommended\",\n useColors: boolean\n): string {\n if (!useColors) {\n return severity;\n }\n return severity === \"required\" ? pc.red(severity) : pc.yellow(severity);\n}\n\n/** Report structure for validate command */\ninterface ValidateReport {\n title?: string;\n structure: unknown;\n progress: unknown;\n form_state: ProgressState;\n issues: {\n ref: string;\n scope: string;\n reason: string;\n message: string;\n priority: number;\n severity: \"required\" | \"recommended\";\n }[];\n}\n\n/**\n * Format validate report for console output.\n */\nfunction formatConsoleReport(\n report: ValidateReport,\n useColors: boolean\n): string {\n const lines: string[] = [];\n const bold = useColors ? pc.bold : (s: string) => s;\n const dim = useColors ? pc.dim : (s: string) => s;\n const cyan = useColors ? pc.cyan : (s: string) => s;\n\n // Header\n lines.push(bold(cyan(\"Form Validation Report\")));\n if (report.title) {\n lines.push(`${bold(\"Title:\")} ${report.title}`);\n }\n lines.push(\"\");\n\n // Form state\n lines.push(\n `${bold(\"Form State:\")} ${formatState(report.form_state, useColors)}`\n );\n lines.push(\"\");\n\n // Structure summary\n const structure = report.structure as {\n groupCount: number;\n fieldCount: number;\n optionCount: number;\n };\n lines.push(bold(\"Structure:\"));\n lines.push(` Groups: ${structure.groupCount}`);\n lines.push(` Fields: ${structure.fieldCount}`);\n lines.push(` Options: ${structure.optionCount}`);\n lines.push(\"\");\n\n // Progress summary\n const progress = report.progress as {\n counts: {\n totalFields: number;\n requiredFields: number;\n submittedFields: number;\n completeFields: number;\n incompleteFields: number;\n invalidFields: number;\n emptyRequiredFields: number;\n emptyOptionalFields: number;\n };\n };\n lines.push(bold(\"Progress:\"));\n lines.push(` Total fields: ${progress.counts.totalFields}`);\n lines.push(` Required: ${progress.counts.requiredFields}`);\n lines.push(` Submitted: ${progress.counts.submittedFields}`);\n lines.push(` Complete: ${progress.counts.completeFields}`);\n lines.push(` Incomplete: ${progress.counts.incompleteFields}`);\n lines.push(` Invalid: ${progress.counts.invalidFields}`);\n lines.push(` Empty (required): ${progress.counts.emptyRequiredFields}`);\n lines.push(` Empty (optional): ${progress.counts.emptyOptionalFields}`);\n lines.push(\"\");\n\n // Issues\n if (report.issues.length > 0) {\n lines.push(bold(`Issues (${report.issues.length}):`));\n for (const issue of report.issues) {\n const priority = formatPriority(issue.priority, useColors);\n const severity = formatSeverity(issue.severity, useColors);\n lines.push(\n ` ${priority} (${severity}) ${dim(`[${issue.scope}]`)} ${dim(issue.ref)}: ${issue.message}`\n );\n }\n } else {\n lines.push(dim(\"No issues found.\"));\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Register the validate command.\n */\nexport function registerValidateCommand(program: Command): void {\n program\n .command(\"validate <file>\")\n .description(\"Validate a form and display summary and issues (no form content)\")\n .action(\n async (file: string, _options: Record<string, unknown>, cmd: Command) => {\n const ctx = getCommandContext(cmd);\n\n try {\n logVerbose(ctx, `Reading file: ${file}`);\n const content = await readFile(file);\n\n logVerbose(ctx, \"Parsing form...\");\n const form = parseForm(content);\n\n logVerbose(ctx, \"Running validation...\");\n const result = inspect(form);\n\n // Build the report structure (without form content)\n const report: ValidateReport = {\n title: form.schema.title,\n structure: result.structureSummary,\n progress: result.progressSummary,\n form_state: result.formState,\n issues: result.issues.map((issue: InspectIssue) => ({\n ref: issue.ref,\n scope: issue.scope,\n reason: issue.reason,\n message: issue.message,\n priority: issue.priority,\n severity: issue.severity,\n })),\n };\n\n // Output in requested format\n const output = formatOutput(ctx, report, (data, useColors) =>\n formatConsoleReport(data as ValidateReport, useColors)\n );\n console.log(output);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logError(message);\n process.exit(1);\n }\n }\n );\n}\n","/**\n * CLI implementation for markform.\n *\n * Provides commands for inspecting, applying patches, exporting,\n * serving, and running harness loops on .form.md files.\n */\n\nimport { Command } from \"commander\";\nimport pc from \"picocolors\";\n\nimport { VERSION } from \"../index.js\";\nimport { registerApplyCommand } from \"./commands/apply.js\";\nimport { registerDumpCommand } from \"./commands/dump.js\";\nimport { registerExamplesCommand } from \"./commands/examples.js\";\nimport { registerExportCommand } from \"./commands/export.js\";\nimport { registerFillCommand } from \"./commands/fill.js\";\nimport { registerInspectCommand } from \"./commands/inspect.js\";\nimport { registerModelsCommand } from \"./commands/models.js\";\nimport { registerRenderCommand } from \"./commands/render.js\";\nimport { registerServeCommand } from \"./commands/serve.js\";\nimport { registerValidateCommand } from \"./commands/validate.js\";\nimport { OUTPUT_FORMATS } from \"./lib/shared.js\";\n\n/**\n * Configure Commander with colored help text and global options display.\n */\nfunction withColoredHelp<T extends Command>(cmd: T): T {\n cmd.configureHelp({\n styleTitle: (str) => pc.bold(pc.cyan(str)),\n styleCommandText: (str) => pc.green(str),\n styleOptionText: (str) => pc.yellow(str),\n showGlobalOptions: true,\n });\n return cmd;\n}\n\n/**\n * Create and configure the CLI program.\n */\nfunction createProgram(): Command {\n const program = withColoredHelp(new Command());\n\n program\n .name(\"markform\")\n .description(\"Agent-friendly, human-readable, editable forms\")\n .version(VERSION)\n .option(\"--verbose\", \"Enable verbose output\")\n .option(\"--quiet\", \"Suppress non-essential output\")\n .option(\"--dry-run\", \"Show what would be done without making changes\")\n .option(\n \"--format <format>\",\n `Output format: ${OUTPUT_FORMATS.join(\", \")}`,\n \"console\"\n );\n\n // Register commands\n registerInspectCommand(program);\n registerValidateCommand(program);\n registerApplyCommand(program);\n registerExportCommand(program);\n registerDumpCommand(program);\n registerRenderCommand(program);\n registerServeCommand(program);\n registerFillCommand(program);\n registerModelsCommand(program);\n registerExamplesCommand(program);\n\n return program;\n}\n\n/**\n * Run the CLI.\n */\nexport async function runCli(): Promise<void> {\n const program = createProgram();\n await program.parseAsync(process.argv);\n}\n"],"mappings":"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"}