let content = import "content.ncl" in let repo_kind_type = [| '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 # ── 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 = [], } 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, }