Skip to documentation
SLOP

tiny.smg.api

Reference tiny.smg api

Defined in tiny.smg.

Render-neutral public-surface facts derived from a scanned graph.

API (63)

Actions

Public operations.

Types and contracts

Public types and contracts.

Values and defaults

Public values and defaults.

No direct callersNo direct callstiny.smgapi
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Called byCallsNo direct callersapideclarationSourceapi.PublicDeclarationbindingSource
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersapideclarationSourceSpanapi.PublicDeclarationbindingSourceSpan
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersapideclarationSourceapi.PublicDeclarationcanonicalSource
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersapideclarationSourceSpanapi.PublicDeclarationcanonicalSourceSpan
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersprivate; no linktools.smg.src.apimoduleNodeprivate; no linktools.smg.src.apisameSourceFileapi.PublicDeclarationdocumentation
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersprivate; no linktools.smg.src.apimemberIdentifierapi.PublicMemberidentifier
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersprivate; no linktools.smg.src.apimemberSourceSpanapi.PublicMembersourceSpan
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersmodelpairValueapi.PublicMembersourceSpelling
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersmodelpairValueapi.PublicMembertypeExpression
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersmodelpairValueapi.PublicMembervalueExpression
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersprivate; no linktools.smg.src.apimemberIdentifierapi.PublicMemberGapidentifier
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersprivate; no linktools.smg.src.apimemberSourceSpanapi.PublicMemberGapsourceSpan
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersmodelpairValueapi.PublicMemberGapsourceSpelling
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate; no linktools.smg.src.scan.testexpectZigPublicProjectiontest; no linktools.smg.src.scan.testtest: zig external import binding doe...test; no linktools.smg.src.scan.testtest: zig public projection admits pa...test; no linktools.smg.src.scan.testtest: zig public projection keeps mod...modelpairValueapialiasTarget
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsapipublicMemberGapsapipublicMembersprivate; no linktools.smg.src.scan.testexpectZigStructMembersmodelpairValueapicontainerKind
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsapi.PublicDeclarationbindingSourceapi.PublicDeclarationcanonicalSourcetest; no linktools.smg.src.apitest: declaration source requires com...test; no linktools.smg.src.apitest: public declaration spans preser...test; no linktools.smg.src.scan.testtest: Chiclet scan preserves public d...apideclarationSourceSpanmodelpairValueapideclarationSource
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsapi.PublicDeclarationbindingSourceSpanapi.PublicDeclarationcanonicalSourceSpanapideclarationSourcetest; no linktools.smg.src.apitest: public declaration spans preser...test; no linktools.smg.src.scan.testtest: Chiclet scan preserves public d...modelpairValueapideclarationSourceSpan
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate; no linktools.smg.src.apiresolveAliasTargettest; no linktools.smg.src.scan.pipeline.scantest: zig tree scan exposes declared ...private; no linktools.smg.src.scan.testexpectZigComplexDeclaredTypesprivate; no linktools.smg.src.scan.testexpectZigDeclaredTypeGraphtest; no linktools.smg.src.scan.testtest: zig ast scan resolves imported ...+3 moremodelpairValueapidirectAliasTarget
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest; no linktools.smg.src.apitest: explicit declared type distingu...test; no linktools.smg.src.scan.pipeline.scantest: zig tree scan exposes declared ...private; no linktools.smg.src.scan.testexpectZigComplexDeclaredTypesprivate; no linktools.smg.src.scan.testexpectZigDeclaredTypeGraphprivate; no linktools.smg.src.scan.testexpectZigRecoveryDeclaredTypestest; no linktools.smg.src.scan.testtest: zig line recovery does not clai...modelpairValueapiexplicitDeclaredType
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsapiresolvePublicPathtest; no linktools.smg.src.apitest: public declarations keep unreso...test; no linktools.smg.src.apitest: public declarations resolve ali...test; no linktools.smg.src.apitest: public declarations resolve dot...test; no linktools.smg.src.apitest: public declarations resolve loc...+16 moreapifreePublicDeclarations
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callstest; no linktools.smg.src.apitest: public member gaps preserve exp...private; no linktools.smg.src.scan.testexpectZigUnionAndPositionalMembersapifreePublicMemberGaps
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callstest; no linktools.smg.src.apitest: public members retain canonical...private; no linktools.smg.src.scan.testexpectZigNestedMembersprivate; no linktools.smg.src.scan.testexpectZigStructMembersprivate; no linktools.smg.src.scan.testexpectZigUnionAndPositionalMembersprivate; no linktools.smg.src.scan.testonlyPublicMemberNametest; no linktools.smg.src.scan.testtest: zig public member refresh retir...apifreePublicMembers
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsapipublicDeclarationsapipublicMemberGapsapipublicMembersapivisibilityapiisPublic
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate; no linktools.smg.src.calls.analyzebuildReachprivate; no linktools.smg.src.context.packisRelevantTestexportsisArchitectureCouplingmodelpairValueapiisTestDeclaration
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest; no linktools.smg.src.apitest: public declarations resolve ali...private; no linktools.smg.src.scan.testexpectZigPublicProjectiontest; no linktools.smg.src.scan.testtest: zig public projection admits pa...private; no linktools.smg.src.apimoduleNodeapiownerForFile
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsapiresolvePublicPathtest; no linktools.smg.src.apitest: public declarations bound recur...test; no linktools.smg.src.apitest: public declarations keep unreso...test; no linktools.smg.src.apitest: public declarations reject nont...test; no linktools.smg.src.apitest: public declarations resolve ali...+18 moreprivate; no linktools.smg.src.apicanonicalDeclarationapiisPublicapipublicDeclarations
Static calls · unresolved targets: 0 · external targets: 4.
Called byCallstest; no linktools.smg.src.apitest: public member gaps preserve exp...private; no linktools.smg.src.scan.testexpectZigUnionAndPositionalMembersapicontainerKindapiisPublicprivate; no linktools.smg.src.apipublicMemberGapapipublicMemberGaps
Static calls · unresolved targets: 0 · external targets: 4.
Called byCallstest; no linktools.smg.src.apitest: public members retain canonical...private; no linktools.smg.src.scan.testexpectZigNestedMembersprivate; no linktools.smg.src.scan.testexpectZigStructMembersprivate; no linktools.smg.src.scan.testexpectZigUnionAndPositionalMembersprivate; no linktools.smg.src.scan.testonlyPublicMemberNametest; no linktools.smg.src.scan.testtest: zig public member refresh retir...apicontainerKindapiisPublicprivate; no linktools.smg.src.apiprojectPublicMembersprivate; no linktools.smg.src.apisupportedMemberKindapipublicMembers
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallstest; no linktools.smg.src.apitest: exact public paths traverse can...test; no linktools.smg.src.apitest: public declarations resolve loc...test; no linktools.smg.src.scan.testtest: zig ast scan resolves imported ...test; no linktools.smg.src.scan.testtest: zig scan resolves same-name imp...private; no linktools.smg.src.apidirectPublicNameapifreePublicDeclarationsapipublicDeclarationsprivate; no linktools.smg.src.apipublicPathComponentEndapiresolvePublicPath
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate; no linktools.smg.src.apiimportBindingtest; no linktools.smg.src.apitest: public declarations resolve ali...private; no linktools.smg.src.scan.testexpectZigPublicProjectiontest; no linktools.smg.src.scan.testtest: zig scan resolves same-name imp...modelpairValueapisignature
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callstest; no linktools.smg.src.apitest: public declaration spans preser...test; no linktools.smg.src.apitest: verified source rejects stale a...apiverifiedSourcetest; no linktools.smg.src.scan.pipeline.scantest: zig tree scan exposes declared ...scan.source_metadataspanMetadataapisourceDigest
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest; no linktools.smg.src.apitest: verified source rejects stale a...apisourceDigestapiverifiedSource
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsapiisPublicprivate; no linktools.smg.src.scan.testexpectZigPublicProjectiontest; no linktools.smg.src.scan.testtest: zig public projection keeps mod...modelpairValueapivisibility
Static calls · unresolved targets: 0 · external targets: 0.

Source: tools/smg/src/api.zig

