Skip to content

SignalQL v0.2 specification

SignalQL v0.2 defines a domain-agnostic language for retrieving and shaping structured evidence from events, entities, relationships, and AI-created memory objects. Interpretation belongs to AI or higher application layers, not SignalQL itself.

Core principle

SignalQL retrieves structured evidence; it does not interpret, decide, or mutate state.

  • No domain-specific semantics in core grammar.
  • No action/mutation language.
  • No built-in labels like "blocked", "priority", or workflow states.

Core constructs

  • Entities: durable objects such as memory_object, decision, summary, fact, claim, plan, artifact, context_bundle, person, repo, thread.
  • Events: timestamped activity attached to entities and actors.
  • Relationships: traversable links between entities.
  • Signals: externally computed values exposed as queryable fields.
  • Probability fields: likelihood/confidence values from external models.
  • Provenance metadata: evidence hygiene fields such as source, created_by, derived_from, confidence, observed_at, updated_at.

Entity names above are core-safe examples, not required core nouns.

Grammar (EBNF)

ebnf
query              ::= retrieve_query | sequence_query

retrieve_query      ::= "FROM" source where_clause? traverse_clause? trend_clause? select_clause
source              ::= entity_source | event_source
entity_source       ::= "entity" "(" qualified_identifier ")"
event_source        ::= "events"

where_clause        ::= "WHERE" predicate_list
predicate_list      ::= predicate ( "AND" predicate )*
predicate           ::= field_path comparator value
comparator          ::= "=" | ">" | "<" | ">=" | "<="
field_path          ::= identifier ( "." identifier )*
                     | "signal" "(" identifier ")"
                     | "probability" "(" identifier ")"
                     | "semantic_match" "(" string_literal ")"

traverse_clause     ::= "TRAVERSE" identifier "DEPTH" "<=" integer
trend_clause        ::= "TREND" trend_dir "OVER" integer time_unit
trend_dir           ::= "UP" | "DOWN" | "FLAT"
time_unit           ::= "d" | "h" | "w"

sequence_query      ::= "FIND" "sequence" "WHERE" sequence_steps "WITHIN" integer time_unit
sequence_steps      ::= sequence_step ( "->" sequence_step )+
sequence_step       ::= identifier | string_literal

select_clause       ::= "RETURN" return_field ( "," return_field )*
return_field        ::= field_path | "count" | "entity_id" | "timestamp"

qualified_identifier ::= identifier ( "." identifier )*
identifier          ::= [a-zA-Z_] [a-zA-Z0-9_]*
integer             ::= [0-9]+
value               ::= string_literal | integer | decimal | boolean
string_literal      ::= '"' { character } '"'
decimal             ::= [0-9]+ "." [0-9]+
boolean             ::= "true" | "false"

Execution model

  1. Parse SignalQL to AST and reject unknown constructs.
  2. Bind references to source metadata (entities/events/relationships/signal catalog).
  3. Build deterministic execution plan (traversal, filters, sequence windows, return fields).
  4. Execute retrieval path in adapter/runtime.
  5. Apply caller permissions before returning evidence.
  6. Return structured evidence + execution metadata.

Execution metadata SHOULD include access-filter details when available.

SignalQL does not score, classify, prioritize, or decide outcomes.

Determinism contract

  • Canonical formatting produces stable clause ordering.
  • Equivalent AST input yields equivalent execution plan output.
  • Output includes machine-readable metadata for explainability.

Example queries

Entity retrieval with derived signal

signalql
FROM entity(memory_object)
WHERE signal(relevance_score) > 0.8
RETURN entity_id, signal(relevance_score)

Graph traversal

signalql
FROM entity(note)
TRAVERSE references DEPTH <= 2
RETURN entity_id, count

Sequence pattern

signalql
FIND sequence
WHERE observed -> linked -> reviewed
WITHIN 3d

Versioned evidence retrieval

signalql
FROM entity(memory_object)
WHERE version > 3
RETURN entity_id, version, updated_at

Current decision retrieval

signalql
FROM entity(decision)
WHERE superseded = false
RETURN entity_id, summary

Namespaced domain-pack entity retrieval

signalql
FROM entity(work.memory_item)
WHERE signal(relevance_score) > 0.8
RETURN entity_id, signal(relevance_score)
signalql
FROM entity(analytics.session)
RETURN entity_id
signalql
FROM entity(code.architecture_decision)
RETURN entity_id

Optional semantic retrieval primitive

signalql
FROM entity(memory_object)
WHERE semantic_match("why did we choose redis") > 0.75
RETURN entity_id, summary

Temporal trend

signalql
FROM entity(context_bundle)
TREND UP OVER 5d
RETURN entity_id, count

Provenance-focused retrieval

signalql
FROM entity(claim)
WHERE confidence >= 0.7
RETURN entity_id, source, created_by, derived_from, observed_at, updated_at

Domain-pack namespacing

Core grammar remains domain-agnostic. Domain packs may use namespaced entity types (for example work.memory_item, analytics.session, code.architecture_decision) without changing core language semantics.

Revision semantics

SignalQL remains retrieval-only. Revision/version fields are queryable evidence (version, superseded, updated_at) and do not imply mutating commands.

Semantic retrieval

semantic_match(...) is an optional retrieval primitive. Adapters may expose it when vector/semantic infrastructure is available; unsupported runtimes MUST return an explicit capability error.

Permissions-aware execution

Execution MUST apply caller permissions before evidence leaves the runtime boundary. When feasible, execution metadata SHOULD describe access filtering that affected result shape.

Non-goals

  • No domain nouns (sprint, epic, story_points, workflow_status) in core grammar.
  • No mutating commands (ASSIGN, EXECUTE, UPDATE, DELETE).
  • No embedded business policy interpretation.

Normative references