Files
v10/internal/design/spf/primitives.md

1.8 KiB

status, date
status date
implemented 2026-03-11

SPF primitives

This record preserves the roles of SPF's composition primitives. Their types, states, scheduling, and cleanup semantics belong to source and tests.

Decisions

  • A behavior is the unit of engine composition. Other primitives live inside a behavior rather than beside it in the engine list.
  • A signal represents state over time and connects otherwise independent behaviors.
  • A task is one cancellable unit of asynchronous work. It does not own long-lived domain state.
  • A runner owns task scheduling policy such as serialization, concurrency, cancellation, or deduplication.
  • An actor owns a message-driven resource or work queue and exposes observable lifecycle when consumers need it.
  • A reactor observes signals, derives lifecycle state, and runs state-scoped setup, reactive work, and cleanup without owning a message channel.
  • Destruction is part of every long-lived primitive's contract and must release active work before the composition finishes destroying.

Selection rule

Use the smallest primitive matching the work:

  • direct derivation or synchronization: signals and effects;
  • cancellable operation: task and runner;
  • message-driven ownership: actor;
  • signal-driven lifecycle with state-specific cleanup: reactor.

Do not add a wrapper solely for naming consistency. Introduce another primitive only after repeated work cannot be expressed cleanly by these roles.

Current sources of truth

  • Signals: packages/spf/src/core/signals/
  • Tasks and runners: packages/spf/src/core/tasks/
  • Actors: packages/spf/src/core/actors/
  • Reactors: packages/spf/src/core/reactors/
  • Composition: packages/spf/src/core/composition/
  • Factory rationale: Actor and reactor factories