HEART Embedded Systems logoHEART

HEART Part 3: Information Model#

Reading tracks1 Basic2 Intermediate3 Advanced
Basic: "In one minute", Sections 2, 3.1, 3.2, 3.4, 4, 5.1 to 5.4, 5.6, 5.7, 7 and 9. Intermediate adds 3.3, 3.7, 5.8, 8, 10 and 11. Advanced adds 3.5, 3.6 and 6. Sections 5.5 and 12 to 14 are reference. Which track am I?

What a HEART tells you, and in what shape

Author: Milind K. Patil, Syncaissa Systems Inc. Status: Working draft 1, November 2026. Part of the HEART Standards Family. Version: 1.0 (draft) Read first: Part 1: Basics, for the words used here. Track: Basic: "In one minute", Sections 2, 3.1, 3.2, 3.4, 4, 5.1 to 5.4, 5.6, 5.7, 7 and 9. Intermediate adds 3.3, 3.7, 5.8, 8, 10 and 11. Advanced adds 3.5, 3.6 and 6. Sections 5.5 and 12 to 14 are reference.


In one minute#

Every HEART says things about itself using seven main messages. Six travel as messages of their own; the Capability lives inside the Card:

MessageIn one sentence
CardWho I am, and what I can do.
PulseHow I am right now.
RhythmWhat has happened, in order.
ArrhythmiaSomething is wrong. Here is what, and why.
CapabilitySomething you can ask me to do.
ActionSomething I am doing, or did, and who allowed it.
ReceiptProof of what data I sent, and to whom.

Every message travels in the same envelope, and uses the same shared word lists. For example, health is always one of healthy, degraded, failing or unknown.

Problems are named with fault codes from one shared list, such as storage.full or sensors.drift. A fault code means the same thing on every product, the way OBD-II code P0300 means "engine misfire" on every car. Outside messages it is written HEART storage.full, and each standard code also has a short number, such as H-04002.

This part describes what is said. It does not say how messages travel (that is Part 4), so the same information can be carried by HTTP, MQTT or, later, industrial standards such as OPC UA.


1. What an "information model" is#

Think of a paper form, like a doctor's check-up form. It has fixed boxes: name, date, blood pressure, temperature, notes. Every doctor fills in the same boxes, so any other doctor can read it.

An information model is the same idea for machines. It says:

  • which forms exist: Card, Pulse, Arrhythmia and so on,
  • which boxes each form has, and which are required,
  • what may be written in each box: a number, a date, or one word from a fixed list.

It does not say how the form is delivered: by post, by fax or by hand. That is Part 4.

Keeping the two apart matters. The forms stay the same while delivery methods change. A tiny sensor and a cloud server can fill in the same forms, and deliver them in completely different ways.

Where the exact definitions live#

This part explains the model in words. The exact, machine-checkable definitions are the JSON Schema files in schemas/1.0/, with one example of each message in examples/. If this part and a schema disagree, that is a mistake in the standard, and should be reported.


2. The envelope#

Every message a HEART sends about itself goes inside the same envelope. Like the outside of a parcel, the envelope says who it is from, what is inside and when it was sent. The message itself sits inside, in data.

HEART does not invent its own envelope. It uses CloudEvents, a widely used standard for event messages, so existing tools can already route HEART messages.

{
  "specversion": "1.0",
  "id": "c7f3a9e2-1b44-4d0e-9a51-2f6c8e1d7b90",
  "source": "/heart/com.example.cool-air.ac-controller/unit-12",
  "type": "heart.pulse",
  "time": "2026-11-08T10:00:00Z",
  "datacontenttype": "application/json",
  "heartversion": "1.0",
  "heartprivacy": "public",
  "data": {
    "system": { "id": "com.example.cool-air.ac-controller", "name": "CoolAir AC Controller", "version": "0.1.0" },
    "status": "healthy",
    "sequence": 90,
    "intervalSec": 60
  }
}
BoxWhat it holds
idA unique number for this message. If the message is sent again, it keeps the same id, so duplicates can be spotted.
sourceWhich system sent it: /heart/ followed by the system's ID, and optionally which copy of the system (the instance).
typeWhich message is inside, such as heart.pulse (Section 3).
timeWhen it was created, in the standard internet time format (RFC 3339).
datacontenttypeAlways application/json.
heartversionWhich version of HEART it follows, such as 1.0.
heartprivacyThe most private level of anything inside, after filtering.
heartredactedtrue if some fields were removed because the receiver may not see them.
dataThe message itself.

All of these are required except heartredacted, which is present only when something was removed.

Requests sent to a system, such as "invoke this capability", are not statements about the system, so they do not need the envelope over HTTP. Part 4 explains how they are carried.


3. The seven main messages#

