# 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,
}
