Skip to content

Events are facts; acknowledgements are derived

Source: harness/docs/decisions/events-are-facts-acks-derived.md
Status: current

Events are facts; acknowledgements are derived

Section titled “Events are facts; acknowledgements are derived”

A result, event, or status field records a state transition that actually occurred — an append, a seal, a consumption, a cancel, a refusal. The platform never emits a synthetic acknowledgement of a transition that did not happen.

States — accepted, delivered, running, processed — are derived from the record, never stored or emitted as claims:

  • accepted ≡ the entry exists on the document (and its consumer is alive)
  • delivered ≡ a consumption cell exists on the consuming turn
  • running ≡ heartbeat/activity facts are fresh
  • processed ≡ the derived output events exist

Three tests for any field or result:

  1. Could this ever be false? A constant-true result is protocol filler — zero information, non-auditable.
  2. What transition does this record? None — it is fiction.
  3. Stored or derived? A stored state that could be derived drifts from the facts — the dual lie.

The honest negative is failure: if the append fails, the call fails. Silence and failure are the two honest poles; synthetic acks sit between them, lying.

When a protocol forces a result, return the minimal fact (the entry ref). When the system synthesizes content, mark it synthetic — the in-tree precedent is message/ack (../packages/harness-server/src/daemon/session/compact-env.ts; MessageChunk.ack on the eat). A sink’s ack is discarded: the verb’s whole return is its effect.

{accepted: true} claims an act of acceptance no component performs. It implies a guarantee the system has not made (the consumer may be dead, over budget, or about to drop the signal), carries no information (constant), and cannot be audited later — the record says “accepted”; nothing accepted. Event-sourced and reactive substrates make the honest shape cheap: the record exists anyway, so results can be references into it. Consumers that need assurance derive it from the record; consumers that don’t are not told comforting fictions.

The ground, not just the rule: the substrate has no messaging layer — no bus, no stream, no command channel. There is synced shape, derivation over shape, and presence (ephemeral shape that retracts). Wants about remote process are therefore expressible only as facts — “I expect this stopped” is a proposal, published on a lane; satisfaction is derived from subsequent facts or not known at all. Every fact has exactly one authority: your proposal is your write; the worker’s admission is its act. A command or ack API would not merely be dishonest — it would claim a causal channel that does not exist. Positive form: every write returns the ref to the fact it made (propose() returns a proposalId; a tingle seals with its tape-entry ref), never a claim about consequences.

A bare stored “Running” status is the most hated lie in this class (stuck agents reporting ACTIVE for hours). A stored state drifting from facts is worse than having no scheduler, because the operator believes the work is covered.