MessagetypeAnswersSchema
Cardheart.cardWho are you, and what can you do?card
Pulseheart.pulseHow are you right now?pulse
Rhythm eventheart.rhythmWhat happened?rhythm
Arrhythmiaheart.arrhythmiaWhat is wrong, and why?arrhythmia
Capability(inside the Card)What can I ask you to do?in card
Actionheart.actionWhat are you doing, and who allowed it?action
Receiptheart.receiptWhat data did you send, and to whom?receipt

Six of these have a type of their own. The Capability does not: it is a part of the Card. One more message belongs with them: Evolution (heart.evolution, schema evolution) says which AI model is pinned and how new candidates tested. It is part of the Full Feature Set ("AI model tracking", Section 7), so the API Standard lists it among its seven core types, in place of the Capability.

There are also smaller messages for optional modules (Section 8), such as heart.component and heart.property. The prefix heart. is reserved for the standard. A product may add its own message types, named with its own reversed domain name, such as com.coolair.service-report (Section 9).

In the tables below, a bold box name means the box is required.

3.1 Card: who I am#

The Card is the system's identity card. A consumer reads it first, and usually only once.

{
  "system": { "id": "com.example.cool-air.ac-controller", "name": "CoolAir AC Controller",
              "version": "0.1.0", "owner": "Example Climate Ltd" },
  "level": "full",
  "bindings": ["http-server", "unix-socket"],
  "pulse": { "intervalSec": 30 },
  "modules": ["control", "properties", "custom", "core"],
  "profiles": ["hvac"],
  "autonomy": { "level": 2, "higher": [ { "level": 4, "areas": ["connectivity", "storage"] } ] },
  "capabilities": [ { "name": "calibrate", "risk": "write", "...": "see Section 3.5" } ]
}
BoxWhat it holds
systemid (unique name, Section 9), name (for people), version, and optionally instance, alias and owner.
levelThe system's Feature Set: basic, connected or full (Section 7). The box keeps its old name, level, for now.
bindingsHow the system can be reached, such as http-server or mqtt (Part 4).
pulseintervalSec: how often a Pulse is sent.
endpointsAddresses: the HEART API, a Gateway, and other standards the system also speaks (MCP, A2A, OpenTelemetry).
modulesOptional modules the system has (Section 8).
profilesProduct profiles it follows, such as hvac (Part 8).
autonomyIts promised Autonomy Level and scope (Part 2).
capabilitiesWhat it can be asked to do (Section 3.5).
eventsProduct-specific Rhythm events it may send.
sharesWho may read each kind of message: keys are message types without heart., such as pulse, and values are public, internal or private (Part 5).
valvePrivacy settings, including the most private level that may ever reach an AI model, and classifications that raise the level of further boxes, each written <message>:<JSON Pointer>, such as rhythm:/attributes/recordingPath (Part 5).
aiWhich ways of thinking it uses, and what it does offline.
coreIts HEART Core size class and ways of thinking (Part 7).
authWhere to log in (Part 4).
identityThe system's identity key, which signs the Card (Part 4).
heartVersionVersion of the HEART implementation it runs.
templateThe HEART template it was built from, if any.
limitsSize limits, for small devices.
labelsOwner's tags, used to pick groups of systems.
extThe product's own extra information (Section 10).

The Card is shown filtered. An anonymous caller sees only the public parts. A capability is shown only to callers allowed to use it.

3.2 Pulse: how I am#

The Pulse is a short message sent at a regular interval, or read on demand. Its first job is to say "I'm alive". Its second is to say how the system is.

BoxWho can see itWhat it holds
systemAnyoneWhich system
statusAnyonehealthy, degraded, failing or unknown (Section 4)
sequenceAnyoneA counter that goes up by one with each Pulse, so a missed one can be spotted
intervalSecAnyoneSeconds until the next Pulse
reconnaissanceOwner's sideCurrent state, the last event, and the Vitals: uptime, error rate, response time, CPU and memory use
aiOwner's sideHow it is thinking right now (rules-only, local or cloud), which model, and today's calls and cost against the budget
tendingOwner's sideHow many problems are open, and the last action taken
autonomyOwner's sidecurrent: its Autonomy Level right now (0 to 5), and limitedBy: why it is lower than promised, if it is: stopped, no-model, no-network, budget, degraded or brain-cut (Part 2). Always present at Full.
evolvingOwner's sideHEART version, and when its AI model last changed

So anyone can learn whether a system is healthy, and only the owner's side learns the details.

Vitals are a summary. Detailed measurements belong in a monitoring standard such as OpenTelemetry, not in the Pulse.

Flatline. If no Pulse has arrived for three intervals, a consumer MUST treat the system's status as unknown. A Gateway or monitoring system SHOULD then raise an Arrhythmia with code system.flatline (Section 5).

3.3 Rhythm: what happened#

The Rhythm is the system's history: a list of events, oldest first. Each event is one thing that happened.

