let c = import "adr-constraints.ncl" in

let status_type   = [| 'Proposed, 'Accepted, 'Superseded, 'Deprecated |] in
let severity_type = [| 'Hard, 'Soft |] in
let verdict_type  = [| 'Safe, 'RequiresJustification |] in

let rationale_entry_type = {
  claim  | String,
  detail | String,
} in

let alternative_type = {
  option       | String,
  why_rejected | String,
} in

# Tag discriminant for typed constraint checks.
# Used by validate.nu to dispatch execution per variant.
let check_tag_type = [|
  'Cargo,
  'Grep,
  'NuCmd,
  'ApiCall,
  'FileExists,
|] in

# Typed constraint check: a tagged record, JSON-serializable.
# Required fields per tag (validated by EachCheckWellFormed in adr-constraints.ncl):
#   'Cargo     -> crate : String, forbidden_deps : Array String
#   'Grep      -> pattern : String, paths : Array String, must_be_empty : Bool
#   'NuCmd     -> cmd : String, expect_exit : Number
#   'ApiCall   -> endpoint : String, json_path : String, expected : Dyn
#   'FileExists-> path : String, present : Bool
let constraint_check_type = {
  tag | check_tag_type,
  ..
} in

let constraint_type = {
  id         | String,
  claim      | String,
  scope      | String,
  severity   | severity_type,
  # Transition period: one of check or check_hint must be present.
  # check_hint is deprecated — migrate existing ADRs to typed check variants.
  check_hint | String | optional,
  check      | constraint_check_type | optional,
  rationale  | String,
} in

let ontology_check_type = {
  decision_string    | String,
  invariants_at_risk | Array String,
  verdict            | verdict_type,
} in

let invariant_justification_type = {
  invariant  | String,
  claim      | String,
  mitigation | String,
} in

let consequences_type = {
  positive | Array String,
  negative | Array String,
} in

let adr_type = {
  id       | String | c.AdrIdFormat,
  title    | String,
  status   | status_type,
  date     | String,

  context           | String,
  decision          | String,
  rationale         | Array rationale_entry_type,
  consequences      | consequences_type,
  alternatives_considered | Array alternative_type,

  constraints    | Array constraint_type | c.NonEmptyConstraints | c.EachConstraintHasCheck,
  ontology_check | ontology_check_type,

  related_adrs             | Array String | default = [],
  supersedes               | String | optional,
  superseded_by            | String | optional,
  invariant_justification  | invariant_justification_type | optional,
} in

{
  AdrStatus              = status_type,
  Severity               = severity_type,
  Verdict                = verdict_type,
  ConstraintCheck        = constraint_check_type,
  Constraint             = constraint_type,
  RationaleEntry         = rationale_entry_type,
  Alternative            = alternative_type,
  OntologyCheck          = ontology_check_type,
  InvariantJustification = invariant_justification_type,
  Adr                    = adr_type,
}
