Comergence — Signal Schema
The universal language every domain speaks.
Design Principles
- Simple enough that a shop floor agent and a finance agent both implement it without translation
- Rich enough that the visual layer, notification router, and action engine get everything they need from one object
- Self-describing — a signal explains itself without requiring external lookup
- Domain-agnostic — the schema knows nothing about business logic; the agent knows everything
The Signal Object
{
"id": "uuid-v4",
"source": {
"domain": "production",
"path": ["production", "work-centers", "cnc-3"],
"agent": "production-master",
"human": "operator-mike"
},
"status": "amber",
"previousStatus": "green",
"statusSince": "2026-02-22T14:32:00Z",
"publishedAt": "2026-02-22T14:32:05Z",
"signal": {
"code": "DRIFT_WARNING",
"message": "X-axis feed rate drifting +2.3% from nominal",
"detail": "Current: 102.3 ipm / Nominal: 100 ipm / Threshold: ±2%",
"data": {}
},
"propagate": true,
"ttl": 3600,
"actions": [
{
"id": "notify-operator",
"label": "Notify Operator",
"type": "message",
"target": "human:operator-mike",
"auto": false
},
{
"id": "spawn-investigation",
"label": "Investigate",
"type": "agent-task",
"agent": "production-master",
"prompt": "Work center cnc-3 has a feed rate drift warning. Assess and guide operator.",
"auto": false
},
{
"id": "andon-amber",
"label": "Andon Signal",
"type": "physical",
"device": "ha:shop-floor-light",
"state": "amber",
"auto": true
}
]
}
Field Reference
Top Level
| Field |
Type |
Required |
Description |
id |
string (uuid) |
✅ |
Unique signal identifier |
source |
object |
✅ |
Where this signal originated |
status |
enum |
✅ |
Current health state |
previousStatus |
enum |
— |
State before this signal |
statusSince |
ISO 8601 |
✅ |
When current status began |
publishedAt |
ISO 8601 |
✅ |
When this signal was published |
signal |
object |
✅ |
What happened |
propagate |
boolean |
✅ |
Whether parent tiles inherit this state |
ttl |
integer (seconds) |
— |
How long signal stays active. Null = persistent until resolved |
actions |
array |
— |
Available responses |
source
| Field |
Type |
Required |
Description |
domain |
string |
✅ |
Top-level domain (matches registry) |
path |
string[] |
✅ |
Full drill-down path to this signal's node |
agent |
string |
✅ |
Agent ID that published this signal |
human |
string |
— |
Human operator paired with this node, if any |
status values
| Value |
Color |
Meaning |
green |
🟢 |
Normal operation, within all thresholds |
amber |
🟡 |
Attention needed, degrading but not critical |
red |
🔴 |
Critical failure, immediate action required |
unknown |
⚪ |
Agent not publishing, data stale, monitoring gap |
offline |
⬛ |
Agent/system confirmed offline |
signal
| Field |
Type |
Required |
Description |
code |
string |
✅ |
Machine-readable signal code (see Standard Codes) |
message |
string |
✅ |
Human-readable one-line summary |
detail |
string |
— |
Extended description with specifics |
data |
object |
— |
Domain-specific payload (any structure) |
actions[*]
| Field |
Type |
Required |
Description |
id |
string |
✅ |
Unique within this signal |
label |
string |
✅ |
Display label in the UI |
type |
enum |
✅ |
Action type (see Action Types) |
auto |
boolean |
✅ |
Whether to fire automatically on signal publish |
target |
string |
— |
For message type: human:id, agent:id, channel:name |
agent |
string |
— |
For agent-task type: agent ID to spawn |
prompt |
string |
— |
For agent-task type: context injected at task start |
device |
string |
— |
For physical type: ha:entity-id |
state |
string |
— |
For physical type: desired device state |
Standard Signal Codes
Codes are dot-namespaced. Domain agents define their own codes under their namespace. Shared codes live under system.*.
system.*
| Code |
Status |
Meaning |
system.healthy |
green |
All checks passing |
system.degraded |
amber |
Performance or availability degrading |
system.critical |
red |
Critical failure |
system.offline |
offline |
System unreachable |
system.stale |
unknown |
Last signal older than expected interval |
agent.*
| Code |
Status |
Meaning |
agent.active |
green |
Agent responding, sessions active |
agent.idle |
green |
Agent responding, no active sessions |
agent.error |
red |
Agent throwing errors or crashing |
agent.cost_spike |
amber |
API cost above threshold |
agent.cron_failed |
amber/red |
Scheduled job failed |
agent.heartbeat_missed |
amber |
Heartbeat not received in expected window |
production.*
| Code |
Status |
Meaning |
production.on_schedule |
green |
All work centers on time |
production.order_aging |
amber |
Orders approaching SLA threshold |
production.sla_breach |
red |
Orders past SLA |
production.machine_down |
red |
Work center offline |
production.drift_warning |
amber |
Process parameter drifting |
fulfillment.*
| Code |
Status |
Meaning |
fulfillment.on_schedule |
green |
Shipments on time |
fulfillment.delay_risk |
amber |
Carrier or inventory delay detected |
fulfillment.sla_breach |
red |
Committed ship date missed |
sales.*
| Code |
Status |
Meaning |
sales.pipeline_healthy |
green |
Normal velocity and conversion |
sales.deal_stall |
amber |
High-value deals without activity |
sales.conversion_drop |
amber |
Spec-to-bid conversion declining |
integration.*
| Code |
Status |
Meaning |
integration.connected |
green |
API healthy, auth valid |
integration.degraded |
amber |
Slow response times or rate limit warnings |
integration.auth_expiring |
amber |
Token expires within 7 days |
integration.auth_failed |
red |
Authentication failure |
integration.sync_failed |
red |
Data sync not completing |
Status Propagation
Parent tiles inherit the worst status of their children, with one exception: unknown does not override a known status.
child: red → parent: red
child: amber → parent: amber (if no children are red)
child: green → parent: green (if all children are green)
child: unknown → parent: unchanged (ghost child — doesn't pull parent down)
child: offline → parent: amber (a constituent going dark is a warning, not a crisis)
An agent can set propagate: false to publish a signal that affects only its own tile without rolling up. Useful for informational signals that don't indicate domain health problems.
Resolution
A signal is resolved when:
1. The agent publishes a new signal with status: "green" on the same source.path
2. The ttl expires and no new signal has been published (node goes unknown)
3. The domain is deregistered
Resolved signals are archived, not deleted. The archive enables historical health views and pattern analysis over time.
Signal Bus Interface
Agents interact with the signal bus through two operations:
PUBLISH path signal_object → publishes signal, notifies subscribers
SUBSCRIBE path_pattern callback → receives signals matching pattern
Path patterns support wildcards:
- production.* — all production signals
- *.work-centers.* — all work center signals across all domains
- * — all signals (dashboard uses this)
Initial implementation: file-based (signals written to ~/.comergence/signals/), watched by chokidar. Upgrade path to Redis pub/sub or NATS for multi-machine deployments.
Example Signals
Agent healthy (AI System domain)
{
"id": "a1b2c3d4",
"source": { "domain": "ai-system", "path": ["ai-system", "agents", "maxrow"], "agent": "main" },
"status": "green",
"statusSince": "2026-02-22T11:05:00Z",
"publishedAt": "2026-02-22T15:00:00Z",
"signal": { "code": "agent.active", "message": "Maxrow active, 1 session running", "data": { "sessions": 1, "cost7d": 4.21 } },
"propagate": true,
"ttl": 600,
"actions": []
}
Integration auth expiring
{
"id": "e5f6g7h8",
"source": { "domain": "integrations", "path": ["integrations", "shopify"], "agent": "main" },
"status": "amber",
"statusSince": "2026-02-22T09:00:00Z",
"publishedAt": "2026-02-22T09:00:00Z",
"signal": { "code": "integration.auth_expiring", "message": "Shopify token expires in 6 days", "detail": "Token refresh cron last ran 14h ago" },
"propagate": true,
"ttl": 86400,
"actions": [
{ "id": "refresh-now", "label": "Refresh Token", "type": "agent-task", "agent": "main", "prompt": "Shopify token is expiring. Run the token refresh script immediately.", "auto": false },
{ "id": "notify-jerry", "label": "Notify Jerry", "type": "message", "target": "human:jerry", "auto": true }
]
}
Shop floor machine down
{
"id": "i9j0k1l2",
"source": { "domain": "production", "path": ["production", "work-centers", "cnc-3"], "agent": "production-master", "human": "operator-mike" },
"status": "red",
"previousStatus": "green",
"statusSince": "2026-02-22T13:47:00Z",
"publishedAt": "2026-02-22T13:47:02Z",
"signal": { "code": "production.machine_down", "message": "CNC-3 offline — spindle fault alarm", "detail": "Alarm code 1043. Machine halted. 3 jobs in queue affected." },
"propagate": true,
"ttl": null,
"actions": [
{ "id": "guide-operator", "label": "Guide Operator", "type": "agent-task", "agent": "production-master", "prompt": "CNC-3 has a spindle fault (alarm 1043). Guide operator Mike through diagnosis and resolution.", "auto": true },
{ "id": "adjust-schedule", "label": "Adjust Schedule", "type": "agent-task", "agent": "production-master", "prompt": "CNC-3 is down. Reschedule its 3 queued jobs to available work centers.", "auto": true },
{ "id": "andon-red", "label": "Andon Red", "type": "physical", "device": "ha:shop-floor-light", "state": "red", "auto": true },
{ "id": "alert-michael", "label": "Alert Michael", "type": "message", "target": "human:michael", "auto": true }
]
}