BoxWhat it holds
sequenceIts position in the history. Always increases.
nameWhat happened, as lower-case words (letters, digits, - or _) joined by dots, such as component.restarted
categoryWhich family the event belongs to (below)
severityHow important it is: info, warning, error or critical
componentWhich part of the system it concerns
summaryA short sentence for people
attributesDetails. Private by default.
CategoryCovers
systemStart, stop, version changes
stateChanges of state or status
componentA part starting, stopping or failing
aiCalls to AI models
tendingProblems noticed and actions taken
evolvingAI models adopted or rejected
valveData released or blocked
circulationMessages to and from other systems
securityLogins, permissions, suspicious activity
domainThe product's own events, such as wash.finished

The event names starting with system., state., component., ai., tending., evolving., valve., circulation. and security. are reserved for the standard. Product events use any other name and the category domain.

The standard event types (the values of name reserved for the standard) are listed in Section 5.8. An event type says that something happened. It is not a fault code.

If old history has been deleted to save space, the system MUST say so (Part 4 explains how), so nobody mistakes a gap for "nothing happened".

3.4 Arrhythmia: something is wrong#

An Arrhythmia is an alert. It is the most important message, because it carries the system's own view of what is wrong.

It answers three questions:

  1. What is wrong? The fault code, for example actuators.short-cycling.
  2. Why? The cause, with its own fault code where known, for example sensors.drift.
  3. What is being done? Its status, and any actions.
{
  "id": "5b1e0c9a-7d2f-4b8e-9c31-0a6f2e4d8b17",
  "code": "actuators.short-cycling",
  "severity": "warning",
  "status": "open",
  "detectedAt": "2026-11-08T09:58:00Z",
  "component": "compressor",
  "summary": "Compressor short cycling",
  "explanation": "The compressor is starting and stopping too often (12 times in the last hour). Cooling may be weak. Your installer has been told.",
  "cause": {
    "code": "sensors.drift",
    "component": "room-sensor",
    "text": "The room sensor reads 3 °C higher than the return-air sensor.",
    "confidence": "medium"
  },
  "evidence": [4012, 4013, 4019]
}
BoxWhat it holds
idA unique ID for this alert
codeWhat is wrong, as a fault code (Section 5)
severityinfo, warning, error or critical
statusWhere the alert is in its life (below)
detectedAtWhen it was first noticed
resolvedAtWhen it was fixed
componentWhich part has the problem
summaryA few words for a list of alerts
explanationPlain language: what happened and what it means for the user. Required for Autonomy Level A1 (Part 2).
causeWhy it happened: a fault code if one fits, the component, a plain-language text, and a confidence of low, medium or high. Required for A2. If the cause is not known, text says so and code is left out.
evidenceThe Rhythm events that led to this alert, so a person can check
actionsActions taken or proposed for it
escalationWhen and why a person was told
acknowledgedAt, acknowledgedByWhen, and by whom, a person first acknowledged it
silencedUntilUntil this time, the alert and repeats of its code are raised and listed but not notified (API Standard 5.1). Set by a silence or by maintenance
kindDeprecated. The older, broad alert type, kept so that existing software keeps working (Section 5.5). Optional.

What is seen, and why. One problem often causes another. In the example, the compressor problem (code) is caused by a sensor problem (cause.code). Both come from the same list of fault codes. This is how a HEART tells you not only "something is wrong", but "this is the real reason".

An alert moves through these states:

open ──► acknowledged ──► tending ──► resolved
  │            │             │           ▲
  │            ▼             │           │
  └──────► escalated ◄───────┘           │
               └─────────────────────────┘

Any state may also move straight to resolved when the problem goes away by itself. acknowledged is reached through POST /arrhythmias/{id}/acknowledge. An escalated alert is resolved by the person it was handed to, or by the HEART once the problem is gone.

StatusMeaning
openNoticed. Nobody has responded yet.
acknowledgedA person has seen it.
tendingThe HEART is working on it.
escalatedHanded to a person, because the HEART cannot or may not fix it.
resolvedFixed.

3.5 Capability: what you can ask me to do#

A capability is something the system can be asked to do. Its boxes are a superset of an MCP tool, so any capability can also be offered to AI assistants as an MCP tool without changes.

