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":"apply-C0vjijlP.mjs","names":["DEFAULT_ROLE_INSTRUCTIONS: Record<string, string>","DEFAULT_PRIORITY: FieldPriorityLevel","SUGGESTED_LLMS: Record<string, string[]>","lines: string[]","parts: string[]","STATE_TO_MARKER: Record<CheckboxValue, string>","attrs: Record<string, unknown>","lines: string[]","selected: Record<string, CheckboxValue>","STATE_TO_GFM_MARKER: Record<CheckboxValue, string>","fieldCountByKind: Record<FieldKind, number>","groupsById: Record<Id, \"field_group\">","fieldsById: Record<Id, FieldKind>","optionsById: Record<\n QualifiedOptionRef,\n { parentFieldId: Id; parentFieldKind: FieldKind }\n >","qualifiedRef: QualifiedOptionRef","result: CheckboxProgressCounts","progress: FieldProgress","fields: Record<Id, FieldProgress>","counts: ProgressCounts","issues: ValidationIssue[]","ctx: ValidatorContext","FIELD_PRIORITY_WEIGHTS: Record<FieldPriorityLevel, number>","ISSUE_TYPE_SCORES: Record<IssueReason, number>","errors: PatchError[]","merged: Record<OptionId, CheckboxValue>","issues: InspectIssue[]","summaries","issues","newValues: Record<Id, FieldValue>"],"sources":["../src/engine/coreTypes.ts","../src/settings.ts","../src/engine/serialize.ts","../src/engine/summaries.ts","../src/engine/validate.ts","../src/engine/inspect.ts","../src/engine/apply.ts"],"sourcesContent":["/**\n * Core types and Zod schemas for Markform.\n *\n * This module defines all TypeScript types and their corresponding Zod schemas\n * for forms, fields, values, validation, patches, and session transcripts.\n */\n\nimport { z } from \"zod\";\n\n// =============================================================================\n// Basic Types\n// =============================================================================\n\n/** Form/group/field ID - globally unique within a document */\nexport type Id = string;\n\n/** Option ID - unique within its containing field */\nexport type OptionId = string;\n\n/** Qualified option reference - used in doc blocks and external references */\nexport type QualifiedOptionRef = `${Id}.${OptionId}`;\n\n/** Validator reference - simple ID or parameterized object */\nexport type ValidatorRef = string | { id: string; [key: string]: unknown };\n\n// =============================================================================\n// Checkbox Types\n// =============================================================================\n\n/** Multi-checkbox states (checkboxMode=\"multi\", default) - 5 states */\nexport type MultiCheckboxState =\n | \"todo\"\n | \"done\"\n | \"incomplete\"\n | \"active\"\n | \"na\";\n\n/** Simple checkbox states (checkboxMode=\"simple\") - 2 states, GFM-compatible */\nexport type SimpleCheckboxState = \"todo\" | \"done\";\n\n/** Explicit checkbox values (checkboxMode=\"explicit\") - requires yes/no answer */\nexport type ExplicitCheckboxValue = \"unfilled\" | \"yes\" | \"no\";\n\n/** Union type for all checkbox values */\nexport type CheckboxValue = MultiCheckboxState | ExplicitCheckboxValue;\n\n/** Checkbox mode determines which states are valid */\nexport type CheckboxMode = \"multi\" | \"simple\" | \"explicit\";\n\n/**\n * Controls how fill handles existing values for target role fields.\n * - 'continue': Skip fields that already have values (default)\n * - 'overwrite': Clear and re-fill all fields for the target role\n */\nexport type FillMode = \"continue\" | \"overwrite\";\n\n/**\n * Controls whether a checkbox field acts as a blocking checkpoint.\n * - 'none': No blocking behavior (default)\n * - 'blocking': Fields after this cannot be filled until checkbox is complete\n */\nexport type ApprovalMode = \"none\" | \"blocking\";\n\n// =============================================================================\n// Field Types\n// =============================================================================\n\n/** Field kind discriminant */\nexport type FieldKind =\n | \"string\"\n | \"number\"\n | \"string_list\"\n | \"checkboxes\"\n | \"single_select\"\n | \"multi_select\";\n\n/** Field priority level for issue scoring */\nexport type FieldPriorityLevel = \"high\" | \"medium\" | \"low\";\n\n/** Base interface for all field types */\nexport interface FieldBase {\n id: Id;\n label: string;\n required: boolean; // explicit: parser defaults to false if not specified\n priority: FieldPriorityLevel; // explicit: parser defaults to 'medium' if not specified\n role: string; // explicit: parser defaults to AGENT_ROLE if not specified\n validate?: ValidatorRef[];\n}\n\n/** String field - single or multiline text */\nexport interface StringField extends FieldBase {\n kind: \"string\";\n multiline?: boolean;\n pattern?: string;\n minLength?: number;\n maxLength?: number;\n}\n\n/** Number field - numeric value with optional constraints */\nexport interface NumberField extends FieldBase {\n kind: \"number\";\n min?: number;\n max?: number;\n integer?: boolean;\n}\n\n/** String list field - array of user-provided strings */\nexport interface StringListField extends FieldBase {\n kind: \"string_list\";\n minItems?: number;\n maxItems?: number;\n itemMinLength?: number;\n itemMaxLength?: number;\n uniqueItems?: boolean;\n}\n\n/** Option in select/checkbox fields */\nexport interface Option {\n id: Id;\n label: string;\n}\n\n/** Checkboxes field - stateful checklist with configurable modes */\nexport interface CheckboxesField extends FieldBase {\n kind: \"checkboxes\";\n checkboxMode: CheckboxMode; // explicit: parser defaults to 'multi' if not specified\n minDone?: number;\n options: Option[];\n approvalMode: ApprovalMode; // explicit: parser defaults to 'none' if not specified\n}\n\n/** Single-select field - exactly one option can be selected */\nexport interface SingleSelectField extends FieldBase {\n kind: \"single_select\";\n options: Option[];\n}\n\n/** Multi-select field - multiple options can be selected */\nexport interface MultiSelectField extends FieldBase {\n kind: \"multi_select\";\n options: Option[];\n minSelections?: number;\n maxSelections?: number;\n}\n\n/** Union of all field types */\nexport type Field =\n | StringField\n | NumberField\n | StringListField\n | CheckboxesField\n | SingleSelectField\n | MultiSelectField;\n\n// =============================================================================\n// Form Structure Types\n// =============================================================================\n\n/** Field group - container for fields (nested groups deferred to future) */\nexport interface FieldGroup {\n kind: \"field_group\";\n id: Id;\n title?: string;\n validate?: ValidatorRef[];\n children: Field[];\n}\n\n/** Form schema - root container with groups */\nexport interface FormSchema {\n id: Id;\n title?: string;\n groups: FieldGroup[];\n}\n\n// =============================================================================\n// Field Value Types\n// =============================================================================\n\n/** String field value */\nexport interface StringValue {\n kind: \"string\";\n value: string | null;\n}\n\n/** Number field value */\nexport interface NumberValue {\n kind: \"number\";\n value: number | null;\n}\n\n/** String list field value */\nexport interface StringListValue {\n kind: \"string_list\";\n items: string[];\n}\n\n/** Checkboxes field value */\nexport interface CheckboxesValue {\n kind: \"checkboxes\";\n values: Record<OptionId, CheckboxValue>;\n}\n\n/** Single-select field value */\nexport interface SingleSelectValue {\n kind: \"single_select\";\n selected: OptionId | null;\n}\n\n/** Multi-select field value */\nexport interface MultiSelectValue {\n kind: \"multi_select\";\n selected: OptionId[];\n}\n\n/** Union of all field value types */\nexport type FieldValue =\n | StringValue\n | NumberValue\n | StringListValue\n | CheckboxesValue\n | SingleSelectValue\n | MultiSelectValue;\n\n// =============================================================================\n// Documentation Block\n// =============================================================================\n\n/** Documentation tag type - determines the semantic purpose of the block */\nexport type DocumentationTag = \"description\" | \"instructions\" | \"documentation\";\n\n/** Documentation block attached to form elements */\nexport interface DocumentationBlock {\n /** The semantic tag type: description, instructions, or documentation */\n tag: DocumentationTag;\n /** Reference to form/group/field ID or qualified option ref (fieldId.optionId) */\n ref: string;\n bodyMarkdown: string;\n}\n\n// =============================================================================\n// Form Metadata (from frontmatter)\n// =============================================================================\n\n/** Form-level metadata from YAML frontmatter, including role configuration */\nexport interface FormMetadata {\n markformVersion: string;\n roles: string[];\n roleInstructions: Record<string, string>;\n}\n\n// =============================================================================\n// Parsed Form\n// =============================================================================\n\n/** ID index entry for fast lookup and validation */\nexport interface IdIndexEntry {\n kind: \"form\" | \"group\" | \"field\" | \"option\";\n parentId?: Id;\n fieldId?: Id;\n}\n\n/** Canonical internal representation returned by parseForm() */\nexport interface ParsedForm {\n schema: FormSchema;\n valuesByFieldId: Record<Id, FieldValue>;\n docs: DocumentationBlock[];\n orderIndex: Id[];\n idIndex: Map<Id, IdIndexEntry>;\n metadata?: FormMetadata; // optional for backward compat with forms without frontmatter\n}\n\n// =============================================================================\n// Validation Types\n// =============================================================================\n\n/** Validation issue severity */\nexport type Severity = \"error\" | \"warning\" | \"info\";\n\n/** Source position for error locations */\nexport interface SourcePosition {\n line: number;\n col: number;\n}\n\n/** Source range for error locations */\nexport interface SourceRange {\n start: SourcePosition;\n end: SourcePosition;\n}\n\n/** Validation issue from the validation pipeline */\nexport interface ValidationIssue {\n severity: Severity;\n message: string;\n code?: string;\n ref?: Id;\n path?: string;\n range?: SourceRange;\n validatorId?: string;\n source: \"builtin\" | \"code\" | \"llm\";\n}\n\n// =============================================================================\n// Inspect Types\n// =============================================================================\n\n/** Standard reason codes for inspect issues */\nexport type IssueReason =\n | \"validation_error\"\n | \"required_missing\"\n | \"checkbox_incomplete\"\n | \"min_items_not_met\"\n | \"optional_empty\";\n\n/** Issue scope - the level at which the issue applies */\nexport type IssueScope = \"form\" | \"group\" | \"field\" | \"option\";\n\n/** Inspect issue - unified type for agent/UI consumption */\nexport interface InspectIssue {\n ref: string;\n scope: IssueScope;\n reason: IssueReason;\n message: string;\n severity: \"required\" | \"recommended\";\n priority: number;\n blockedBy?: Id; // if field is blocked by an incomplete blocking checkpoint\n}\n\n// =============================================================================\n// Summary Types\n// =============================================================================\n\n/** Structure summary - describes static form schema */\nexport interface StructureSummary {\n groupCount: number;\n fieldCount: number;\n optionCount: number;\n fieldCountByKind: Record<FieldKind, number>;\n groupsById: Record<Id, \"field_group\">;\n fieldsById: Record<Id, FieldKind>;\n optionsById: Record<\n QualifiedOptionRef,\n { parentFieldId: Id; parentFieldKind: FieldKind }\n >;\n}\n\n/** Progress state for a field or form */\nexport type ProgressState = \"empty\" | \"incomplete\" | \"invalid\" | \"complete\";\n\n/** Checkbox progress counts */\nexport interface CheckboxProgressCounts {\n total: number;\n // Multi mode\n todo: number;\n done: number;\n incomplete: number;\n active: number;\n na: number;\n // Explicit mode\n unfilled: number;\n yes: number;\n no: number;\n}\n\n/** Field progress tracking */\nexport interface FieldProgress {\n kind: FieldKind;\n required: boolean;\n submitted: boolean;\n state: ProgressState;\n valid: boolean;\n issueCount: number;\n checkboxProgress?: CheckboxProgressCounts;\n}\n\n/** Progress counts rollup */\nexport interface ProgressCounts {\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/** Progress summary - tracks filling progress */\nexport interface ProgressSummary {\n counts: ProgressCounts;\n fields: Record<Id, FieldProgress>;\n}\n\n// =============================================================================\n// Inspect/Apply Result Types\n// =============================================================================\n\n/** Result from inspect operation */\nexport interface InspectResult {\n structureSummary: StructureSummary;\n progressSummary: ProgressSummary;\n issues: InspectIssue[];\n isComplete: boolean;\n formState: ProgressState;\n}\n\n/** Result from apply operation */\nexport interface ApplyResult {\n applyStatus: \"applied\" | \"rejected\";\n structureSummary: StructureSummary;\n progressSummary: ProgressSummary;\n issues: InspectIssue[];\n isComplete: boolean;\n formState: ProgressState;\n}\n\n// =============================================================================\n// Patch Types\n// =============================================================================\n\n/** Set string field value */\nexport interface SetStringPatch {\n op: \"set_string\";\n fieldId: Id;\n value: string | null;\n}\n\n/** Set number field value */\nexport interface SetNumberPatch {\n op: \"set_number\";\n fieldId: Id;\n value: number | null;\n}\n\n/** Set string list field value */\nexport interface SetStringListPatch {\n op: \"set_string_list\";\n fieldId: Id;\n items: string[];\n}\n\n/** Set checkboxes field value (merges with existing) */\nexport interface SetCheckboxesPatch {\n op: \"set_checkboxes\";\n fieldId: Id;\n values: Record<OptionId, CheckboxValue>;\n}\n\n/** Set single-select field value */\nexport interface SetSingleSelectPatch {\n op: \"set_single_select\";\n fieldId: Id;\n selected: OptionId | null;\n}\n\n/** Set multi-select field value */\nexport interface SetMultiSelectPatch {\n op: \"set_multi_select\";\n fieldId: Id;\n selected: OptionId[];\n}\n\n/** Clear field value */\nexport interface ClearFieldPatch {\n op: \"clear_field\";\n fieldId: Id;\n}\n\n/** Union of all patch types */\nexport type Patch =\n | SetStringPatch\n | SetNumberPatch\n | SetStringListPatch\n | SetCheckboxesPatch\n | SetSingleSelectPatch\n | SetMultiSelectPatch\n | ClearFieldPatch;\n\n// =============================================================================\n// Harness Types\n// =============================================================================\n\n/** Result from harness step */\nexport interface StepResult {\n structureSummary: StructureSummary;\n progressSummary: ProgressSummary;\n issues: InspectIssue[];\n stepBudget: number;\n isComplete: boolean;\n turnNumber: number;\n}\n\n// =============================================================================\n// Session Transcript Types\n// =============================================================================\n\n/** Harness configuration */\nexport interface HarnessConfig {\n maxIssues: number;\n maxPatchesPerTurn: number;\n maxTurns: number;\n /** Maximum unique fields to include issues for per turn (undefined = unlimited) */\n maxFieldsPerTurn?: number;\n /** Maximum unique groups to include issues for per turn (undefined = unlimited) */\n maxGroupsPerTurn?: number;\n /** Target roles to fill (default: [AGENT_ROLE], '*' for all) */\n targetRoles?: string[];\n /** Fill mode: 'continue' (skip filled) or 'overwrite' (re-fill) */\n fillMode?: FillMode;\n}\n\n/** Session turn - one iteration of the harness loop */\nexport interface SessionTurn {\n turn: number;\n inspect: {\n issues: InspectIssue[];\n };\n apply: {\n patches: Patch[];\n };\n after: {\n requiredIssueCount: number;\n markdownSha256: string;\n };\n}\n\n/** Final session expectations */\nexport interface SessionFinal {\n expectComplete: boolean;\n expectedCompletedForm: string;\n}\n\n/** Session transcript for golden testing */\nexport interface SessionTranscript {\n sessionVersion: string;\n mode: \"mock\" | \"live\";\n form: {\n path: string;\n };\n validators?: {\n code?: string;\n };\n mock?: {\n completedMock: string;\n };\n live?: {\n modelId: string;\n };\n harness: HarnessConfig;\n turns: SessionTurn[];\n final: SessionFinal;\n}\n\n// =============================================================================\n// Frontmatter Types\n// =============================================================================\n\n/** Markform frontmatter structure */\nexport interface MarkformFrontmatter {\n markformVersion: string;\n formSummary: StructureSummary;\n formProgress: ProgressSummary;\n formState: ProgressState;\n}\n\n// =============================================================================\n// Validator Types\n// =============================================================================\n\n/** Context passed to validator functions */\nexport interface ValidatorContext {\n schema: FormSchema;\n values: Record<Id, FieldValue>;\n targetId: Id;\n targetSchema: Field | FieldGroup | FormSchema;\n params: Record<string, unknown>;\n}\n\n/** Validator function signature */\nexport type ValidatorFn = (ctx: ValidatorContext) => ValidationIssue[];\n\n/** Validator registry from sidecar files */\nexport type ValidatorRegistry = Record<string, ValidatorFn>;\n\n// =============================================================================\n// Zod Schemas\n// =============================================================================\n\n// Basic schemas\nexport const IdSchema = z.string().min(1);\nexport const OptionIdSchema = z.string().min(1);\n\nexport const ValidatorRefSchema = z.union([\n z.string(),\n z.object({ id: z.string() }).passthrough(),\n]);\n\n// Checkbox state schemas\nexport const MultiCheckboxStateSchema = z.enum([\n \"todo\",\n \"done\",\n \"incomplete\",\n \"active\",\n \"na\",\n]);\n\nexport const SimpleCheckboxStateSchema = z.enum([\"todo\", \"done\"]);\n\nexport const ExplicitCheckboxValueSchema = z.enum([\"unfilled\", \"yes\", \"no\"]);\n\nexport const CheckboxValueSchema = z.union([\n MultiCheckboxStateSchema,\n ExplicitCheckboxValueSchema,\n]);\n\nexport const CheckboxModeSchema = z.enum([\"multi\", \"simple\", \"explicit\"]);\n\nexport const FillModeSchema = z.enum([\"continue\", \"overwrite\"]);\n\nexport const ApprovalModeSchema = z.enum([\"none\", \"blocking\"]);\n\n// Field kind schema\nexport const FieldKindSchema = z.enum([\n \"string\",\n \"number\",\n \"string_list\",\n \"checkboxes\",\n \"single_select\",\n \"multi_select\",\n]);\n\nexport const FieldPriorityLevelSchema = z.enum([\"high\", \"medium\", \"low\"]);\n\n// Option schema\nexport const OptionSchema = z.object({\n id: IdSchema,\n label: z.string(),\n});\n\n// Field base schema (partial, used for extension)\n// NOTE: required, priority, and role are explicit (not optional) - parser assigns defaults\nconst FieldBaseSchemaPartial = {\n id: IdSchema,\n label: z.string(),\n required: z.boolean(),\n priority: FieldPriorityLevelSchema,\n role: z.string(),\n validate: z.array(ValidatorRefSchema).optional(),\n};\n\n// Field schemas\nexport const StringFieldSchema = z.object({\n ...FieldBaseSchemaPartial,\n kind: z.literal(\"string\"),\n multiline: z.boolean().optional(),\n pattern: z.string().optional(),\n minLength: z.number().int().nonnegative().optional(),\n maxLength: z.number().int().nonnegative().optional(),\n});\n\nexport const NumberFieldSchema = z.object({\n ...FieldBaseSchemaPartial,\n kind: z.literal(\"number\"),\n min: z.number().optional(),\n max: z.number().optional(),\n integer: z.boolean().optional(),\n});\n\nexport const StringListFieldSchema = z.object({\n ...FieldBaseSchemaPartial,\n kind: z.literal(\"string_list\"),\n minItems: z.number().int().nonnegative().optional(),\n maxItems: z.number().int().nonnegative().optional(),\n itemMinLength: z.number().int().nonnegative().optional(),\n itemMaxLength: z.number().int().nonnegative().optional(),\n uniqueItems: z.boolean().optional(),\n});\n\nexport const CheckboxesFieldSchema = z.object({\n ...FieldBaseSchemaPartial,\n kind: z.literal(\"checkboxes\"),\n checkboxMode: CheckboxModeSchema, // explicit: parser defaults to 'multi'\n minDone: z.number().int().optional(),\n options: z.array(OptionSchema),\n approvalMode: ApprovalModeSchema, // explicit: parser defaults to 'none'\n});\n\nexport const SingleSelectFieldSchema = z.object({\n ...FieldBaseSchemaPartial,\n kind: z.literal(\"single_select\"),\n options: z.array(OptionSchema),\n});\n\nexport const MultiSelectFieldSchema = z.object({\n ...FieldBaseSchemaPartial,\n kind: z.literal(\"multi_select\"),\n options: z.array(OptionSchema),\n minSelections: z.number().int().nonnegative().optional(),\n maxSelections: z.number().int().nonnegative().optional(),\n});\n\nexport const FieldSchema = z.discriminatedUnion(\"kind\", [\n StringFieldSchema,\n NumberFieldSchema,\n StringListFieldSchema,\n CheckboxesFieldSchema,\n SingleSelectFieldSchema,\n MultiSelectFieldSchema,\n]);\n\n// Field group schema\nexport const FieldGroupSchema = z.object({\n kind: z.literal(\"field_group\"),\n id: IdSchema,\n title: z.string().optional(),\n validate: z.array(ValidatorRefSchema).optional(),\n children: z.array(FieldSchema),\n});\n\n// Form schema\nexport const FormSchemaSchema = z.object({\n id: IdSchema,\n title: z.string().optional(),\n groups: z.array(FieldGroupSchema),\n});\n\n// Field value schemas\nexport const StringValueSchema = z.object({\n kind: z.literal(\"string\"),\n value: z.string().nullable(),\n});\n\nexport const NumberValueSchema = z.object({\n kind: z.literal(\"number\"),\n value: z.number().nullable(),\n});\n\nexport const StringListValueSchema = z.object({\n kind: z.literal(\"string_list\"),\n items: z.array(z.string()),\n});\n\nexport const CheckboxesValueSchema = z.object({\n kind: z.literal(\"checkboxes\"),\n values: z.record(OptionIdSchema, CheckboxValueSchema),\n});\n\nexport const SingleSelectValueSchema = z.object({\n kind: z.literal(\"single_select\"),\n selected: OptionIdSchema.nullable(),\n});\n\nexport const MultiSelectValueSchema = z.object({\n kind: z.literal(\"multi_select\"),\n selected: z.array(OptionIdSchema),\n});\n\nexport const FieldValueSchema = z.discriminatedUnion(\"kind\", [\n StringValueSchema,\n NumberValueSchema,\n StringListValueSchema,\n CheckboxesValueSchema,\n SingleSelectValueSchema,\n MultiSelectValueSchema,\n]);\n\n// Documentation block schema\nexport const DocumentationTagSchema = z.enum([\n \"description\",\n \"instructions\",\n \"documentation\",\n]);\n\nexport const DocumentationBlockSchema = z.object({\n tag: DocumentationTagSchema,\n ref: z.string(),\n bodyMarkdown: z.string(),\n});\n\n// Form metadata schema\nexport const FormMetadataSchema = z.object({\n markformVersion: z.string(),\n roles: z.array(z.string()).min(1),\n roleInstructions: z.record(z.string(), z.string()),\n});\n\n// Validation schemas\nexport const SeveritySchema = z.enum([\"error\", \"warning\", \"info\"]);\n\nexport const SourcePositionSchema = z.object({\n line: z.number().int().positive(),\n col: z.number().int().positive(),\n});\n\nexport const SourceRangeSchema = z.object({\n start: SourcePositionSchema,\n end: SourcePositionSchema,\n});\n\nexport const ValidationIssueSchema = z.object({\n severity: SeveritySchema,\n message: z.string(),\n code: z.string().optional(),\n ref: IdSchema.optional(),\n path: z.string().optional(),\n range: SourceRangeSchema.optional(),\n validatorId: z.string().optional(),\n source: z.enum([\"builtin\", \"code\", \"llm\"]),\n});\n\n// Inspect issue schema\nexport const IssueReasonSchema = z.enum([\n \"validation_error\",\n \"required_missing\",\n \"checkbox_incomplete\",\n \"min_items_not_met\",\n \"optional_empty\",\n]);\n\nexport const IssueScopeSchema = z.enum([\n \"form\",\n \"group\",\n \"field\",\n \"option\",\n]);\n\nexport const InspectIssueSchema = z.object({\n ref: z.union([IdSchema, z.string()]), // Id or QualifiedOptionRef\n scope: IssueScopeSchema,\n reason: IssueReasonSchema,\n message: z.string(),\n severity: z.enum([\"required\", \"recommended\"]),\n priority: z.number().int().positive(),\n blockedBy: IdSchema.optional(),\n});\n\n// Summary schemas\nexport const ProgressStateSchema = z.enum([\n \"empty\",\n \"incomplete\",\n \"invalid\",\n \"complete\",\n]);\n\nexport const CheckboxProgressCountsSchema = z.object({\n total: z.number().int().nonnegative(),\n // Multi mode\n todo: z.number().int().nonnegative(),\n done: z.number().int().nonnegative(),\n incomplete: z.number().int().nonnegative(),\n active: z.number().int().nonnegative(),\n na: z.number().int().nonnegative(),\n // Explicit mode\n unfilled: z.number().int().nonnegative(),\n yes: z.number().int().nonnegative(),\n no: z.number().int().nonnegative(),\n});\n\nexport const FieldProgressSchema = z.object({\n kind: FieldKindSchema,\n required: z.boolean(),\n submitted: z.boolean(),\n state: ProgressStateSchema,\n valid: z.boolean(),\n issueCount: z.number().int().nonnegative(),\n checkboxProgress: CheckboxProgressCountsSchema.optional(),\n});\n\nexport const ProgressCountsSchema = z.object({\n totalFields: z.number().int().nonnegative(),\n requiredFields: z.number().int().nonnegative(),\n submittedFields: z.number().int().nonnegative(),\n completeFields: z.number().int().nonnegative(),\n incompleteFields: z.number().int().nonnegative(),\n invalidFields: z.number().int().nonnegative(),\n emptyRequiredFields: z.number().int().nonnegative(),\n emptyOptionalFields: z.number().int().nonnegative(),\n});\n\nexport const ProgressSummarySchema = z.object({\n counts: ProgressCountsSchema,\n fields: z.record(IdSchema, FieldProgressSchema),\n});\n\nexport const StructureSummarySchema = z.object({\n groupCount: z.number().int().nonnegative(),\n fieldCount: z.number().int().nonnegative(),\n optionCount: z.number().int().nonnegative(),\n fieldCountByKind: z.record(FieldKindSchema, z.number().int().nonnegative()),\n groupsById: z.record(IdSchema, z.literal(\"field_group\")),\n fieldsById: z.record(IdSchema, FieldKindSchema),\n optionsById: z.record(\n z.string(),\n z.object({\n parentFieldId: IdSchema,\n parentFieldKind: FieldKindSchema,\n })\n ),\n});\n\n// Result schemas\nexport const InspectResultSchema = z.object({\n structureSummary: StructureSummarySchema,\n progressSummary: ProgressSummarySchema,\n issues: z.array(InspectIssueSchema),\n isComplete: z.boolean(),\n formState: ProgressStateSchema,\n});\n\nexport const ApplyResultSchema = z.object({\n applyStatus: z.enum([\"applied\", \"rejected\"]),\n structureSummary: StructureSummarySchema,\n progressSummary: ProgressSummarySchema,\n issues: z.array(InspectIssueSchema),\n isComplete: z.boolean(),\n formState: ProgressStateSchema,\n});\n\n// Patch schemas\nexport const SetStringPatchSchema = z.object({\n op: z.literal(\"set_string\"),\n fieldId: IdSchema,\n value: z.string().nullable(),\n});\n\nexport const SetNumberPatchSchema = z.object({\n op: z.literal(\"set_number\"),\n fieldId: IdSchema,\n value: z.number().nullable(),\n});\n\nexport const SetStringListPatchSchema = z.object({\n op: z.literal(\"set_string_list\"),\n fieldId: IdSchema,\n items: z.array(z.string()),\n});\n\nexport const SetCheckboxesPatchSchema = z.object({\n op: z.literal(\"set_checkboxes\"),\n fieldId: IdSchema,\n values: z.record(OptionIdSchema, CheckboxValueSchema),\n});\n\nexport const SetSingleSelectPatchSchema = z.object({\n op: z.literal(\"set_single_select\"),\n fieldId: IdSchema,\n selected: OptionIdSchema.nullable(),\n});\n\nexport const SetMultiSelectPatchSchema = z.object({\n op: z.literal(\"set_multi_select\"),\n fieldId: IdSchema,\n selected: z.array(OptionIdSchema),\n});\n\nexport const ClearFieldPatchSchema = z.object({\n op: z.literal(\"clear_field\"),\n fieldId: IdSchema,\n});\n\nexport const PatchSchema = z.discriminatedUnion(\"op\", [\n SetStringPatchSchema,\n SetNumberPatchSchema,\n SetStringListPatchSchema,\n SetCheckboxesPatchSchema,\n SetSingleSelectPatchSchema,\n SetMultiSelectPatchSchema,\n ClearFieldPatchSchema,\n]);\n\n// Harness schemas\nexport const StepResultSchema = z.object({\n structureSummary: StructureSummarySchema,\n progressSummary: ProgressSummarySchema,\n issues: z.array(InspectIssueSchema),\n stepBudget: z.number().int().nonnegative(),\n isComplete: z.boolean(),\n turnNumber: z.number().int().positive(),\n});\n\n// Session transcript schemas\nexport const HarnessConfigSchema = z.object({\n maxIssues: z.number().int().positive(),\n maxPatchesPerTurn: z.number().int().positive(),\n maxTurns: z.number().int().positive(),\n maxFieldsPerTurn: z.number().int().positive().optional(),\n maxGroupsPerTurn: z.number().int().positive().optional(),\n targetRoles: z.array(z.string()).optional(),\n fillMode: FillModeSchema.optional(),\n});\n\nexport const SessionTurnSchema = z.object({\n turn: z.number().int().positive(),\n inspect: z.object({\n issues: z.array(InspectIssueSchema),\n }),\n apply: z.object({\n patches: z.array(PatchSchema),\n }),\n after: z.object({\n requiredIssueCount: z.number().int().nonnegative(),\n markdownSha256: z.string(),\n }),\n});\n\nexport const SessionFinalSchema = z.object({\n expectComplete: z.boolean(),\n expectedCompletedForm: z.string(),\n});\n\nexport const SessionTranscriptSchema = z.object({\n sessionVersion: z.string(),\n mode: z.enum([\"mock\", \"live\"]),\n form: z.object({\n path: z.string(),\n }),\n validators: z\n .object({\n code: z.string().optional(),\n })\n .optional(),\n mock: z\n .object({\n completedMock: z.string(),\n })\n .optional(),\n live: z\n .object({\n modelId: z.string(),\n })\n .optional(),\n harness: HarnessConfigSchema,\n turns: z.array(SessionTurnSchema),\n final: SessionFinalSchema,\n});\n\n// Frontmatter schema\nexport const MarkformFrontmatterSchema = z.object({\n markformVersion: z.string(),\n formSummary: StructureSummarySchema,\n formProgress: ProgressSummarySchema,\n formState: ProgressStateSchema,\n});\n","/**\n * Global settings and constants for Markform.\n *\n * This file consolidates non-changing default values that were previously\n * scattered across the codebase. These are NOT runtime configurable - they\n * are compile-time constants.\n */\n\nimport type { FieldPriorityLevel } from \"./engine/coreTypes.js\";\n\n// =============================================================================\n// Role System Constants\n// =============================================================================\n\n/** Default role for fields without explicit role attribute */\nexport const AGENT_ROLE = \"agent\" as const;\n\n/** Role for human-filled fields in interactive mode */\nexport const USER_ROLE = \"user\" as const;\n\n/** Default roles list for forms without explicit roles in frontmatter */\nexport const DEFAULT_ROLES: readonly [typeof USER_ROLE, typeof AGENT_ROLE] = [\n USER_ROLE,\n AGENT_ROLE,\n] as const;\n\n/** Default instructions per role (used when form doesn't specify role_instructions) */\nexport const DEFAULT_ROLE_INSTRUCTIONS: Record<string, string> = {\n [USER_ROLE]: \"Fill in the fields you have direct knowledge of.\",\n [AGENT_ROLE]: \"Complete the remaining fields based on the provided context.\",\n};\n\n/** Pattern for valid role names: starts with letter, alphanumeric with underscores/hyphens */\nexport const ROLE_NAME_PATTERN = /^[a-z][a-z0-9_-]*$/;\n\n/** Reserved role identifiers (not allowed as role names in forms) */\nexport const RESERVED_ROLE_NAMES = [\"*\"] as const;\n\n/**\n * Normalize a role name: trim whitespace, lowercase.\n * Throws if invalid pattern or reserved name.\n */\nexport function normalizeRole(role: string): string {\n const normalized = role.trim().toLowerCase();\n if (!ROLE_NAME_PATTERN.test(normalized)) {\n throw new Error(\n `Invalid role name: \"${role}\" (must match pattern: start with letter, alphanumeric with underscores/hyphens)`\n );\n }\n if ((RESERVED_ROLE_NAMES as readonly string[]).includes(normalized)) {\n throw new Error(`Reserved role name: \"${role}\"`);\n }\n return normalized;\n}\n\n/**\n * Parse --roles CLI flag value into normalized role array.\n * Handles comma-separated values and '*' wildcard.\n */\nexport function parseRolesFlag(raw: string): string[] {\n if (raw === \"*\") {\n return [\"*\"];\n }\n return raw.split(\",\").map((r) => normalizeRole(r));\n}\n\n// =============================================================================\n// Field Defaults\n// =============================================================================\n\n/**\n * The default priority level for fields when not explicitly specified.\n * Used by the parser to set default values and by the serializer to\n * determine whether to emit the priority attribute.\n */\nexport const DEFAULT_PRIORITY: FieldPriorityLevel = \"medium\";\n\n// =============================================================================\n// CLI Defaults\n// =============================================================================\n\n/**\n * The default port for the serve command.\n */\nexport const DEFAULT_PORT = 3344;\n\n// =============================================================================\n// Harness Defaults\n// =============================================================================\n\n/**\n * Default maximum turns for the fill harness.\n * Prevents runaway loops during agent execution.\n */\nexport const DEFAULT_MAX_TURNS = 100;\n\n/**\n * Default maximum patches per turn.\n */\nexport const DEFAULT_MAX_PATCHES_PER_TURN = 20;\n\n/**\n * Default maximum issues to show per step.\n */\nexport const DEFAULT_MAX_ISSUES = 10;\n\n// =============================================================================\n// LLM Suggestions\n// =============================================================================\n\n/**\n * Suggested LLM models for the fill command, organized by provider.\n * These are shown in help/error messages. Only includes models from the\n * authoritative models.yaml configuration.\n */\nexport const SUGGESTED_LLMS: Record<string, string[]> = {\n openai: [\n \"gpt-5-mini\",\n \"gpt-5-nano\",\n \"gpt-5.1\",\n \"gpt-5-pro\",\n \"gpt-5.2\",\n \"gpt-5.2-pro\",\n ],\n anthropic: [\n \"claude-opus-4-5\",\n \"claude-opus-4-1\",\n \"claude-sonnet-4-5\",\n \"claude-sonnet-4-0\",\n \"claude-haiku-4-5\",\n ],\n google: [\n \"gemini-2.5-pro\",\n \"gemini-2.5-flash\",\n \"gemini-2.0-flash\",\n \"gemini-2.0-flash-lite\",\n \"gemini-3-pro-preview\",\n ],\n xai: [\"grok-4\", \"grok-4-fast\"],\n deepseek: [\"deepseek-chat\", \"deepseek-reasoner\"],\n};\n\n/**\n * Format suggested LLMs for display in help/error messages.\n */\nexport function formatSuggestedLlms(): string {\n const lines: string[] = [\"Available providers and example models:\"];\n for (const [provider, models] of Object.entries(SUGGESTED_LLMS)) {\n lines.push(` ${provider}/`);\n for (const model of models) {\n lines.push(` - ${provider}/${model}`);\n }\n }\n return lines.join(\"\\n\");\n}\n","/**\n * Canonical serializer for .form.md files.\n *\n * Serializes a ParsedForm back to a Markdoc markdown document.\n * The output is deterministic and suitable for round-trip testing.\n */\n\nimport type {\n CheckboxesField,\n CheckboxesValue,\n CheckboxValue,\n DocumentationBlock,\n Field,\n FieldGroup,\n FieldValue,\n FormSchema,\n Id,\n MultiSelectField,\n MultiSelectValue,\n NumberField,\n NumberValue,\n Option,\n ParsedForm,\n SingleSelectField,\n SingleSelectValue,\n StringField,\n StringListField,\n StringListValue,\n StringValue,\n} from \"./coreTypes.js\";\nimport { AGENT_ROLE, DEFAULT_PRIORITY } from \"../settings.js\";\n\n// =============================================================================\n// Options\n// =============================================================================\n\nexport interface SerializeOptions {\n /** Markform version to use in frontmatter. Defaults to \"0.1.0\". */\n markformVersion?: string;\n}\n\n// =============================================================================\n// Attribute Serialization\n// =============================================================================\n\n/**\n * Serialize an attribute value to Markdoc format.\n */\nfunction serializeAttrValue(value: unknown): string {\n if (typeof value === \"string\") {\n // Escape backslashes and quotes\n const escaped = value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n return `\"${escaped}\"`;\n }\n if (typeof value === \"number\") {\n return String(value);\n }\n if (typeof value === \"boolean\") {\n return value ? \"true\" : \"false\";\n }\n if (value === null) {\n return \"null\";\n }\n if (Array.isArray(value)) {\n const items = value.map((v) => serializeAttrValue(v)).join(\", \");\n return `[${items}]`;\n }\n if (typeof value === \"object\") {\n // Serialize plain objects as Markdoc object literals: {key: value, key2: value2}\n const entries = Object.entries(value as Record<string, unknown>);\n const parts = entries.map(([k, v]) => `${k}: ${serializeAttrValue(v)}`);\n return `{${parts.join(\", \")}}`;\n }\n // Handle remaining primitive types (bigint, symbol, undefined, function)\n // These shouldn't appear in form attributes but handle gracefully\n if (typeof value === \"bigint\") {\n return String(value);\n }\n if (typeof value === \"undefined\") {\n return \"null\";\n }\n // For functions and symbols, throw - these are invalid in form attributes\n throw new Error(`Cannot serialize value of type ${typeof value} to Markdoc`);\n}\n\n/**\n * Serialize attributes to Markdoc format with alphabetical ordering.\n */\nfunction serializeAttrs(attrs: Record<string, unknown>): string {\n const keys = Object.keys(attrs).sort();\n const parts: string[] = [];\n\n for (const key of keys) {\n const value = attrs[key];\n if (value !== undefined) {\n parts.push(`${key}=${serializeAttrValue(value)}`);\n }\n }\n\n return parts.join(\" \");\n}\n\n// =============================================================================\n// Checkbox Marker Serialization\n// =============================================================================\n\n/** Map checkbox state to marker character */\nconst STATE_TO_MARKER: Record<CheckboxValue, string> = {\n // Multi mode\n todo: \" \",\n done: \"x\",\n incomplete: \"/\",\n active: \"*\",\n na: \"-\",\n // Explicit mode\n unfilled: \" \",\n yes: \"y\",\n no: \"n\",\n};\n\n/**\n * Get the checkbox marker for a state.\n */\nfunction getMarker(state: CheckboxValue): string {\n return STATE_TO_MARKER[state] ?? \" \";\n}\n\n// =============================================================================\n// Field Serialization\n// =============================================================================\n\n/**\n * Serialize a string field.\n */\nfunction serializeStringField(\n field: StringField,\n value: StringValue | undefined,\n): string {\n const attrs: Record<string, unknown> = { id: field.id, label: field.label };\n if (field.required) {\n attrs.required = field.required;\n }\n if (field.priority !== DEFAULT_PRIORITY) {\n attrs.priority = field.priority;\n }\n if (field.role !== AGENT_ROLE) {\n attrs.role = field.role;\n }\n if (field.multiline) {\n attrs.multiline = field.multiline;\n }\n if (field.pattern) {\n attrs.pattern = field.pattern;\n }\n if (field.minLength !== undefined) {\n attrs.minLength = field.minLength;\n }\n if (field.maxLength !== undefined) {\n attrs.maxLength = field.maxLength;\n }\n if (field.validate) {\n attrs.validate = field.validate;\n }\n\n const attrStr = serializeAttrs(attrs);\n let content = \"\";\n\n if (value?.value) {\n content = `\\n\\`\\`\\`value\\n${value.value}\\n\\`\\`\\`\\n`;\n }\n\n return `{% string-field ${attrStr} %}${content}{% /string-field %}`;\n}\n\n/**\n * Serialize a number field.\n */\nfunction serializeNumberField(\n field: NumberField,\n value: NumberValue | undefined,\n): string {\n const attrs: Record<string, unknown> = { id: field.id, label: field.label };\n if (field.required) {\n attrs.required = field.required;\n }\n if (field.priority !== DEFAULT_PRIORITY) {\n attrs.priority = field.priority;\n }\n if (field.role !== AGENT_ROLE) {\n attrs.role = field.role;\n }\n if (field.min !== undefined) {\n attrs.min = field.min;\n }\n if (field.max !== undefined) {\n attrs.max = field.max;\n }\n if (field.integer) {\n attrs.integer = field.integer;\n }\n if (field.validate) {\n attrs.validate = field.validate;\n }\n\n const attrStr = serializeAttrs(attrs);\n let content = \"\";\n\n if (value?.value !== null && value?.value !== undefined) {\n content = `\\n\\`\\`\\`value\\n${value.value}\\n\\`\\`\\`\\n`;\n }\n\n return `{% number-field ${attrStr} %}${content}{% /number-field %}`;\n}\n\n/**\n * Serialize a string-list field.\n */\nfunction serializeStringListField(\n field: StringListField,\n value: StringListValue | undefined,\n): string {\n const attrs: Record<string, unknown> = { id: field.id, label: field.label };\n if (field.required) {\n attrs.required = field.required;\n }\n if (field.priority !== DEFAULT_PRIORITY) {\n attrs.priority = field.priority;\n }\n if (field.role !== AGENT_ROLE) {\n attrs.role = field.role;\n }\n if (field.minItems !== undefined) {\n attrs.minItems = field.minItems;\n }\n if (field.maxItems !== undefined) {\n attrs.maxItems = field.maxItems;\n }\n if (field.itemMinLength !== undefined) {\n attrs.itemMinLength = field.itemMinLength;\n }\n if (field.itemMaxLength !== undefined) {\n attrs.itemMaxLength = field.itemMaxLength;\n }\n if (field.uniqueItems) {\n attrs.uniqueItems = field.uniqueItems;\n }\n if (field.validate) {\n attrs.validate = field.validate;\n }\n\n const attrStr = serializeAttrs(attrs);\n let content = \"\";\n\n if (value?.items && value.items.length > 0) {\n content = `\\n\\`\\`\\`value\\n${value.items.join(\"\\n\")}\\n\\`\\`\\`\\n`;\n }\n\n return `{% string-list ${attrStr} %}${content}{% /string-list %}`;\n}\n\n/**\n * Serialize options (for single-select, multi-select, checkboxes).\n */\nfunction serializeOptions(\n options: Option[],\n selected: Record<string, CheckboxValue>,\n): string {\n const lines: string[] = [];\n\n for (const opt of options) {\n const state = selected[opt.id] ?? \"todo\";\n const marker = getMarker(state);\n lines.push(`- [${marker}] ${opt.label} {% #${opt.id} %}`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Serialize a single-select field.\n */\nfunction serializeSingleSelectField(\n field: SingleSelectField,\n value: SingleSelectValue | undefined,\n): string {\n const attrs: Record<string, unknown> = { id: field.id, label: field.label };\n if (field.required) {\n attrs.required = field.required;\n }\n if (field.priority !== DEFAULT_PRIORITY) {\n attrs.priority = field.priority;\n }\n if (field.role !== AGENT_ROLE) {\n attrs.role = field.role;\n }\n if (field.validate) {\n attrs.validate = field.validate;\n }\n\n const attrStr = serializeAttrs(attrs);\n\n // Convert selected to checkbox state format\n const selected: Record<string, CheckboxValue> = {};\n for (const opt of field.options) {\n selected[opt.id] = opt.id === value?.selected ? \"done\" : \"todo\";\n }\n\n const options = serializeOptions(field.options, selected);\n return `{% single-select ${attrStr} %}\\n${options}\\n{% /single-select %}`;\n}\n\n/**\n * Serialize a multi-select field.\n */\nfunction serializeMultiSelectField(\n field: MultiSelectField,\n value: MultiSelectValue | undefined,\n): string {\n const attrs: Record<string, unknown> = { id: field.id, label: field.label };\n if (field.required) {\n attrs.required = field.required;\n }\n if (field.priority !== DEFAULT_PRIORITY) {\n attrs.priority = field.priority;\n }\n if (field.role !== AGENT_ROLE) {\n attrs.role = field.role;\n }\n if (field.minSelections !== undefined) {\n attrs.minSelections = field.minSelections;\n }\n if (field.maxSelections !== undefined) {\n attrs.maxSelections = field.maxSelections;\n }\n if (field.validate) {\n attrs.validate = field.validate;\n }\n\n const attrStr = serializeAttrs(attrs);\n\n // Convert selected to checkbox state format\n const selected: Record<string, CheckboxValue> = {};\n const selectedSet = new Set(value?.selected ?? []);\n for (const opt of field.options) {\n selected[opt.id] = selectedSet.has(opt.id) ? \"done\" : \"todo\";\n }\n\n const options = serializeOptions(field.options, selected);\n return `{% multi-select ${attrStr} %}\\n${options}\\n{% /multi-select %}`;\n}\n\n/**\n * Serialize a checkboxes field.\n */\nfunction serializeCheckboxesField(\n field: CheckboxesField,\n value: CheckboxesValue | undefined,\n): string {\n const attrs: Record<string, unknown> = { id: field.id, label: field.label };\n if (field.required) {\n attrs.required = field.required;\n }\n if (field.priority !== DEFAULT_PRIORITY) {\n attrs.priority = field.priority;\n }\n if (field.role !== AGENT_ROLE) {\n attrs.role = field.role;\n }\n if (field.checkboxMode !== \"multi\") {\n attrs.checkboxMode = field.checkboxMode;\n }\n if (field.minDone !== undefined) {\n attrs.minDone = field.minDone;\n }\n if (field.approvalMode !== \"none\") {\n attrs.approvalMode = field.approvalMode;\n }\n if (field.validate) {\n attrs.validate = field.validate;\n }\n\n const attrStr = serializeAttrs(attrs);\n\n const options = serializeOptions(field.options, value?.values ?? {});\n return `{% checkboxes ${attrStr} %}\\n${options}\\n{% /checkboxes %}`;\n}\n\n/**\n * Serialize a field to Markdoc format.\n */\nfunction serializeField(field: Field, values: Record<Id, FieldValue>): string {\n const value = values[field.id];\n\n switch (field.kind) {\n case \"string\":\n return serializeStringField(field, value as StringValue | undefined);\n case \"number\":\n return serializeNumberField(field, value as NumberValue | undefined);\n case \"string_list\":\n return serializeStringListField(\n field,\n value as StringListValue | undefined,\n );\n case \"single_select\":\n return serializeSingleSelectField(\n field,\n value as SingleSelectValue | undefined,\n );\n case \"multi_select\":\n return serializeMultiSelectField(\n field,\n value as MultiSelectValue | undefined,\n );\n case \"checkboxes\":\n return serializeCheckboxesField(\n field,\n value as CheckboxesValue | undefined,\n );\n }\n}\n\n// =============================================================================\n// Doc Block Serialization\n// =============================================================================\n\n/**\n * Serialize a documentation block.\n * Uses the semantic tag name (description, instructions, documentation).\n */\nfunction serializeDocBlock(doc: DocumentationBlock): string {\n const attrs: Record<string, unknown> = { ref: doc.ref };\n const attrStr = serializeAttrs(attrs);\n return `{% ${doc.tag} ${attrStr} %}\\n${doc.bodyMarkdown}\\n{% /${doc.tag} %}`;\n}\n\n// =============================================================================\n// Group and Form Serialization\n// =============================================================================\n\n/**\n * Serialize a field group.\n */\nfunction serializeFieldGroup(\n group: FieldGroup,\n values: Record<Id, FieldValue>,\n docs: DocumentationBlock[],\n): string {\n const attrs: Record<string, unknown> = { id: group.id };\n if (group.title) {\n attrs.title = group.title;\n }\n if (group.validate) {\n attrs.validate = group.validate;\n }\n\n const attrStr = serializeAttrs(attrs);\n const lines: string[] = [`{% field-group ${attrStr} %}`];\n\n // Group doc blocks by ref\n const docsByRef = new Map<string, DocumentationBlock[]>();\n for (const doc of docs) {\n const list = docsByRef.get(doc.ref) ?? [];\n list.push(doc);\n docsByRef.set(doc.ref, list);\n }\n\n for (const field of group.children) {\n lines.push(\"\");\n lines.push(serializeField(field, values));\n\n // Add any doc blocks for this field\n const fieldDocs = docsByRef.get(field.id);\n if (fieldDocs) {\n for (const doc of fieldDocs) {\n lines.push(\"\");\n lines.push(serializeDocBlock(doc));\n }\n }\n }\n\n lines.push(\"\");\n lines.push(\"{% /field-group %}\");\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Serialize a form schema.\n */\nfunction serializeFormSchema(\n schema: FormSchema,\n values: Record<Id, FieldValue>,\n docs: DocumentationBlock[],\n): string {\n const attrs: Record<string, unknown> = { id: schema.id };\n if (schema.title) {\n attrs.title = schema.title;\n }\n\n const attrStr = serializeAttrs(attrs);\n const lines: string[] = [`{% form ${attrStr} %}`];\n\n // Group doc blocks by ref\n const docsByRef = new Map<string, DocumentationBlock[]>();\n for (const doc of docs) {\n const list = docsByRef.get(doc.ref) ?? [];\n list.push(doc);\n docsByRef.set(doc.ref, list);\n }\n\n // Add form-level doc blocks\n const formDocs = docsByRef.get(schema.id);\n if (formDocs) {\n for (const doc of formDocs) {\n lines.push(\"\");\n lines.push(serializeDocBlock(doc));\n }\n }\n\n for (const group of schema.groups) {\n lines.push(\"\");\n lines.push(serializeFieldGroup(group, values, docs));\n }\n\n lines.push(\"\");\n lines.push(\"{% /form %}\");\n\n return lines.join(\"\\n\");\n}\n\n// =============================================================================\n// Main Serializer\n// =============================================================================\n\n/**\n * Serialize a ParsedForm to canonical Markdoc markdown format.\n *\n * @param form - The parsed form to serialize\n * @param opts - Serialization options\n * @returns The canonical markdown string\n */\nexport function serialize(form: ParsedForm, opts?: SerializeOptions): string {\n const version = opts?.markformVersion ?? \"0.1.0\";\n\n // Build frontmatter\n const frontmatter = `---\nmarkform:\n markform_version: \"${version}\"\n---`;\n\n // Serialize form body\n const body = serializeFormSchema(\n form.schema,\n form.valuesByFieldId,\n form.docs,\n );\n\n return `${frontmatter}\\n\\n${body}\\n`;\n}\n\n// =============================================================================\n// Raw Markdown Serialization (human-readable, no markdoc)\n// =============================================================================\n\n/** Map checkbox state to GFM marker for raw markdown output */\nconst STATE_TO_GFM_MARKER: Record<CheckboxValue, string> = {\n // Multi mode\n todo: \" \",\n done: \"x\",\n incomplete: \"/\",\n active: \"*\",\n na: \"-\",\n // Explicit mode\n unfilled: \" \",\n yes: \"x\",\n no: \" \",\n};\n\n/**\n * Serialize a field value to raw markdown (human-readable).\n */\nfunction serializeFieldRaw(\n field: Field,\n values: Record<Id, FieldValue>,\n): string {\n const value = values[field.id];\n const lines: string[] = [];\n\n lines.push(`**${field.label}:**`);\n\n switch (field.kind) {\n case \"string\": {\n const strValue = value as StringValue | undefined;\n if (strValue?.value) {\n lines.push(strValue.value);\n } else {\n lines.push(\"_(empty)_\");\n }\n break;\n }\n case \"number\": {\n const numValue = value as NumberValue | undefined;\n if (numValue?.value !== null && numValue?.value !== undefined) {\n lines.push(String(numValue.value));\n } else {\n lines.push(\"_(empty)_\");\n }\n break;\n }\n case \"string_list\": {\n const listValue = value as StringListValue | undefined;\n if (listValue?.items && listValue.items.length > 0) {\n for (const item of listValue.items) {\n lines.push(`- ${item}`);\n }\n } else {\n lines.push(\"_(empty)_\");\n }\n break;\n }\n case \"single_select\": {\n const selectValue = value as SingleSelectValue | undefined;\n const selected = field.options.find(\n (opt) => opt.id === selectValue?.selected,\n );\n if (selected) {\n lines.push(selected.label);\n } else {\n lines.push(\"_(none selected)_\");\n }\n break;\n }\n case \"multi_select\": {\n const multiValue = value as MultiSelectValue | undefined;\n const selectedSet = new Set(multiValue?.selected ?? []);\n const selectedOpts = field.options.filter((opt) =>\n selectedSet.has(opt.id),\n );\n if (selectedOpts.length > 0) {\n for (const opt of selectedOpts) {\n lines.push(`- ${opt.label}`);\n }\n } else {\n lines.push(\"_(none selected)_\");\n }\n break;\n }\n case \"checkboxes\": {\n const cbValue = value as CheckboxesValue | undefined;\n for (const opt of field.options) {\n const state = cbValue?.values[opt.id] ?? \"todo\";\n const marker = STATE_TO_GFM_MARKER[state] ?? \" \";\n lines.push(`- [${marker}] ${opt.label}`);\n }\n break;\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Serialize a ParsedForm to plain, human-readable markdown.\n *\n * This output does NOT contain markdoc directives and cannot be parsed back\n * into a form. It's intended for human consumption and export.\n *\n * @param form - The parsed form to serialize\n * @returns Plain markdown string\n */\nexport function serializeRawMarkdown(form: ParsedForm): string {\n const lines: string[] = [];\n\n // Group doc blocks by ref\n const docsByRef = new Map<string, DocumentationBlock[]>();\n for (const doc of form.docs) {\n const list = docsByRef.get(doc.ref) ?? [];\n list.push(doc);\n docsByRef.set(doc.ref, list);\n }\n\n // Add form title\n if (form.schema.title) {\n lines.push(`# ${form.schema.title}`);\n lines.push(\"\");\n }\n\n // Add form-level docs\n const formDocs = docsByRef.get(form.schema.id);\n if (formDocs) {\n for (const doc of formDocs) {\n lines.push(doc.bodyMarkdown.trim());\n lines.push(\"\");\n }\n }\n\n // Process each group\n for (const group of form.schema.groups) {\n // Add group title as H2\n if (group.title) {\n lines.push(`## ${group.title}`);\n lines.push(\"\");\n }\n\n // Add group-level docs\n const groupDocs = docsByRef.get(group.id);\n if (groupDocs) {\n for (const doc of groupDocs) {\n lines.push(doc.bodyMarkdown.trim());\n lines.push(\"\");\n }\n }\n\n // Process fields\n for (const field of group.children) {\n lines.push(serializeFieldRaw(field, form.valuesByFieldId));\n lines.push(\"\");\n\n // Add field-level docs\n const fieldDocs = docsByRef.get(field.id);\n if (fieldDocs) {\n for (const doc of fieldDocs) {\n lines.push(doc.bodyMarkdown.trim());\n lines.push(\"\");\n }\n }\n }\n }\n\n return lines.join(\"\\n\").trim() + \"\\n\";\n}\n","/**\n * Summary computation for Markform documents.\n *\n * Computes structure and progress summaries from parsed forms.\n */\n\nimport type {\n CheckboxesField,\n CheckboxesValue,\n CheckboxProgressCounts,\n Field,\n FieldKind,\n FieldProgress,\n FieldValue,\n FormSchema,\n Id,\n InspectIssue,\n MultiSelectValue,\n NumberValue,\n ProgressCounts,\n ProgressState,\n ProgressSummary,\n QualifiedOptionRef,\n SingleSelectValue,\n StringListValue,\n StringValue,\n StructureSummary,\n} from \"./coreTypes.js\";\n\n// =============================================================================\n// Structure Summary Computation\n// =============================================================================\n\n/**\n * Compute a structure summary from a form schema.\n *\n * @param schema - The form schema to summarize\n * @returns Structure summary with counts and indices\n */\nexport function computeStructureSummary(schema: FormSchema): StructureSummary {\n const fieldCountByKind: Record<FieldKind, number> = {\n string: 0,\n number: 0,\n string_list: 0,\n checkboxes: 0,\n single_select: 0,\n multi_select: 0,\n };\n\n const groupsById: Record<Id, \"field_group\"> = {};\n const fieldsById: Record<Id, FieldKind> = {};\n const optionsById: Record<\n QualifiedOptionRef,\n { parentFieldId: Id; parentFieldKind: FieldKind }\n > = {};\n\n let groupCount = 0;\n let fieldCount = 0;\n let optionCount = 0;\n\n for (const group of schema.groups) {\n groupCount++;\n groupsById[group.id] = \"field_group\";\n\n for (const field of group.children) {\n fieldCount++;\n fieldCountByKind[field.kind]++;\n fieldsById[field.id] = field.kind;\n\n // Count options for select/checkbox fields\n if (\"options\" in field) {\n for (const opt of field.options) {\n optionCount++;\n const qualifiedRef: QualifiedOptionRef = `${field.id}.${opt.id}`;\n optionsById[qualifiedRef] = {\n parentFieldId: field.id,\n parentFieldKind: field.kind,\n };\n }\n }\n }\n }\n\n return {\n groupCount,\n fieldCount,\n optionCount,\n fieldCountByKind,\n groupsById,\n fieldsById,\n optionsById,\n };\n}\n\n// =============================================================================\n// Field Progress Computation\n// =============================================================================\n\n/**\n * Determine if a field value is \"submitted\" (has some user input).\n */\nfunction isFieldSubmitted(field: Field, value: FieldValue | undefined): boolean {\n if (!value) {\n return false;\n }\n\n switch (field.kind) {\n case \"string\": {\n const v = value as StringValue;\n return v.value !== null && v.value.trim() !== \"\";\n }\n case \"number\": {\n const v = value as NumberValue;\n return v.value !== null;\n }\n case \"string_list\": {\n const v = value as StringListValue;\n return v.items.length > 0;\n }\n case \"single_select\": {\n const v = value as SingleSelectValue;\n return v.selected !== null;\n }\n case \"multi_select\": {\n const v = value as MultiSelectValue;\n return v.selected.length > 0;\n }\n case \"checkboxes\": {\n const v = value as CheckboxesValue;\n const checkboxField = field;\n // For checkboxes, check if any option has been changed from default\n const mode = checkboxField.checkboxMode ?? \"multi\";\n\n for (const opt of checkboxField.options) {\n const state = v.values[opt.id];\n if (mode === \"explicit\") {\n // In explicit mode, \"unfilled\" is default, anything else is submitted\n if (state !== \"unfilled\") {\n return true;\n }\n } else {\n // In multi/simple mode, \"todo\" is default, anything else is submitted\n if (state !== \"todo\") {\n return true;\n }\n }\n }\n return false;\n }\n }\n}\n\n/**\n * Compute checkbox progress counts for a checkboxes field.\n */\nfunction computeCheckboxProgress(\n field: CheckboxesField,\n value: CheckboxesValue | undefined\n): CheckboxProgressCounts {\n const result: CheckboxProgressCounts = {\n total: field.options.length,\n todo: 0,\n done: 0,\n incomplete: 0,\n active: 0,\n na: 0,\n unfilled: 0,\n yes: 0,\n no: 0,\n };\n\n if (!value) {\n // All options in default state\n const defaultState = field.checkboxMode === \"explicit\" ? \"unfilled\" : \"todo\";\n for (const _opt of field.options) {\n result[defaultState]++;\n }\n return result;\n }\n\n for (const opt of field.options) {\n const state = value.values[opt.id] ?? \"todo\";\n result[state]++;\n }\n\n return result;\n}\n\n/**\n * Check if a checkboxes field is complete based on its mode.\n */\nfunction isCheckboxesComplete(\n field: CheckboxesField,\n value: CheckboxesValue | undefined\n): boolean {\n if (!value) {\n return false;\n }\n\n const mode = field.checkboxMode ?? \"multi\";\n\n for (const opt of field.options) {\n const state = value.values[opt.id];\n if (mode === \"explicit\") {\n // Explicit mode: must be yes or no (not unfilled)\n if (state === \"unfilled\") {\n return false;\n }\n } else if (mode === \"multi\") {\n // Multi mode: must be done or na (not todo, incomplete, or active)\n if (state === \"todo\" || state === \"incomplete\" || state === \"active\") {\n return false;\n }\n }\n // Simple mode: any state is valid (just checked or unchecked)\n }\n\n return true;\n}\n\n/**\n * Compute the progress state for a field.\n */\nfunction computeFieldState(\n field: Field,\n value: FieldValue | undefined,\n issueCount: number\n): ProgressState {\n const submitted = isFieldSubmitted(field, value);\n\n if (!submitted) {\n return \"empty\";\n }\n\n if (issueCount > 0) {\n return \"invalid\";\n }\n\n // For checkboxes, check if all items are in a \"complete\" state\n if (field.kind === \"checkboxes\" && value?.kind === \"checkboxes\") {\n const checkboxField = field;\n if (!isCheckboxesComplete(checkboxField, value)) {\n return \"incomplete\";\n }\n }\n\n return \"complete\";\n}\n\n/**\n * Compute progress for a single field.\n */\nfunction computeFieldProgress(\n field: Field,\n value: FieldValue | undefined,\n issues: InspectIssue[]\n): FieldProgress {\n const fieldIssues = issues.filter((i) => i.ref === field.id);\n const issueCount = fieldIssues.length;\n const submitted = isFieldSubmitted(field, value);\n const valid = issueCount === 0;\n const state = computeFieldState(field, value, issueCount);\n\n const progress: FieldProgress = {\n kind: field.kind,\n required: field.required,\n submitted,\n state,\n valid,\n issueCount,\n };\n\n // Add checkbox progress for checkboxes fields\n if (field.kind === \"checkboxes\") {\n progress.checkboxProgress = computeCheckboxProgress(\n field,\n value as CheckboxesValue | undefined\n );\n }\n\n return progress;\n}\n\n// =============================================================================\n// Progress Summary Computation\n// =============================================================================\n\n/**\n * Compute a progress summary for a form.\n *\n * @param schema - The form schema\n * @param values - Current field values\n * @param issues - Validation issues (from inspect)\n * @returns Progress summary with field states and counts\n */\nexport function computeProgressSummary(\n schema: FormSchema,\n values: Record<Id, FieldValue>,\n issues: InspectIssue[]\n): ProgressSummary {\n const fields: Record<Id, FieldProgress> = {};\n const counts: ProgressCounts = {\n totalFields: 0,\n requiredFields: 0,\n submittedFields: 0,\n completeFields: 0,\n incompleteFields: 0,\n invalidFields: 0,\n emptyRequiredFields: 0,\n emptyOptionalFields: 0,\n };\n\n for (const group of schema.groups) {\n for (const field of group.children) {\n const value = values[field.id];\n const progress = computeFieldProgress(field, value, issues);\n fields[field.id] = progress;\n\n // Update counts\n counts.totalFields++;\n if (progress.required) {\n counts.requiredFields++;\n }\n if (progress.submitted) {\n counts.submittedFields++;\n }\n if (progress.state === \"complete\") {\n counts.completeFields++;\n }\n if (progress.state === \"incomplete\") {\n counts.incompleteFields++;\n }\n if (progress.state === \"invalid\") {\n counts.invalidFields++;\n }\n if (progress.state === \"empty\") {\n if (progress.required) {\n counts.emptyRequiredFields++;\n } else {\n counts.emptyOptionalFields++;\n }\n }\n }\n }\n\n return { counts, fields };\n}\n\n// =============================================================================\n// Form State Computation\n// =============================================================================\n\n/**\n * Compute the overall form state from progress summary.\n *\n * @param progress - The progress summary\n * @returns The overall form state\n */\nexport function computeFormState(progress: ProgressSummary): ProgressState {\n // If any field is invalid, form is invalid\n if (progress.counts.invalidFields > 0) {\n return \"invalid\";\n }\n\n // If any field is incomplete, form is incomplete\n if (progress.counts.incompleteFields > 0) {\n return \"incomplete\";\n }\n\n // If all required fields are complete and no invalid fields\n if (progress.counts.emptyRequiredFields === 0) {\n return \"complete\";\n }\n\n // If any field is submitted but not all complete\n if (progress.counts.submittedFields > 0) {\n return \"incomplete\";\n }\n\n return \"empty\";\n}\n\n/**\n * Determine if the form is complete (ready for submission).\n *\n * @param progress - The progress summary\n * @returns True if the form is complete\n */\nexport function isFormComplete(progress: ProgressSummary): boolean {\n return (\n progress.counts.invalidFields === 0 &&\n progress.counts.incompleteFields === 0 &&\n progress.counts.emptyRequiredFields === 0\n );\n}\n\n// =============================================================================\n// Helper to compute all summaries at once\n// =============================================================================\n\nexport interface ComputedSummaries {\n structureSummary: StructureSummary;\n progressSummary: ProgressSummary;\n formState: ProgressState;\n isComplete: boolean;\n}\n\n/**\n * Compute all summaries for a parsed form.\n *\n * @param schema - The form schema\n * @param values - Current field values\n * @param issues - Validation issues\n * @returns All computed summaries\n */\nexport function computeAllSummaries(\n schema: FormSchema,\n values: Record<Id, FieldValue>,\n issues: InspectIssue[]\n): ComputedSummaries {\n const structureSummary = computeStructureSummary(schema);\n const progressSummary = computeProgressSummary(schema, values, issues);\n const formState = computeFormState(progressSummary);\n const isComplete = isFormComplete(progressSummary);\n\n return {\n structureSummary,\n progressSummary,\n formState,\n isComplete,\n };\n}\n","/**\n * Validation engine for Markform documents.\n *\n * Runs built-in validators and optional code validators.\n */\n\nimport type {\n CheckboxesField,\n CheckboxesValue,\n Field,\n FieldGroup,\n FieldValue,\n FormSchema,\n Id,\n MultiSelectField,\n MultiSelectValue,\n NumberField,\n NumberValue,\n ParsedForm,\n SingleSelectField,\n SingleSelectValue,\n StringField,\n StringListField,\n StringListValue,\n StringValue,\n ValidationIssue,\n ValidatorContext,\n ValidatorRef,\n ValidatorRegistry,\n} from \"./coreTypes.js\";\n\n// =============================================================================\n// Validation Options and Results\n// =============================================================================\n\nexport interface ValidateOptions {\n /** Skip code validators (only run built-in validation). */\n skipCodeValidators?: boolean;\n /** Custom validator registry (for testing or overrides). */\n validatorRegistry?: ValidatorRegistry;\n}\n\nexport interface ValidateResult {\n /** All validation issues found. */\n issues: ValidationIssue[];\n /** Whether the form is valid (no required-severity issues). */\n isValid: boolean;\n}\n\n// =============================================================================\n// Built-in Validators\n// =============================================================================\n\n/**\n * Validate a string field.\n */\nfunction validateStringField(\n field: StringField,\n value: StringValue | undefined,\n): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const strValue = value?.value ?? null;\n\n // Required check\n if (field.required && (strValue === null || strValue.trim() === \"\")) {\n issues.push({\n severity: \"error\",\n message: `Required field \"${field.label}\" is empty`,\n ref: field.id,\n source: \"builtin\",\n });\n return issues; // Skip other checks if required and empty\n }\n\n // Skip other checks if no value\n if (strValue === null || strValue === \"\") {\n return issues;\n }\n\n // Min length\n if (field.minLength !== undefined && strValue.length < field.minLength) {\n issues.push({\n severity: \"error\",\n message: `\"${field.label}\" must be at least ${field.minLength} characters (got ${strValue.length})`,\n ref: field.id,\n source: \"builtin\",\n });\n }\n\n // Max length\n if (field.maxLength !== undefined && strValue.length > field.maxLength) {\n issues.push({\n severity: \"error\",\n message: `\"${field.label}\" must be at most ${field.maxLength} characters (got ${strValue.length})`,\n ref: field.id,\n source: \"builtin\",\n });\n }\n\n // Pattern\n if (field.pattern) {\n try {\n const regex = new RegExp(field.pattern);\n if (!regex.test(strValue)) {\n issues.push({\n severity: \"error\",\n message: `\"${field.label}\" does not match required pattern`,\n ref: field.id,\n source: \"builtin\",\n });\n }\n } catch {\n issues.push({\n severity: \"error\",\n message: `Invalid pattern \"${field.pattern}\" for field \"${field.label}\"`,\n ref: field.id,\n source: \"builtin\",\n });\n }\n }\n\n return issues;\n}\n\n/**\n * Validate a number field.\n */\nfunction validateNumberField(\n field: NumberField,\n value: NumberValue | undefined,\n): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const numValue = value?.value ?? null;\n\n // Required check\n if (field.required && numValue === null) {\n issues.push({\n severity: \"error\",\n message: `Required field \"${field.label}\" is empty`,\n ref: field.id,\n source: \"builtin\",\n });\n return issues;\n }\n\n // Skip other checks if no value\n if (numValue === null) {\n return issues;\n }\n\n // Integer check\n if (field.integer && !Number.isInteger(numValue)) {\n issues.push({\n severity: \"error\",\n message: `\"${field.label}\" must be an integer`,\n ref: field.id,\n source: \"builtin\",\n });\n }\n\n // Min\n if (field.min !== undefined && numValue < field.min) {\n issues.push({\n severity: \"error\",\n message: `\"${field.label}\" must be at least ${field.min} (got ${numValue})`,\n ref: field.id,\n source: \"builtin\",\n });\n }\n\n // Max\n if (field.max !== undefined && numValue > field.max) {\n issues.push({\n severity: \"error\",\n message: `\"${field.label}\" must be at most ${field.max} (got ${numValue})`,\n ref: field.id,\n source: \"builtin\",\n });\n }\n\n return issues;\n}\n\n/**\n * Validate a string-list field.\n */\nfunction validateStringListField(\n field: StringListField,\n value: StringListValue | undefined,\n): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const items = value?.items ?? [];\n\n // Required check\n if (field.required && items.length === 0) {\n issues.push({\n severity: \"error\",\n message: `Required field \"${field.label}\" is empty`,\n ref: field.id,\n source: \"builtin\",\n });\n return issues;\n }\n\n // Skip other checks if no items\n if (items.length === 0) {\n return issues;\n }\n\n // Min items\n if (field.minItems !== undefined && items.length < field.minItems) {\n issues.push({\n severity: \"error\",\n message: `\"${field.label}\" must have at least ${field.minItems} items (got ${items.length})`,\n ref: field.id,\n source: \"builtin\",\n });\n }\n\n // Max items\n if (field.maxItems !== undefined && items.length > field.maxItems) {\n issues.push({\n severity: \"error\",\n message: `\"${field.label}\" must have at most ${field.maxItems} items (got ${items.length})`,\n ref: field.id,\n source: \"builtin\",\n });\n }\n\n // Item constraints\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n if (item === undefined) {\n continue;\n }\n\n // Item min length\n if (\n field.itemMinLength !== undefined &&\n item.length < field.itemMinLength\n ) {\n issues.push({\n severity: \"error\",\n message: `Item ${i + 1} in \"${field.label}\" must be at least ${field.itemMinLength} characters`,\n ref: field.id,\n source: \"builtin\",\n });\n }\n\n // Item max length\n if (\n field.itemMaxLength !== undefined &&\n item.length > field.itemMaxLength\n ) {\n issues.push({\n severity: \"error\",\n message: `Item ${i + 1} in \"${field.label}\" must be at most ${field.itemMaxLength} characters`,\n ref: field.id,\n source: \"builtin\",\n });\n }\n }\n\n // Unique items\n if (field.uniqueItems) {\n const seen = new Set<string>();\n for (const item of items) {\n if (seen.has(item)) {\n issues.push({\n severity: \"error\",\n message: `Duplicate item \"${item}\" in \"${field.label}\"`,\n ref: field.id,\n source: \"builtin\",\n });\n break; // Only report once\n }\n seen.add(item);\n }\n }\n\n return issues;\n}\n\n/**\n * Validate a single-select field.\n */\nfunction validateSingleSelectField(\n field: SingleSelectField,\n value: SingleSelectValue | undefined,\n): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const selected = value?.selected ?? null;\n\n // Required check\n if (field.required && selected === null) {\n issues.push({\n severity: \"error\",\n message: `Required field \"${field.label}\" has no selection`,\n ref: field.id,\n source: \"builtin\",\n });\n return issues;\n }\n\n // Validate selected option exists\n if (selected !== null) {\n const validOptions = new Set(field.options.map((o) => o.id));\n if (!validOptions.has(selected)) {\n issues.push({\n severity: \"error\",\n message: `Invalid selection \"${selected}\" in \"${field.label}\"`,\n ref: field.id,\n source: \"builtin\",\n });\n }\n }\n\n return issues;\n}\n\n/**\n * Validate a multi-select field.\n */\nfunction validateMultiSelectField(\n field: MultiSelectField,\n value: MultiSelectValue | undefined,\n): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const selected = value?.selected ?? [];\n\n // Required check\n if (field.required && selected.length === 0) {\n issues.push({\n severity: \"error\",\n message: `Required field \"${field.label}\" has no selections`,\n ref: field.id,\n source: \"builtin\",\n });\n return issues;\n }\n\n // Skip other checks if no selections\n if (selected.length === 0) {\n return issues;\n }\n\n // Min selections\n if (\n field.minSelections !== undefined &&\n selected.length < field.minSelections\n ) {\n issues.push({\n severity: \"error\",\n message: `\"${field.label}\" must have at least ${field.minSelections} selections (got ${selected.length})`,\n ref: field.id,\n source: \"builtin\",\n });\n }\n\n // Max selections\n if (\n field.maxSelections !== undefined &&\n selected.length > field.maxSelections\n ) {\n issues.push({\n severity: \"error\",\n message: `\"${field.label}\" must have at most ${field.maxSelections} selections (got ${selected.length})`,\n ref: field.id,\n source: \"builtin\",\n });\n }\n\n // Validate selected options exist\n const validOptions = new Set(field.options.map((o) => o.id));\n for (const sel of selected) {\n if (!validOptions.has(sel)) {\n issues.push({\n severity: \"error\",\n message: `Invalid selection \"${sel}\" in \"${field.label}\"`,\n ref: field.id,\n source: \"builtin\",\n });\n }\n }\n\n return issues;\n}\n\n/**\n * Validate a checkboxes field.\n */\nfunction validateCheckboxesField(\n field: CheckboxesField,\n value: CheckboxesValue | undefined,\n): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const values = value?.values ?? {};\n const mode = field.checkboxMode ?? \"multi\";\n\n // Count completed items based on mode\n let doneCount = 0;\n let incompleteCount = 0;\n let unfilledCount = 0;\n\n for (const opt of field.options) {\n const state = values[opt.id] ?? (mode === \"explicit\" ? \"unfilled\" : \"todo\");\n\n if (mode === \"explicit\") {\n if (state === \"unfilled\") {\n unfilledCount++;\n } else {\n doneCount++; // yes or no counts as answered\n }\n } else if (mode === \"multi\") {\n if (state === \"done\" || state === \"na\") {\n doneCount++;\n } else if (state === \"incomplete\" || state === \"active\") {\n incompleteCount++;\n }\n } else {\n // simple mode\n if (state === \"done\") {\n doneCount++;\n }\n }\n }\n\n // Required check - for checkboxes, required means all must be addressed\n if (field.required) {\n if (mode === \"explicit\" && unfilledCount > 0) {\n issues.push({\n severity: \"error\",\n message: `All items in \"${field.label}\" must be answered (${unfilledCount} unfilled)`,\n ref: field.id,\n source: \"builtin\",\n });\n } else if (mode === \"multi\" && (incompleteCount > 0 || doneCount === 0)) {\n issues.push({\n severity: \"error\",\n message: `All items in \"${field.label}\" must be completed`,\n ref: field.id,\n source: \"builtin\",\n });\n } else if (mode === \"simple\" && doneCount < field.options.length) {\n const remaining = field.options.length - doneCount;\n issues.push({\n severity: \"error\",\n message: `All items in \"${field.label}\" must be checked (${remaining} unchecked)`,\n ref: field.id,\n source: \"builtin\",\n });\n }\n }\n\n // Min done (optional constraint)\n if (field.minDone !== undefined && doneCount < field.minDone) {\n issues.push({\n severity: \"error\",\n message: `\"${field.label}\" requires at least ${field.minDone} items done (got ${doneCount})`,\n ref: field.id,\n source: \"builtin\",\n });\n }\n\n return issues;\n}\n\n/**\n * Validate a single field.\n */\nfunction validateField(\n field: Field,\n values: Record<Id, FieldValue>,\n): ValidationIssue[] {\n const value = values[field.id];\n\n switch (field.kind) {\n case \"string\":\n return validateStringField(field, value as StringValue | undefined);\n case \"number\":\n return validateNumberField(field, value as NumberValue | undefined);\n case \"string_list\":\n return validateStringListField(\n field,\n value as StringListValue | undefined,\n );\n case \"single_select\":\n return validateSingleSelectField(\n field,\n value as SingleSelectValue | undefined,\n );\n case \"multi_select\":\n return validateMultiSelectField(\n field,\n value as MultiSelectValue | undefined,\n );\n case \"checkboxes\":\n return validateCheckboxesField(\n field,\n value as CheckboxesValue | undefined,\n );\n }\n}\n\n// =============================================================================\n// Code Validator Support\n// =============================================================================\n\n/**\n * Parse a validator reference to extract id and params.\n */\nfunction parseValidatorRef(ref: ValidatorRef): {\n id: string;\n params: Record<string, unknown>;\n} {\n if (typeof ref === \"string\") {\n return { id: ref, params: {} };\n }\n const { id, ...params } = ref;\n return { id, params };\n}\n\n/**\n * Run code validators for a field.\n */\nfunction runCodeValidators(\n field: Field,\n schema: FormSchema,\n values: Record<Id, FieldValue>,\n registry: ValidatorRegistry,\n): ValidationIssue[] {\n if (!field.validate) {\n return [];\n }\n\n const refs = Array.isArray(field.validate)\n ? field.validate\n : [field.validate];\n const issues: ValidationIssue[] = [];\n\n for (const ref of refs) {\n const { id, params } = parseValidatorRef(ref);\n const validator = registry[id];\n\n if (!validator) {\n issues.push({\n severity: \"warning\",\n message: `Validator \"${id}\" not found for field \"${field.label}\"`,\n ref: field.id,\n source: \"code\",\n validatorId: id,\n });\n continue;\n }\n\n const ctx: ValidatorContext = {\n schema,\n values,\n targetId: field.id,\n targetSchema: field,\n params,\n };\n\n try {\n const validatorIssues = validator(ctx);\n issues.push(...validatorIssues);\n } catch (err) {\n issues.push({\n severity: \"error\",\n message: `Validator \"${id}\" threw an error: ${err instanceof Error ? err.message : String(err)}`,\n ref: field.id,\n source: \"code\",\n validatorId: id,\n });\n }\n }\n\n return issues;\n}\n\n/**\n * Run code validators for a field group.\n */\nfunction runGroupValidators(\n group: FieldGroup,\n schema: FormSchema,\n values: Record<Id, FieldValue>,\n registry: ValidatorRegistry,\n): ValidationIssue[] {\n if (!group.validate) {\n return [];\n }\n\n const refs = Array.isArray(group.validate)\n ? group.validate\n : [group.validate];\n const issues: ValidationIssue[] = [];\n\n for (const ref of refs) {\n const { id, params } = parseValidatorRef(ref);\n const validator = registry[id];\n\n if (!validator) {\n issues.push({\n severity: \"warning\",\n message: `Validator \"${id}\" not found for group \"${group.id}\"`,\n ref: group.id,\n source: \"code\",\n validatorId: id,\n });\n continue;\n }\n\n const ctx: ValidatorContext = {\n schema,\n values,\n targetId: group.id,\n targetSchema: group,\n params,\n };\n\n try {\n const validatorIssues = validator(ctx);\n issues.push(...validatorIssues);\n } catch (err) {\n issues.push({\n severity: \"error\",\n message: `Validator \"${id}\" threw an error: ${err instanceof Error ? err.message : String(err)}`,\n ref: group.id,\n source: \"code\",\n validatorId: id,\n });\n }\n }\n\n return issues;\n}\n\n// =============================================================================\n// Main Validate Function\n// =============================================================================\n\n/**\n * Validate a parsed form.\n *\n * @param form - The parsed form to validate\n * @param opts - Validation options\n * @returns Validation result with issues and validity flag\n */\nexport function validate(\n form: ParsedForm,\n opts?: ValidateOptions,\n): ValidateResult {\n const issues: ValidationIssue[] = [];\n const registry = opts?.validatorRegistry ?? {};\n\n // Validate each field\n for (const group of form.schema.groups) {\n for (const field of group.children) {\n // Built-in validation\n issues.push(...validateField(field, form.valuesByFieldId));\n\n // Code validators\n if (!opts?.skipCodeValidators) {\n issues.push(\n ...runCodeValidators(\n field,\n form.schema,\n form.valuesByFieldId,\n registry,\n ),\n );\n }\n }\n\n // Group-level validators\n if (!opts?.skipCodeValidators) {\n issues.push(\n ...runGroupValidators(\n group,\n form.schema,\n form.valuesByFieldId,\n registry,\n ),\n );\n }\n }\n\n // Determine if valid (no error-severity issues)\n const isValid = !issues.some((i) => i.severity === \"error\");\n\n return { issues, isValid };\n}\n","/**\n * Inspect module - provides the main entry point for form inspection.\n *\n * Combines validation results with summaries into a unified InspectResult,\n * with issues sorted by priority (ascending, 1 = highest).\n */\nimport type {\n ParsedForm,\n InspectResult,\n InspectIssue,\n ValidationIssue,\n IssueScope,\n IssueReason,\n FieldPriorityLevel,\n Field,\n Id,\n} from \"./coreTypes\";\nimport { DEFAULT_PRIORITY } from \"../settings.js\";\nimport { validate } from \"./validate\";\nimport {\n computeStructureSummary,\n computeProgressSummary,\n computeFormState,\n} from \"./summaries\";\n\n/**\n * Inspect options for customizing behavior.\n */\nexport interface InspectOptions {\n /** Skip code validators */\n skipCodeValidators?: boolean;\n /** Target roles to filter issues by (default: all roles, '*' means all) */\n targetRoles?: string[];\n}\n\n/**\n * Inspect a parsed form and return a unified result with summaries and issues.\n *\n * This is the main entry point for form inspection. It:\n * 1. Runs validation to get all issues\n * 2. Converts ValidationIssues to InspectIssues\n * 3. Computes structure and progress summaries\n * 4. Adds issues for empty optional fields\n * 5. Sorts all issues by priority (ascending, 1 = highest)\n *\n * @param form - The parsed form to inspect\n * @param options - Optional inspection options\n * @returns InspectResult with summaries and prioritized issues\n */\nexport function inspect(\n form: ParsedForm,\n options: InspectOptions = {}\n): InspectResult {\n // Run validation (synchronous)\n const validationResult = validate(form, {\n skipCodeValidators: options.skipCodeValidators,\n });\n\n // Convert validation issues to inspect issues first\n const validationInspectIssues = convertValidationIssues(\n validationResult.issues,\n form\n );\n\n // Compute structure summary\n const structureSummary = computeStructureSummary(form.schema);\n\n // Compute progress summary with the converted issues\n const progressSummary = computeProgressSummary(\n form.schema,\n form.valuesByFieldId,\n validationInspectIssues\n );\n const formState = computeFormState(progressSummary);\n\n // Add issues for empty optional fields\n const allIssues = addOptionalEmptyIssues(\n validationInspectIssues,\n form,\n progressSummary.fields\n );\n\n // Sort and assign priorities\n const sortedIssues = sortAndAssignPriorities(allIssues, form);\n\n // Filter by role and add blocking annotations\n const filteredIssues = filterIssuesByRole(sortedIssues, form, options.targetRoles);\n\n // Check if complete (no required issues in filtered set)\n const isComplete = !filteredIssues.some((i) => i.severity === \"required\");\n\n return {\n structureSummary,\n progressSummary,\n issues: filteredIssues,\n isComplete,\n formState,\n };\n}\n\n/**\n * Convert ValidationIssues to InspectIssues.\n */\nfunction convertValidationIssues(\n validationIssues: ValidationIssue[],\n form: ParsedForm\n): InspectIssue[] {\n return validationIssues.map((vi) => ({\n ref: vi.ref ?? \"\",\n scope: determineScope(vi.ref ?? \"\", form),\n reason: mapValidationToInspectReason(vi),\n message: vi.message,\n severity: vi.severity === \"error\" ? \"required\" : \"recommended\",\n priority: 0, // Will be assigned after sorting\n }));\n}\n\n/**\n * Add issues for empty optional fields that don't already have issues.\n */\nfunction addOptionalEmptyIssues(\n existingIssues: InspectIssue[],\n form: ParsedForm,\n fieldProgress: Record<string, { state: string }>\n): InspectIssue[] {\n const issues = [...existingIssues];\n const fieldsWithIssues = new Set(existingIssues.map((i) => i.ref));\n\n for (const [fieldId, progress] of Object.entries(fieldProgress)) {\n if (\n progress.state === \"empty\" &&\n !fieldsWithIssues.has(fieldId) &&\n !isRequiredField(fieldId, form)\n ) {\n issues.push({\n ref: fieldId,\n scope: \"field\",\n reason: \"optional_empty\",\n message: \"Optional field has no value\",\n severity: \"recommended\",\n priority: 0,\n });\n }\n }\n\n return issues;\n}\n\n/**\n * Map ValidationIssue to InspectIssue reason code.\n */\nfunction mapValidationToInspectReason(vi: ValidationIssue): IssueReason {\n // Check for specific patterns in the message or code\n // Required empty - check both code and message patterns\n if (\n vi.code === \"REQUIRED_EMPTY\" ||\n (vi.message.toLowerCase().includes(\"required\") &&\n vi.message.toLowerCase().includes(\"empty\"))\n ) {\n return \"required_missing\";\n }\n\n // Invalid checkbox state\n if (\n vi.code === \"INVALID_CHECKBOX_STATE\" ||\n vi.code === \"CHECKBOXES_INCOMPLETE\" ||\n vi.message.toLowerCase().includes(\"checkbox\")\n ) {\n return \"checkbox_incomplete\";\n }\n\n // Min items violations\n if (\n vi.code === \"MULTI_SELECT_TOO_FEW\" ||\n vi.code === \"STRING_LIST_MIN_ITEMS\" ||\n vi.message.includes(\"at least\")\n ) {\n return \"min_items_not_met\";\n }\n\n // Default to validation_error for other issues\n return \"validation_error\";\n}\n\n/**\n * Determine the scope of an issue based on the ref.\n */\nfunction determineScope(ref: string, form: ParsedForm): IssueScope {\n // Check if it's an option reference (contains a dot)\n if (ref.includes(\".\")) {\n return \"option\";\n }\n\n // Check if it's the form ID\n if (ref === form.schema.id) {\n return \"form\";\n }\n\n // Check if it's a group ID\n for (const group of form.schema.groups) {\n if (ref === group.id) {\n return \"group\";\n }\n }\n\n // Default to field\n return \"field\";\n}\n\n/**\n * Check if a field is required.\n */\nfunction isRequiredField(fieldId: string, form: ParsedForm): boolean {\n for (const group of form.schema.groups) {\n for (const field of group.children) {\n if (field.id === fieldId) {\n return field.required;\n }\n }\n }\n return false;\n}\n\n/**\n * Priority scoring constants.\n *\n * Field priority weights:\n * - high: 3\n * - medium: 2 (default)\n * - low: 1\n *\n * Issue type scores:\n * - required_missing: 3\n * - validation_error: 2\n * - checkbox_incomplete: 3 (when required), 2 (when recommended)\n * - min_items_not_met: 2\n * - optional_empty: 1\n *\n * Total score = field_priority_weight + issue_type_score\n *\n * Priority tiers:\n * - P1: score >= 5\n * - P2: score >= 4\n * - P3: score >= 3\n * - P4: score >= 2\n * - P5: score >= 1\n */\nconst FIELD_PRIORITY_WEIGHTS: Record<FieldPriorityLevel, number> = {\n high: 3,\n medium: 2,\n low: 1,\n};\n\nconst ISSUE_TYPE_SCORES: Record<IssueReason, number> = {\n required_missing: 3,\n validation_error: 2,\n checkbox_incomplete: 2, // Base score, adjusted by severity\n min_items_not_met: 2,\n optional_empty: 1,\n};\n\n/**\n * Calculate the priority tier (1-5) from a score.\n */\nfunction scoreToTier(score: number): number {\n if (score >= 5) {\nreturn 1;\n}\n if (score >= 4) {\nreturn 2;\n}\n if (score >= 3) {\nreturn 3;\n}\n if (score >= 2) {\nreturn 4;\n}\n return 5;\n}\n\n/**\n * Get the issue type score, potentially adjusted by severity.\n */\nfunction getIssueTypeScore(reason: IssueReason, severity: \"required\" | \"recommended\"): number {\n const baseScore = ISSUE_TYPE_SCORES[reason];\n // checkbox_incomplete gets +1 when required\n if (reason === \"checkbox_incomplete\" && severity === \"required\") {\n return baseScore + 1;\n }\n return baseScore;\n}\n\n/**\n * Sort issues by priority tier and assign priority numbers.\n *\n * Priority is computed as a tier (1-5, P1-P5) based on:\n * - Field priority weight (high=3, medium=2, low=1)\n * - Issue type score (required_missing=3, validation_error=2, optional_empty=1)\n *\n * Within each tier, issues are sorted by severity (required first) then by ref.\n */\nfunction sortAndAssignPriorities(\n issues: InspectIssue[],\n form: ParsedForm\n): InspectIssue[] {\n // Calculate scores and assign tier-based priorities\n const scoredIssues = issues.map((issue) => {\n const fieldPriority = getFieldPriority(issue.ref, form);\n const fieldWeight = FIELD_PRIORITY_WEIGHTS[fieldPriority];\n const issueScore = getIssueTypeScore(issue.reason, issue.severity);\n const totalScore = fieldWeight + issueScore;\n const tier = scoreToTier(totalScore);\n\n return {\n ...issue,\n priority: tier,\n _score: totalScore, // For sorting within tier\n };\n });\n\n // Sort by:\n // 1. Priority tier (ascending, P1 first)\n // 2. Severity (required before recommended)\n // 3. Score (descending, higher scores first within tier)\n // 4. Ref (alphabetically for deterministic output)\n scoredIssues.sort((a, b) => {\n if (a.priority !== b.priority) {\nreturn a.priority - b.priority;\n}\n if (a.severity !== b.severity) {\n return a.severity === \"required\" ? -1 : 1;\n }\n if (a._score !== b._score) {\nreturn b._score - a._score;\n}\n return a.ref.localeCompare(b.ref);\n });\n\n // Remove internal _score field\n return scoredIssues.map(({ _score, ...issue }) => issue);\n}\n\n/**\n * Get the priority level for a field.\n */\nfunction getFieldPriority(ref: string, form: ParsedForm): FieldPriorityLevel {\n // Handle option refs (fieldId.optionId)\n const fieldId = ref.includes(\".\") ? ref.split(\".\")[0] : ref;\n\n for (const group of form.schema.groups) {\n for (const field of group.children) {\n if (field.id === fieldId) {\n return field.priority;\n }\n }\n }\n return DEFAULT_PRIORITY; // Fallback for non-field refs (groups, form)\n}\n\n// =============================================================================\n// Role Filtering and Blocking Checkpoint Helpers\n// =============================================================================\n\n/**\n * Get all fields from the form schema as a flat array.\n */\nexport function getAllFields(form: ParsedForm): Field[] {\n return form.schema.groups.flatMap((g) => g.children);\n}\n\n/**\n * Find a field by its ID.\n */\nexport function findFieldById(form: ParsedForm, fieldId: Id): Field | undefined {\n for (const group of form.schema.groups) {\n for (const field of group.children) {\n if (field.id === fieldId) {\n return field;\n }\n }\n }\n return undefined;\n}\n\n/**\n * Get fields that match the target roles.\n * If targetRoles includes '*', returns all fields.\n */\nexport function getFieldsForRoles(form: ParsedForm, targetRoles: string[]): Field[] {\n const allFields = getAllFields(form);\n if (targetRoles.includes(\"*\")) {\n return allFields;\n }\n return allFields.filter((field) => targetRoles.includes(field.role));\n}\n\n/**\n * Check if a checkbox field is complete based on its mode.\n *\n * Completion semantics by mode:\n * - 'all': All options must be done or n/a\n * - 'any': At least minDone (default 1) options must be done\n * - 'explicit': No options may be 'unfilled'\n */\nexport function isCheckboxComplete(form: ParsedForm, fieldId: Id): boolean {\n const field = findFieldById(form, fieldId);\n if (field?.kind !== \"checkboxes\") {\n return true; // Non-checkbox fields are not blocking\n }\n\n const checkboxField = field;\n const value = form.valuesByFieldId[fieldId];\n if (value?.kind !== \"checkboxes\") {\n return false;\n }\n\n const values = value.values;\n const optionIds = checkboxField.options.map((o) => o.id);\n const mode = checkboxField.checkboxMode;\n\n if (mode === \"multi\") {\n // Multi mode: all options must be done or na (not todo, incomplete, or active)\n // If minDone is set, at least that many must be done\n const minDone = checkboxField.minDone;\n if (minDone !== undefined) {\n const doneCount = optionIds.filter((id) => values[id] === \"done\").length;\n return doneCount >= minDone;\n }\n // Otherwise, all must be done or na\n return optionIds.every((id) => values[id] === \"done\" || values[id] === \"na\");\n }\n\n if (mode === \"simple\") {\n // Simple mode (GFM-compatible): all options must be done (not todo)\n return optionIds.every((id) => values[id] === \"done\");\n }\n\n if (mode === \"explicit\") {\n // Explicit mode: no unfilled values remain (all must be yes or no)\n return optionIds.every((id) => values[id] !== \"unfilled\");\n }\n\n // Default case (shouldn't happen with valid CheckboxMode)\n return true;\n}\n\n/**\n * Result of finding a blocking checkpoint.\n */\nexport interface BlockingCheckpointResult {\n /** Index in orderIndex where the blocking checkpoint is */\n index: number;\n /** Field ID of the blocking checkpoint */\n fieldId: Id;\n}\n\n/**\n * Find the first incomplete blocking checkpoint in the form.\n * Returns null if no blocking checkpoint is incomplete.\n */\nexport function findBlockingCheckpoint(form: ParsedForm): BlockingCheckpointResult | null {\n for (let i = 0; i < form.orderIndex.length; i++) {\n const fieldId = form.orderIndex[i];\n if (!fieldId) {\ncontinue;\n}\n\n const field = findFieldById(form, fieldId);\n if (field?.kind !== \"checkboxes\") {\ncontinue;\n}\n\n const checkboxField = field;\n if (checkboxField.approvalMode === \"blocking\" && !isCheckboxComplete(form, fieldId)) {\n return { index: i, fieldId };\n }\n }\n return null;\n}\n\n/**\n * Get the set of field IDs that are blocked by a checkpoint.\n * These are all fields that appear after the blocking checkpoint in orderIndex.\n */\nexport function getBlockedFieldIds(\n form: ParsedForm,\n blockingCheckpoint: BlockingCheckpointResult\n): Set<Id> {\n const blocked = new Set<Id>();\n for (let i = blockingCheckpoint.index + 1; i < form.orderIndex.length; i++) {\n const fieldId = form.orderIndex[i];\n if (fieldId) {\n blocked.add(fieldId);\n }\n }\n return blocked;\n}\n\n/**\n * Filter issues to only include those for fields matching target roles.\n * Also adds blockedBy annotation for fields blocked by a checkpoint.\n */\nexport function filterIssuesByRole(\n issues: InspectIssue[],\n form: ParsedForm,\n targetRoles?: string[]\n): InspectIssue[] {\n // Find blocking checkpoint first\n const blockingCheckpoint = findBlockingCheckpoint(form);\n const blockedFieldIds = blockingCheckpoint\n ? getBlockedFieldIds(form, blockingCheckpoint)\n : new Set<Id>();\n\n // Get field IDs for target roles\n const targetFieldIds = targetRoles && !targetRoles.includes(\"*\")\n ? new Set(getFieldsForRoles(form, targetRoles).map((f) => f.id))\n : null;\n\n return issues.map((issue) => {\n // Extract field ID from ref (handles both field refs and option refs)\n const fieldId = issue.ref.includes(\".\") ? issue.ref.split(\".\")[0] : issue.ref;\n\n // Check if this field is blocked\n const isBlocked = fieldId && blockedFieldIds.has(fieldId);\n const annotatedIssue: InspectIssue = isBlocked\n ? { ...issue, blockedBy: blockingCheckpoint!.fieldId }\n : issue;\n\n return annotatedIssue;\n }).filter((issue) => {\n // If no target roles specified, include all issues\n if (!targetFieldIds) {\n return true;\n }\n\n // Extract field ID and check if it matches target roles\n const fieldId = issue.ref.includes(\".\") ? (issue.ref.split(\".\")[0] ?? issue.ref) : issue.ref;\n\n // Include if field matches target roles, or if it's not a field ref (form/group level)\n const field = findFieldById(form, fieldId);\n return !field || targetFieldIds.has(fieldId);\n });\n}\n","/**\n * Patch application for Markform documents.\n *\n * Applies patches to update field values with validation.\n */\n\nimport type {\n ApplyResult,\n CheckboxesValue,\n CheckboxValue,\n ClearFieldPatch,\n Field,\n FieldValue,\n Id,\n InspectIssue,\n MultiSelectValue,\n NumberValue,\n OptionId,\n ParsedForm,\n Patch,\n SetCheckboxesPatch,\n SetMultiSelectPatch,\n SetNumberPatch,\n SetSingleSelectPatch,\n SetStringListPatch,\n SetStringPatch,\n SingleSelectValue,\n StringListValue,\n StringValue,\n} from \"./coreTypes.js\";\nimport {\n computeAllSummaries,\n computeFormState,\n isFormComplete,\n} from \"./summaries.js\";\nimport { validate } from \"./validate.js\";\n\n// =============================================================================\n// Patch Validation\n// =============================================================================\n\ninterface PatchError {\n patchIndex: number;\n message: string;\n}\n\n/**\n * Find a field by ID in the form schema.\n */\nfunction findField(form: ParsedForm, fieldId: Id): Field | undefined {\n for (const group of form.schema.groups) {\n for (const field of group.children) {\n if (field.id === fieldId) {\n return field;\n }\n }\n }\n return undefined;\n}\n\n/**\n * Validate a single patch against the form schema.\n */\nfunction validatePatch(\n form: ParsedForm,\n patch: Patch,\n index: number,\n): PatchError | null {\n const field = findField(form, patch.fieldId);\n\n if (!field) {\n return {\n patchIndex: index,\n message: `Field \"${patch.fieldId}\" not found`,\n };\n }\n\n switch (patch.op) {\n case \"set_string\":\n if (field.kind !== \"string\") {\n return {\n patchIndex: index,\n message: `Cannot apply set_string to ${field.kind} field \"${field.id}\"`,\n };\n }\n break;\n\n case \"set_number\":\n if (field.kind !== \"number\") {\n return {\n patchIndex: index,\n message: `Cannot apply set_number to ${field.kind} field \"${field.id}\"`,\n };\n }\n break;\n\n case \"set_string_list\":\n if (field.kind !== \"string_list\") {\n return {\n patchIndex: index,\n message: `Cannot apply set_string_list to ${field.kind} field \"${field.id}\"`,\n };\n }\n break;\n\n case \"set_single_select\": {\n if (field.kind !== \"single_select\") {\n return {\n patchIndex: index,\n message: `Cannot apply set_single_select to ${field.kind} field \"${field.id}\"`,\n };\n }\n const selectField = field;\n if (patch.selected !== null) {\n const validOptions = new Set(selectField.options.map((o) => o.id));\n if (!validOptions.has(patch.selected)) {\n return {\n patchIndex: index,\n message: `Invalid option \"${patch.selected}\" for field \"${field.id}\"`,\n };\n }\n }\n break;\n }\n\n case \"set_multi_select\": {\n if (field.kind !== \"multi_select\") {\n return {\n patchIndex: index,\n message: `Cannot apply set_multi_select to ${field.kind} field \"${field.id}\"`,\n };\n }\n const multiField = field;\n const validOptions = new Set(multiField.options.map((o) => o.id));\n for (const optId of patch.selected) {\n if (!validOptions.has(optId)) {\n return {\n patchIndex: index,\n message: `Invalid option \"${optId}\" for field \"${field.id}\"`,\n };\n }\n }\n break;\n }\n\n case \"set_checkboxes\": {\n if (field.kind !== \"checkboxes\") {\n return {\n patchIndex: index,\n message: `Cannot apply set_checkboxes to ${field.kind} field \"${field.id}\"`,\n };\n }\n const checkboxField = field;\n const validOptions = new Set(checkboxField.options.map((o) => o.id));\n for (const optId of Object.keys(patch.values)) {\n if (!validOptions.has(optId)) {\n return {\n patchIndex: index,\n message: `Invalid option \"${optId}\" for field \"${field.id}\"`,\n };\n }\n }\n break;\n }\n\n case \"clear_field\":\n // Any field can be cleared\n break;\n }\n\n return null;\n}\n\n/**\n * Validate all patches against the form schema.\n */\nfunction validatePatches(form: ParsedForm, patches: Patch[]): PatchError[] {\n const errors: PatchError[] = [];\n for (let i = 0; i < patches.length; i++) {\n const patch = patches[i];\n if (patch) {\n const error = validatePatch(form, patch, i);\n if (error) {\n errors.push(error);\n }\n }\n }\n return errors;\n}\n\n// =============================================================================\n// Patch Application\n// =============================================================================\n\n/**\n * Apply a set_string patch.\n */\nfunction applySetString(\n values: Record<Id, FieldValue>,\n patch: SetStringPatch,\n): void {\n values[patch.fieldId] = {\n kind: \"string\",\n value: patch.value,\n } as StringValue;\n}\n\n/**\n * Apply a set_number patch.\n */\nfunction applySetNumber(\n values: Record<Id, FieldValue>,\n patch: SetNumberPatch,\n): void {\n values[patch.fieldId] = {\n kind: \"number\",\n value: patch.value,\n } as NumberValue;\n}\n\n/**\n * Apply a set_string_list patch.\n */\nfunction applySetStringList(\n values: Record<Id, FieldValue>,\n patch: SetStringListPatch,\n): void {\n values[patch.fieldId] = {\n kind: \"string_list\",\n items: patch.items,\n } as StringListValue;\n}\n\n/**\n * Apply a set_single_select patch.\n */\nfunction applySetSingleSelect(\n values: Record<Id, FieldValue>,\n patch: SetSingleSelectPatch,\n): void {\n values[patch.fieldId] = {\n kind: \"single_select\",\n selected: patch.selected,\n } as SingleSelectValue;\n}\n\n/**\n * Apply a set_multi_select patch.\n */\nfunction applySetMultiSelect(\n values: Record<Id, FieldValue>,\n patch: SetMultiSelectPatch,\n): void {\n values[patch.fieldId] = {\n kind: \"multi_select\",\n selected: patch.selected,\n } as MultiSelectValue;\n}\n\n/**\n * Apply a set_checkboxes patch (merges with existing values).\n */\nfunction applySetCheckboxes(\n values: Record<Id, FieldValue>,\n patch: SetCheckboxesPatch,\n): void {\n const existing = values[patch.fieldId] as CheckboxesValue | undefined;\n const existingValues = existing?.values ?? {};\n\n // Merge patch values with existing\n const merged: Record<OptionId, CheckboxValue> = {\n ...existingValues,\n ...patch.values,\n };\n\n values[patch.fieldId] = {\n kind: \"checkboxes\",\n values: merged,\n } as CheckboxesValue;\n}\n\n/**\n * Apply a clear_field patch.\n */\nfunction applyClearField(\n form: ParsedForm,\n values: Record<Id, FieldValue>,\n patch: ClearFieldPatch,\n): void {\n const field = findField(form, patch.fieldId);\n if (!field) {\nreturn;\n}\n\n // Create empty value based on field kind\n switch (field.kind) {\n case \"string\":\n values[patch.fieldId] = { kind: \"string\", value: null } as StringValue;\n break;\n case \"number\":\n values[patch.fieldId] = { kind: \"number\", value: null } as NumberValue;\n break;\n case \"string_list\":\n values[patch.fieldId] = { kind: \"string_list\", items: [] } as StringListValue;\n break;\n case \"single_select\":\n values[patch.fieldId] = { kind: \"single_select\", selected: null } as SingleSelectValue;\n break;\n case \"multi_select\":\n values[patch.fieldId] = { kind: \"multi_select\", selected: [] } as MultiSelectValue;\n break;\n case \"checkboxes\":\n values[patch.fieldId] = { kind: \"checkboxes\", values: {} } as CheckboxesValue;\n break;\n }\n}\n\n/**\n * Apply a single patch to the values.\n */\nfunction applyPatch(\n form: ParsedForm,\n values: Record<Id, FieldValue>,\n patch: Patch,\n): void {\n switch (patch.op) {\n case \"set_string\":\n applySetString(values, patch);\n break;\n case \"set_number\":\n applySetNumber(values, patch);\n break;\n case \"set_string_list\":\n applySetStringList(values, patch);\n break;\n case \"set_single_select\":\n applySetSingleSelect(values, patch);\n break;\n case \"set_multi_select\":\n applySetMultiSelect(values, patch);\n break;\n case \"set_checkboxes\":\n applySetCheckboxes(values, patch);\n break;\n case \"clear_field\":\n applyClearField(form, values, patch);\n break;\n }\n}\n\n// =============================================================================\n// Issue Conversion (ValidationIssue -> InspectIssue)\n// =============================================================================\n\n/**\n * Convert validation issues to inspect issues with priorities.\n */\nfunction convertToInspectIssues(\n form: ParsedForm,\n): InspectIssue[] {\n const result = validate(form, { skipCodeValidators: true });\n const issues: InspectIssue[] = [];\n let priority = 1;\n\n for (const vi of result.issues) {\n issues.push({\n ref: vi.ref ?? \"\",\n scope: \"field\", // Default to field scope; can be refined based on validator context\n reason: vi.severity === \"error\" ? \"validation_error\" : \"optional_empty\",\n message: vi.message,\n severity: vi.severity === \"error\" ? \"required\" : \"recommended\",\n priority: priority++,\n });\n }\n\n return issues;\n}\n\n// =============================================================================\n// Main Apply Function\n// =============================================================================\n\n/**\n * Apply patches to a parsed form.\n *\n * Uses transaction semantics - all patches succeed or none are applied.\n *\n * @param form - The parsed form to update\n * @param patches - Array of patches to apply\n * @returns Apply result with new summaries and status\n */\nexport function applyPatches(\n form: ParsedForm,\n patches: Patch[],\n): ApplyResult {\n // Validate all patches first (transaction semantics)\n const errors = validatePatches(form, patches);\n if (errors.length > 0) {\n // Reject - compute summaries from current state\n const summaries = computeAllSummaries(form.schema, form.valuesByFieldId, []);\n const issues = convertToInspectIssues(form);\n\n return {\n applyStatus: \"rejected\",\n structureSummary: summaries.structureSummary,\n progressSummary: summaries.progressSummary,\n issues,\n isComplete: summaries.isComplete,\n formState: summaries.formState,\n };\n }\n\n // Create new values object (don't mutate original)\n const newValues: Record<Id, FieldValue> = { ...form.valuesByFieldId };\n\n // Apply all patches\n for (const patch of patches) {\n applyPatch(form, newValues, patch);\n }\n\n // Update form with new values\n form.valuesByFieldId = newValues;\n\n // Compute new summaries\n const issues = convertToInspectIssues(form);\n const summaries = computeAllSummaries(form.schema, newValues, issues);\n\n return {\n applyStatus: \"applied\",\n structureSummary: summaries.structureSummary,\n progressSummary: summaries.progressSummary,\n issues,\n isComplete: isFormComplete(summaries.progressSummary),\n formState: computeFormState(summaries.progressSummary),\n };\n}\n"],"mappings":"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"}
package/dist/bin.mjs.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"bin.mjs","names":[],"sources":["../src/cli/bin.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * CLI entry point for the markform command.\n *\n * Loads environment variables from .env files before running the CLI.\n * Loading order: .env.local first (local overrides), then .env (defaults).\n * Existing environment variables are not overwritten.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\n\nimport { config } from \"dotenv\";\n\nimport { runCli } from \"./cli.js\";\n\n// Load .env files from current working directory\n// .env.local takes precedence over .env, shell env takes precedence over both\nconst cwd = process.cwd();\nfor (const file of [\".env.local\", \".env\"]) {\n const path = resolve(cwd, file);\n if (existsSync(path)) {\n // quiet: true suppresses the tip messages added in dotenv v17\n config({ path, override: false, debug: false, quiet: true });\n }\n}\n\nrunCli().catch((error: unknown) => {\n console.error(\"Fatal error:\", error);\n process.exit(1);\n});\n"],"mappings":";;;;;;;;;;;;;;;;AAkBA,MAAM,MAAM,QAAQ,KAAK;AACzB,KAAK,MAAM,QAAQ,CAAC,cAAc,OAAO,EAAE;CACzC,MAAM,OAAO,QAAQ,KAAK,KAAK;AAC/B,KAAI,WAAW,KAAK,CAElB,QAAO;EAAE;EAAM,UAAU;EAAO,OAAO;EAAO,OAAO;EAAM,CAAC;;AAIhE,QAAQ,CAAC,OAAO,UAAmB;AACjC,SAAQ,MAAM,gBAAgB,MAAM;AACpC,SAAQ,KAAK,EAAE;EACf"}