# Project card schema — typed self-definition for any project.
# Source of truth for display metadata, web assets, and portfolio publication.
#
# Each project maintains card.ncl locally and publishes (copies) to the
# portfolio repo alongside its assets/. The portfolio is self-contained —
# it does not depend on the original project repo being alive.

let source_type = [| 'Local, 'Remote, 'Historical |] in

let project_pub_status_type = [| 'Active, 'Beta, 'Maintenance, 'Archived, 'Stealth |] in

# ADR-040: a per-language guideline binding. Names a source + version; does NOT
# inline content. Content is authoritative under .ontoref/conventions/<lang>/,
# materialized into .claude/guidelines/<lang> as a view. Per-file resolution
# (symlink to origin | vendored | local-own) is DERIVED by inspecting the files,
# not stored here.
let guideline_binding_type = {
  lang    | String,                          # rust | nushell | nickel | markdown | …
  source  | String,                          # origin id (e.g. "dev-system") or "local"
  version | String       | default = "",     # declared version of the bound guideline set
  origin_path | String   | optional,         # absolute path to the shared origin dir (if any)
} in

# ADR-040: convention bindings — guidelines/CI/config a project binds. Optional;
# a project may declare none and stay valid (formalization-vs-adoption).
let conventions_type = {
  guidelines | Array guideline_binding_type | default = [],
  # CI is REFERENCED from the workflow layer (ADR-038), never re-declared here.
  ci         | { workflow_layer | String | default = "" } | default = { workflow_layer = "" },
  config     | { schema | String | default = "", profile | String | default = "" }
             | default = { schema = "", profile = "" },
} in

let project_card_type = {
  id          | String,                          # matches ontology_node in jpl DAG
  name        | String,
  tagline     | String,                          # stable identity statement
  description | String,
  primary_value_prop_id | String       | optional,  # ADR-035: canonical value-prop in .ontoref/positioning/value-props/; downstream renderers MAY prefer its claim over `tagline`
  conventions | conventions_type        | default = { guidelines = [], ci = { workflow_layer = "" }, config = { schema = "", profile = "" } },  # ADR-040: bound guidelines/CI/config. Default (not optional) — a record-contract optional field is dropped on export through the card's `d.ProjectCard & {...}` merge; default makes it always materialize.
  version     | String                 | default = "",
  status      | project_pub_status_type,
  source      | source_type            | default = 'Local,
  url         | String                 | default = "",
  repo        | String                 | default = "",
  docs        | String                 | default = "",
  logo        | String                 | default = "",
  started_at  | String                 | default = "",
  tags        | Array String           | default = [],
  tools       | Array String           | default = [],
  features    | Array String           | default = [],
  featured    | Bool                   | default = false,
  sort_order  | Number                 | default = 0,
  # Constellation layout: digest of assets materialized into this repo via `onre sync assets`.
  # Written by `onre sync assets`; checked by `onre sync assets check`. Optional so projects
  # without constellation assets layout remain valid.
  synced_assets | {
    source    | String,
    digest    | String,    # sha256:<hex> — aggregate over sorted file:hash pairs
    synced_at | String,    # ISO-8601 UTC
  } | optional,
} in

{
  SourceType         = source_type,
  ProjectPubStatus   = project_pub_status_type,
  GuidelineBinding   = guideline_binding_type,
  Conventions        = conventions_type,
  ProjectCard        = project_card_type,
}
