/// A statically registered node contribution, submitted at link time.
///
/// Crates that derive `OntologyNode` emit an
/// `inventory::submit!(NodeContribution { ... })` call, which is collected
/// here. All submissions are merged into [`Core`] via
/// [`Core::merge_contributors`](crate::ontology::Core::merge_contributors) —
/// NCL-loaded nodes always win on id collision.
///
/// [`Core`]: crate::ontology::Core
pub struct NodeContribution {
    /// Returns the node to contribute. Called once per contribution during
    /// merge.
    pub supplier: fn() -> crate::types::Node,
}

inventory::collect!(NodeContribution);

/// A statically registered test coverage entry, submitted at test-binary link
/// time.
///
/// Produced by `#[onto_validates(practice = "...", adr = "...")]` from
/// `ontoref-derive`. Collected by [`Core::uncovered_practices`] to identify
/// practices without test coverage.
///
/// Only present in test binaries — zero production binary impact because
/// `#[cfg(all(test, feature = "derive"))]` gates all `inventory::submit!`
/// calls.
///
/// [`Core::uncovered_practices`]: crate::ontology::Core::uncovered_practices
pub struct TestCoverage {
    /// Practice node id validated by this test, if any.
    pub practice_id: Option<&'static str>,
    /// ADR id validated by this test, if any.
    pub adr_id: Option<&'static str>,
}

inventory::collect!(TestCoverage);

/// A statically registered config field inventory entry.
///
/// Consumer projects derive `#[derive(ConfigFields)]` on their serde config
/// structs to emit `inventory::submit!(ConfigFieldsEntry { ... })` at link
/// time. Ontoref daemon and test helpers iterate these entries to compare
/// against NCL section exports — detecting unclaimed NCL fields and fields
/// expected by Rust but absent in the contract.
///
/// Field names respect `#[serde(rename = "...")]` — the registered name is
/// what serde would use to match the JSON key, not the Rust identifier.
pub struct ConfigFieldsEntry {
    /// Matches the `id` in the project's `manifest.ncl
    /// config_surface.sections`.
    pub section_id: &'static str,
    /// Path to the NCL file for this section, relative to the project root.
    /// Used to locate the file for export during coherence verification.
    pub ncl_file: &'static str,
    /// Fully-qualified Rust type name (e.g.
    /// `"vapora_backend::config::ServerConfig"`). Informational — used in
    /// coherence reports for traceability.
    pub struct_name: &'static str,
    /// All serde field names this struct expects from the NCL JSON export.
    pub fields: &'static [&'static str],
}

inventory::collect!(ConfigFieldsEntry);