zig
//! Render-neutral public-surface facts derived from a scanned graph.const std = @import("std");const graph_mod = @import("graph.zig");const limits_mod = @import("limits/root.zig");const model = @import("model.zig");const testing_limits = @import("root.zig").default_limits.api;pub const visibility_key = "visibility";pub const test_key = "test";pub const signature_key = "signature";pub const alias_target_key = "alias_target";pub const direct_alias_target_key = "zig_direct_alias_target";pub const declared_type_key = "zig_declared_type";pub const declared_type_state_key = "zig_declared_type_state";pub const container_kind_key = "zig_container_kind";pub const member_identifier_key = "zig_member_identifier";pub const member_order_key = "zig_member_order";pub const source_spelling_key = "zig_source_spelling";pub const member_type_key = "zig_member_type";pub const member_expression_key = "zig_member_expression";pub const member_gap_key = "zig_member_gap";pub const source_start_byte_key = "source_start_byte";pub const source_end_byte_key = "source_end_byte";pub const source_hash_key = "source_sha256";pub const source_digest_bytes = std.crypto.hash.sha2.Sha256.digest_length;pub const source_digest_hex_bytes = source_digest_bytes * 2;pub const Error = graph_mod.Error || error{    AliasCycle,    DeclaredTypeUnavailable,    InvalidPublicPath,    InvalidSourceDigest,    InvalidSourceSpan,    InvalidPublicMember,    NotPublicDeclaration,    PublicPathDepthExceeded,    PublicPathNotFound,    SourceDigestUnavailable,    SourceDigestMismatch,    SourceFileUnavailable,    SourceSpanUnavailable,};/// A Zig container category preserved independently from graph node roles.pub const ContainerKind = enum {    @"struct",    @"enum",    error_set,    @"union",    @"opaque",};/// A source-level member category that is part of a public Zig type surface.pub const MemberKind = enum {    field,    enum_tag,    error_member,};/// Why a source member is preserved but not projected as a PublicMember.pub const MemberGapKind = enum {    unsupported_container_member,    unsupported_member_syntax,};/// An exact half-open byte range in a source file.pub const SourceSpan = struct {    start_byte: u32,    end_byte: u32,};/// Validated source location and digest for one declaration.pub const DeclarationSource = struct {    file: []const u8,    span: SourceSpan,    digest: [source_digest_bytes]u8,};/// A public binding and the definition reached through its alias chain.pub const PublicDeclaration = struct {    exported: model.Node,    canonical: model.Node,    /// Returns source-owned export docs or docs on the exact canonical declaration.    pub fn documentation(self: PublicDeclaration) ?[]const u8 {        if (self.exported.docstring) |docstring| return docstring;        if (sameSourceFile(self.exported, self.canonical)) {            if (moduleNode(self.canonical)) return null;        }        return self.canonical.docstring;    }    /// Returns the exact source span of the exported binding.    pub fn bindingSourceSpan(self: PublicDeclaration) Error!SourceSpan {        return declarationSourceSpan(self.exported);    }    /// Returns the exact source span of the canonical definition.    pub fn canonicalSourceSpan(self: PublicDeclaration) Error!SourceSpan {        return declarationSourceSpan(self.canonical);    }    /// Returns validated source evidence for the exported binding.    pub fn bindingSource(self: PublicDeclaration) Error!DeclarationSource {        return declarationSource(self.exported);    }    /// Returns validated source evidence for the canonical definition.    pub fn canonicalSource(self: PublicDeclaration) Error!DeclarationSource {        return declarationSource(self.canonical);    }};/// Returns a validated exact source span stored on one declaration node.pub fn declarationSourceSpan(node: model.Node) Error!SourceSpan {    const start_raw = model.pairValue(node.metadata, source_start_byte_key);    const end_raw = model.pairValue(node.metadata, source_end_byte_key);    if (start_raw == null and end_raw == null) return error.SourceSpanUnavailable;    if (start_raw == null or end_raw == null) return error.InvalidSourceSpan;    const start = std.fmt.parseInt(u32, start_raw.?, 10) catch        return error.InvalidSourceSpan;    const end = std.fmt.parseInt(u32, end_raw.?, 10) catch        return error.InvalidSourceSpan;    if (start >= end) return error.InvalidSourceSpan;    return .{ .start_byte = start, .end_byte = end };}/// Returns validated file, span, and digest evidence for one declaration node.pub fn declarationSource(node: model.Node) Error!DeclarationSource {    const file = node.file orelse return error.SourceFileUnavailable;    if (file.len == 0) return error.SourceFileUnavailable;    const encoded = model.pairValue(node.metadata, source_hash_key) orelse        return error.SourceDigestUnavailable;    if (encoded.len != source_digest_hex_bytes) {        return error.InvalidSourceDigest;    }    for (encoded) |byte| {        if (!std.ascii.isHex(byte) or std.ascii.isUpper(byte)) {            return error.InvalidSourceDigest;        }    }    var digest: [source_digest_bytes]u8 = undefined;    _ = std.fmt.hexToBytes(&digest, encoded) catch        return error.InvalidSourceDigest;    return .{        .file = file,        .span = try declarationSourceSpan(node),        .digest = digest,    };}/// Returns the SHA-256 digest for exact source bytes.pub fn sourceDigest(source: []const u8) [source_digest_bytes]u8 {    var digest: [source_digest_bytes]u8 = undefined;    std.crypto.hash.sha2.Sha256.hash(source, &digest, .{});    return digest;}/// Returns the exact declaration bytes after validating their stored span and digest.pub fn verifiedSource(    evidence: DeclarationSource,    contents: []const u8,) Error![]const u8 {    if (evidence.span.start_byte >= evidence.span.end_byte or        evidence.span.end_byte > contents.len)    {        return error.InvalidSourceSpan;    }    const exact = contents[evidence.span.start_byte..evidence.span.end_byte];    const digest = sourceDigest(exact);    if (!std.mem.eql(u8, &digest, &evidence.digest)) {        return error.SourceDigestMismatch;    }    return exact;}/// A member admitted through a public export and owned by its canonical type.////// The record and its strings borrow from the unchanged graph. Only the slice/// returned by publicMembers is allocated.pub const PublicMember = struct {    owner: PublicDeclaration,    node: model.Node,    kind: MemberKind,    /// The zero-based ordinal among source members owned by the canonical type.    order: u32,    /// Returns the exact identifier token, or null for a positional field.    pub fn identifier(self: PublicMember) ?[]const u8 {        return memberIdentifier(self.node);    }    /// Returns the exact source spelling of the member, excluding its docs.    pub fn sourceSpelling(self: PublicMember) []const u8 {        return model.pairValue(self.node.metadata, source_spelling_key) orelse            unreachable;    }    /// Returns the exact field type expression when the source has one.    pub fn typeExpression(self: PublicMember) ?[]const u8 {        return model.pairValue(self.node.metadata, member_type_key);    }    /// Returns an exact field default or enum assigned-value expression.    ///    /// The explicit member kind determines how a renderer labels the value.    pub fn valueExpression(self: PublicMember) ?[]const u8 {        return model.pairValue(self.node.metadata, member_expression_key);    }    /// Returns source-owned documentation attached to this member.    pub fn documentation(self: PublicMember) ?[]const u8 {        return self.node.docstring;    }    /// Returns the exact half-open source byte range of sourceSpelling.    pub fn sourceSpan(self: PublicMember) SourceSpan {        return memberSourceSpan(self.node) orelse unreachable;    }};/// A source member deliberately outside the supported public projection.////// The record and its strings borrow from the unchanged graph. Only the slice/// returned by publicMemberGaps is allocated.pub const PublicMemberGap = struct {    owner: PublicDeclaration,    node: model.Node,    kind: MemberGapKind,    /// The zero-based ordinal among source members owned by the canonical type.    order: u32,    /// Returns an exact identifier token when the source member has one.    pub fn identifier(self: PublicMemberGap) ?[]const u8 {        return memberIdentifier(self.node);    }    /// Returns the exact source spelling of the unsupported member.    pub fn sourceSpelling(self: PublicMemberGap) []const u8 {        return model.pairValue(self.node.metadata, source_spelling_key) orelse            unreachable;    }    /// Returns source-owned documentation attached to this member.    pub fn documentation(self: PublicMemberGap) ?[]const u8 {        return self.node.docstring;    }    /// Returns the exact half-open source byte range of sourceSpelling.    pub fn sourceSpan(self: PublicMemberGap) SourceSpan {        return memberSourceSpan(self.node) orelse unreachable;    }};/// Returns the borrowed name of the scanned module or package that owns a source file.pub fn ownerForFile(graph: graph_mod.Graph, file: []const u8) Error![]const u8 {    var owner: ?[]const u8 = null;    for (graph.nodes.items) |node| {        if (!moduleNode(node)) continue;        if (!std.mem.eql(u8, node.file orelse continue, file)) continue;        if (owner != null) return error.AmbiguousName;        owner = node.name;    }    return owner orelse error.NodeNotFound;}/// Returns public children in stable exported-name order.////// The slice owns only its records. Node strings borrow from the unchanged graph.pub fn publicDeclarations(    allocator: std.mem.Allocator,    graph: graph_mod.Graph,    owner: []const u8,    limits: limits_mod.Api,) (std.mem.Allocator.Error || Error)![]PublicDeclaration {    if (graph_mod.getNode(&graph, owner) == null) return error.NodeNotFound;    var count: usize = 0;    for (graph_mod.outgoingEdges(&graph, owner)) |edge_index| {        const edge = graph.edges.items[edge_index];        if (!std.mem.eql(u8, edge.rel, model.RelType.contains)) continue;        const node = graph_mod.getNode(&graph, edge.target) orelse continue;        if (isPublic(node)) count += 1;    }    const declarations = try allocator.alloc(PublicDeclaration, count);    errdefer allocator.free(declarations);    var index: usize = 0;    for (graph_mod.outgoingEdges(&graph, owner)) |edge_index| {        const edge = graph.edges.items[edge_index];        if (!std.mem.eql(u8, edge.rel, model.RelType.contains)) continue;        const node = graph_mod.getNode(&graph, edge.target) orelse continue;        if (!isPublic(node)) continue;        declarations[index] = .{            .exported = node,            .canonical = try canonicalDeclaration(graph, node, limits),        };        index += 1;    }    std.debug.assert(index == declarations.len);    std.mem.sort(PublicDeclaration, declarations, {}, declarationLessThan);    return declarations;}/// Releases the record slice returned by publicDeclarations.pub fn freePublicDeclarations(    allocator: std.mem.Allocator,    declarations: []PublicDeclaration,) void {    allocator.free(declarations);}/// Resolves one exact dotted path through the public surface of an owner.////// The returned nodes borrow from the unchanged graph. A quoted Zig identifier/// may contain dots and is treated as one path component.pub fn resolvePublicPath(    allocator: std.mem.Allocator,    graph: graph_mod.Graph,    owner: []const u8,    path: []const u8,    limits: limits_mod.Api,) (std.mem.Allocator.Error || Error)!PublicDeclaration {    if (path.len == 0 or path[0] == '.' or path[path.len - 1] == '.') {        return error.InvalidPublicPath;    }    var current_owner = owner;    var remaining = path;    for (0..limits.public_path_depth) |_| {        const component_end = try publicPathComponentEnd(remaining);        const component = remaining[0..component_end];        if (component.len == 0) return error.InvalidPublicPath;        const declarations = try publicDeclarations(allocator, graph, current_owner, limits);        defer freePublicDeclarations(allocator, declarations);        var found: ?PublicDeclaration = null;        for (declarations) |declaration| {            const name = directPublicName(current_owner, declaration.exported.name) orelse                continue;            if (!std.mem.eql(u8, name, component)) continue;            if (found != null) return error.AmbiguousName;            found = declaration;        }        const declaration = found orelse return error.PublicPathNotFound;        if (component_end == remaining.len) return declaration;        current_owner = declaration.canonical.name;        remaining = remaining[component_end + 1 ..];    }    return error.PublicPathDepthExceeded;}fn directPublicName(owner: []const u8, name: []const u8) ?[]const u8 {    if (!std.mem.startsWith(u8, name, owner)) return null;    if (name.len <= owner.len or name[owner.len] != '.') return null;    const suffix = name[owner.len + 1 ..];    if (suffix.len == 0) return null;    return suffix;}fn publicPathComponentEnd(path: []const u8) Error!usize {    if (std.mem.startsWith(u8, path, "@\"")) {        var index: usize = 2;        var escaped = false;        while (index < path.len) : (index += 1) {            const byte = path[index];            if (escaped) {                escaped = false;                continue;            }            if (byte == '\\') {                escaped = true;                continue;            }            if (byte != '"') continue;            if (index + 1 == path.len or path[index + 1] == '.') return index + 1;            return error.InvalidPublicPath;        }        return error.InvalidPublicPath;    }    return std.mem.indexOfScalar(u8, path, '.') orelse path.len;}/// Returns canonical members admitted through one public Zig declaration.////// The slice owns only its records. Nodes and strings borrow from the unchanged/// graph. Opaque and non-container declarations return an empty slice.pub fn publicMembers(    allocator: std.mem.Allocator,    graph: graph_mod.Graph,    declaration: PublicDeclaration,) (std.mem.Allocator.Error || Error)![]PublicMember {    if (!isPublic(declaration.exported)) return error.NotPublicDeclaration;    const owner = graph_mod.getNode(&graph, declaration.canonical.name) orelse        return error.NodeNotFound;    const expected = supportedMemberKind(containerKind(owner) orelse return &.{}) orelse        return &.{};    return try projectPublicMembers(allocator, graph, declaration, owner, expected);}fn projectPublicMembers(    allocator: std.mem.Allocator,    graph: graph_mod.Graph,    declaration: PublicDeclaration,    owner: model.Node,    expected: MemberKind,) (std.mem.Allocator.Error || Error)![]PublicMember {    var count: usize = 0;    for (graph_mod.outgoingEdges(&graph, owner.name)) |edge_index| {        const edge = graph.edges.items[edge_index];        if (!std.mem.eql(u8, edge.rel, model.RelType.contains)) continue;        const node = graph_mod.getNode(&graph, edge.target) orelse continue;        const kind = nodeMemberKind(node) orelse continue;        if (kind != expected) return error.InvalidPublicMember;        count += 1;    }    if (count == 0) return &.{};    const members = try allocator.alloc(PublicMember, count);    errdefer allocator.free(members);    var index: usize = 0;    for (graph_mod.outgoingEdges(&graph, owner.name)) |edge_index| {        const edge = graph.edges.items[edge_index];        if (!std.mem.eql(u8, edge.rel, model.RelType.contains)) continue;        const node = graph_mod.getNode(&graph, edge.target) orelse continue;        const kind = nodeMemberKind(node) orelse continue;        std.debug.assert(kind == expected);        members[index] = try publicMember(declaration, node, kind);        index += 1;    }    std.debug.assert(index == members.len);    std.mem.sort(PublicMember, members, {}, memberLessThan);    return members;}/// Releases the record slice returned by publicMembers.pub fn freePublicMembers(    allocator: std.mem.Allocator,    members: []PublicMember,) void {    if (members.len != 0) allocator.free(members);}/// Returns explicit source members omitted from the supported projection.////// The slice owns only its records. Nodes and strings borrow from the unchanged/// graph. A container with no unsupported source members returns an empty slice.pub fn publicMemberGaps(    allocator: std.mem.Allocator,    graph: graph_mod.Graph,    declaration: PublicDeclaration,) (std.mem.Allocator.Error || Error)![]PublicMemberGap {    if (!isPublic(declaration.exported)) return error.NotPublicDeclaration;    const owner = graph_mod.getNode(&graph, declaration.canonical.name) orelse        return error.NodeNotFound;    if (containerKind(owner) == null) return &.{};    var count: usize = 0;    for (graph_mod.outgoingEdges(&graph, owner.name)) |edge_index| {        const edge = graph.edges.items[edge_index];        if (!std.mem.eql(u8, edge.rel, model.RelType.contains)) continue;        const node = graph_mod.getNode(&graph, edge.target) orelse continue;        if (!std.mem.eql(u8, node.type, model.NodeType.member_gap)) continue;        count += 1;    }    if (count == 0) return &.{};    const gaps = try allocator.alloc(PublicMemberGap, count);    errdefer allocator.free(gaps);    var index: usize = 0;    for (graph_mod.outgoingEdges(&graph, owner.name)) |edge_index| {        const edge = graph.edges.items[edge_index];        if (!std.mem.eql(u8, edge.rel, model.RelType.contains)) continue;        const node = graph_mod.getNode(&graph, edge.target) orelse continue;        if (!std.mem.eql(u8, node.type, model.NodeType.member_gap)) continue;        gaps[index] = try publicMemberGap(declaration, node);        index += 1;    }    std.debug.assert(index == gaps.len);    std.mem.sort(PublicMemberGap, gaps, {}, memberGapLessThan);    return gaps;}/// Releases the record slice returned by publicMemberGaps.pub fn freePublicMemberGaps(    allocator: std.mem.Allocator,    gaps: []PublicMemberGap,) void {    if (gaps.len != 0) allocator.free(gaps);}pub fn visibility(node: model.Node) ?[]const u8 {    return model.pairValue(node.metadata, visibility_key);}pub fn isPublic(node: model.Node) bool {    return std.mem.eql(u8, visibility(node) orelse return false, "public");}/// Returns whether the scanner marked a declaration as test-only.pub fn isTestDeclaration(node: model.Node) bool {    return std.mem.eql(u8, model.pairValue(node.metadata, test_key) orelse return false, "true");}pub fn signature(node: model.Node) ?[]const u8 {    return model.pairValue(node.metadata, signature_key);}pub fn aliasTarget(node: model.Node) ?[]const u8 {    return model.pairValue(node.metadata, alias_target_key);}/// Returns a source expression proved to be a direct declaration alias.pub fn directAliasTarget(node: model.Node) ?[]const u8 {    return model.pairValue(node.metadata, direct_alias_target_key);}/// Returns the exact source-spelled Zig type annotation, or null when omitted.////// The returned slice borrows node metadata from the unchanged graph./// DeclaredTypeUnavailable means the scanner could not prove either state or/// encountered contradictory metadata. This fact makes no semantic type-/// equality claim.pub fn explicitDeclaredType(node: model.Node) Error!?[]const u8 {    const state = model.pairValue(node.metadata, declared_type_state_key) orelse        return error.DeclaredTypeUnavailable;    const value = model.pairValue(node.metadata, declared_type_key);    if (std.mem.eql(u8, state, "omitted")) {        if (value != null) return error.DeclaredTypeUnavailable;        return null;    }    if (!std.mem.eql(u8, state, "explicit")) {        return error.DeclaredTypeUnavailable;    }    const raw = value orelse        return error.DeclaredTypeUnavailable;    if (raw.len == 0) return error.DeclaredTypeUnavailable;    return raw;}test "explicit declared type distinguishes omitted and unavailable states" {    const Expectation = union(enum) {        unavailable,        omitted,        explicit: []const u8,    };    const cases = [_]struct {        name: []const u8,        metadata: []const model.Pair,        expectation: Expectation,    }{        .{ .name = "missing state", .metadata = &.{}, .expectation = .unavailable },        .{ .name = "unknown state", .metadata = &.{.{ .key = declared_type_state_key, .value = "unknown" }}, .expectation = .unavailable },        .{ .name = "explicit missing value", .metadata = &.{.{ .key = declared_type_state_key, .value = "explicit" }}, .expectation = .unavailable },        .{ .name = "explicit empty value", .metadata = &.{ .{ .key = declared_type_state_key, .value = "explicit" }, .{ .key = declared_type_key, .value = "" } }, .expectation = .unavailable },        .{ .name = "omitted with value", .metadata = &.{ .{ .key = declared_type_state_key, .value = "omitted" }, .{ .key = declared_type_key, .value = "u8" } }, .expectation = .unavailable },        .{ .name = "omitted", .metadata = &.{.{ .key = declared_type_state_key, .value = "omitted" }}, .expectation = .omitted },        .{ .name = "explicit", .metadata = &.{ .{ .key = declared_type_state_key, .value = "explicit" }, .{ .key = declared_type_key, .value = "?*const u8" } }, .expectation = .{ .explicit = "?*const u8" } },    };    for (cases) |case| {        const node: model.Node = .{ .name = case.name, .type = model.NodeType.constant, .metadata = case.metadata };        switch (case.expectation) {            .unavailable => try std.testing.expectError(error.DeclaredTypeUnavailable, explicitDeclaredType(node)),            .omitted => try std.testing.expect((try explicitDeclaredType(node)) == null),            .explicit => |expected| {                const actual = (try explicitDeclaredType(node)).?;                try std.testing.expectEqualStrings(expected, actual);                try std.testing.expect(actual.ptr == model.pairValue(node.metadata, declared_type_key).?.ptr);            },        }    }}/// Returns the explicit Zig container category stored by the scanner.pub fn containerKind(node: model.Node) ?ContainerKind {    const raw = model.pairValue(node.metadata, container_kind_key) orelse return null;    return std.meta.stringToEnum(ContainerKind, raw);}fn publicMember(    owner: PublicDeclaration,    node: model.Node,    kind: MemberKind,) Error!PublicMember {    if (kind != .field and memberIdentifier(node) == null) {        return error.InvalidPublicMember;    }    if (model.pairValue(node.metadata, source_spelling_key) == null) {        return error.InvalidPublicMember;    }    const order = memberOrder(node) orelse return error.InvalidPublicMember;    _ = memberSourceSpan(node) orelse return error.InvalidPublicMember;    if (node.file == null or node.line == null or node.end_line == null) {        return error.InvalidPublicMember;    }    return .{ .owner = owner, .node = node, .kind = kind, .order = order };}fn publicMemberGap(    owner: PublicDeclaration,    node: model.Node,) Error!PublicMemberGap {    const raw = model.pairValue(node.metadata, member_gap_key) orelse        return error.InvalidPublicMember;    const kind = std.meta.stringToEnum(MemberGapKind, raw) orelse        return error.InvalidPublicMember;    if (model.pairValue(node.metadata, source_spelling_key) == null) {        return error.InvalidPublicMember;    }    const order = memberOrder(node) orelse return error.InvalidPublicMember;    _ = memberSourceSpan(node) orelse return error.InvalidPublicMember;    if (node.file == null or node.line == null or node.end_line == null) {        return error.InvalidPublicMember;    }    return .{ .owner = owner, .node = node, .kind = kind, .order = order };}fn memberIdentifier(node: model.Node) ?[]const u8 {    return model.pairValue(node.metadata, member_identifier_key);}fn memberOrder(node: model.Node) ?u32 {    const raw = model.pairValue(node.metadata, member_order_key) orelse return null;    return std.fmt.parseInt(u32, raw, 10) catch null;}fn memberSourceSpan(node: model.Node) ?SourceSpan {    const start_raw = model.pairValue(node.metadata, source_start_byte_key) orelse        return null;    const end_raw = model.pairValue(node.metadata, source_end_byte_key) orelse        return null;    const start = std.fmt.parseInt(u32, start_raw, 10) catch return null;    const end = std.fmt.parseInt(u32, end_raw, 10) catch return null;    if (start > end) return null;    return .{ .start_byte = start, .end_byte = end };}fn supportedMemberKind(kind: ContainerKind) ?MemberKind {    return switch (kind) {        .@"struct", .@"union" => .field,        .@"enum" => .enum_tag,        .error_set => .error_member,        .@"opaque" => null,    };}fn nodeMemberKind(node: model.Node) ?MemberKind {    if (std.mem.eql(u8, node.type, model.NodeType.field)) return .field;    if (std.mem.eql(u8, node.type, model.NodeType.enum_tag)) return .enum_tag;    if (std.mem.eql(u8, node.type, model.NodeType.error_member)) {        return .error_member;    }    return null;}fn canonicalDeclaration(graph: graph_mod.Graph, declaration: model.Node, limits: limits_mod.Api) Error!model.Node {    return canonicalDeclarationDepth(graph, declaration, 0, limits);}fn canonicalDeclarationDepth(    graph: graph_mod.Graph,    declaration: model.Node,    depth: usize,    limits: limits_mod.Api,) Error!model.Node {    if (depth == limits.alias_resolution_depth) return error.AliasCycle;    var current = declaration;    for (0..graph.nodes.items.len + 1) |_| {        const owner = declarationOwner(graph, current.name) orelse return current;        const next = try resolveAliasTarget(graph, owner, current, depth, limits) orelse return current;        if (std.mem.eql(u8, next.name, current.name)) return current;        if (std.mem.eql(u8, next.name, declaration.name)) {            if (current.file != null and declaration.file != null and                !std.mem.eql(u8, current.file.?, declaration.file.?)) return current;            return error.AliasCycle;        }        current = next;    }    return error.AliasCycle;}fn resolveAliasTarget(    graph: graph_mod.Graph,    owner: []const u8,    declaration: model.Node,    depth: usize,    limits: limits_mod.Api,) Error!?model.Node {    const raw = directAliasTarget(declaration) orelse return null;    if (graph_mod.getNode(&graph, raw)) |node| return node;    const dot = std.mem.indexOfScalar(u8, raw, '.') orelse {        const child = childNamed(graph, owner, raw);        if (child) |node| {            if (!std.mem.eql(u8, node.name, declaration.name)) return node;        }        if (!importBinding(declaration)) return child;        return localPackageRoot(graph, owner, raw) orelse child;    };    const binding = childNamed(graph, owner, raw[0..dot]) orelse return null;    if (std.mem.eql(u8, binding.name, declaration.name)) return declaration;    const base = try canonicalDeclarationDepth(graph, binding, depth + 1, limits);    return joinedNode(graph, base.name, raw[dot..]);}fn importBinding(node: model.Node) bool {    return std.mem.indexOf(u8, signature(node) orelse return false, "@import(") != null;}fn localPackageRoot(    graph: graph_mod.Graph,    owner: []const u8,    raw: []const u8,) ?model.Node {    if (std.mem.indexOfScalar(u8, raw, '.') != null) return null;    var end = std.mem.lastIndexOfScalar(u8, owner, '.') orelse return null;    while (true) {        const prefix = owner[0..end];        const candidate = joinedChildNode(graph, prefix, raw);        if (candidate) |node| {            if (moduleNode(node)) {                if (std.mem.eql(u8, node.type, model.NodeType.package)) {                    return childNamed(graph, node.name, "root") orelse node;                }                return node;            }        }        end = std.mem.lastIndexOfScalar(u8, prefix, '.') orelse break;    }    return null;}fn joinedChildNode(    graph: graph_mod.Graph,    prefix: []const u8,    leaf: []const u8,) ?model.Node {    return dottedJoinedNode(graph, prefix, leaf);}fn dottedJoinedNode(    graph: graph_mod.Graph,    prefix: []const u8,    leaf: []const u8,) ?model.Node {    if (leaf.len != 0) {        var iterator = graph_mod.suffixIterator(&graph, leaf);        while (iterator.nextNode()) |node| {            if (node.name.len != prefix.len + 1 + leaf.len) continue;            if (!std.mem.startsWith(u8, node.name, prefix)) continue;            if (node.name[prefix.len] != '.') continue;            if (std.mem.eql(u8, node.name[prefix.len + 1 ..], leaf)) return node.*;        }        return null;    }    for (graph.nodes.items) |node| {        if (node.name.len != prefix.len + 1 + leaf.len) continue;        if (!std.mem.startsWith(u8, node.name, prefix)) continue;        if (node.name[prefix.len] != '.') continue;        if (std.mem.eql(u8, node.name[prefix.len + 1 ..], leaf)) return node;    }    return null;}fn declarationOwner(graph: graph_mod.Graph, name: []const u8) ?[]const u8 {    var owner: ?[]const u8 = null;    for (graph_mod.incomingEdges(&graph, name)) |edge_index| {        const edge = graph.edges.items[edge_index];        if (!std.mem.eql(u8, edge.rel, model.RelType.contains)) continue;        if (owner != null) return null;        owner = edge.source;    }    return owner;}fn childNamed(    graph: graph_mod.Graph,    owner: []const u8,    leaf: []const u8,) ?model.Node {    for (graph_mod.outgoingEdges(&graph, owner)) |edge_index| {        const edge = graph.edges.items[edge_index];        if (!std.mem.eql(u8, edge.rel, model.RelType.contains)) continue;        const node = graph_mod.getNode(&graph, edge.target) orelse continue;        const split = std.mem.lastIndexOfScalar(u8, node.name, '.') orelse 0;        const start = split + @intFromBool(split != 0);        if (std.mem.eql(u8, node.name[start..], leaf)) return node;    }    return null;}fn joinedNode(    graph: graph_mod.Graph,    prefix: []const u8,    suffix: []const u8,) ?model.Node {    if (suffix.len != 0 and suffix[0] == '.') {        return dottedJoinedNode(graph, prefix, suffix[1..]);    }    for (graph.nodes.items) |node| {        if (node.name.len != prefix.len + suffix.len) continue;        if (!std.mem.startsWith(u8, node.name, prefix)) continue;        if (std.mem.eql(u8, node.name[prefix.len..], suffix)) return node;    }    return null;}fn expectExactJoinedNodes(graph: graph_mod.Graph) !void {    try std.testing.expectEqualStrings(        "pkg.foo.Value",        joinedChildNode(graph, "pkg.foo", "Value").?.name,    );    try std.testing.expectEqualStrings(        "pkg.foo.Part.Value",        joinedNode(graph, "pkg.foo", ".Part.Value").?.name,    );    try std.testing.expectEqualStrings(        "pkg.foo.@\"dot.name\"",        joinedNode(graph, "pkg.foo", ".@\"dot.name\"").?.name,    );    try std.testing.expectEqualStrings(        "pkg.foox",        joinedNode(graph, "pkg.foo", "x").?.name,    );    try std.testing.expectEqualStrings(        "pkg.foo",        joinedNode(graph, "pkg.foo", "").?.name,    );    try std.testing.expectEqualStrings(        "pkg.foo.",        joinedNode(graph, "pkg.foo", ".").?.name,    );    try std.testing.expectEqualStrings(        "pkg.foo.",        joinedChildNode(graph, "pkg.foo", "").?.name,    );    try std.testing.expect(joinedNode(graph, "pkg.foo", ".Missing") == null);}test "exact joined nodes preserve indexed and linear semantics" {    var graph = graph_mod.init(std.testing.allocator);    defer graph_mod.deinit(&graph);    for ([_][]const u8{        "pkg.foo",        "pkg.foo.Value",        "pkg.foobar.Value",        "alt.foo.Value",        "other.foo.Value",        "pkg.foo.Part.Value",        "pkg.foo.@\"dot.name\"",        "pkg.foox",        "pkg.foo.",    }) |name| try graph_mod.addNode(&graph, .{ .name = name, .type = model.NodeType.type });    try expectExactJoinedNodes(graph);    try graph_mod.buildSuffixIndex(&graph);    try std.testing.expect(graph_mod.suffixIndexReady(graph));    try expectExactJoinedNodes(graph);    try graph_mod.addNode(&graph, .{ .name = "new.foo.Value", .type = model.NodeType.type });    try std.testing.expect(!graph_mod.suffixIndexReady(graph));    try expectExactJoinedNodes(graph);    try std.testing.expectEqualStrings(        "new.foo.Value",        joinedChildNode(graph, "new.foo", "Value").?.name,    );}fn moduleNode(node: model.Node) bool {    return std.mem.eql(u8, node.type, model.NodeType.module) or        std.mem.eql(u8, node.type, model.NodeType.package);}fn sameSourceFile(left: model.Node, right: model.Node) bool {    const left_file = left.file orelse return false;    const right_file = right.file orelse return false;    return std.mem.eql(u8, left_file, right_file);}fn declarationLessThan(_: void, left: PublicDeclaration, right: PublicDeclaration) bool {    return std.mem.lessThan(u8, left.exported.name, right.exported.name);}fn memberLessThan(_: void, left: PublicMember, right: PublicMember) bool {    if (left.order != right.order) return left.order < right.order;    return std.mem.lessThan(u8, left.node.name, right.node.name);}fn memberGapLessThan(_: void, left: PublicMemberGap, right: PublicMemberGap) bool {    if (left.order != right.order) return left.order < right.order;    return std.mem.lessThan(u8, left.node.name, right.node.name);}test "public declaration spans preserve binding and canonical evidence" {    const binding_bytes = "pub const Alias";    const canonical_bytes = "pub const Value = struct {};";    const binding_hash = std.fmt.bytesToHex(sourceDigest(binding_bytes), .lower);    const canonical_hash = std.fmt.bytesToHex(sourceDigest(canonical_bytes), .lower);    const binding_metadata = [_]model.Pair{        .{ .key = source_start_byte_key, .value = "4" },        .{ .key = source_end_byte_key, .value = "19" },        .{ .key = source_hash_key, .value = &binding_hash },    };    const canonical_metadata = [_]model.Pair{        .{ .key = source_start_byte_key, .value = "30" },        .{ .key = source_end_byte_key, .value = "90" },        .{ .key = source_hash_key, .value = &canonical_hash },    };    const declaration = PublicDeclaration{        .exported = .{ .name = "root.Alias", .type = model.NodeType.constant, .file = "root.zig", .metadata = &binding_metadata },        .canonical = .{ .name = "root.Value", .type = model.NodeType.class, .file = "value.zig", .metadata = &canonical_metadata },    };    try std.testing.expectEqual(@as(u32, 4), (try declaration.bindingSourceSpan()).start_byte);    try std.testing.expectEqual(@as(u32, 90), (try declaration.canonicalSourceSpan()).end_byte);    try std.testing.expectEqualStrings("root.zig", (try declaration.bindingSource()).file);    try std.testing.expectEqual(binding_hash, std.fmt.bytesToHex(        (try declaration.bindingSource()).digest,        .lower,    ));    const missing = model.Node{ .name = "root.Missing", .type = model.NodeType.constant };    try std.testing.expectError(error.SourceSpanUnavailable, declarationSourceSpan(missing));    try std.testing.expectError(error.SourceFileUnavailable, declarationSource(missing));    const malformed = [_]model.Pair{        .{ .key = source_start_byte_key, .value = "9" },        .{ .key = source_end_byte_key, .value = "9" },        .{ .key = source_hash_key, .value = "not-a-digest" },    };    const invalid = model.Node{        .name = "root.Invalid",        .type = model.NodeType.constant,        .file = "root.zig",        .metadata = &malformed,    };    try std.testing.expectError(error.InvalidSourceSpan, declarationSourceSpan(invalid));    try std.testing.expectError(error.InvalidSourceDigest, declarationSource(invalid));}test "declaration source requires complete lower-case evidence" {    const span_only = [_]model.Pair{        .{ .key = source_start_byte_key, .value = "0" },        .{ .key = source_end_byte_key, .value = "8" },    };    const missing_digest = model.Node{        .name = "root.MissingDigest",        .type = model.NodeType.constant,        .file = "root.zig",        .metadata = &span_only,    };    try std.testing.expectError(        error.SourceDigestUnavailable,        declarationSource(missing_digest),    );    const upper_hash = [_]model.Pair{        .{ .key = source_start_byte_key, .value = "0" },        .{ .key = source_end_byte_key, .value = "8" },        .{ .key = source_hash_key, .value = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" },    };    var invalid = missing_digest;    invalid.metadata = &upper_hash;    try std.testing.expectError(error.InvalidSourceDigest, declarationSource(invalid));}test "verified source rejects stale and out-of-range declaration evidence" {    const contents = "prefix pub fn run() void {} suffix";    const exact = "pub fn run() void {}";    const start = std.mem.indexOf(u8, contents, exact).?;    var evidence = DeclarationSource{        .file = "root.zig",        .span = .{            .start_byte = @intCast(start),            .end_byte = @intCast(start + exact.len),        },        .digest = sourceDigest(exact),    };    try std.testing.expectEqualStrings(        exact,        try verifiedSource(evidence, contents),    );    evidence.digest[0] ^= 1;    try std.testing.expectError(        error.SourceDigestMismatch,        verifiedSource(evidence, contents),    );    evidence.span.end_byte = @intCast(contents.len + 1);    try std.testing.expectError(error.InvalidSourceSpan, verifiedSource(evidence, contents));}test "exact public paths traverse canonical aliases and quoted identifiers" {    const public = [_]model.Pair{.{ .key = visibility_key, .value = "public" }};    const alias = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = direct_alias_target_key, .value = "core.Block" },    };    var graph = graph_mod.init(std.testing.allocator);    defer graph_mod.deinit(&graph);    for ([_]model.Node{        .{ .name = "root", .type = model.NodeType.module },        .{ .name = "root.Block", .type = model.NodeType.type, .metadata = &alias },        .{ .name = "core", .type = model.NodeType.module },        .{ .name = "core.Block", .type = model.NodeType.class, .metadata = &public },        .{            .name = "core.Block.getPredecessors",            .type = model.NodeType.method,            .metadata = &public,        },        .{            .name = "core.Block.@\"dot.name\"",            .type = model.NodeType.method,            .metadata = &public,        },    }) |node| try graph_mod.addNode(&graph, node);    for ([_]model.Edge{        .{ .source = "root", .rel = model.RelType.contains, .target = "root.Block" },        .{ .source = "core", .rel = model.RelType.contains, .target = "core.Block" },        .{            .source = "core.Block",            .rel = model.RelType.contains,            .target = "core.Block.getPredecessors",        },        .{            .source = "core.Block",            .rel = model.RelType.contains,            .target = "core.Block.@\"dot.name\"",        },    }) |edge| try graph_mod.addEdge(&graph, edge);    const method = try resolvePublicPath(        std.testing.allocator,        graph,        "root",        "Block.getPredecessors",        testing_limits,    );    try std.testing.expectEqualStrings(        "core.Block.getPredecessors",        method.canonical.name,    );    const quoted = try resolvePublicPath(        std.testing.allocator,        graph,        "root",        "Block.@\"dot.name\"",        testing_limits,    );    try std.testing.expectEqualStrings("core.Block.@\"dot.name\"", quoted.canonical.name);    try std.testing.expectError(        error.PublicPathNotFound,        resolvePublicPath(std.testing.allocator, graph, "root", "Block.missing", testing_limits),    );    try std.testing.expectError(        error.InvalidPublicPath,        resolvePublicPath(std.testing.allocator, graph, "root", "Block.", testing_limits),    );}test "public declarations resolve aliases and retain export facts" {    var arena = std.heap.ArenaAllocator.init(std.testing.allocator);    defer arena.deinit();    const allocator = arena.allocator();    var graph = graph_mod.init(allocator);    defer graph_mod.deinit(&graph);    try addProjectionFixture(&graph);    const owner = try ownerForFile(graph, "lib/api/src/root.zig");    try std.testing.expectEqualStrings("lib.api.src.root", owner);    const declarations = try publicDeclarations(std.testing.allocator, graph, owner, testing_limits);    defer freePublicDeclarations(std.testing.allocator, declarations);    try std.testing.expectEqual(@as(usize, 2), declarations.len);    try std.testing.expectEqualStrings("lib.api.src.root.run", declarations[0].exported.name);    try std.testing.expectEqualStrings("lib.api.src.site.root.run", declarations[0].canonical.name);    try std.testing.expectEqualStrings("Runs the site.", declarations[0].documentation().?);    try std.testing.expectEqualStrings("pub const run = site.run;", signature(declarations[0].exported).?);    try std.testing.expectEqualStrings("lib.api.src.site.root", declarations[1].canonical.name);}test "public declarations resolve local packages through private import bindings" {    const public_alias = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = direct_alias_target_key, .value = "schema" },        .{ .key = signature_key, .value = "pub const event = @import(\"schema\");" },    };    const public_event_alias = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = direct_alias_target_key, .value = "event.Event" },    };    const public_schema_event_alias = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = direct_alias_target_key, .value = "event_data.Event" },    };    const private_import = [_]model.Pair{        .{ .key = visibility_key, .value = "private" },        .{ .key = direct_alias_target_key, .value = "pkg.src.schema.event" },    };    var graph = graph_mod.init(std.testing.allocator);    defer graph_mod.deinit(&graph);    const nodes = [_]model.Node{        .{ .name = "pkg.src.root", .type = model.NodeType.module },        .{ .name = "pkg.src.root.event", .type = model.NodeType.constant, .metadata = &public_alias },        .{ .name = "pkg.src.root.Event", .type = model.NodeType.type, .metadata = &public_event_alias },        .{ .name = "pkg.src.schema", .type = model.NodeType.package },        .{ .name = "pkg.src.schema.root", .type = model.NodeType.module },        .{ .name = "pkg.src.schema.root.event_data", .type = model.NodeType.constant, .metadata = &private_import },        .{ .name = "pkg.src.schema.root.Event", .type = model.NodeType.type, .metadata = &public_schema_event_alias },        .{ .name = "pkg.src.schema.event", .type = model.NodeType.module },        .{ .name = "pkg.src.schema.event.Event", .type = model.NodeType.class, .docstring = "Durable event." },    };    for (nodes) |node| try graph_mod.addNode(&graph, node);    const edges = [_]model.Edge{        .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.event" },        .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.Event" },        .{ .source = "pkg.src.schema", .rel = model.RelType.contains, .target = "pkg.src.schema.root" },        .{ .source = "pkg.src.schema.root", .rel = model.RelType.contains, .target = "pkg.src.schema.root.event_data" },        .{ .source = "pkg.src.schema.root", .rel = model.RelType.contains, .target = "pkg.src.schema.root.Event" },        .{ .source = "pkg.src.schema.event", .rel = model.RelType.contains, .target = "pkg.src.schema.event.Event" },    };    for (edges) |edge| try graph_mod.addEdge(&graph, edge);    try graph_mod.buildSuffixIndex(&graph);    const declarations = try publicDeclarations(        std.testing.allocator,        graph,        "pkg.src.root",        testing_limits,    );    defer freePublicDeclarations(std.testing.allocator, declarations);    try std.testing.expectEqual(@as(usize, 2), declarations.len);    try std.testing.expectEqualStrings(        "pkg.src.schema.event.Event",        declarations[0].canonical.name,    );    try std.testing.expectEqualStrings(        "pkg.src.schema.root",        declarations[1].canonical.name,    );}test "public declarations resolve local packages through same-name import bindings" {    const public_capacity = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = direct_alias_target_key, .value = "capacity" },        .{ .key = signature_key, .value = "pub const capacity = @import(\"capacity\");" },    };    const public_helper = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = direct_alias_target_key, .value = "support" },    };    const private_support = [_]model.Pair{        .{ .key = visibility_key, .value = "private" },    };    const public_budget = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },    };    var graph = graph_mod.init(std.testing.allocator);    defer graph_mod.deinit(&graph);    const nodes = [_]model.Node{        .{ .name = "pkg.src.root", .type = model.NodeType.module, .file = "pkg/src/root.zig" },        .{ .name = "pkg.src.root.capacity", .type = model.NodeType.constant, .file = "pkg/src/root.zig", .line = 3, .metadata = &public_capacity },        .{ .name = "pkg.src.root.helper", .type = model.NodeType.constant, .file = "pkg/src/root.zig", .line = 4, .metadata = &public_helper },        .{ .name = "pkg.src.root.support", .type = model.NodeType.constant, .file = "pkg/src/root.zig", .line = 5, .metadata = &private_support },        .{ .name = "pkg.src.capacity", .type = model.NodeType.package },        .{ .name = "pkg.src.capacity.root", .type = model.NodeType.module, .file = "pkg/src/capacity/root.zig" },        .{ .name = "pkg.src.capacity.root.Budget", .type = model.NodeType.class, .file = "pkg/src/capacity/root.zig", .line = 2, .docstring = "Bounded byte budget.", .metadata = &public_budget },    };    for (nodes) |node| try graph_mod.addNode(&graph, node);    const edges = [_]model.Edge{        .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.capacity" },        .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.helper" },        .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.support" },        .{ .source = "pkg.src.capacity", .rel = model.RelType.contains, .target = "pkg.src.capacity.root" },        .{ .source = "pkg.src.capacity.root", .rel = model.RelType.contains, .target = "pkg.src.capacity.root.Budget" },    };    for (edges) |edge| try graph_mod.addEdge(&graph, edge);    try graph_mod.buildSuffixIndex(&graph);    const declarations = try publicDeclarations(        std.testing.allocator,        graph,        "pkg.src.root",        testing_limits,    );    defer freePublicDeclarations(std.testing.allocator, declarations);    try std.testing.expectEqual(@as(usize, 2), declarations.len);    try std.testing.expectEqualStrings("pkg.src.root.capacity", declarations[0].exported.name);    try std.testing.expectEqualStrings("pkg.src.capacity.root", declarations[0].canonical.name);    try std.testing.expectEqualStrings("pkg/src/root.zig", declarations[0].exported.file.?);    try std.testing.expectEqualStrings("pkg/src/capacity/root.zig", declarations[0].canonical.file.?);    try std.testing.expectEqualStrings("pkg.src.root.helper", declarations[1].exported.name);    try std.testing.expectEqualStrings("pkg.src.root.support", declarations[1].canonical.name);    const member = try resolvePublicPath(        std.testing.allocator,        graph,        "pkg.src.root",        "capacity.Budget",        testing_limits,    );    try std.testing.expectEqualStrings("pkg.src.capacity.root.Budget", member.canonical.name);    try std.testing.expectEqualStrings("Bounded byte budget.", member.documentation().?);}test "public declarations keep unresolvable same-name import bindings terminal" {    const public_std = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = direct_alias_target_key, .value = "std" },        .{ .key = signature_key, .value = "pub const std = @import(\"std\");" },    };    const public_capacity = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = direct_alias_target_key, .value = "capacity" },        .{ .key = signature_key, .value = "pub const capacity = @import(\"capacity\");" },    };    var graph = graph_mod.init(std.testing.allocator);    defer graph_mod.deinit(&graph);    const nodes = [_]model.Node{        .{ .name = "pkg.src.root", .type = model.NodeType.module, .file = "pkg/src/root.zig" },        .{ .name = "pkg.src.root.std", .type = model.NodeType.constant, .file = "pkg/src/root.zig", .metadata = &public_std },        .{ .name = "pkg.src.root.capacity", .type = model.NodeType.constant, .file = "pkg/src/root.zig", .metadata = &public_capacity },        .{ .name = "other.src.capacity", .type = model.NodeType.package },        .{ .name = "other.src.capacity.root", .type = model.NodeType.module, .file = "other/src/capacity/root.zig" },    };    for (nodes) |node| try graph_mod.addNode(&graph, node);    const edges = [_]model.Edge{        .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.std" },        .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.capacity" },        .{ .source = "other.src.capacity", .rel = model.RelType.contains, .target = "other.src.capacity.root" },    };    for (edges) |edge| try graph_mod.addEdge(&graph, edge);    try graph_mod.buildSuffixIndex(&graph);    const declarations = try publicDeclarations(        std.testing.allocator,        graph,        "pkg.src.root",        testing_limits,    );    defer freePublicDeclarations(std.testing.allocator, declarations);    try std.testing.expectEqual(@as(usize, 2), declarations.len);    try std.testing.expectEqualStrings("pkg.src.root.capacity", declarations[0].exported.name);    try std.testing.expectEqualStrings("pkg.src.root.capacity", declarations[0].canonical.name);    try std.testing.expectEqualStrings("pkg.src.root.std", declarations[1].exported.name);    try std.testing.expectEqualStrings("pkg.src.root.std", declarations[1].canonical.name);}test "public declarations resolve dotted private alias chains" {    const public_harness = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = direct_alias_target_key, .value = "harness.Harness" },    };    const public_agent = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = direct_alias_target_key, .value = "pkg.src.agent.root" },    };    const public_harness_namespace = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = direct_alias_target_key, .value = "pkg.src.agent.harness.root" },    };    const private_harness = [_]model.Pair{        .{ .key = visibility_key, .value = "private" },        .{ .key = direct_alias_target_key, .value = "agent.harness" },    };    const public_log = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = direct_alias_target_key, .value = "log.Log" },    };    const private_history = [_]model.Pair{        .{ .key = visibility_key, .value = "private" },        .{ .key = direct_alias_target_key, .value = "pkg.src.history.root" },    };    const private_log = [_]model.Pair{        .{ .key = visibility_key, .value = "private" },        .{ .key = direct_alias_target_key, .value = "history.log" },    };    const public_history_log = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = direct_alias_target_key, .value = "pkg.src.history.log" },    };    var graph = graph_mod.init(std.testing.allocator);    defer graph_mod.deinit(&graph);    const nodes = [_]model.Node{        .{ .name = "pkg.src.root", .type = model.NodeType.module },        .{ .name = "pkg.src.root.agent", .type = model.NodeType.constant, .metadata = &public_agent },        .{ .name = "pkg.src.root.harness", .type = model.NodeType.constant, .metadata = &private_harness },        .{ .name = "pkg.src.root.Harness", .type = model.NodeType.type, .metadata = &public_harness },        .{ .name = "pkg.src.root.history", .type = model.NodeType.constant, .metadata = &private_history },        .{ .name = "pkg.src.root.log", .type = model.NodeType.constant, .metadata = &private_log },        .{ .name = "pkg.src.root.Log", .type = model.NodeType.type, .metadata = &public_log },        .{ .name = "pkg.src.agent.root", .type = model.NodeType.module },        .{ .name = "pkg.src.agent.root.harness", .type = model.NodeType.constant, .metadata = &public_harness_namespace },        .{ .name = "pkg.src.agent.harness.root", .type = model.NodeType.module },        .{ .name = "pkg.src.agent.harness.root.Harness", .type = model.NodeType.class, .docstring = "Deterministic session owner." },        .{ .name = "pkg.src.history.root", .type = model.NodeType.module },        .{ .name = "pkg.src.history.root.log", .type = model.NodeType.constant, .metadata = &public_history_log },        .{ .name = "pkg.src.history.log", .type = model.NodeType.module },        .{ .name = "pkg.src.history.log.Log", .type = model.NodeType.class, .docstring = "Committed history owner." },    };    for (nodes) |node| try graph_mod.addNode(&graph, node);    const edges = [_]model.Edge{        .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.agent" },        .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.harness" },        .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.Harness" },        .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.history" },        .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.log" },        .{ .source = "pkg.src.root", .rel = model.RelType.contains, .target = "pkg.src.root.Log" },        .{ .source = "pkg.src.agent.root", .rel = model.RelType.contains, .target = "pkg.src.agent.root.harness" },        .{ .source = "pkg.src.agent.harness.root", .rel = model.RelType.contains, .target = "pkg.src.agent.harness.root.Harness" },        .{ .source = "pkg.src.history.root", .rel = model.RelType.contains, .target = "pkg.src.history.root.log" },        .{ .source = "pkg.src.history.log", .rel = model.RelType.contains, .target = "pkg.src.history.log.Log" },    };    for (edges) |edge| try graph_mod.addEdge(&graph, edge);    try graph_mod.buildSuffixIndex(&graph);    const declarations = try publicDeclarations(        std.testing.allocator,        graph,        "pkg.src.root",        testing_limits,    );    defer freePublicDeclarations(std.testing.allocator, declarations);    try std.testing.expectEqual(@as(usize, 3), declarations.len);    try std.testing.expectEqualStrings(        "pkg.src.agent.harness.root.Harness",        declarations[0].canonical.name,    );    try std.testing.expectEqualStrings(        "pkg.src.history.log.Log",        declarations[1].canonical.name,    );    try std.testing.expectEqualStrings("pkg.src.agent.root", declarations[2].canonical.name);}test "public declarations stop at self-resolving import bindings" {    const public_import = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = alias_target_key, .value = "pretty" },        .{ .key = direct_alias_target_key, .value = "pretty" },    };    var graph = graph_mod.init(std.testing.allocator);    defer graph_mod.deinit(&graph);    try graph_mod.addNode(&graph, .{        .name = "root",        .type = model.NodeType.module,    });    try graph_mod.addNode(&graph, .{        .name = "root.pretty",        .type = model.NodeType.constant,        .metadata = &public_import,    });    try graph_mod.addEdge(&graph, .{        .source = "root",        .rel = model.RelType.contains,        .target = "root.pretty",    });    const declarations = try publicDeclarations(std.testing.allocator, graph, "root", testing_limits);    defer freePublicDeclarations(std.testing.allocator, declarations);    try std.testing.expectEqual(@as(usize, 1), declarations.len);    try std.testing.expectEqualStrings("root.pretty", declarations[0].canonical.name);}test "public declarations reject nontrivial alias cycles" {    const public_first = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = alias_target_key, .value = "second" },        .{ .key = direct_alias_target_key, .value = "second" },    };    const private_second = [_]model.Pair{        .{ .key = alias_target_key, .value = "first" },        .{ .key = direct_alias_target_key, .value = "first" },    };    var graph = graph_mod.init(std.testing.allocator);    defer graph_mod.deinit(&graph);    try graph_mod.addNode(&graph, .{ .name = "root", .type = model.NodeType.module });    try graph_mod.addNode(&graph, .{        .name = "root.first",        .type = model.NodeType.constant,        .metadata = &public_first,    });    try graph_mod.addNode(&graph, .{        .name = "root.second",        .type = model.NodeType.constant,        .metadata = &private_second,    });    try graph_mod.addEdge(&graph, .{        .source = "root",        .rel = model.RelType.contains,        .target = "root.first",    });    try graph_mod.addEdge(&graph, .{        .source = "root",        .rel = model.RelType.contains,        .target = "root.second",    });    try std.testing.expectError(        error.AliasCycle,        publicDeclarations(std.testing.allocator, graph, "root", testing_limits),    );}test "public declarations bound recursive dotted alias cycles" {    const public_value = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = direct_alias_target_key, .value = "first.Value" },    };    const first = [_]model.Pair{        .{ .key = visibility_key, .value = "private" },        .{ .key = direct_alias_target_key, .value = "second.Value" },    };    const second = [_]model.Pair{        .{ .key = visibility_key, .value = "private" },        .{ .key = direct_alias_target_key, .value = "first.Value" },    };    var graph = graph_mod.init(std.testing.allocator);    defer graph_mod.deinit(&graph);    const nodes = [_]model.Node{        .{ .name = "root", .type = model.NodeType.module },        .{ .name = "root.Value", .type = model.NodeType.type, .metadata = &public_value },        .{ .name = "root.first", .type = model.NodeType.constant, .metadata = &first },        .{ .name = "root.second", .type = model.NodeType.constant, .metadata = &second },    };    for (nodes) |node| try graph_mod.addNode(&graph, node);    for (nodes[1..]) |node| try graph_mod.addEdge(&graph, .{        .source = "root",        .rel = model.RelType.contains,        .target = node.name,    });    try std.testing.expectError(        error.AliasCycle,        publicDeclarations(std.testing.allocator, graph, "root", testing_limits),    );}test "public members retain canonical ownership and stable source order" {    const public_container = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = container_kind_key, .value = "struct" },    };    const later = memberFixtureMetadata("later", "1", "later: u8", "20", "29");    const earlier = memberFixtureMetadata("earlier", "0", "earlier: u8", "5", "16");    var graph = graph_mod.init(std.testing.allocator);    defer graph_mod.deinit(&graph);    try graph_mod.addNode(&graph, .{ .name = "root", .type = model.NodeType.module });    try graph_mod.addNode(&graph, .{        .name = "root.Options",        .type = model.NodeType.class,        .file = "root.zig",        .metadata = &public_container,    });    try addMemberFixtureNode(&graph, "root.Options.later", &later);    try addMemberFixtureNode(&graph, "root.Options.earlier", &earlier);    try graph_mod.addEdge(&graph, .{ .source = "root", .rel = model.RelType.contains, .target = "root.Options" });    try graph_mod.addEdge(&graph, .{ .source = "root.Options", .rel = model.RelType.contains, .target = "root.Options.later" });    try graph_mod.addEdge(&graph, .{ .source = "root.Options", .rel = model.RelType.contains, .target = "root.Options.earlier" });    const declarations = try publicDeclarations(std.testing.allocator, graph, "root", testing_limits);    defer freePublicDeclarations(std.testing.allocator, declarations);    const members = try publicMembers(std.testing.allocator, graph, declarations[0]);    defer freePublicMembers(std.testing.allocator, members);    try std.testing.expectEqual(@as(usize, 2), members.len);    try std.testing.expectEqualStrings("earlier", members[0].identifier().?);    try std.testing.expectEqualStrings(declarations[0].canonical.name, members[0].owner.canonical.name);    try std.testing.expectEqual(@as(u32, 5), members[0].sourceSpan().start_byte);    const malformed = [_]model.Pair{        .{ .key = member_identifier_key, .value = "broken" },        .{ .key = member_order_key, .value = "2" },        .{ .key = source_spelling_key, .value = "broken: u8" },        .{ .key = source_start_byte_key, .value = "30" },    };    try addMemberFixtureNode(&graph, "root.Options.broken", &malformed);    try graph_mod.addEdge(&graph, .{ .source = "root.Options", .rel = model.RelType.contains, .target = "root.Options.broken" });    try std.testing.expectError(        error.InvalidPublicMember,        publicMembers(std.testing.allocator, graph, declarations[0]),    );}test "public member gaps preserve explicit unsupported source facts" {    const public_container = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = container_kind_key, .value = "struct" },    };    const gap_metadata = [_]model.Pair{        .{ .key = member_gap_key, .value = "unsupported_member_syntax" },        .{ .key = member_order_key, .value = "0" },        .{ .key = source_spelling_key, .value = "u8" },        .{ .key = source_start_byte_key, .value = "5" },        .{ .key = source_end_byte_key, .value = "7" },    };    var graph = graph_mod.init(std.testing.allocator);    defer graph_mod.deinit(&graph);    try graph_mod.addNode(&graph, .{ .name = "root", .type = model.NodeType.module });    try graph_mod.addNode(&graph, .{        .name = "root.Tuple",        .type = model.NodeType.class,        .file = "root.zig",        .metadata = &public_container,    });    try graph_mod.addNode(&graph, .{        .name = "root.Tuple.$smg-gap-0",        .type = model.NodeType.member_gap,        .file = "root.zig",        .line = 1,        .end_line = 1,        .metadata = &gap_metadata,    });    try graph_mod.addEdge(&graph, .{ .source = "root", .rel = model.RelType.contains, .target = "root.Tuple" });    try graph_mod.addEdge(&graph, .{ .source = "root.Tuple", .rel = model.RelType.contains, .target = "root.Tuple.$smg-gap-0" });    const declarations = try publicDeclarations(std.testing.allocator, graph, "root", testing_limits);    defer freePublicDeclarations(std.testing.allocator, declarations);    const gaps = try publicMemberGaps(std.testing.allocator, graph, declarations[0]);    defer freePublicMemberGaps(std.testing.allocator, gaps);    try std.testing.expectEqual(@as(usize, 1), gaps.len);    try std.testing.expectEqual(MemberGapKind.unsupported_member_syntax, gaps[0].kind);    try std.testing.expect(gaps[0].identifier() == null);    try std.testing.expectEqualStrings("u8", gaps[0].sourceSpelling());    try std.testing.expectEqual(@as(u32, 5), gaps[0].sourceSpan().start_byte);}test "public member record allocation propagates out of memory" {    const public_container = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = container_kind_key, .value = "struct" },    };    const member_metadata = memberFixtureMetadata("field", "0", "field: u8", "0", "9");    var graph = graph_mod.init(std.testing.allocator);    defer graph_mod.deinit(&graph);    try graph_mod.addNode(&graph, .{        .name = "root.Options",        .type = model.NodeType.class,        .file = "root.zig",        .metadata = &public_container,    });    try addMemberFixtureNode(&graph, "root.Options.field", &member_metadata);    try graph_mod.addEdge(&graph, .{ .source = "root.Options", .rel = model.RelType.contains, .target = "root.Options.field" });    const owner = graph_mod.getNode(&graph, "root.Options").?;    var failing = std.testing.FailingAllocator.init(std.testing.allocator, .{        .fail_index = 0,    });    try std.testing.expectError(        error.OutOfMemory,        projectPublicMembers(            failing.allocator(),            graph,            .{ .exported = owner, .canonical = owner },            owner,            .field,        ),    );}fn memberFixtureMetadata(    comptime identifier: []const u8,    comptime order: []const u8,    comptime spelling: []const u8,    comptime start: []const u8,    comptime end: []const u8,) [5]model.Pair {    return .{        .{ .key = member_identifier_key, .value = identifier },        .{ .key = member_order_key, .value = order },        .{ .key = source_spelling_key, .value = spelling },        .{ .key = source_start_byte_key, .value = start },        .{ .key = source_end_byte_key, .value = end },    };}fn addMemberFixtureNode(    graph: *graph_mod.Graph,    name: []const u8,    metadata: []const model.Pair,) !void {    try graph_mod.addNode(graph, .{        .name = name,        .type = model.NodeType.field,        .file = "root.zig",        .line = 1,        .end_line = 1,        .metadata = metadata,    });}fn addProjectionFixture(graph: *graph_mod.Graph) !void {    const scanned = [_]model.Pair{.{ .key = "source", .value = "scan" }};    const public_site = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = alias_target_key, .value = "lib.api.src.site.root" },        .{ .key = direct_alias_target_key, .value = "lib.api.src.site.root" },    };    const public_run = [_]model.Pair{        .{ .key = visibility_key, .value = "public" },        .{ .key = signature_key, .value = "pub const run = site.run;" },        .{ .key = alias_target_key, .value = "site.run" },        .{ .key = direct_alias_target_key, .value = "site.run" },    };    try graph_mod.addNode(graph, .{        .name = "lib.api.src.root",        .type = model.NodeType.module,        .file = "lib/api/src/root.zig",        .metadata = &scanned,    });    try graph_mod.addNode(graph, .{        .name = "lib.api.src.root.site",        .type = model.NodeType.constant,        .metadata = &public_site,    });    try graph_mod.addNode(graph, .{        .name = "lib.api.src.root.run",        .type = model.NodeType.constant,        .file = "lib/api/src/root.zig",        .metadata = &public_run,    });    try graph_mod.addNode(graph, .{        .name = "lib.api.src.root.hidden",        .type = model.NodeType.constant,        .metadata = &scanned,    });    try graph_mod.addNode(graph, .{        .name = "lib.api.src.site.root",        .type = model.NodeType.module,        .file = "lib/api/src/site/root.zig",        .metadata = &scanned,    });    try graph_mod.addNode(graph, .{        .name = "lib.api.src.site.root.run",        .type = model.NodeType.function,        .file = "lib/api/src/site/root.zig",        .docstring = "Runs the site.",        .metadata = &scanned,    });    const contains = model.RelType.contains;    try graph_mod.addEdge(graph, .{ .source = "lib.api.src.root", .rel = contains, .target = "lib.api.src.root.site" });    try graph_mod.addEdge(graph, .{ .source = "lib.api.src.root", .rel = contains, .target = "lib.api.src.root.run" });    try graph_mod.addEdge(graph, .{ .source = "lib.api.src.root", .rel = contains, .target = "lib.api.src.root.hidden" });    try graph_mod.addEdge(graph, .{ .source = "lib.api.src.site.root", .rel = contains, .target = "lib.api.src.site.root.run" });}

Source: tools/smg/src/root.zig:11

zig
/// Projects public declarations, members, and exact source evidence.pub const api = @import("api.zig");

Complete caller list for api.directAliasTarget

8 direct callers.

Complete caller list for api.freePublicDeclarations

21 direct callers.

Complete caller list for api.publicDeclarations

23 direct callers.

Audit

Definitions64
Public names64
Members25
Version26.7.0
Revisiondaab053ee433