Skip to content

SignalQL v0.5 — derivation, dependency state, and lineage ​

Status: Draft with reference implementation. Part of the v0.5 specification. Builds on the object model.

Derivation ​

A derivation records that one object revision was produced from another:

sales.csv  →  analysis  →  forecast  →  board-summary

forecast DERIVED FROM sales.csv is a stronger statement than forecast RELATED TO sales.csv. v0.5 defines five derivation relations:

RelationMeaning
derived_fromgeneric derivation
generated_fromproduced by a model or program from the source
extracted_froma part or claim lifted out of the source
summarized_froma condensed form of the source
transformed_froma format or structure change of the source

All five share one model: a link from a derived revision to a source revision.

(from_object, from_rev)  —relation→  (to_object, to_rev)

The link is pinned: it names the exact source revision that was read. This is what makes staleness computable.

These relation names are part of the core vocabulary, unlike domain relationship names, which stay in packs. They are written in snake_case, matching the derived_from edge already used for v0.4 lineage; the camelCase spellings (derivedFrom, …) are accepted on input and normalized. Because derivations are projected as graph edges, v0.4 TRACE … VIA derived_from works over objects as well.

A link MAY carry metadata such as a locator (the paragraph, timestamp, or cell range the derived content came from).

Dependency state ​

Every object revision has a dependency state, one of:

CURRENT   POSSIBLY_STALE   STALE   INVALID

State is a computed fact, not an interpretation. It is a pure function of revision facts as of the query time T — no clocks, thresholds, or domain meaning — so the same facts always give the same state. This is why it does not conflict with the v0.4 rule that stale is not an operator: there is still no STALE operator. state is a field, read through ordinary predicates. Interpretive staleness ("no activity in 3 days") remains a signal(...).

For a link pinned to (source, n), with latest(source, T) the source's latest revision as of T:

Link stateCondition
invalidrevision n of the source does not exist as of T, or the source is tombstoned at or before T
staleotherwise, latest(source, T) > n
currentotherwise

Object state ​

For revision r of object X, let its direct links be the derivations recorded from (X, r) at or before T, and its pinned lineage be the links reached by following each source at its pinned revision, transitively. The first matching rule wins:

  1. invalid — a direct link is invalid.
  2. stale — a direct link is stale.
  3. possibly_stale — a link deeper in the pinned lineage is stale or invalid.
  4. current — otherwise, including objects with no derivations.

The traversal MUST guard against cycles on (object, revision) and MUST be bounded; the reference bound is 16 levels.

This lets SignalQL answer a question conventional retrieval cannot:

Which generated knowledge may no longer be valid because its sources changed?

Grammar (EBNF, additive) ​

ebnf
find_object     ::= "FIND" "OBJECT" ( "(" name ")" )?
                    ( "WHERE" object_predicate )? as_of_clause? limit_clause?
find_dependents ::= "FIND" "DEPENDENTS" "OF" object_ref
                    via_derivation? depth_clause? ( "WHERE" object_predicate )?
                    as_of_clause? limit_clause?
trace_object    ::= "TRACE" ( object_ref | "CLAIM" ( object_uri | name ) )
                    via_derivation? depth_clause? as_of_clause?
via_derivation  ::= "VIA" derivation_rel ( "," derivation_rel )*
derivation_rel  ::= "derived_from" | "generated_from" | "extracted_from"
                  | "summarized_from" | "transformed_from"
depth_clause    ::= "DEPTH" "<=" integer

object_predicate is the v0.3 predicate_expr over object fields.

Object fields ​

FieldMeaningOperators
id (object_id)object idall
type, title, projectobject attributesall
rev (revision)selected revision numberall
created_atobject creation timeall
origin, trust, validationrevision metadata=, !=, IN
rolerevision roles; = means "has this role"=, !=, IN
statedependency state=, !=, IN
any other name, or metadata.<key>a metadata keyall

Values of the closed vocabularies (state, origin, trust, validation, role) MAY be written as bare words or as strings, in any case: STATE = STALE and state = "stale" are the same query. An unknown value is a parse error.

FIND OBJECT ​

Returns live (non-tombstoned) objects at their latest revision as of T, ordered by id.

signalql
FIND OBJECT WHERE STATE = STALE
FIND OBJECT(document) WHERE trust IN (verified, authoritative) AND project = "SignalQL"

Columns: object_id, type, title, project, revision, state, origin, trust, validation, roles, revised_at.

FIND DEPENDENTS ​

Returns the objects whose current revision derives, directly or transitively, from the given object. Links recorded from a superseded revision of a dependent are history and do not count. With @n, only objects derived from that revision are seeds.

signalql
FIND DEPENDENTS OF OBJECT source_data
FIND DEPENDENTS OF OBJECT object://source_data WHERE state != current

One row per dependent, at its nearest depth; ties resolve to the lowest (source_object, relation). Ordered by depth, then id. Default depth 6, maximum 16.

Columns: object_id, type, title, project, revision, depth, relation, source_object, pinned_revision, state.

TRACE OBJECT and TRACE CLAIM ​

TRACE OBJECT returns the upstream lineage of one object revision: the target, then every derivation link reachable by following pinned source revisions.

signalql
TRACE OBJECT board_summary
board_summary@3
  generated_from  forecast@7        current
    derived_from  sales_data@18     stale   (latest is 19)
    derived_from  assumptions@4     current

Each step carries object_id, type, revision, relation, from_object, latest_revision, link_state, depth, metadata. Step 0 is the target. Steps are ordered by depth, then from_object, object_id, relation. A source appears at the revision the link is pinned to. metadata.truncated reports that links exist beyond the depth bound.

A claim is an object of type claim, linked to its source by extracted_from. TRACE CLAIM is TRACE OBJECT that requires the target to be a claim, so the result identifies the exact source revision — and, through link metadata, the location — a claim came from:

signalql
TRACE CLAIM launch_date

TRACE returns lineage. It renders no verdict on whether the reasoning was good.

Timestamps ​

AS OF and timestamp comparisons use the literal as written. A literal without a zone is interpreted in the executing engine's session time zone, so for portable queries write an explicit zone ("2026-08-12T00:00:00Z"). Implementations SHOULD execute in UTC.