Context for finding queries and lifecycle operations.
Read-path: strategies query active findings during init/2.
Write-path: post-converge persists raise/update/clear actions.
Subject queries use denormalized subject_kind and subject_id columns
instead of JSON operators for SQL Server 2017 compatibility.
Upserts use transactions (read-then-write) instead of ON CONFLICT
for SQL Server compatibility.
Summary
Functions
Query active findings with flexible filters.
Mode-aware query: automatically prefixes :actor and :finding_key filters
when the episode is a dry run with persist_findings enabled.
Walks the causal chain upward from a finding, returning ancestors.
Returns active child findings caused by the given finding key.
Count active findings matching the given filters. Accepts same opts as active_for/2.
Persist a finding action from a ConvergeResult.
Returns true if an active finding with the given key was updated within window_ms milliseconds.
Returns the root cause finding for the given finding key.
Functions
Query active findings with flexible filters.
Examples
Cyclium.Findings.active_for(actor: :po_status, class: "po_stalled")
Cyclium.Findings.active_for(subject: %{kind: "po", id: "PO-1955"})
Cyclium.Findings.active_for(finding_key: "po_stalled:PO-1955")
Cyclium.Findings.active_for(class: "non_responsive")Options
:limit— max rows to return:offset— rows to skip (default: 0):exclude_archived— whentrue, excludes findings with a non-nilarchived_at(default:false)
Mode-aware query: automatically prefixes :actor and :finding_key filters
when the episode is a dry run with persist_findings enabled.
In live mode (or dry runs without persist_findings), behaves identically to active_for/2.
In dry run mode with a persist prefix, rewrites filter keys so strategies can
transparently read their own dry run findings.
Examples
# In a strategy's init/2, pass the episode to get mode-aware results:
Cyclium.Findings.active_for_mode([actor: "po_monitor"], episode)
# Dry run with persist_findings: true → queries actor: "dry_run:po_monitor"
# Live mode → queries actor: "po_monitor" (unchanged)
Walks the causal chain upward from a finding, returning ancestors.
Starting from the given finding, follows caused_by_key links up
to max_depth levels. Returns a list of findings from immediate parent
to root (oldest ancestor).
Options
:max_depth— maximum chain depth (default: 10)
Returns active child findings caused by the given finding key.
Count active findings matching the given filters. Accepts same opts as active_for/2.
Persist a finding action from a ConvergeResult.
Actions
{:raise, params}— upsert active finding (last writer wins on mutable fields){:update, key, changes}— update mutable fields on an active finding{:clear, key}— idempotent clear (set status to:cleared){:clear, key, reason}— clear with reason stored in evidence_refs
Returns true if an active finding with the given key was updated within window_ms milliseconds.
Useful for per-subject dedup in strategies — skip re-runs when a recent finding already exists.
Examples
Cyclium.Findings.recent?("client:advisor:123", :timer.minutes(5))
Returns the root cause finding for the given finding key.
Walks up the causal chain and returns the first finding with no caused_by_key.
Returns nil if the finding itself is not found.