# Validation contracts for .coder/ entries. # Applied after schema — enforce semantic invariants. # Entry must have a non-empty title let _non_empty_title = std.contract.custom ( fun label => fun value => if std.string.length (std.string.trim value.title) == 0 then 'Error { message = "Entry: title must not be empty — extracted from first markdown heading or filename" } else 'Ok value ) in # Entry must have a non-empty author let _non_empty_author = std.contract.custom ( fun label => fun value => if std.string.length (std.string.trim value.author) == 0 then 'Error { message = "Entry: author must not be empty — derived from workspace directory name" } else 'Ok value ) in # Entry in Inbox category should not have relates_to (not yet triaged) let _inbox_no_relations = std.contract.custom ( fun label => fun value => if value.category == 'Inbox && std.array.length value.relates_to > 0 then 'Error { message = "Entry in Inbox should not have relates_to — triage first, then add relations" } else 'Ok value ) in { NonEmptyTitle = _non_empty_title, NonEmptyAuthor = _non_empty_author, InboxNoRelations = _inbox_no_relations, }