// Moved from docs/src/internal/HOLA_PROTOCOL.adoc to docs/working/scratch/src/internal/HOLA_PROTOCOL.adoc on 2026-06-16 (docs reorg Phase 2)
= HOLA Shared Memory Protocol (Phase 1)
:author: StarForth Physics Working Group
:revdate: 2025-10-23

Phase 1 introduces the **Host Observation & Logistics Adapter (HOLA)** as the stable contract between the StarForth VM and external analyzers.
The runtime now exposes a fixed-size analytics heap (default 10 MiB) implemented by
`physics_runtime.c`.
This document captures the shared-memory schema and command flow expected by Phase 1 tooling.

== Memory Layout

The analytics heap is split into four regions:

[%header,cols="1,1,1,2"]
|===
|Region |Offset |Size |Notes
|Header |`0` |`sizeof(physics_analytics_header_t)` |Single producer / consumer metadata (`HOLA_SHARED_MAGIC`).
|Event ring |`ring_offset` |`ring_bytes` |Lock-free ring buffer of physics events.
|Summary |`summary_offset` |`summary_bytes` |Aggregated statistics & Bayesian posteriors.
|Scratch |`scratch_offset` |`scratch_bytes` |Reserved for governance-approved features.
|===

The header matches the C structure in `include/physics_runtime.h` and MUST remain packed/aligned exactly as defined.
All multi-byte fields use native endianness (same as the VM).
Consumers should validate `magic`, `version_major`, and
`version_minor` before interacting with the heap.

== Event Records

Each ring entry starts with `physics_analytics_event_header_t`:

[,c]
----
struct physics_analytics_event_header {
    uint32_t channel;        // Logical stream id
    uint16_t payload_bytes;  // Raw payload size
    uint16_t reserved;       // Alignment padding (zero)
    uint64_t timestamp_ns;   // Producer timestamp (sf_monotonic_ns)
};
----

* Payloads are 8-byte padded.
* The producer updates `produce_seq` atomically after writing each record.
* Consumers advance `read_offset` and bump `consume_seq` once an event is fully processed.
* Overflow is signalled by incrementing `dropped_events` while leaving the ring untouched; consumers MUST treat the next readable event as the resynchronisation point.

=== Host Snapshot Payload

Channel `0x00000002` carries a binary `physics_host_snapshot_t` structure.
All multi-byte fields use native endianness.
New fields introduced in Phase 1:

[%header,cols="1,2"]
|===
|Field |Description
|`psi_*` |Pressure Stall Information averages (`avg10/60/300`) scaled by 1000.
|`cpu_total_jiffies`, `cpu_idle_jiffies` |Snapshots of `/proc/stat` totals for consumer-side delta calculations.
|`cgroup_cpu_usage_us` |`cpu.stat` `usage_usec` (cgroup v2). Zero when unavailable.
|`cgroup_memory_current_bytes` |`memory.current` reading (cgroup v2). Zero when unavailable.
|`flags` |Bitmask indicating which groups were populated (`PHYSICS_HOST_FLAG_*`).
|===

Consumers should honour the flag bits to differentiate between kernels that expose PSI, cgroup v2, or `/proc/stat` data.
The full structure is defined in
`include/physics_runtime.h`.

Recommended channels:

[%header,cols="1,3"]
|===
|Channel |Purpose
|`0x00000001` |Word execution samples (`entropy`, latency, dictionary id).
|`0x00000002` |Host snapshot deltas (compressed `physics_host_snapshot_t`).
|`0x0000FF00` – `0x0000FFFF` |Governance-reserved control/alert events.
|===

== Command Protocol

Commands travel via the summary region.
The first 256 bytes are reserved for a simple request / response mail box:

[,c]
----
struct hola_command {
    uint32_t opcode;      // See table below
    uint32_t arg0;        // Optional argument / status
    uint64_t arg1;        // Optional payload pointer (offset from heap base)
};
----

[%header,cols="1,2,3"]
|===
|Opcode |Direction |Semantics
|`0x0000_0000` (`HOLA_NOP`) |Either |No-op; producer clears when idle.
|`0x0000_0001` (`HOLA_REQUEST_SNAPSHOT`) |Consumer→VM |Request immediate host snapshot; VM publishes on channel `0x2`.
|`0x0000_0002` (`HOLA_RESET_RING`) |Consumer→VM |Consumer processed all data; VM zeroes cursors when safe.
|`0x0000_8000` (`HOLA_STATUS_OK`) |VM→Consumer |Acknowledges command completion.
|`0x0000_8001` (`HOLA_STATUS_BUSY`) |VM→Consumer |Command deferred; consumer should retry after next tick.
|`0x0000_8002` (`HOLA_STATUS_UNSUPPORTED`) |VM→Consumer |Opcode not understood in this protocol revision.
|===

The VM polls the command mailbox at the end of each observation window hop.
All responses are written back into the same structure before the next poll.
Phase 1 only implements `HOLA_REQUEST_SNAPSHOT`; other opcodes are reserved for future phases.

== Synchronisation Rules

* **Single producer**: the VM is the sole writer to the ring buffer.
Multiple producers must funnel through the runtime shim.
* **Single consumer**: Phase 1 assumes exactly one analyzer; multi-consumer support will require an additional indirection table inside the summary region.
* **Memory ordering**: producers write payload → header → bump `produce_seq`.
Consumers read `produce_seq` before pulling events and bump `consume_seq`
after advancing `read_offset`.
* **Failure semantics**: if `dropped_events` increases the consumer must treat the last coherent boundary as unknown and resynchronise from the first complete record following the drop.

== Artefacts

*Runtime implementation*: `include/physics_runtime.h`, `src/physics_runtime.c`
(`physics_runtime_init`, `physics_host_snapshot`, `physics_analytics_publish_event`).

*Formal model linkage*: `docs/src/internal/formal/Physics_StateMachine.thy` and
`Physics_Observation.thy` capture the observation window semantics assumed by this protocol.

Future revisions will document multi-node governance flows and captable wiring for L4Re tasks once Phase 2 moves the analyzer into a dedicated microkernel service.
