Manifest Self-Interrogation Layer — Three Semantic Axes
Accepted
Context
The manifest.ncl schema described structural facts (layers, modes, consumption modes, tools, config surface) but had no typed layer for self-interrogation: agents and operators could not query why a capability exists, what it needs to run, or what external dependencies have a documented blast radius. The existing tools[] field covered only dev tooling (install_method, version) — no prod/dev classification, no services, no environment variables, no infrastructure dependencies. Practice/node descriptions in core.ncl carry architectural meaning (invariant=true, ADR-backed) but are not the right home for operational, audience-facing descriptions of what a project offers. Capabilities, requirements, and dependency blast-radius analysis are three orthogonal concerns that needed typed, queryable homes in the manifest schema.
Decision
Three new typed arrays are added to manifest_type: capabilities[] (capability_type), requirements[] (requirement_type), and critical_deps[] (critical_dep_type). These are semantically distinct layers: capabilities answer 'what does this project do, why does it exist, and how does it work' with explicit cross-references to ontology node IDs and ADR IDs; requirements classify prerequisites by env_target_type ('Production | 'Development | 'Both) and requirement_kind_type ('Tool | 'Service | 'EnvVar | 'Infrastructure); critical_deps document blast radius — what breaks when an external dependency disappears or breaks its contract — distinct from requirements because the concern is runtime failure impact, not startup prerequisites. A description | String | default = '' field is also added to manifest_type, fixing a pre-existing bug where collect-identity in describe.nu read manifest.description? (always null) instead of a field that existed. describe requirements is added as a new subcommand; describe capabilities is extended to render manifest capabilities; describe guides output gains capabilities/requirements/critical_deps keys so agents on cold start receive full self-interrogation context.
Constraints
- Soft capability_type.nodes[] entries must reference valid node IDs declared in .ontology/core.ncl
- Hard critical_dep_type.failure_impact must be a non-empty string — undocumented blast radius defeats the purpose of the type
Alternatives considered
- Extend tools[] with env and kind fields — rejected: tools[] is semantically 'dev tooling required to build'. Extending it to cover SurrealDB (a production service) or ONTOREF_ADMIN_TOKEN_FILE (an env var) would violate the field's implied meaning. A type named tool_requirement_type that has kind = 'Service is confusing. Separate types with clear names are preferable to an overloaded catch-all.
- Add capability descriptions to Practice nodes in core.ncl — rejected: Practice nodes are architectural: invariant=true nodes are ADR-protected and represent constraints future contributors must follow. Adding 'what does this offer to end users' to the invariant graph would force every capability description through the ADR lifecycle. capabilities[] is per-project, evolves freely, and belongs to the manifest (the operational layer), not the ontology (the architectural layer).
- Merge critical_deps into requirements with an is_critical flag — rejected: The concern is different: requirements are prerequisites (the system cannot start without them). critical_deps are runtime load-bearing with a documented blast radius. A requirement that is optional (required = false) can still be a critical dep. The is_critical flag on requirement_type would blur this distinction and make failure_impact logically optional (not required for non-critical items) — creating a type that is partially applicable based on a flag, which is a code smell in typed schemas.