Causal system handbook

Causality is an interface.

SlOS records execution as a chain of typed causes. The causal system gives the machine a way to name events, relate them, replay them, and expose them to the operator.

Lamport clock Parent edges Timeline cursor Replay callback
A SlOS causal demonstration frame
The showcase demonstrates a system that narrates its own activity.

Why the system exists

An operating system changes state continuously. SlOS records those changes as causal events so the operator can follow execution through drivers, syscalls, tasks, applications, and mesh peers. The graph gives each state change a stable reference and a place in the history of the machine.

The result is a single technical substrate for debugging, provenance, teaching, replay, and distribution. A note, a packet, a task switch, and an actor message all enter the same ordered field.

Operator services

Explanation The operator can ask why a state exists and receive a parent chain.
Provenance Data movement carries source, subsystem, event ID, and causal ancestry.
Replay Timeline cursors reconstruct past application state from the same event chain.
Teaching The implementation and its execution appear in one visible substrate.
Distribution Remote actor and mesh events can enter the same causal order.

Eight chapters from event to federation.

Chapter 01

A machine action receives a name

A shell command, packet receive, task switch, filesystem mutation, or actor delivery becomes an addressable event.

Chapter 02

The event record carries facts

The record stores identity, subsystem, description, payload, time, parent IDs, and child count.

Chapter 03

Parent edges carry cause

Every event joins the current task context or an explicit parent set, producing a directed acyclic graph.

Chapter 04

Time has two instruments

Lamport time orders cause; wall ticks and TSC fragments help the operator correlate events with the machine.

Chapter 05

Queries become operating commands

The shell exposes recent events, ancestry, children, graph health, and compact graph drawings.

Chapter 06

Timelines turn events into state

Applications build named chains over causal events and reconstruct state by replaying to a cursor.

Chapter 07

Applications become graph-native

Notes, mail, editor, and scheduler state share the same event material as the kernel.

Chapter 08

Federation extends the graph

Actors, mesh identity, node hashes, and Lamport merge rules prepare causality for peers and future cores.

A machine action receives a name

The first idea is simple: a meaningful state change receives an event ID. A shell command, task creation, filesystem write, packet transmit, actor send, or timeline edit becomes a named item in the kernel. The ID gives later commands a handle for inspection.

That handle is the beginning of explanation. The operator can list recent events, select one, and ask for its parents or children. A running system becomes a catalogue of operations with stable addresses.

slos:/$ note add compiler notes survive replay pressure
Note #6 added.
slos:/$ note tag last compiler
slos:/$ note search compiler survive
6: compiler notes survive replay pressure [compiler]
slos:/$ events 5
1831 syscall write pid=30
1832 notes note added
1833 notes tag attached
1834 syscall causal pid=30
1835 shell command complete

Basic interpretation

Event 1832 records the note insertion. Event 1833 records the tag attachment. Event 1834 records the following causal syscall. The sequence is readable by the operator and available to kernel query functions.

The event record carries facts

The causal event record is deliberately small. It holds a monotonic ID, a node hash for federation, a dual time value, a subsystem type, a short description, an optional payload, parent event IDs, and a child count.

Listing A include/causal.h
typedef struct {
    uint32_t       id;
    uint32_t       node_hash;
    causal_time_t  time;
    causal_type_t  type;
    char           subsystem[16];
    char           desc[CAUSAL_DESC_LEN];
    uint8_t        payload[CAUSAL_PAYLOAD_LEN];
    uint32_t       payload_len;
    uint32_t       parents[CAUSAL_MAX_PARENTS];
    uint8_t        num_parents;
    uint16_t       child_count;
} causal_event_t;

Field notes

id The permanent event number within the current boot stream.
time Lamport ordering, wall ticks, and low TSC bits.
subsystem A short source label such as sched, fs, tcp, actor, or notes.
parents The immediate causes of the event.
payload Typed application or subsystem data stored with the record.

Parent edges carry cause

Each event joins the graph by parent edge. Explicit parent IDs represent known causes. The current task context supplies an automatic parent for ordinary emissions. The child count on each parent is updated as the graph grows.

This rule turns a stream of operations into a directed graph. A filesystem event can hang beneath a syscall. An actor receive can join sender and receiver histories. A timeline event can point back to the previous head.

