Signal
Definition
A Signal is an external (or computed) trigger that may warrant investigation — a DSCR breach, a utilization spike, a
watchlist flag. It is anchored to a subject (the entity it concerns), carries a severity, and runs through its own
disposition lifecycle. Signals are the most common entry point into an investigation: a signal-driven Insight names the
Signal in its entry_context.trigger, and closing an investigation requires every linked Signal to be resolved or
dismissed. Signals are never deleted — archiving is recorded as a dismissal with an audit marker, preserving the trail.
Canonical schema: cortex/docs/spec/des-objects.yml:578. Runtime model: cortex/cortex/models/intelligence.py:374.
Command logic: cortex/cortex/signal.py (plus cortex/cortex/tools/signal.py). Persistence: a UDS DAO over the shared
Elasticsearch intelligence index under the signal alias, id sig_ + 12 hex.
Lifecycle
status: new → acknowledged → investigating → {resolved | dismissed}. The transition map is SIGNAL_TRANSITIONS
(signal.py:61):
new → {acknowledged, investigating, dismissed}acknowledged → {investigating, dismissed}investigating → {resolved, dismissed}resolved,dismissed— terminal
Transitions happen through signal_acknowledge (new → acknowledged), signal_set_disposition (any valid edge, fully
audited), and signal_archive (any non-terminal → dismissed plus an archive marker). Two edges auto-advance: starting
an investigation moves a new/acknowledged Signal to investigating (insight.py:264), and attesting the Edition
that closes the investigation auto-resolves the source Signal investigating → resolved (edition.py:1052).
Journey through the code
Creation enters via MCP create_signal (tools/signal.py:541) — which requires a subject, builds the source and
subject, sets status = new, and writes Signal().update(uid=sig_…) — or via REST POST /signal →
crud.signal_create (crud.py:119). Mutation goes through signal_acknowledge, signal_set_disposition,
signal_archive, and signal_link_insight (signal.py:231 onward); each strips system fields, writes the update, and
appends to metadata.status_history[]. When a Signal is linked to an Insight, the disposition/link change also writes a
signal_disposition_set / signal_linked InsightEvent onto the Insight ledger.
Reads: REST GET /signal/{uid} and GET /signal/by-entity/{entity_id}. The monitor dashboard scans Signals to compute
active-count KPIs (monitor_tools.py:141) — it reads them, it never emits them. _format_signal (signal.py:123)
reshapes the Signal into the subject{name} form Beacon expects.
Data shape
Required (des-objects.yml:583): schema_version, signal_type (freeform), source (with type ∈ webhook | mcp |
polling | internal | manual | computed), severity (critical | high | medium | low | info), subject (type + id +
name), title, detected_at.
Key optional / computed: status (default new), description, expires_at (defaulted by signal type),
confidence (0–1), metadata (status_history[], resolved_by_edition, resolved_by_insight, archive markers),
related_signals[], linked_insight_ids[], acknowledged_by / acknowledged_at, acknowledgment_note, routing,
visibility_context. Storage: intelligence index, signal alias; key queryable fields signal_id, status,
severity, subject.id.
Invariants
- Never deleted. Archiving = dismissed + marker; the audit trail is preserved (DES Invariant 2,
signal.py:420). - Forward-only status with
resolved/dismissedterminal; every status change is recorded inmetadata.status_history[]with from/to/by/at/rationale. - A subject is required at creation — a Signal is always about something.
Related products
product.insight— Signals link bidirectionally with Insights (linked_insight_ids[]↔linked_signal_ids[]) and are theentry_context.triggerof signal-driven investigations.product.edition— attesting an Edition auto-resolves the source Signal and back-references it viametadata.resolved_by_edition.product.block— monitor Blocks aggregate over Signals for KPIs but do not create them.
Open questions
actorandsource.type: computed. DES adds anactorobject (who/what raised the Signal) and thecomputedsource type; the runtimeSignalmodel has noactorfield yet.suppressedstatus. It appears in theintelligence.yamlenum but is not in the enforced state machine — unreconciled.- Subject rename. REST
subject_ref/display_namevs Beaconsubject/name— flagged in the DES changelog, not yet unified.
Realized by: component.cortex.decision-evidence, component.cortex.intelligence, component.cortex.signal-lifecycle, component.parallax.adi-integration, component.parallax.signal-payload