ontoref/ontology/schemas/manifest.ncl
Jesús Pérez 472952e29b
Some checks failed
Rust CI / Security Audit (push) Has been cancelled
Rust CI / Check + Test + Lint (nightly) (push) Has been cancelled
Rust CI / Check + Test + Lint (stable) (push) Has been cancelled
Nickel Type Check / Nickel Type Checking (push) Has been cancelled
feat: domain extension system, VCS abstraction, personal/provisioning domains, web subpages
Domain extension system (ADR-012): bash-layer dispatch activates repo_kind-conditional CLI
  domains. install.nu copies domains/ tree; short_alias wrappers generated (personal, prov).
  ore help and describe capabilities domain-aware.

  personal domain (PersonalOntology): career skills/talks/publications/positioning, CFP
  pipeline (Watching→Delivered), opportunities lifecycle, content pipeline, Sessionize
  integration. Daemon pages: /career, /personal.

  provisioning domain (DevWorkspace/Mixed): FSM state, next transitions, connections graph,
  gates, workspace card, capabilities, backlog. Daemon page: /provisioning.

  VCS abstraction layer (ADR-013): reflection/modules/vcs.nu — uniform jj/git API via
  filesystem detection (.jj/ vs .git/). opmode.nu and git-event.nu migrated off ^git.
  reflection/bin/jjw.nu — jj + ontoref + Radicle agent workspace lifecycle. jjw-ncl-merge.nu
  registered as jj merge tool for .ontology/ NCL conflicts. init-repo.nu for new_project mode.
  jj/rad not in ontoref requirements — belong in orchestration project manifests.

  'Framework RepoKind: ontology/schemas/manifest.ncl gains 'Framework variant; ontoref
  self-identifies as framework — no domain activates for the protocol itself.

  Web presence: personal.html and provisioning.html domain subpages. index.html gains
  "Project Types — Domain Extensions" section with type cards and subpage links. Nav
  compacted (Arch/Prov labels, solid backdrop-filter background).

  on+re: vcs-abstraction (adrs: adr-013) and agent-workspace-orchestration Practice nodes;
  21 manifest capabilities; state.ncl catalysts updated.
2026-04-07 23:08:29 +01:00

413 lines
18 KiB
Text

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