{
  "name": "calibrate",
  "title": "Calibrate a sensor",
  "description": "Recalibrates one temperature sensor against the reference sensor. Takes about 2 minutes.",
  "inputSchema": { "type": "object", "required": ["sensor"], "properties": { "sensor": { "type": "string" } } },
  "risk": "write",
  "physical": false,
  "reversible": true,
  "idempotent": true,
  "privacy": "internal",
  "callers": ["human", "rule", "ai"],
  "kind": "standard"
}
BoxWhat it holds
nameA short name of up to 128 letters, digits, _, . or -. Use a standard name where one exists (Section 6).
titleA short title for people
descriptionWhat it does, for people and for AI models deciding what to call
inputSchemaThe shape of what goes in (JSON Schema). Use {"type": "object"} with no properties when it takes nothing.
outputSchemaThe shape of what comes out (JSON Schema)
riskread, write or destructive (Part 1)
physicaltrue if it moves, heats, powers or switches something in the real world
reversibleWhether it can be undone
idempotentWhether doing it twice has the same effect as doing it once
privacyHow private its results are: public, internal or private. A caller needs at least this clearance to see or use it.
callersWho may start it: human, peer, ai, rule. The default is human only.
kindstandard (a standard name), product (the product's own, the default) or custom (from a custom definition, Part 8)
guardsChecks made just before it runs: whenStates, whenStatus, requiresMaintenance, minIntervalSec, maxPerHour and interlocks (API Standard 14.4). Each interlock is a check: a signal (a Signal Table signal or a property of this system), an operator and a number, read from the device at that moment. A boolean reads as 1 or 0. An interlock that cannot be read counts as failed.

3.6 Action: what I am doing#

When anyone asks for a capability, the system creates an Action. The Action records the whole story: who asked, who approved, what happened.

BoxWhat it holds
idA unique ID (a UUID). The client may choose it, as actionId in its request, so it can compute the digest in advance (API Standard 6.3).
capability or operationWhat is being done: a capability name, or for any other API operation operation written "METHOD /path", such as "PUT /heart/v1/tending/autonomy". Exactly one of the two.
statusWhere it is in its life (below)
riskread, write or destructive: the risk the gate applied, which may be higher than the capability's own (API Standard 6.3)
createdAtWhen it was requested
expiresAtWhen it expires if still awaiting approval
digestSHA-256 fingerprint of what is being approved: system, id, capability or operation, arguments and physical (API Standard 6.3). It cannot change once approval is asked for.
argumentsThe inputs. Private.
initiatorWho started it: kind is human, peer, ai or rule (a Playbook). For an AI, onBehalfOf says whose authority it is using.
decisionApprove, deny or cancel, when, by whom, and how presence was proved (webauthn, ciba, device-button or remote-site)
approvedByFor a later step or the undo of a Trial: the first Action of that Trial, whose approval covered the whole plan (Core Standard)
arrhythmiaIdThe alert it is fixing, if any
explanationPlain language: what it does and why
physicalWhether it affects the real world
dryRuntrue if it only reports what would happen
progress, result, errorHow it is going, and how it ended
cancellableWhether a cancel can still take effect
nextReachableAtFor shutdown, sleep and restarts: when the system expects to answer again
awaiting-approval ──► approved ──► running ──► succeeded
        │                │            │     └─► failed
        ├──► denied      │            └──► cancelling ──► cancelled
        ├──► expired     └──► refused
        └──► cancelled

denied: a person said no. refused: the system said no (a guard, a precondition or the autonomy mode). cancelling: a cancel takes effect at the next safe point; see API Standard 6.3, rule 5.

An Action that needs no approval starts at running. The rules for who must approve what are in Part 6.

3.7 Receipt: what data I sent#

Whenever non-public data leaves the system, to an AI provider, a Gateway or another system, the HEART writes a Receipt. It records who received the data, why, how private it was, how many bytes were sent, and a salted commitment to exactly what was sent: SHA-256 over a fresh random salt followed by the payload. The salt goes to the recipient, never into the Receipt, so nobody can guess short values back from it. A Receipt never contains the data itself.

Part 5 explains Receipts fully.


4. Shared word lists#

Many boxes accept only words from a fixed list. That is what lets a program understand any HEART without guessing.

ListWords
Statushealthy, degraded, failing, unknown
Severityinfo, warning, error, critical
Riskread, write, destructive
Privacy levelpublic, internal, private, never-share
Confidencelow (a guess worth checking), medium (likely), high (well supported by the evidence given)
Initiatorhuman, peer, ai, rule
Arrhythmia statusopen, acknowledged, tending, escalated, resolved
Action statusawaiting-approval, approved, running, cancelling, succeeded, failed, denied, refused, cancelled, expired
Component kindservice, process, sensor, actuator, board, module, library, store, network, other
Rhythm categorySection 3.3
AreaSection 5.2
UnitsUCUM codes, the standard list of units of measure, such as Cel for degrees Celsius

The four statuses mean exactly this:

StatusMeaningAir-conditioner example
healthyWorking normallyCooling as expected
degradedWorking, but less wellCooling, but weakly
failingCannot do its main jobNot cooling at all
unknownCannot tell yetJust switched on, or no Pulse for a while

5. Fault codes#

5.1 Why fault codes#

A message like "error 0x3F" means nothing outside one company. A message like "something is wrong" means nothing to a program. A fault code fixes both. It is a short, readable name for one specific problem, with one fixed meaning on every product.

A building dashboard watching 500 different devices can then count every storage.full across all of them, without knowing any of the brands.

HEART fault codes are words, not numbers. sensors.drift is easier to read and remember than S0402, and still easy for programs. For a small screen, a blinking light or a phone call, each standard code also has a short fixed number, its H-number, such as H-08005 for sensors.drift (Section 5.7). The name stays the main form.

5.2 How a code is built#

A fault code has two parts, separated by a dot:

     sensors . drift
     ───┬───   ──┬──
      area    problem

The area is where the problem is. The areas are the same as in Part 2, plus system for the whole system:

AreaNumberCovers
system01The whole system
power02Supply, battery, charging
connectivity03Network and links to other systems
storage04Disk, memory cards, databases
performance05Speed, load, heat
software06Crashes, versions, updates, settings
ai07AI providers, models, budgets
sensors08Readings and calibration
actuators09Motors, valves, heaters, compressors
data10Data quality, sync, backups
security11Logins, certificates, tampering

The number is the first part of the H-number of every code in that area (Section 5.7). A new area takes the next free number, 12 to 99.

The problem is one or more lower-case words joined by hyphens, such as nearly-full.

5.3 Three kinds of code#

KindLooks likeWho defines itExample
Standardarea.problemThis standard (Section 5.4)storage.full
Profileprofile.problemA product profile (Part 8)hvac.refrigerant-low
Productreversed domain name, then the problemThe product's makercom.coolair.filter-clogged

Rules:

  1. A system MUST use a standard code when one fits.
  2. If none fits, it SHOULD use a profile code, and only then a product code.
  3. Product codes MUST start with a domain the maker owns, so two makers never clash.
  4. A product code SHOULD be described in the Card's events, with a sentence saying what it means.
  5. Only standard codes have an H-number (Section 5.7). Profile and product codes have none: they are always written by name.

5.4 The standard fault codes#

This is the starting list. It will grow through the registry process (Section 11). Each code has its H-number beside it (Section 5.7). These codes are all faults: things that are wrong. Things that simply happen, such as a start or a restart, are event types (Section 5.8).

A page for each code, with its likely causes, how to fix or prevent it, and what a HEART does by itself, is at https://heartcortex.ai/faults/<code>, such as /faults/storage.full. The same facts are in one machine-readable file, fault-codes/1.0/fault-codes.json, checked against the tables below by tools/validate.py.

system: the whole system

CodeH-numberMeaning
system.main-function-lostH-01001The system cannot do its main job. Every HEART MUST be able to detect this (Part 2, A1).
system.main-function-degradedH-01002The main job works, but less well than normal.
system.flatlineH-01003No Pulse for three intervals. Raised by whoever is watching, not by the system itself.
system.unexpected-restartH-01004The system restarted without being asked to.
system.heart-unwellH-01005The HEART itself has a problem. The product may be fine.
system.undo-failedH-01006A change the HEART made could not be undone, so the system is left changed (HEART Core, Section 7.5). A person must look.

power

CodeH-numberMeaning
power.supply-lostH-02001Main power is gone. Running on battery or backup, if any.
power.supply-unstableH-02002Voltage or supply is outside the normal range.
power.battery-lowH-02003The battery needs charging soon.
power.battery-failingH-02004The battery no longer holds charge as it should.

connectivity

CodeH-numberMeaning
connectivity.link-lostH-03001A network link is down.
connectivity.link-unstableH-03002A link keeps dropping or is very slow.
connectivity.dependency-unreachableH-03003An outside service or system it relies on cannot be reached.
connectivity.clock-unsyncedH-03004The clock cannot be checked against a time source.

storage

CodeH-numberMeaning
storage.nearly-fullH-04001Storage is almost full (the system states the threshold).
storage.fullH-04002Storage is full. Writing new data fails.
storage.write-failedH-04003Data could not be written, for a reason other than being full.
storage.wearing-outH-04004Storage hardware is near the end of its life.
storage.corruptedH-04005Stored data or the file system is damaged.

performance

CodeH-numberMeaning
performance.slowH-05001Responses take much longer than normal.
performance.overloadedH-05002More work is arriving than can be handled.
performance.backlogH-05003A queue of waiting work keeps growing.
performance.memory-exhaustedH-05004Memory is (nearly) used up.
performance.too-hotH-05005The device is overheating and may slow itself down.
performance.overshootH-05006A controlled value goes past its target by more than the system's stated limit, such as a room getting colder than its setpoint.

software

CodeH-numberMeaning
software.error-spikeH-06001Errors are happening far more often than normal.
software.crashedH-06002A program or component crashed.
software.crash-loopH-06003A component keeps crashing and restarting.
software.update-failedH-06004An update did not install.
software.config-invalidH-06005Settings are wrong or contradict each other.
software.version-mismatchH-06006Parts that must work together have incompatible versions.

ai

CodeH-numberMeaning
ai.provider-unavailableH-07001The AI model or provider cannot be reached.
ai.cost-spikeH-07002AI spending is rising much faster than normal.
ai.budget-near-limitH-07003AI spending has reached 80% of the budget.
ai.budget-exceededH-07004The AI budget is used up. AI calls are stopped.
ai.model-driftH-07005The AI model's answers have changed in quality or behaviour.
ai.output-rejectedH-07006AI suggestions keep failing the HEART's checks.
ai.lease-expiredH-07007The brain lease ran out without a renewal, so the system is brainless (API Standard 7.4).
ai.brain-revokedH-07008The brain was cut: by a Command Center signal, by the owner, or by the system's own tripwire.
ai.answer-rejectedH-07009A brain answer was refused: unsigned, wrongly signed, for another request, or outside the lease.
ai.disagreementH-07010The brain's answer disagreed with the system's own checks on something safety-relevant.

sensors

CodeH-numberMeaning
sensors.no-readingH-08001A sensor gives no value.
sensors.out-of-rangeH-08002A reading is outside what is physically possible.
sensors.stuckH-08003A reading has not changed when it should have.
sensors.noisyH-08004Readings jump around far more than normal.
sensors.driftH-08005A sensor has slowly moved away from the true value.
sensors.disagreeH-08006Two sensors that should agree do not.

actuators

CodeH-numberMeaning
actuators.not-respondingH-09001A motor, valve or similar part does not react to commands.
actuators.position-mismatchH-09002It ended up somewhere other than where it was told to go.
actuators.stalledH-09003It is blocked or cannot move.
actuators.short-cyclingH-09004It switches on and off far too often.
actuators.overcurrentH-09005It is drawing more current than it should.

data

CodeH-numberMeaning
data.invalidH-10001Data fails its checks.
data.missingH-10002Expected data has not arrived.
data.out-of-syncH-10003Two copies of the same data disagree.
data.backup-failedH-10004A backup did not complete.
data.integrity-failedH-10005Data has been changed or damaged when it should not have been.

security

CodeH-numberMeaning
security.login-failuresH-11001Many failed login attempts.
security.unexpected-accessH-11002Access from an unknown place, or at an unusual time.
security.certificate-expiringH-11003A security certificate expires soon.
security.certificate-expiredH-11004A security certificate has expired.
security.tamper-detectedH-11005Someone may have opened or altered the device or its software.
security.policy-violationH-11006Something broke the owner's rules, such as data that should not have left.
security.anomalyH-11007Unusual activity that may be an attack.

5.5 The older kind box#

Before fault codes, alerts had a kind: one of 11 broad types. To keep existing software working, a system SHOULD send both code and kind during the change-over, when an old kind fits:

Old kindFault code
error-spikesoftware.error-spike
latency-spikeperformance.slow
resource-exhaustionperformance.memory-exhausted or storage.full
cost-spikeai.cost-spike
dependency-failureconnectivity.dependency-unreachable
model-unavailableai.provider-unavailable
model-driftai.model-drift
security-anomalysecurity.anomaly
policy-violationsecurity.policy-violation
data-integritydata.integrity-failed
flatlinesystem.flatline

kind will be removed in version 2.0.

5.6 Writing a code outside messages#

Inside a message, a code is written bare:

"code": "storage.full"

Outside messages, in logs, tickets, documents, screens and searches, it is written with HEART and a space in front: HEART storage.full. The word tells a reader, or a search engine, which list the code comes from. The same holds for profile and product codes, such as HEART hvac.refrigerant-low.

A program reading a message MUST NOT expect the prefix. A program writing a message MUST NOT add it.

5.7 H-numbers#

Each standard fault code has a short number for places where a name does not fit: a two-digit display, a blinking light, a code read out over the phone. It is written H-AACCC:

PartMeaningExample
H-A HEART fault code
AAThe area's number (Section 5.2)04: storage
CCCThe code's place in its area, from 001002: full

So H-04002 is storage.full, and H-01001 is system.main-function-lost.

Rules:

  1. An H-number is fixed for ever. It is never changed, never reused, and never given to another code, even if its code is deprecated.
  2. A new code takes the next free number in its area. A new area takes the next free area number.
  3. Only standard codes have H-numbers. Profile codes, product codes and event types have none.
  4. The name is the main form. Messages carry the name, never the H-number. A screen, label or manual MAY show the H-number beside the name, or alone where the name does not fit.
  5. A person can look up any H-number at https://heartcortex.ai/system-code/H-AACCC, such as /system-code/H-04002. A part of a number, such as H-04, lists every code that starts with it.

5.8 Event types: not fault codes#

An event type names something that happened: the system started, a part was restarted, a message arrived. It is the name of a Rhythm event (Section 3.3). It is not a fault, and MUST NOT be used as an alert's code or cause.code.

Event types look like fault codes, area.name, but they are a separate list. They have no H-number. When an event shows that something is wrong, the HEART raises an alert with a fault code. For example, a component.failed event three times in 30 seconds may raise connectivity.dependency-unreachable, and a restart nobody asked for raises system.unexpected-restart beside the system.started event.

These standard event types are defined so far. Each has the category of its prefix (Section 3.3).

Event typeMeaning
system.startedThe system started.
system.restartedThe HEART resumed after a restart, from saved state.
system.stoppingThe system is shutting down on purpose.
system.port.fallbackThe standard port was taken, so the system runs on a fallback port.
system.custom.changedA custom definition was added, changed or removed.
system.lifecycle.started, system.lifecycle.done, system.lifecycle.failed, system.lifecycle.cancelledA lifecycle operation, such as a restart, started, finished, failed or was cancelled (API Standard 13.2 rule 3).
system.lifecycle.maintenance-windowA maintenance window began (module schedules).
system.lifecycle.maintenance-endedMaintenance ended by itself at maintenanceUntil.
component.failedA component failed or stopped answering.
component.recoveredA failed component works again.
component.restartedA component was restarted.
ai.call.failedA call to an AI model failed.
ai.tier.changedThe way of thinking in use changed, such as from cloud to local.
tending.autonomy.changedA person changed the autonomy ceiling max.
tending.silence.endedA silence on an alert's code was ended early.
tending.stoppedStop was pressed: all autonomous action stopped.
tending.action.failedAn Action ended failed.
tending.guard.refusedA guard or interlock refused a command.
tending.rule.proposed, tending.rule.suspended, tending.rule.failed, tending.rule.refusedA Playbook was proposed, suspended, failed when run, or was refused by the gate.
tending.proposal.receivedA brain's Proposal arrived.
tending.trial.started, tending.trial.undoing, tending.trial.kept, tending.undo-failedA Trial started, began its undo, was kept, or could not be undone.
tending.envelope.exceededAn automatic change would have gone outside its envelope, and was refused.
circulation.receivedA message from another system arrived.
circulation.gateway.joined, circulation.gateway.unreachableThe system joined its Gateway, or cannot reach it.
circulation.system.joined, circulation.system.leftAt a Gateway: a system joined or left.
security.model.invented, security.model.ungroundedA model's answer named something that does not exist, or was not grounded in the system's own data, and was refused.

More event types are added through the registry (Section 11).


6. Standard action names#

If a product offers one of these actions, it SHOULD use the name given here. Then one command, such as "restart that", works across a whole building or fleet of different products.

AreaNames
Tendingretry_operation, restart_component, switch_provider, clear_cache, throttle, rollback
Devicesidentify, calibrate, zero, self_test, sync_time, reset_counters
Actuatorsstart, halt, pause, resume, home, set_target
Dataflush_buffer, compact_storage, export_data
Connectivityreconnect, rescan, switch_network

halt stops a machine or one of its parts. It is not the HEART's Stop, which stops only automatic action and leaves the machine as it is (Part 6, Section 6).

Product profiles (Part 8) add names for their own kind of product.


7. Feature Sets: how much a system must say#

A Feature Set says how much of the information model a system offers. There are three. Each includes everything in the one before it.

Feature SetWhat it addsSuits
BasicCard, Pulse, Arrhythmias, the ValveEvery product, including small sensors
ConnectedRhythm history, questions in plain language, messages from other systems, subscriptions, Receipts, the full CardMost apps and connected devices

The full Card means the Card served at the caller's clearance (GET /heart/v1/card), and not only its public view (Part 4). | Full | Capabilities and Actions with approval, the stop control, AI model tracking, AI reasoning in the standard format | Systems that fix themselves or act on request |

A system states its Feature Set in its Card. If something is asked for that is above its Feature Set, it MUST answer "not implemented" (Part 4 says how).

Every Feature Set, even Basic, MUST also meet Autonomy Level A1 (Part 2). A system that only reports, without noticing problems and telling someone, is not a HEART.

Feature Sets and Autonomy Levels are different scales. The Feature Set says how much you can ask. The Autonomy Level says how much it does on its own. See Part 1, Section 5.6.


8. Modules: optional extras#

Feature Sets stay small, so a tiny sensor can take part. Everything else is an optional module. A system lists its modules in the Card's modules. It MUST offer all of a module, or none of it.

ModuleAddsTypical user
inventoryA tree of the system's parts, and what it relies onMost systems
propertiesNamed values to read or set, such as a temperature or a setpointDevices
configVersioned settings that can be checked before use, and rolled backMost systems
telemetryMetrics and logs, for systems that do not use OpenTelemetrySmall devices
diagnosticsSelf-tests and support bundlesDevices, appliances
lifecyclePower and operating phases, such as sleep or maintenanceDevices
softwareVersions, signed updates and lists of included softwareMost systems
artifactsFiles and large dataApps, printers, cameras
schedulesDo something later, and maintenance windowsMost systems
controlThe stop button and Playbook rules. Required for Full.Systems that act
privacyValve settings, consent and personal data requestsSystems with personal data
aiAI providers, budgets and usageSystems using AI
brainThe brain lease and the switch: a Command Center can cut the AI model, and it is cut by itself when the lease runs out (API Standard 7.4). Required at A3 and above with a brainSystems using AI to act
memoryWhat the system remembers, and forgetting it on requestSystems using AI
evolvingAI model versions, lessons and feedbackSystems using AI
securityKeys, proof of identity, and audit recordsMost systems
platformHardware, power, network and clockDevices
provisioningFirst setup, and changing ownerDevices
peersWhich other systems it trustsSystems that talk to each other
batchSeveral requests in one go, for slow linksSmall or remote devices
fleetOne command to many systemsGateways
customThe product's own commands (Part 8)Most devices
nativeDirect access to the device's own protocol. Off by default.Engineers only
coreThe built-in HEART Core (Part 7)Systems with a Core

Two of the most useful module messages:

  • Component (inventory): one part of the system, with an id, a kind (Section 4), its own status, and optionally its parent, version, maker and what it depends on.
  • Property (properties): one value, with its name, value, unit (UCUM), whether it is writable, a quality of good, uncertain or bad (the three severities of OPC UA's StatusCode), the time it was measured, and its privacy level. The value takes the level given in privacy; this is the only box whose level is set per message (its schema marks it dynamic).

9. Naming rules#

Names are how systems find each other and avoid clashes. These rules keep them unique and readable.

WhatRuleExample
System IDA reversed domain name the owner controls, then the product namecom.example.cool-air.ac-controller
InstanceWhich copy of the system. MUST NOT reveal who the user or owner is.unit-12, browser-7f2c
Standard message typesStart with heart. (reserved)heart.pulse
Product message types and fault codesStart with the maker's reversed domain namecom.coolair.service-report
Capability namesUp to 128 letters, digits, _, . or - (the same as MCP tool names)calibrate
Event typesDotted lower-case words (Section 5.8)wash.finished
Fault codesSection 5sensors.drift

Using a reversed domain name works the way Java packages and Android apps do. Only the owner of coolair.com can create names starting com.coolair, so names never clash.


10. Rules for change#

Products will mix HEART versions for years. These rules make sure old and new keep understanding each other.

  1. Ignore what you don't know. A consumer MUST ignore boxes it does not recognise. It MUST NOT fail.
  2. Missing means "not available to you". A missing box never means zero, false or empty. It may have been filtered out for privacy.
  3. Versions 1.x only add. A minor version may add boxes, words and codes. It MUST NOT remove anything or change what something means. Removing or changing needs version 2.0.
  4. Codes are forever. A fault code, its H-number, an action name or an event type, once published, never changes meaning and is never reused. It can only be marked deprecated (no longer recommended).
  5. Extras go in ext. A product's own extra boxes go inside ext, under the maker's reversed domain name, so they never clash with future standard boxes. They are private unless the Card says otherwise.
"ext": { "com.coolair": { "filterHours": 412 } }

11. Registries: the shared lists#

A registry is an official, shared list that everyone uses, such as the list of country codes or of internet port numbers. HEART keeps these registries:

RegistryHoldsSection
Fault codesStandard fault codes and their H-numbers5.4, 5.7
Action namesStandard capability names6
AreasThe areas used by fault codes and Autonomy Levels5.2
ProfilesProduct profiles, and their prefixes for fault codes and namesPart 8
Event typesStandard Rhythm event types5.8
Message typesheart. message types3
ModulesModule names8

How to add an entry#

Anyone may propose an entry. A proposal gives:

  1. the name,
  2. one sentence saying exactly what it means,
  3. an example from a real product,
  4. why no existing entry fits.

An entry is accepted when it is clear, does not overlap an existing entry, and is likely to be useful to more than one maker. Until HEART has a neutral home (see the Standards Family), the editor of this standard keeps the registries in this repository.


12. Carrying the model in other standards#

The model in this part is the meaning. Part 4 defines the main ways to carry it: HTTP and JSON, MQTT, local sockets and in-process use.

Other carriers can be added later without changing the model, as long as they follow one rule:

Same boxes, same meanings, same privacy. Any carrier MUST keep every box with the meaning given here, and MUST apply the Valve's filtering (Part 5) before anything leaves the system.

Planned carriers:

CarrierWhy
CBOR (compact binary JSON)For very small devices that cannot afford text messages
OPC UASo factory machines can offer HEART inside the standard factories already use
Asset Administration ShellSo a HEART can be one section ("submodel") of a factory digital twin
OMA LwM2MFor small managed IoT devices

Each needs work with the group that owns that standard.


13. Changes needed in other files#

ChangeWhere
A machine-readable copy of each other registry, checked by tools/validate.pyNew registries/ folder
Rename "conformance level" to "Feature Set" in textAPI Standard, Core Standard, paper. The Card box stays level until version 2.0.

14. Open items#

ItemWhy it matters
Is the starting fault-code list right?It should be checked against real fault logs from several kinds of product before 1.0 final.
ThresholdsCodes such as storage.nearly-full and performance.slow depend on limits each product sets. Profiles may set defaults.
Mapping to existing code systemsNAMUR NE 107 (industrial device status), OBD-II and similar code lists could map to HEART codes, so existing devices can join easily.
TranslationsCodes stay in English. The meaning sentences and explanations need agreed translations.
CBOR profileNeeded before the smallest microcontrollers can take part.