LoopSignal
LoopSignal is a draft preference-signal model for lab discussions of demand or surplus intent by material category. It can be used in examples of routing and matching, but it does not collect community input, govern a node, or determine operational priorities.
Lab-only status. Lab-only: exploratory documentation and demo evidence; not a public deployment or compliance claim.
Scope & boundaries
In scope
Draft signal configuration, proposed voting fields, and scenario routing weights.
Out of scope
Individual user preference tracking, binding regulatory commitments, or financial instruments.
Status
Lab-demo concept only — no public pilots or deployments yet.
How it works
Signal values
Lab examples use a 0.0–1.0 value to represent an illustrative scenario input, not measured demand or surplus.
Material categories
Signals cover 30+ standardised categories: plastics (PET, HDPE, PVC, mixed), metals (steel, aluminium, copper), organics, glass, paper, cardboard, textiles, and e-waste.
Governance
Draft SignalProposal, LoopVote, and LoopSignalConfig payloads include fields that could support a future governance process; no approval or publication process is running here.
Routing effect
Examples may use values as inputs to a draft penalty calculation; they do not predict offers, routing, or locality.
Validity window
Draft payloads include valid_from and valid_until fields; they do not ensure that a routing system uses current or approved values.
Data model snapshot
Current status
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://localloop.urbnia.com/projects/loop-protocol/schemas/v0.2.0/loopsignal.schema.json",
"title": "LoopSignal",
"description": "Schema for LoopSignal configuration and voting",
"oneOf": [
{
"$ref": "#/definitions/LoopSignalConfig"
},
{
"$ref": "#/definitions/LoopVote"
},
{
"$ref": "#/definitions/SignalProposal"
}
],
"definitions": {
"LoopSignalConfig": {
"type": "object",
"required": [
"@context",
"@type",
"node",
"signals",
"valid_from",
"valid_until"
],
"properties": {
"@context": {
"type": "string",
"enum": [
"https://localloop.urbnia.com/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"https://localloop.urbnia.com/projects/loop-protocol/contexts/loop-v0.2.0.jsonld"
]
},
"@type": {
"type": "string",
"const": "LoopSignalConfig"
},
"schema_version": {
"description": "Optional schema version identifier.",
"type": "string",
"pattern": "^0\\.[1-9]\\d*\\.\\d+$",
"examples": [
"0.2.0"
]
},
"node": {
"description": "Node identifier",
"type": "string",
"pattern": "^[a-z0-9\\-]+\\.loop$",
"examples": [
"munich.loop"
]
},
"signals": {
"description": "Signal values by category",
"type": "object",
"properties": {
"plastic-pet": {
"$ref": "#/definitions/signalValue"
},
"plastic-hdpe": {
"$ref": "#/definitions/signalValue"
},
"plastic-pvc": {
"$ref": "#/definitions/signalValue"
},
"plastic-ldpe": {
"$ref": "#/definitions/signalValue"
},
"plastic-pp": {
"$ref": "#/definitions/signalValue"
},
"plastic-ps": {
"$ref": "#/definitions/signalValue"
},
"plastic-mixed": {
"$ref": "#/definitions/signalValue"
},
"metal-steel": {
"$ref": "#/definitions/signalValue"
},
"metal-aluminum": {
"$ref": "#/definitions/signalValue"
},
"metal-copper": {
"$ref": "#/definitions/signalValue"
},
"metal-mixed": {
"$ref": "#/definitions/signalValue"
},
"organic-food": {
"$ref": "#/definitions/signalValue"
},
"organic-garden": {
"$ref": "#/definitions/signalValue"
},
"organic-wood": {
"$ref": "#/definitions/signalValue"
},
"glass-clear": {
"$ref": "#/definitions/signalValue"
},
"glass-brown": {
"$ref": "#/definitions/signalValue"
},
"glass-green": {
"$ref": "#/definitions/signalValue"
},
"glass-mixed": {
"$ref": "#/definitions/signalValue"
},
"paper-clean": {
"$ref": "#/definitions/signalValue"
},
"paper-newsprint": {
"$ref": "#/definitions/signalValue"
},
"cardboard": {
"$ref": "#/definitions/signalValue"
},
"paper-mixed": {
"$ref": "#/definitions/signalValue"
},
"textile-cotton": {
"$ref": "#/definitions/signalValue"
},
"textile-wool": {
"$ref": "#/definitions/signalValue"
},
"textile-synthetic": {
"$ref": "#/definitions/signalValue"
},
"textile-mixed": {
"$ref": "#/definitions/signalValue"
},
"ewaste-computers": {
"$ref": "#/definitions/signalValue"
},
"ewaste-phones": {
"$ref": "#/definitions/signalValue"
},
"ewaste-batteries": {
"$ref": "#/definitions/signalValue"
},
"ewaste-mixed": {
"$ref": "#/definitions/signalValue"
},
"default": {
"$ref": "#/definitions/signalValue"
}
},
"additionalProperties": false
},
"valid_from": {
"description": "When signals become active",
"type": "string",
"format": "date-time",
"examples": [
"2025-06-01T00:00:00Z"
]
},
"valid_until": {
"description": "When signals expire",
"type": "string",
"format": "date-time",
"examples": [
"2025-06-30T23:59:59Z"
]
},
"approved_by": {
"description": "Voting record",
"type": "object",
"properties": {
"vote_id": {
"type": "string",
"examples": [
"2025-05-vote"
]
},
"turnout": {
"type": "number",
"minimum": 0,
"maximum": 1,
"examples": [
0.35
]
},
"approval": {
"type": "number",
"minimum": 0,
"maximum": 1,
"examples": [
0.68
]
}
}
}
},
"additionalProperties": true
},
"LoopVote": {
"type": "object",
"required": [
"@context",
"@type",
"node",
"vote_id",
"proposals",
"voting_period",
"results"
],
"properties": {
"@context": {
"type": "string",
"enum": [
"https://localloop.urbnia.com/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"https://localloop.urbnia.com/projects/loop-protocol/contexts/loop-v0.2.0.jsonld"
]
},
"@type": {
"type": "string",
"const": "LoopVote"
},
"schema_version": {
"description": "Optional schema version identifier.",
"type": "string",
"pattern": "^0\\.[1-9]\\d*\\.\\d+$",
"examples": [
"0.2.0"
]
},
"node": {
"type": "string",
"pattern": "^[a-z0-9\\-]+\\.loop$"
},
"vote_id": {
"type": "string",
"examples": [
"2025-05-plastic-increase"
]
},
"proposals": {
"type": "array",
"items": {
"type": "object",
"required": [
"category",
"current_value",
"proposed_value"
],
"properties": {
"category": {
"type": "string"
},
"current_value": {
"$ref": "#/definitions/signalValue"
},
"proposed_value": {
"$ref": "#/definitions/signalValue"
},
"rationale": {
"type": "string",
"maxLength": 500
}
}
}
},
"voting_period": {
"type": "object",
"required": [
"start",
"end"
],
"properties": {
"start": {
"type": "string",
"format": "date-time"
},
"end": {
"type": "string",
"format": "date-time"
}
}
},
"results": {
"type": "object",
"required": [
"total_eligible",
"total_voted",
"votes_for",
"votes_against",
"status"
],
"properties": {
"total_eligible": {
"type": "integer",
"minimum": 0
},
"total_voted": {
"type": "integer",
"minimum": 0
},
"votes_for": {
"type": "integer",
"minimum": 0
},
"votes_against": {
"type": "integer",
"minimum": 0
},
"status": {
"type": "string",
"enum": [
"passed",
"failed",
"pending"
]
}
}
}
},
"additionalProperties": true
},
"SignalProposal": {
"type": "object",
"required": [
"@context",
"@type",
"node",
"changes",
"voting_opens",
"voting_closes"
],
"properties": {
"@context": {
"type": "string",
"enum": [
"https://localloop.urbnia.com/projects/loop-protocol/contexts/loop-v0.1.1.jsonld",
"https://localloop.urbnia.com/projects/loop-protocol/contexts/loop-v0.2.0.jsonld"
]
},
"@type": {
"type": "string",
"const": "SignalProposal"
},
"schema_version": {
"description": "Optional schema version identifier.",
"type": "string",
"pattern": "^0\\.[1-9]\\d*\\.\\d+$",
"examples": [
"0.2.0"
]
},
"node": {
"type": "string",
"pattern": "^[a-z0-9\\-]+\\.loop$"
},
"changes": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"category",
"current",
"proposed"
],
"properties": {
"category": {
"type": "string"
},
"current": {
"$ref": "#/definitions/signalValue"
},
"proposed": {
"$ref": "#/definitions/signalValue"
},
"reason": {
"type": "string",
"maxLength": 500
}
}
}
},
"voting_opens": {
"type": "string",
"format": "date-time"
},
"voting_closes": {
"type": "string",
"format": "date-time"
}
},
"additionalProperties": true
},
"signalValue": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Signal strength (0.0 to 1.0)"
}
}
}