%% SCRAP: architecture/03-architecture/heartbeat-system/architecture %% SOURCE: docs/working/architecture/03-architecture/heartbeat-system/architecture.md %% STATUS: WORKING %% FITS: dev-guide/ch-heartbeat %% EDITORIAL: lifted — prose rewritten to press voice \subsection{Heartbeat Architecture: Centralised Time-Based Tuning} The heartbeat mechanism coordinates all time-driven VM operations through a single dispatcher, \texttt{vm\_tick()}. Both Loop~\#5 (rolling-window tuning) and Loop~\#3 (heat-decay validation) are time-driven events that belong in one place rather than scattered through execution paths. The same dispatcher is designed to evolve into a background thread for system observability without touching core VM logic. \subsubsection{HeartbeatState} The \texttt{HeartbeatState} struct, declared in \texttt{include/vm.h} and embedded in the \texttt{VM} struct, holds the tick counter and per-plugin cursors: \begin{lstlisting}[language=C] typedef struct { uint64_t tick_count; /* total ticks since VM init */ uint64_t last_window_tune_tick; /* tick of last window tune */ uint64_t last_slope_tune_tick; /* tick of last decay validation */ int heartbeat_enabled; /* 1 = active, 0 = disabled */ } HeartbeatState; \end{lstlisting} \subsubsection{Dispatcher} \texttt{vm\_tick()} in \texttt{src/vm.c} increments the global tick counter and dispatches each plugin at its configured interval: \begin{lstlisting}[language=C] void vm_tick(VM *vm) { if (!vm || !vm->heartbeat.heartbeat_enabled) return; vm->heartbeat.tick_count++; /* Plugin 1: Window Tuning (Loop #5) */ if (ENABLE_PIPELINING && (vm->heartbeat.tick_count - vm->heartbeat.last_window_tune_tick) >= WINDOW_TUNING_FREQUENCY) { vm_tick_window_tuner(vm); vm->heartbeat.last_window_tune_tick = vm->heartbeat.tick_count; } /* Plugin 2: Heat Decay Slope Validation (Loop #3) */ if ((vm->heartbeat.tick_count - vm->heartbeat.last_slope_tune_tick) >= SLOPE_VALIDATION_FREQUENCY) { vm_tick_slope_validator(vm); vm->heartbeat.last_slope_tune_tick = vm->heartbeat.tick_count; } } \end{lstlisting} \subsubsection{Window Tuner Plugin} \texttt{vm\_tick\_window\_tuner()} in \texttt{src/physics\_pipelining\_metrics.c} computes the current prefetch accuracy and delegates to \texttt{loop\_5\_binary\_chop\_suggest\_window()} for the next candidate size: \begin{lstlisting}[language=C] void vm_tick_window_tuner(VM *vm) { RollingWindowOfTruth *window = &vm->rolling_window; PipelineGlobalMetrics *metrics = &vm->pipeline_metrics; if (!window->is_warm || metrics->prefetch_attempts == 0) return; double accuracy = (double)metrics->prefetch_hits / (double)metrics->prefetch_attempts; uint32_t suggested = loop_5_binary_chop_suggest_window( metrics, window->effective_window_size, ADAPTIVE_MIN_WINDOW_SIZE, ROLLING_WINDOW_SIZE); if (suggested != window->effective_window_size) window->effective_window_size = suggested; metrics->last_checked_window_size = window->effective_window_size; metrics->last_checked_accuracy = accuracy; metrics->window_tuning_checks++; } \end{lstlisting} \subsubsection{Slope Validator Plugin} \texttt{vm\_tick\_slope\_validator()} in \texttt{src/physics\_metadata.c} scans the dictionary and classifies entries by execution heat, using execution frequency as a proxy for thermal energy. It logs the hot-word count, the stale-word ratio, and the mean heat, providing the raw signal needed to assess whether the linear decay function is removing cache pollution at the right rate. A follow-on phase will compare the stale-word ratio trend over consecutive ticks to decide whether a different decay function (exponential, logarithmic) would converge faster. \subsubsection{Integration into the Execution Path} Two integration modes are supported. \textbf{Synchronous (current default).} The main interpreter increments an execution counter and fires \texttt{vm\_tick()} every \texttt{HEARTBEAT\_FREQUENCY} word executions: \begin{lstlisting}[language=C] if (++vm->execution_count % HEARTBEAT_FREQUENCY == 0) vm_tick(vm); \end{lstlisting} This adds negligible latency as long as plugin work remains lightweight. \textbf{Background thread (future).} When \texttt{HEARTBEAT\_THREAD\_ENABLED=1}, a POSIX thread wakes at \texttt{HEARTBEAT\_INTERVAL\_MS} and calls \texttt{vm\_tick()} independently of the execution hot-path. State shared between threads must be protected by \texttt{vm->tuning\_lock}. \subsubsection{Configuration Knobs} \begin{tabular}{lll} \toprule Knob & Default & Meaning \\ \midrule \texttt{HEARTBEAT\_FREQUENCY} & 256 & Executions between ticks \\ \texttt{WINDOW\_TUNING\_FREQUENCY} & 1000 & Ticks between window-tuner calls \\ \texttt{SLOPE\_VALIDATION\_FREQUENCY}& 5000 & Ticks between decay validations \\ \texttt{HEARTBEAT\_THREAD\_ENABLED} & 0 & 1 = background thread \\ \texttt{HEARTBEAT\_THREAD\_INTERVAL\_MS} & 100 & Thread wake interval (ms) \\ \bottomrule \end{tabular} \subsubsection{Code Locations} \begin{itemize} \item \texttt{include/vm.h} --- \texttt{HeartbeatState} struct; \texttt{vm\_tick()} prototype \item \texttt{src/vm.c} --- \texttt{vm\_tick()} dispatcher; execution-path integration \item \texttt{src/physics\_pipelining\_metrics.c} --- \texttt{vm\_tick\_window\_tuner()} \item \texttt{src/physics\_metadata.c} --- \texttt{vm\_tick\_slope\_validator()} \end{itemize}