JSON Schemas
All Spec Graph files are validated against JSON Schemas using JSON Schema Draft 2020-12.
Schema Files
| Schema | Validates | Required? |
|---|---|---|
graph.schema.json | graph.json index file | Yes |
node.schema.json | Individual node files | Yes |
graph-index.schema.json | Generated edge index | Optional |
manifest-lock.schema.json | Manifestation lockfile | Optional |
Schema $id base URL: https://oco-adam.github.io/specgraph/schemas/
graph.schema.json
Validates the graph.json entry point file. Required fields:
specgraphVersion— semver string (e.g.,"1.0.0")nodes— array of node references withidandpath
Optional fields:
root— root node IDnodeSearchPaths— additional directories to scandefaults— default values for tooling
Node References
Each entry in nodes has:
{
"id": "AUTH-01",
"path": "nodes/behaviors/AUTH-01.json",
"sha256": "...", // optional: content hash
"expectedType": "behavior" // optional: quick type check
}
node.schema.json
Validates individual node files. Uses oneOf to distinguish four shapes:
Feature Nodes
Required: id, type (= "feature"), title, description
Layer Nodes
Required: id, type (= "layer"), title, description
Behavior Nodes
Required: id, type (= "behavior"), title, expectation, verification
Optional: constraints (array)
Authoring convention: include constraints explicitly on behavior nodes and use [] when none apply. Omission remains schema-valid for backward compatibility.
Contract Nodes
All other types (foundation, decision, domain, policy, and extensions).
Required: id, type, title, statement, verification (array)
Type-specific requirements:
decisionnodes requirecategoryandmetadata.rationale(min length 10)policynodes requireseverityartifactnodes require anartifactobject with a normativesha256hash (and optionalsource/format)
Other optional fields: constraints (array), links, metadata, pins (for derived nodes)
Metadata supports optional rejected_alternatives entries (title + reason) for decision history context.
The links Field
Available on all node types. Supports seven edge types:
"links": {
"contains": ["..."],
"depends_on": ["..."],
"constrains": ["..."],
"implements": ["..."],
"derived_from": ["..."],
"verified_by": ["..."],
"supersedes": ["..."]
}
Verification Entries
Contract nodes use an array of verification entries. Each entry is either a string or a structured object:
"verification": [
"pytest tests/architecture/test_auth_provider.py -k DEC_AUTH_01",
{
"kind": "command",
"command": "cargo test auth::provider::contract -- --exact",
"timeoutSeconds": 120
},
{
"kind": "http",
"method": "GET",
"url": "http://localhost:3000/api/health",
"expectStatus": 200
}
]
Supported kind values: command, http, manual, observation, policy.
Node ID Format
Node IDs must match: ^[A-Z][A-Z0-9-]{0,79}$
Feature IDs must match: ^[A-Z][A-Z0-9-]{0,19}$
Node Types
Core: feature, layer, foundation, behavior, decision, domain, policy
Extensions: design_token, ui_contract, api_contract, data_model, artifact, equivalence_contract, pipeline
graph-index.schema.json
Validates the optional generated edge index. Required fields:
specgraphVersiongeneratedFrom— path (and optional hash) of the sourcegraph.jsonedges— array of{ from, type, to }triples
This file is a derived artifact. It should be regenerated from node files and never hand-edited.
manifest-lock.schema.json
Validates the optional manifestation lockfile. Required fields:
specgraphVersiongraph— path and SHA-256 hash of the manifested graphmanifestedAt— ISO 8601 timestamp
Optional fields:
equivalenceContractId— node ID of the equivalence contract usedtoolchain— pinned tool versionsartifacts— resolved artifact hasheschecks— verification results from manifestation
Validation
Use ajv or any JSON Schema Draft 2020-12 compatible validator:
# Validate a graph index
npx ajv validate -s schemas/graph.schema.json -d specgraph/graph.json
# Validate a node file
npx ajv validate -s schemas/node.schema.json -d specgraph/nodes/behaviors/AUTH-01.json
Or use the provided validation script:
node validate.js
For graph-level integrity checks (edges, missing targets, depends_on cycles, pins), run:
node graph_check.js