From 60e517d493fdefbeca59acdfaa7681e7286ca4fe Mon Sep 17 00:00:00 2001 From: tegwick Date: Wed, 24 Jun 2026 18:34:49 +0200 Subject: [PATCH] Add NBGM specification v0.1 baseline Author the domain-agnostic graph model spec covering nodes, edges, attributes, provenance, and inspection operations. Mark VANTAGE-WP-0002 finished with the spec deliverable documented in the workplan task. --- docs/nbgm-spec-v0.1.md | 671 ++++++++++++++++++ .../VANTAGE-WP-0002-nbgm-spec-baseline.md | 10 +- 2 files changed, 677 insertions(+), 4 deletions(-) create mode 100644 docs/nbgm-spec-v0.1.md diff --git a/docs/nbgm-spec-v0.1.md b/docs/nbgm-spec-v0.1.md new file mode 100644 index 0000000..25d553c --- /dev/null +++ b/docs/nbgm-spec-v0.1.md @@ -0,0 +1,671 @@ +# NBGM Specification v0.1 + +Network-Based Graph Model (NBGM) baseline for Vantage Point. + +**Status:** draft baseline +**Version:** `vantage.nbgm/v0.1` +**Related:** `INTENT.md`, `SCOPE.md` + +--- + +## 1. Purpose + +This document defines the domain-agnostic graph model that Vantage Point uses +to represent, inspect, and reason about dependency structures. + +An NBGM is a typed graph of entities (nodes) and relationships (edges) with +attributes and provenance. Meaning is not baked into the core model. Domains +attach interpretation through bindings, lenses, and vantage points. + +The vocabulary is grounded in Tamara Munzner's nested design model and the +Network-Based Graph Model framing in Meyer, Sedlmair, and Munzner +([BELIV 2012](https://miriah.github.io/publications/nbgm-beliv.pdf)). In that +framing, a **network** is a data-abstraction block: nodes, links, and +attributes are the structural primitives on which tasks, encodings, and +algorithms are stacked. + +### 1.1 Scope of v0.1 + +In scope: + +- core identity and typing rules for nodes and edges +- attribute model and namespaces +- provenance and lineage +- a baseline catalog of inspection operations +- alignment notes for repo-native graph bindings (for example Railiance Fabric) + +Out of scope for v0.1: + +- storage engines, query languages, or visualization encodings +- domain-specific node/edge type catalogs +- lens and vantage-point configuration schemas +- validation tooling and serialization formats (future workplans) + +### 1.2 Design principles + +1. **Neutral core, interpreted surface.** The model stores facts; bindings + supply domain semantics. +2. **Inspectable by default.** Every element should be explainable: what it + is, why it exists, and how it was derived. +3. **Provenance over assertion.** Observed and derived facts carry origin, + method, confidence, and freshness. +4. **Perspective-friendly structure.** The same graph supports multiple + inspection operations without duplicating source data. +5. **Composable bindings.** Repo-native declarations, scanners, and exports can + project into NBGM without becoming the authoring authority. + +--- + +## 2. Terminology + +| Term | Definition | +|------|------------| +| **Graph** | A bounded collection of nodes and edges sharing one identity and metadata envelope. | +| **Node** | An entity vertex with stable identity, kind, and attributes. | +| **Edge** | A directed or undirected relationship between two nodes. | +| **Kind** | A domain-defined type label for a node or edge (for example `Service`, `requires`). | +| **Attribute** | A named property on a node or edge, optionally typed and namespaced. | +| **Provenance** | Metadata describing how and when a fact entered the graph. | +| **Binding** | A domain projection that maps external declarations or observations into NBGM elements. | +| **Lens** | A named interpretation layer that selects, re-labels, or aggregates graph elements for a task. | +| **Vantage point** | A saved or ephemeral lens plus inspection context (focus, depth, filters). | +| **Inspection operation** | A read-only graph query or explanation primitive. | + +--- + +## 3. Graph envelope + +Every NBGM instance is wrapped in a graph envelope. + +```yaml +apiVersion: vantage.nbgm/v0.1 +kind: Graph +metadata: + id: example.ecosystem + title: Example ecosystem graph + domain: infotech # optional binding domain + created_at: "2026-06-24T00:00:00Z" + updated_at: "2026-06-24T00:00:00Z" + source_bindings: + - binding_id: railiance-fabric.export + source_ref: railiance-fabric/registry +spec: + node_count: 0 # informational; implementations may omit + edge_count: 0 + default_direction: directed +``` + +### 3.1 Required envelope fields + +| Field | Requirement | +|-------|-------------| +| `apiVersion` | Must be `vantage.nbgm/v0.1` for this revision. | +| `kind` | Must be `Graph`. | +| `metadata.id` | Stable graph identifier. Prefer dotted, lower-case slugs. | +| `metadata.title` | Human-readable graph name. | +| `metadata.updated_at` | ISO-8601 timestamp of last material change. | +| `spec.default_direction` | `directed` or `undirected`. Edge-level direction may override. | + +### 3.2 Optional envelope fields + +- `metadata.domain` — primary interpretation domain for the graph. +- `metadata.created_at` — first materialization time. +- `metadata.source_bindings[]` — list of bindings that produced or refreshed the graph. +- `metadata.labels` — arbitrary string tags for indexing and filtering. +- `metadata.description` — narrative summary of graph intent and coverage. + +--- + +## 4. Nodes + +A node represents one addressable entity in the modeled system. + +```yaml +kind: Node +metadata: + id: railiance-platform.openbao + stable_key: railiance-platform.openbao # durable id across renames + name: OpenBao + labels: + repo: railiance-platform + domain: railiance +spec: + node_kind: Service + lifecycle: active # planned | active | deprecated | retired + layer: service # optional stratification hint +attributes: + core: + description: Runtime secrets service + display: + label: OpenBao + visual_weight: 1.0 +provenance: + assertion_type: declared # declared | observed | derived | inferred + sources: + - ref: fabric/services/openbao.yaml + method: declaration_load + observed_at: "2026-06-24T00:00:00Z" + confidence: 1.0 + freshness_state: current # current | stale | unknown +``` + +### 4.1 Identity rules + +1. `metadata.id` is unique within a graph. +2. `metadata.stable_key` is optional but recommended when display ids may change. + Profile rules, deep links, and temporal comparison should prefer + `stable_key` when present. +3. IDs should be stable across re-ingestion when the underlying entity is + unchanged. Bindings must document their ID strategy. + +### 4.2 Required node fields + +| Field | Requirement | +|-------|-------------| +| `metadata.id` | Unique node identifier. | +| `spec.node_kind` | Domain-defined entity kind. | +| `provenance.assertion_type` | How the node fact was obtained. | +| `provenance.sources[]` | At least one source record for non-synthetic nodes. | + +### 4.3 Recommended node fields + +| Field | Purpose | +|-------|---------| +| `metadata.name` | Short display name. | +| `metadata.labels` | Cross-cutting indices (`repo`, `domain`, `environment`, etc.). | +| `spec.lifecycle` | Entity lifecycle state. | +| `spec.layer` | Layer or stratum for layout and filtering. | +| `attributes.core` | Domain-neutral or lightly-bound descriptive fields. | +| `provenance.confidence` | Numeric confidence in `[0, 1]`. | +| `provenance.freshness_state` | Whether the fact is current enough to trust for the active task. | + +### 4.4 Node kinds + +`spec.node_kind` is binding-defined. Vantage Point does not mandate a global +ontology in v0.1. Bindings should publish their kind catalog and mapping rules. + +Examples from existing ecosystem graphs: + +| Binding | Example node kinds | +|---------|-------------------| +| Railiance Fabric | `Repository`, `Service`, `Capability`, `Interface` | +| Repo-scoping | `Fact`, `Evidence`, `Feature`, `Capability`, `Ability`, `Scope` | + +Bindings may attach additional kind metadata under `attributes.binding.*` but +must not overload `spec.node_kind` with multiple meanings. + +--- + +## 5. Edges + +An edge represents a relationship between exactly two nodes. + +```yaml +kind: Edge +metadata: + id: railiance-platform.state-hub.requires.runtime-secrets + stable_key: railiance-platform.state-hub->runtime-secrets +spec: + edge_kind: requires + source_id: railiance-platform.state-hub + target_id: railiance-platform.openbao + direction: directed # directed | undirected + cardinality: many_to_one # optional: one_to_one | one_to_many | many_to_one | many_to_many + strength: required # optional qualitative or numeric weight + same_layer: false +attributes: + core: + criticality: high + environments: [dev, staging, prod] +provenance: + assertion_type: declared + sources: + - ref: fabric/dependencies/state-hub-runtime-secrets.yaml + method: declaration_load + observed_at: "2026-06-24T00:00:00Z" + confidence: 1.0 + freshness_state: current +``` + +### 5.1 Required edge fields + +| Field | Requirement | +|-------|-------------| +| `metadata.id` | Unique edge identifier within the graph. | +| `spec.edge_kind` | Domain-defined relationship type. | +| `spec.source_id` | Existing node `metadata.id`. | +| `spec.target_id` | Existing node `metadata.id`. | +| `spec.direction` | `directed` or `undirected`. | +| `provenance` | Same minimum provenance requirements as nodes. | + +### 5.2 Edge semantics + +- **Directed edges** express dependency, production, consumption, containment, + or influence from `source_id` to `target_id`. +- **Undirected edges** express equivalence, association, or co-location when + direction would be misleading. +- `spec.same_layer: true` marks intra-layer normalization or peer links that + should be visually and analytically distinct from cross-layer dependencies. +- `spec.strength` may be categorical (`required`, `optional`, `weak`) or + numeric. Bindings must document their scale. + +### 5.3 Multi-edges + +Multiple edges may connect the same node pair when they differ in `edge_kind`, +binding origin, or distinguishing attributes. Re-ingestion should update the +same logical edge in place when `metadata.stable_key` or a binding-supplied +dedupe key matches. + +--- + +## 6. Attributes + +Attributes carry descriptive, analytical, and presentational facts on nodes and +edges. They are grouped by namespace to keep the neutral core separable from +binding-specific and display-specific data. + +### 6.1 Namespaces + +| Namespace | Purpose | Examples | +|-----------|---------|----------| +| `core` | Stable descriptive fields useful across lenses | `description`, `owner`, `version` | +| `display` | Presentation hints for explorers | `label`, `color`, `visual_weight`, `display_state` | +| `analytical` | Metrics and derived indicators | `fan_in`, `cycle_member`, `cluster_id` | +| `binding` | Binding-private structured payload | Fabric deployment overlays, scanner hashes | +| `temporal` | Time-oriented fields | `valid_from`, `valid_to`, `observed_at` | + +Namespaces are conventional in v0.1. Implementations may store them as nested +objects (`attributes.core.description`) or flattened keys with a prefix +(`core.description`). + +### 6.2 Attribute records + +Each attribute SHOULD be representable as: + +```yaml +name: description +namespace: core +value: Runtime secrets service +value_type: string # string | number | boolean | enum | object | array | timestamp +cardinality: single # single | multi +mutable: true # whether re-ingestion may change this field in place +source: declared # declared | observed | derived | inferred +``` + +### 6.3 Typing and validation + +v0.1 does not mandate a global attribute schema. Bindings SHOULD publish: + +- allowed attributes per node/edge kind +- value types and enumerations +- required vs optional attributes +- deprecation notes for renamed attributes + +Inspection operations must treat unknown attributes as opaque but returnable. + +### 6.4 Display state + +When a graph is prepared for interactive exploration, elements may carry a +display attribute: + +| Value | Meaning | +|-------|---------| +| `show` | Fully visible with normal styling and labels. | +| `blur` | Visible but de-emphasized; details on hover or selection. | +| `hide` | Excluded from the active view but retained in the source graph. | + +Display state is a vantage-point concern. It does not change graph truth data. + +--- + +## 7. Provenance + +Provenance makes graph facts auditable. Every node and edge MUST include a +provenance block sufficient to answer: + +1. How was this fact introduced? +2. From what source material or observation? +3. How much should an operator trust it right now? + +### 7.1 Assertion types + +| Type | Meaning | +|------|---------| +| `declared` | Authored by a repo-local declaration or human assertion. | +| `observed` | Captured from runtime, repository scan, or external system query. | +| `derived` | Computed from other graph elements or transformations. | +| `inferred` | Produced by heuristic or ML extraction with weaker guarantees. | + +### 7.2 Source records + +Each `provenance.sources[]` entry SHOULD include: + +| Field | Requirement | +|-------|-------------| +| `ref` | Pointer to source artifact (path, URL, export id, scan id). | +| `method` | Binding-specific ingestion or transformation step. | +| `observed_at` | ISO-8601 timestamp for when the source was read or captured. | + +Optional source fields: + +- `actor` — human, service, or agent that triggered ingestion +- `version` — source artifact version or commit +- `checksum` — content hash for reproducibility +- `notes` — free-text operator context + +### 7.3 Confidence and freshness + +- `confidence` is a float in `[0, 1]`. Bindings should define default confidence + by assertion type when not explicitly set. +- `freshness_state` is one of `current`, `stale`, or `unknown`. +- `freshness_evaluated_at` MAY record when freshness was last assessed. + +Derived and inferred facts SHOULD reference upstream source ids or derivation +recipes under `provenance.derived_from[]`: + +```yaml +provenance: + assertion_type: derived + derived_from: + - node_id: repo:railiance-fabric + - edge_id: railiance-fabric.state-hub.requires.runtime-secrets + derivation: + method: impact_closure + recipe_version: "1" +``` + +### 7.4 Lineage inspection + +Provenance must be sufficient for the `explain` inspection operation (see +section 8.6) to reconstruct a human-readable chain from source artifacts to the +displayed fact. + +--- + +## 8. Inspection operations + +Inspection operations are read-only primitives over an NBGM graph. They are the +stable API surface between graph stores, agents, and vantage-point UIs. + +Implementations MAY expose additional operations but SHOULD support the v0.1 +baseline set or declare partial support explicitly. + +### 8.1 Operation envelope + +Operation requests and responses use a common envelope: + +```yaml +apiVersion: vantage.nbgm/v0.1 +kind: InspectionRequest +metadata: + operation: neighborhood + graph_id: example.ecosystem +spec: + parameters: {} +``` + +```yaml +apiVersion: vantage.nbgm/v0.1 +kind: InspectionResponse +metadata: + operation: neighborhood + graph_id: example.ecosystem +spec: + complete: true + result: {} + warnings: [] +``` + +### 8.2 `lookup` + +**Purpose:** Fetch one node or edge by id or stable key. + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `element_type` | yes | `node` or `edge` | +| `id` | one of | Primary identifier | +| `stable_key` | one of | Durable identifier | + +**Result:** The matching element or `not_found`. + +### 8.3 `neighborhood` + +**Purpose:** Expand around a focus node to a controlled depth. + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `focus_id` | yes | Starting node id | +| `depth` | yes | Hop count (1–N) | +| `edge_kinds` | no | Relationship filter | +| `direction` | no | `out`, `in`, or `both` (default `both`) | +| `max_nodes` | no | Safety cap | + +**Result:** Subgraph of nodes and edges reachable under the parameters. + +### 8.4 `path` + +**Purpose:** Find connecting paths between nodes for dependency or impact +analysis. + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `source_id` | yes | Start node | +| `target_id` | yes | End node | +| `edge_kinds` | no | Allowed relationship types | +| `max_depth` | no | Search bound | +| `strategy` | no | `shortest`, `all_bounded`, or `weighted` | + +**Result:** Zero or more paths, each an ordered list of node and edge ids. + +### 8.5 `filter` + +**Purpose:** Select a subgraph by declarative predicates. + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `predicate` | yes | Structured filter over kinds, labels, attributes, lifecycle, freshness | +| `include_isolated` | no | Keep nodes with no matching edges (default false) | + +**Result:** Induced subgraph containing matching elements and connecting edges +when requested. + +### 8.6 `explain` + +**Purpose:** Produce a human- and agent-readable justification for an element. + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `element_type` | yes | `node` or `edge` | +| `id` | yes | Element identifier | +| `include_derivation` | no | Expand derived-from chain (default true) | + +**Result:** + +- element summary +- provenance sources and timestamps +- confidence and freshness assessment +- optional upstream path for derived/inferred facts + +### 8.7 `summarize` + +**Purpose:** Aggregate statistics for a subgraph or whole graph. + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `scope` | no | Whole graph or subgraph selector | +| `metrics` | no | Requested aggregates | + +**Default metrics:** + +- counts by `node_kind` and `edge_kind` +- unresolved or stale fact counts +- top hubs by in-degree and out-degree +- connected component count + +### 8.8 `compare` + +**Purpose:** Diff two graph snapshots that share identity rules. + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `baseline_graph` | yes | Reference graph id or snapshot | +| `candidate_graph` | yes | Graph to compare | +| `match_key` | no | `id` or `stable_key` (default `stable_key`) | + +**Result:** + +- `added`, `removed`, and `changed` nodes and edges +- attribute-level deltas for changed elements +- provenance changes when sources or confidence differ + +### 8.9 `violations` + +**Purpose:** Evaluate structural expectations declared by a binding or lens. + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `rule_set` | yes | Binding-published constraint set | +| `severity_at_least` | no | Minimum severity to return | + +**Result:** List of violations with element refs, rule id, severity, and +recommended inspection follow-up. + +### 8.10 Operation composition + +Vantage points compose inspection operations rather than mutating the graph: + +```text +filter(layer=service) + -> neighborhood(focus=selected, depth=2, edge_kinds=[requires]) + -> summarize(metrics=[hub_rank]) + -> explain(id=top_hub) +``` + +Bindings and lenses may publish recommended operation chains for common tasks. + +--- + +## 9. Binding alignment + +NBGM is intentionally abstract. Existing repo-native graph models should +project into it without losing source-of-truth boundaries. + +### 9.1 Railiance Fabric mapping + +| Fabric concept | NBGM element | Notes | +|----------------|--------------|-------| +| Declaration `metadata.id` | `Node.metadata.id` | Preserve dotted ids. | +| Declaration kind | `Node.spec.node_kind` | `Service`, `Capability`, etc. | +| Dependency requirement | `Edge.spec.edge_kind = requires` | Directed to provider capability or interface node. | +| Binding assertion | `Edge.spec.edge_kind = binds` | Resolves consumer requirement. | +| `metadata.source_links` | `provenance.sources[].ref` | Multiple links become multiple source records. | +| Graph export payload | NBGM graph envelope + elements | Explorer display fields map to `attributes.display`. | + +Fabric remains authoritative for declarations. Vantage Point consumes exports as +an inspection-ready NBGM binding. + +### 9.2 Repo-scoping mapping + +| Repo-scoping layer | NBGM usage | +|--------------------|------------| +| `facts`, `evidence`, `features`, `capabilities`, `abilities`, `scope` | `Node.spec.layer` and `Node.spec.node_kind` | +| Evidence bridges | `Edge` with `edge_kind` reflecting support/challenge/link semantics | +| Display states in profiles | `attributes.display.display_state` | + +### 9.3 Source-of-truth rule + +Authoritative data lives in repo-native declarations, scans, or curated stores. +NBGM graphs are inspection-ready projections. Re-ingestion refreshes +projections; it does not rewrite authoritative sources. + +--- + +## 10. Examples + +### 10.1 Minimal service dependency graph + +```yaml +apiVersion: vantage.nbgm/v0.1 +kind: Graph +metadata: + id: demo.minimal + title: Minimal dependency demo + updated_at: "2026-06-24T00:00:00Z" +spec: + default_direction: directed +elements: + - kind: Node + metadata: + id: consumer.app + name: Consumer App + spec: + node_kind: Service + provenance: + assertion_type: declared + sources: + - ref: fabric/services/consumer.yaml + method: declaration_load + observed_at: "2026-06-24T00:00:00Z" + - kind: Node + metadata: + id: provider.db + name: Database + spec: + node_kind: Service + provenance: + assertion_type: declared + sources: + - ref: fabric/services/database.yaml + method: declaration_load + observed_at: "2026-06-24T00:00:00Z" + - kind: Edge + metadata: + id: consumer.app.requires.provider.db + spec: + edge_kind: requires + source_id: consumer.app + target_id: provider.db + direction: directed + provenance: + assertion_type: declared + sources: + - ref: fabric/dependencies/consumer-db.yaml + method: declaration_load + observed_at: "2026-06-24T00:00:00Z" +``` + +### 10.2 Neighborhood inspection + +```yaml +apiVersion: vantage.nbgm/v0.1 +kind: InspectionRequest +metadata: + operation: neighborhood + graph_id: demo.minimal +spec: + parameters: + focus_id: consumer.app + depth: 2 + direction: out + edge_kinds: [requires] +``` + +--- + +## 11. Open questions for v0.2 + +- Canonical serialization format (single JSON schema vs multi-document YAML) +- Global registries for cross-domain `node_kind` and `edge_kind` aliases +- Lens and vantage-point configuration schema +- Standard binding interface for incremental graph refresh +- Normative confidence and freshness scoring recipes per assertion type + +--- + +## 12. References + +- `INTENT.md` — project purpose and guiding principles +- `SCOPE.md` — repository boundary +- Meyer, Sedlmair, Munzner — *The Four-Level Nested Model Revisited: Blocks and Guidelines* ([PDF](https://miriah.github.io/publications/nbgm-beliv.pdf)) +- Railiance Fabric — `docs/declaration-schema.md`, `docs/graph-explorer-contract.md` +- Repo-scoping — dependency visualization layer model (`RREG-WP-0010`) \ No newline at end of file diff --git a/workplans/VANTAGE-WP-0002-nbgm-spec-baseline.md b/workplans/VANTAGE-WP-0002-nbgm-spec-baseline.md index f65127e..1f6af1e 100644 --- a/workplans/VANTAGE-WP-0002-nbgm-spec-baseline.md +++ b/workplans/VANTAGE-WP-0002-nbgm-spec-baseline.md @@ -4,11 +4,11 @@ type: workplan title: "NBGM model specification baseline" domain: infotech repo: vantage-point -status: ready +status: finished owner: codex topic_slug: infotech created: "2026-06-22" -updated: "2026-06-22" +updated: "2026-06-24" state_hub_workstream_id: "bd2d70eb-4c83-4fa3-94ff-7f44b32aeba9" --- @@ -20,9 +20,11 @@ Author the network-based graph model specification baseline. ```task id: VANTAGE-WP-0002-T01 -status: todo +status: done priority: high state_hub_task_id: "d13bd898-15b0-41ba-aa3b-8c5f96a09fd8" ``` -Write spec covering nodes, edges, attributes, provenance, and inspection operations. +Result 2026-06-24: Authored `docs/nbgm-spec-v0.1.md` covering graph envelope, +nodes, edges, attribute namespaces, provenance/lineage, inspection operations, +and binding alignment for Railiance Fabric and repo-scoping.