let content = import "content.ncl" in

let repo_kind_type = [|
  'Framework,
  'DevWorkspace,
  'PublishedCrate,
  'Service,
  'Library,
  'AgentResource,
  'Mixed,
  'PersonalOntology,
|] in

let consumer_type = [|
  'Developer,
  'Agent,
  'EndUser,
  'CI,
  'Downstream,
|] in

let artifact_kind_type = [|
  'RustDoc,
  'JsonSchema,
  'ContainerImage,
  'CratePackage,
  'StaticSite,
  'NuPlugin,
  'OntologyExport,
|] in

let audit_level_type = [|
  'Quick,
  'Standard,
  'Strict,
|] in

# ── Operational layers ──────────────────────────────────────────────────────
# A layer is a named region of the repo with visibility rules per mode.
# The `committed` flag distinguishes product (true) from process (false).

let layer_type = {
  id          | String,
  paths       | Array String,
  committed   | Bool,
  description | String | default = "",
} in

# ── Operational modes ───────────────────────────────────────────────────────
# A mode is an active perspective the developer/agent switches into.
# It determines which layers are visible and what audit level applies.

let op_mode_type = {
  id              | String,
  description     | String           | default = "",
  visible_layers  | Array String,
  audit_level     | audit_level_type | default = 'Standard,
  pre_activate    | Array String     | default = [],
  post_activate   | Array String     | default = [],
} in

# ── Publication service ─────────────────────────────────────────────────────
# Where artifacts go and what operations surround the publish action.

let auth_method_type = [|
  'SSH,
  'Token,
  'OIDC,
  'None,
|] in

let service_scope_type = [|
  'Public,
  'PrivateNetwork,
  'LocalRegistry,
  'SelfHosted,
|] in

let publication_service_type = {
  id           | String,
  artifact     | artifact_kind_type,
  scope        | service_scope_type,
  registry_url | String              | default = "",
  auth_method  | auth_method_type    | default = 'None,
  pre_publish  | Array String        | default = [],
  post_publish | Array String        | default = [],
  condition    | String              | default = "",
  trigger      | String,
} in

# ── Consumption modes (who consumes, what they need) ────────────────────────

let consumption_mode_type = {
  consumer     | consumer_type,
  needs        | Array artifact_kind_type,
  audit_level  | audit_level_type        | default = 'Standard,
  description  | String                  | default = "",
} in

# ── Tool requirements ─────────────────────────────────────────────────────
# Declares what tools the project needs. install-tools.nu and sync audit
# consume this to verify availability or trigger installation.

let install_method_type = [|
  'Builtin,
  'Cargo,
  'Npm,
  'Brew,
  'Pip,
  'Manual,
|] in

let tool_requirement_type = {
  name           | String,
  install_method | install_method_type | default = 'Builtin,
  version        | String             | default = "",
  required       | Bool               | default = true,
} in

# ── Justfile convention ──────────────────────────────────────────────────
# Declares expected justfile structure so sync audit can verify completeness.

