Outputs and the Graph Format
File |
Contents |
|---|---|
|
Nodes ( |
|
Summary and coverage, the most queried columns (with usage on), business terms, the most used columns, orphans, untested models, columns with no lineage, columns documented in dbt but missing from the warehouse, and warnings |
|
The entities, measures, relationships and rules derived from the graph, each with its confidence (see The Ontology); |
|
The data laws |
|
The index of search by meaning and every node’s blocks, written by the first search by meaning and brought up to date by the first after each build (see Searching by Meaning) |
|
The answer receipts |
|
A single offline file (open it with |
|
What |
Edge |
Direction |
Meaning |
|---|---|---|
|
relation to column |
The column belongs to the relation |
|
upstream to downstream |
Relation to relation, task to the table it writes, table to the task that reads it. With |
|
column to the column it comes from |
Column-level lineage, with |
|
DAG to task, task to dbt node |
What a DAG or task executes |
|
task to task |
Airflow ordering, Dagster op and asset ordering, and sensors that start one job after another |
|
test to relation or column |
What a dbt test checks |
|
term to column or relation |
The column that holds a business term |
|
term to term |
Related business terms; with |
A relation that SQL writes has conditions in its attrs: the joins, filters and grouping that shape its rows, in terms of physical columns, each labelled with where it applies (WHERE: ..., LEFT JOIN ON: ...); conditions covers every statement that writes the relation (a CREATE and an INSERT, say), as do nullable, read_before and star_reads, the relations it reads on the side of an outer join that may find no row, before a window or LIMIT, and through a star; an earlier Konstruct kept the last statement’s alone. Each of its columns has row_conditions, the positions in that list of the conditions that hold on every source row the column’s value is computed from: those on every input of the value, read through the alias each input is read through (the ON of an outer join holds only on the side that can find no row), whose filters read no other reading of a table the value is read from (a filter on one alias of a table, or on a column copied from another alias of it, says nothing of the rows of the first), before any window or aggregate it comes from, in every statement that writes the relation. A column read row for row from one reading of one relation has row_reading, that reading’s name (db.main.orders#2 where the statement reads orders more than once, else the relation’s key): two columns of the relation with the same row_reading come from the same rows. A column whose value aggregates rows or computes a window over them, in any of those statements, has aggregates_rows: true: a filter of a relation that reads it does not hold on the rows it was made from. A column without row_conditions (in a graph an earlier Konstruct built) says nothing about which conditions hold on it.
With Columns on, graph.html is a column-level map of the whole project:

Compatibility
Scripts, agents and CI that read Konstruct’s outputs keep working from one release to the next. These are the interfaces Konstruct keeps stable:
graph.json,conflicts.json,verify.json,laws.jsonand the receipts inkonstruct-out/,ontology.yml, andkonstruct.lock, whichkonstruct lockwrites at the project’s root and whoseformatchanges only with its layout;the
--jsonoutput of every command, and--format jsonand--json-fileofdiffandgate;the MCP tools: their names, their inputs and the shape of their results;
the command line: commands, options, choices and exit statuses;
the Python API: the names
konstructexports and the methods ofkonstruct.Project;the keys of
konstruct.toml(and[tool.konstruct]inpyproject.toml) that Konstruct names; a Snowflake, Databricks or Trino warehouse’s other keys go to its driver as they are, and follow the driver;the GitHub Action’s inputs and outputs, and the columns of the CSV export, in their order.
A release can add commands, options, fields, tools and keys, make a required argument optional,
and let an argument or parameter take more types. Removing or renaming one, or changing
what it means, is a breaking change: the changelog lists it under BREAKING CHANGE, and while
the version is 0.x it raises the minor version (0.12.x to 0.13.0). Every other release is a patch,
so konstruct>=0.12.2,<0.13 takes every release without a breaking change. A patch release can
still find more lineage, or correct lineage it had wrong: the shape of each answer stays the same,
its content follows the code.
Format Versions
Every JSON document Konstruct writes for programs carries format_version, an integer, as its
first field: graph.json, each command’s --json output and the MCP tool of the same name, and
conflicts.json, verify.json and laws.json (which also carries it as format, as Konstruct 0.13
wrote it), and each receipt in receipts/. A document’s format version changes only with a breaking change
to its shape, so a reader that checks it, and ignores fields it does not know, reads every later
document of that format. ontology.yml, and the ontology’s JSON, also carry version, the
ontology’s format from before format_version, which follows the same rule.
Konstruct reads every graph.json an earlier release wrote (one without format_version is format
1). It refuses one written by a newer Konstruct, with a message that says to upgrade, rather than
misread it; konstruct status reports such a graph rather than failing.
Document |
|
|---|---|
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
The exports follow their own specifications: OpenLineage events carry their schemaURL, and an
Apache Ossie model its Ossie version. Mermaid and Graphviz DOT are drawn for people, and their
text can change in any release.