SPEC-0018: Artifact Graph
Overview
Formalizes the artifact-to-artifact relationship graph that underlies impact analysis, lineage queries, orphan detection, and any future graph/RAG MCP for the SDD plugin. Defines the frontmatter edge schema for ADRs and specs, the graph builder behavior (parsing, inverse derivation, validation), the /sdd:graph skill verbs and output formats, and the assisted backfill workflow for migrating existing prose-encoded relationships. See 📝 ADR-0023.
This spec is intentionally narrow: it defines the artifact-level graph layer. It does not specify a local MCP — that is a future decision whose consumer contract is the JSON output format defined here. This spec is also the first artifact in the SDD repo to use the new frontmatter edge schema (implements: [ADR-0023], requires: [SPEC-0014]), demonstrating the format end-to-end.
Requirements
Requirement: Frontmatter Edge Schema
ADRs and specs SHALL declare relationships to other artifacts via optional fields in their YAML frontmatter. All edge fields MUST be lists of artifact IDs (e.g., [ADR-0008, ADR-0009]). All edge fields are OPTIONAL — an artifact with no declared edges is valid. Edges MUST be forward-only as defined in the schema below; reverse-direction fields (e.g., governed-by:, implemented-by:) MUST NOT be authored — they are derived per Requirement: Inverse Edge Derivation.
ADR edge fields:
| Field | Meaning | Example |
|---|---|---|
supersedes | Hard replacement — the referenced ADR moves to status superseded | supersedes: [ADR-0003] |
extends | Builds on without replacing | extends: [ADR-0008, ADR-0009] |
enables | Unblocks a downstream decision | enables: [ADR-0016] |
governs | Names specs this decision governs | governs: [SPEC-0007, SPEC-0010] |
related | Weak association, no semantic claim | related: [ADR-0010] |
Spec edge fields:
| Field | Meaning | Example |
|---|---|---|
implements | ADRs this spec realizes | implements: [ADR-0009, ADR-0011] |
requires | Capability dependency on another spec | requires: [SPEC-0007] |
extends | Behavioral extension of another spec | extends: [SPEC-0007] |
supersedes | Hard replacement — referenced spec moves to status deprecated (the spec status enum has no superseded; per /sdd:status) | supersedes: [SPEC-0XXX] |
The schema MUST be artifact-level only in v1. Requirement-level edges (e.g., a SPEC-0014 REQ "Cross-Module Aggregation" declaring it is governed by ADR-0016) are explicitly out of scope for this spec.
Scenario: ADR with multiple edge types
- WHEN an ADR has frontmatter containing
supersedes: [ADR-0003],extends: [ADR-0008], andgoverns: [SPEC-0007] - THEN the graph builder SHALL record three forward edges from this ADR plus the corresponding derived inverses on 📝 ADR-0003, 📝 ADR-0008, and SPEC-0007
Scenario: Spec implements an ADR
- WHEN a spec has frontmatter
implements: [ADR-0023] - THEN the graph builder SHALL record a forward edge
SPEC-XXXX --implements--> ADR-0023and a derived inverseADR-0023 --governed-by--> SPEC-XXXX
Scenario: Artifact with no declared edges
- WHEN an artifact has no edge fields in its frontmatter
- THEN the graph builder SHALL record the artifact as a node with no outgoing edges and SHALL NOT raise an error
Scenario: Reverse-direction field rejected
- WHEN an artifact's frontmatter contains a derived field name (e.g.,
governed-by:,implemented-by:,superseded-by:) - THEN the graph builder MUST emit a warning identifying the file and field, and MUST NOT process it as an edge
Requirement: Graph Construction
The /sdd:graph skill SHALL build an in-memory directed graph at query time from two sources: (a) artifact frontmatter edges per Requirement: Frontmatter Edge Schema, and (b) file-level governing comment blocks per 📝 ADR-0020 / SPEC-0016 REQ "Governing Comment Format". The graph MUST NOT be persisted between invocations in v1 — each invocation rebuilds from current files. Caching MAY be added in a future revision when query latency becomes a concern.
Scenario: Build from frontmatter only
- WHEN the skill is invoked in a project with N ADRs and M specs but no source code
- THEN the graph SHALL contain N + M nodes and edges derived solely from frontmatter
Scenario: Build from frontmatter and governing comments
- WHEN the skill is invoked in a project with ADRs, specs, and source files containing
// Governing: ADR-XXXXand// Implements: SPEC-XXXX REQ "..."blocks - THEN the graph SHALL contain artifact nodes plus file nodes, with edges from each file to its governing artifacts
Scenario: Files without governing comments
- WHEN a source file lacks a governing comment block
- THEN the file MUST NOT be added as a node in the graph — it remains invisible to traversal queries and surfaces only via the
orphansverb
Requirement: Inverse Edge Derivation
For every forward edge declared in frontmatter, the graph builder SHALL derive a corresponding reverse edge at build time. Derived edges MUST NOT be authored in frontmatter. The complete derivation table:
| Forward edge | Derived inverse |
|---|---|
supersedes (ADR → ADR, spec → spec) | superseded-by |
extends (ADR → ADR, spec → spec) | extended-by |
enables (ADR → ADR) | enabled-by |
governs (ADR → spec) | governed-by |
related (ADR ↔ ADR) | related (symmetric) |
implements (spec → ADR) | implemented-by |
requires (spec → spec) | depended-on-by |
Derived edges MUST be queryable via the same skill verbs as authored edges. Output formats MUST distinguish derived edges from authored edges (e.g., a derived: true field in JSON output, an "(derived)" annotation in markdown output).
Scenario: Derived inverse from governs
- WHEN 📝 ADR-0009 declares
governs: [SPEC-0007] - THEN querying ancestors of SPEC-0007 SHALL return 📝 ADR-0009 with edge type
governed-bymarked as derived
Scenario: Symmetric related edge
- WHEN 📝 ADR-0010 declares
related: [ADR-0001]and 📝 ADR-0001 does NOT declarerelated: [ADR-0010] - THEN the graph SHALL contain a
relatededge in both directions; the