Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Signal integration

Signal uses locally loaded profiles for typed extension input, MiniJinja templates for presentation, and measures for grouped search. It never executes or renders definitions received through federation.

Input profiles

Members can inspect the profiles installed on their node:

!profiles
!profiles rainfall

A profile turns whitespace-delimited name=value fields into extension envelopes:

!saw Rain gauge :: rainfall millimeters=12

When the supplied field names identify exactly one profile, its name can be omitted:

!saw Rain gauge :: millimeters=12

Unknown fields, missing required fields, invalid values, duplicate fields, and ambiguous inference fail without creating an observation. A plain !saw command creates no extension envelopes.

After profile-based creation, each populated extension may append its optional receipt_template output. For example, the bird count manifest declares x{{ data.count }}, producing:

Recorded: Common Loon x3

The complete command syntax belongs in Using Signal. The manifest declarations belong in Authoring extensions.

Observation presentation

A manifest’s detail_template renders in observation cards returned by !today, !recent, and !obs, and in the detailed !show response. The bird count manifest renders:

Count: 3

Compact list search remains compact, while grouped search uses configured measures rather than detail templates.

Signal falls back to an Extensions: ... line for unknown IDs, unsupported versions, missing detail templates, empty output, and rendering errors. A bad extension value therefore cannot fail an observation query or hide the fact that an envelope exists. Use event export or Grist’s read-only Extensions JSON column to inspect the complete envelopes.

Templates are compiled and bounded when the local registry loads. The context, syntax, limits, and failure behavior are defined in Authoring extensions.

Grouped-search measures

A loaded manifest can expose a numeric measure. For the rainfall example, the qualified reference is:

org.example.observations/rainfall.total

The node configuration may include it as a numeric grouped-search field:

[extensions]
manifests = ["extensions/rainfall.toml"]

[signal.views.search]
layout = "grouped"
header = "Found {observation_count} {observation_count:plural(observation)}"

[signal.views.search.group]
by = "subject"
normalize = "casefold"
label = "latest"
heading = "{group_label:highlight}"
sort_by = "core.last_seen"
sort_order = "descending"

[[signal.views.search.group.fields]]
label = "Rainfall"
measure = "org.example.observations/rainfall.total"
format = "number"
singular = "millimeter"
plural = "millimeters"

Birdd filters observations for local visibility and direct trust before grouping. It then sums supported numeric values in each normalized subject group. A missing envelope contributes the manifest’s missing value. An unsupported version or malformed field contributes nothing. Arithmetic overflow fails the view rather than wrapping.

Core date and text measures can be included alongside extension measures. The authoritative grouped-view configuration is in Node configuration.