Listing B kernel/graph/causal.c
if (np > 0 && parent_ids) {
    for (int i = 0; i < np; i++)
        ev->parents[i] = parent_ids[i];
    ev->num_parents = (uint8_t)np;
} else {
    uint32_t ctx = causal_get_current();
    if (ctx) {
        ev->parents[0] = ctx;
        ev->num_parents = 1;
    }
}
slos:/$ why 1833
event 1833 type=user subsystem=notes
desc: tag attached
parents:
  1832 notes note added
  1829 syscall BLOCKFS pid=30
children:
  1834 syscall causal pid=30

Time has two instruments

SlOS records logical and physical time together. The Lamport clock increments on each event and merges remote clocks through the standard max-plus-one rule. Wall ticks are the 100 Hz operator timebase. The low TSC value gives sub-tick correlation.

This division gives the graph two readings. Lamport order serves causal reasoning. Wall ticks and TSC fragments serve human diagnosis, serial output, screenshots, and repeatable demonstrations.

Instrument Stored field Use
Lamport time.lamport Logical ordering and federation merge.
Wall ticks time.wall_ticks Operator-facing uptime at 100 Hz.
TSC low bits time.tsc_lo Sub-tick ordering aid for local correlation.

Queries become operating commands

The causal graph is queried from two surfaces. Kernel code calls direct functions for recent events, tick ranges, children, and ancestors. The shell presents the same idea as operator commands: events, why, trace, graph, and graph-health.

Listing C include/causal.h
causal_event_t *causal_get(uint32_t event_id);
int causal_query_recent(causal_type_t type, causal_event_t **out, int max);
int causal_query_range(uint32_t start_tick, uint32_t end_tick,
                       causal_event_t **out, int max);
int causal_query_children(uint32_t event_id, causal_event_t **out, int max);
int causal_query_ancestors(uint32_t event_id, causal_event_t **out, int max);

Shell surface

events 10
why <event-id>
trace <event-id>
graph
graph-health

Timelines turn events into state

A timeline is a named chain of causal events owned by one application. The payload stores the timeline ID, application sub-type, data length, and event data. The previous head becomes the parent of the next event, creating an ordered chain inside the larger graph.

The cursor gives the chain its time-travel property. Rewind moves the cursor backward. Forward moves it ahead. Replay walks from creation to the cursor and calls the application's reconstruction function.

Listing D kernel/graph/timeline.c
/* payload: {uint32_t tl_id, uint32_t sub_type,
 *           uint16_t data_len, data[]} */
memcpy(payload + plen, &id_val, 4);     plen += 4;
memcpy(payload + plen, &sub_type, 4);   plen += 4;
memcpy(payload + plen, &dlen, 2);       plen += 2;

uint32_t parents[1];
int nparents = 0;
if (tl->head_id != 0) {
    parents[0] = tl->head_id;
    nparents = 1;
}

Timeline commands

tl show notes
tl stats notes
tl mark notes demo-checkpoint
tl rewind notes 20
tl forward notes 20
tl export notes -n 10 /notes-recent.txt

Applications become graph-native

Notes, mail, editor, and scheduler commands use timelines as their native state material. A note insertion, mail read, editor character insertion, and scheduled shell command are all application events with causal ancestry.

Durable current state is supplied by application snapshots or exports on SlFS. The live causal ring supplies recent explanation. The application keeps the compact current view, while the graph supplies the route by which that view came into being.

Application Timeline use Operator commands
Notes Add, tag, search, import, export, and snapshot note state. note add, note tag, note search, note export
Mail Receive, read, send, and delete mail events. mail, tl show inbox
Editor Store character edits and reconstruct the buffer by replay. edit, tl show doc:<name>
Scheduler Record scheduled command history and execution marks. schedule, scheduled, tl tail schedule

Federation extends the graph

The causal record includes a node hash, and the clock API accepts remote Lamport values. Actor delivery, mesh identity, and federation use these fields to place remote activity into the same form as local activity.

This design gives SlOS a path from single-machine introspection to peer-aware execution. A remote actor message can carry its causal history. A mesh peer can merge clocks. A future per-core transport can use the same actor and timeline vocabulary over a shared-memory channel.

Local machine

task
->
actor
->
causal event

Federated machine

mesh peer
->
Lamport merge
->
node-marked event

Operational rule: the global causal ring is for recent causality. Applications that require durable current state keep snapshots or timeline exports on SlFS. The graph explains the present; the application decides what must survive a reboot.