let justfile_system_type = [| 'Import, 'Mod, 'Hybrid, 'Flat, 'None |] in

let justfile_convention_type = {
  system           | justfile_system_type | default = 'Mod,
  required_modules | Array String         | default = ["build", "test", "dev", "ci"],
  required_recipes | Array String         | default = ["default", "help"],
} in

# ── Config surface ──────────────────────────────────────────────────────
# Describes the project's configuration system: where the NCL config lives,
# how it is structured, and which consumers (Rust structs, Nushell scripts,
# CI pipelines, external tools) read each section.
#
# A field in a section is "unclaimed" only if no consumer declares it —
# not merely absent from the Rust struct. CI/CD scripts and external tooling
# are first-class consumers.
#
# Mutation uses an override layer: original NCL files are never modified.
# Changes are written to {section}.overrides.ncl and merged via & at the
# entry point. Comments, contracts, and formatting in originals are preserved.

let config_kind_type = [|
  'NclMerge,    # multiple .ncl files merged via & operator
  'TypeDialog,  # .typedialog/ structure with form.toml + validators + fragments
  'SingleFile,  # single monolithic .ncl file
|] in

let consumer_kind_type = [|
  'RustStruct,  # serde::Deserialize struct in a Rust crate
  'NuScript,    # Nushell script accessing $config.field paths
  'CiPipeline,  # CI pipeline (Woodpecker, GitHub Actions, etc.)
  'External,    # external tool or process reading config JSON
|] in

let config_consumer_type = {
  # Identifier for this consumer (e.g. "vapora-backend", "deploy-script").
  id     | String,
  kind   | consumer_kind_type,
  # Reference path: Rust fully-qualified type or script path.
  # e.g. "vapora_backend::config::ServerConfig" or "scripts/deploy.nu"
  ref    | String         | default = "",
  # Fields this consumer reads. Empty means the consumer reads all fields,
  # which is treated as claiming all NCL keys for orphan analysis.
  fields | Array String   | default = [],
} in

let config_section_type = {
  # Section identifier, must match the top-level NCL key (e.g. "server").
  id          | String,
  # Path to the NCL file for this section, relative to config_root.
  file        | String,
  # Path to the NCL contract file that types this section. Relative to
  # contracts_path (or project root if contracts_path is empty).
  contract    | String         | default = "",
  description | String         | default = "",
  # Why this section exists and why the current values were chosen.
  # Consumed by the quickref generator to explain decisions, not just values.
  rationale   | String         | default = "",
  # When false: ontoref will only read, never write, this section.
  mutable     | Bool           | default = true,
  # All consumers of this section. A NCL field present in no consumer is
  # flagged as unclaimed in the coherence report.
  consumers   | Array config_consumer_type | default = [],
} in

let config_surface_type = {
  # Directory containing config NCL files, relative to project root.
  # e.g. "config/", "site/config/", ".typedialog/provisioning/"
  config_root    | String,
  # Main NCL file that merges all sections (entry point for nickel export).
  entry_point    | String           | default = "config.ncl",
  kind           | config_kind_type | default = 'NclMerge,
  # Directory containing NCL contract files. Relative to project root.
  # Passed as NICKEL_IMPORT_PATH component when exporting.
  contracts_path | String           | default = "",
  # Directory where ontoref writes {section}.overrides.ncl files.
  # Defaults to config_root when empty.
  overrides_dir  | String           | default = "",
  sections       | Array config_section_type | default = [],
} in

# ── Claude baseline ─────────────────────────────────────────────────────
# Declares expected .claude/ structure per project.

let claude_baseline_type = {
  guidelines       | Array String | default = ["bash", "nushell"],
  session_hook     | Bool         | default = true,
  stratum_commands | Bool         | default = true,
} in

# ── Capabilities ────────────────────────────────────────────────────────────
# Declares what the project does, why it was built, how it works, and what
# artifacts it produces. Answers the "what IS this, why does it exist, how
# does it work" questions that Practice nodes in core.ncl don't — those are
# architectural; capabilities are operational and audience-facing.

let capability_type = {
  # Unique identifier, e.g. "protocol-spec", "daemon-api".
  id        | String,
  name      | String,
  # One-line answer to "what does this capability do?" for quick scanning.
  summary   | String,
  # The WHY: motivation, problem solved, alternatives consciously rejected.
  rationale | String        | default = "",
  # Implementation level: key patterns, entry points, data flows.
  how       | String        | default = "",
  # Observable artifacts: crate paths, API routes, NCL schemas, CLI commands.
  artifacts | Array String  | default = [],
  # ADR IDs that formalize architectural decisions in this capability.
  adrs      | Array String  | default = [],
  # Ontology node IDs this capability manifests in the DAG.
  nodes     | Array String  | default = [],
} in

# ── Requirements ─────────────────────────────────────────────────────────────
# Declares what the project needs to run (production) or develop (development).
# Covers tools, external services, environment variables, and infrastructure —
# not just dev tooling. Enables agents and operators to audit readiness.

let env_target_type = [|
  'Production,   # required only in production deployments
  'Development,  # required only during development / CI
  'Both,         # required in all environments
|] in

let requirement_kind_type = [|
  'Tool,           # executable on PATH (e.g. nushell, nickel, just)
  'Service,        # external service (e.g. surrealdb, nats, postgres)
  'EnvVar,         # environment variable that must be set
  'Infrastructure, # filesystem layout, network, or platform dependency
|] in

let requirement_type = {
  id        | String,
  name      | String,
  env       | env_target_type       | default = 'Both,
  kind      | requirement_kind_type,
  # Minimum version or value constraint. Empty means no constraint.
  version   | String                | default = "",
  required  | Bool                  | default = true,
  # What breaks or degrades if this requirement is absent.
  impact    | String                | default = "",
  # How to install, set, or provision this requirement.
  provision | String                | default = "",
} in

# ── Critical Dependencies ────────────────────────────────────────────────────
# External dependencies (crates, services, infra) whose contract breakage or
# disappearance has a documented blast radius. Distinct from requirements:
# requirements are prerequisites to run; critical_deps are runtime load-bearing
# dependencies whose failure affects specific capabilities.

let critical_dep_type = {
  id             | String,
  name           | String,
  # Canonical reference: crates.io identifier, GitHub URL, or service name.
  ref            | String,
  # Which capabilities or features depend on this dependency.
  used_for       | String,
  # What breaks if this dep disappears or breaks its API contract.
  failure_impact | String,
  # Mitigation: feature flags, fallbacks, alternative build targets.
  mitigation     | String | default = "",
} in

# ── Domain ontology layer ───────────────────────────────────────────────────
# A project may have two distinct ontological layers:
#   1. Self-ontology  (.ontology/) — the project describing itself: state, ADRs, practices.
#      Present in any project using the ontoref protocol.
#   2. Domain ontology — schemas and contracts the project defines for others to consume
#      (domain_provides), or schemas the project imports from an upstream framework
#      (domain_origin). These may be NCL-based or expressed in code (Rust traits, etc.).
#
# A project that only has self-ontology omits both fields.
# A project that is a framework defines domain_provides.
# A project that is an implementation defines domain_origin.
# Both fields are optional and independent.

let domain_ontology_kind_type = [|
  'Ncl,       # domain schemas are NCL contracts (importable via NICKEL_IMPORT_PATH)
  'RustTrait, # domain contracts are Rust traits / type-system boundaries
  'Mixed,     # combination of NCL contracts and code-level contracts
  'Implicit,  # no formal schema; the domain is implicit in conventions and documentation
|] in

let domain_provides_type = {
  # Canonical identifier for the domain this project defines.
  id          | String,
  # Human-readable domain name.
  name        | String,
  # Where the domain schemas / contracts live within this project.
  schema_path | String           | default = "ontology/schemas/",
  # repo_kind expected for implementation projects consuming this domain.
  impl_repo_kind | String        | default = "",
  # How the domain is expressed: NCL, RustTrait, Mixed, or Implicit.
  kind        | domain_ontology_kind_type | default = 'Ncl,
  description | String           | default = "",
} in

let domain_origin_type = {
  # Identifier matching the upstream framework's domain_provides.id.
  id          | String,
  # Human-readable name of the upstream framework / core project.
  name        | String,
  # Local filesystem path to the upstream framework project root.
  # Used to resolve NICKEL_IMPORT_PATH entries and CLI navigation.
  path        | String           | default = "",
  # Which schema stems from the upstream domain are imported/extended.
  # Empty means the project inherits the full domain surface.
  extends     | Array String     | default = [],
  # If true, this project's self-ontology (.ontology/) IS the domain implementation.
  # If false, the domain schemas are consumed but the self-ontology is independent.
  integrated  | Bool             | default = true,
} in

# ── Root manifest ───────────────────────────────────────────────────────────

let manifest_type = {
  project              | String,
  repo_kind            | repo_kind_type,
  # Human-readable project description. Consumed by collect-identity in describe.nu.
  description          | String                         | default = "",
  layers               | Array layer_type              | default = [],
  operational_modes    | Array op_mode_type             | default = [],
  consumption_modes    | Array consumption_mode_type,
  publication_services | Array publication_service_type | default = [],
  tools                | Array tool_requirement_type    | default = [],
  justfile             | justfile_convention_type       | default = {},
  claude               | claude_baseline_type           | default = {},
  default_audit        | audit_level_type               | default = 'Standard,
  default_mode         | String                         | default = "dev",
  # Node ID this project maps to in the ontology DAG.
  # Used by portfolio tooling to cross-reference publication cards.
  ontology_node        | String                         | default = "",
  # Publishable content assets (logos, diagrams, web pages).
  # Declares source paths and publication targets; consumed by publish modes
  # and sync drift detection to verify assets exist and are deployed correctly.
  content_assets       | Array content.ContentAsset     | default = [],
  # Reusable NCL templates for mode steps, agent prompts, and publication cards.
  # Each template is a parameterised NCL function at source_path.
  templates            | Array content.ContentTemplate  | default = [],
  # Configuration surface: where the project's NCL config lives, which
  # consumers read each section, and mutation rules. Optional — projects
  # without a structured config system omit this field.
  config_surface       | config_surface_type            | optional,
  # What the project does, why it was built, how each capability works,
  # and which artifacts/ADRs/nodes it manifests.
  capabilities         | Array capability_type          | default = [],
  # Prerequisites for production and/or development: tools, services,
  # env vars, infrastructure. Superset of the legacy `tools` field.
  requirements         | Array requirement_type         | default = [],
  # External dependencies with documented failure blast radius.
  critical_deps        | Array critical_dep_type        | default = [],
  # Domain ontology layer — optional, independent of self-ontology (.ontology/).
  # Set when this project IS a domain framework defining schemas for others.
  domain_provides      | domain_provides_type           | optional,
  # Set when this project IS an implementation extending an upstream domain framework.
  domain_origin        | domain_origin_type             | optional,
} in

{
  RepoKind            = repo_kind_type,
  ConsumerType        = consumer_type,
  ArtifactKind        = artifact_kind_type,
  AuditLevel          = audit_level_type,
  AuthMethod          = auth_method_type,
  ServiceScope        = service_scope_type,
  InstallMethod       = install_method_type,
  JustfileSystem      = justfile_system_type,
  Layer               = layer_type,
  OperationalMode     = op_mode_type,
  ConsumptionMode     = consumption_mode_type,
  PublicationService  = publication_service_type,
  ToolRequirement     = tool_requirement_type,
  JustfileConvention  = justfile_convention_type,
  ClaudeBaseline      = claude_baseline_type,
  ProjectManifest     = manifest_type,
  ConfigKind          = config_kind_type,
  ConsumerKind        = consumer_kind_type,
  ConfigConsumer      = config_consumer_type,
  ConfigSection       = config_section_type,
  ConfigSurface       = config_surface_type,
  EnvTarget           = env_target_type,
  RequirementKind     = requirement_kind_type,
  Capability          = capability_type,
  Requirement         = requirement_type,
  CriticalDep         = critical_dep_type,
  DomainOntologyKind  = domain_ontology_kind_type,
  DomainProvides      = domain_provides_type,
  DomainOrigin        = domain_origin_type,
}
