Log fleet_k_q48/fleet_conserved; K holds exactly, 775/775 ticks (FABRIC-3.md §XVIII)
doe_log.c's per-heartbeat-tick CSV gains two columns: fleet_k_q48 (vm_physics_fleet_heat_sum() over ALL live VMs -- the genuine fleet-wide conservation invariant K, not reconstructable from the 3 named-Tripod- member heat columns already logged, which omit every identity VM's own heat) and fleet_conserved (vm_physics_conserved() as 0/1). Requested explicitly after the first heartbeat-telemetry analysis pass (analysis-20260912/) omitted K entirely. Kernel rebuilt on all three architectures, full 3x9x3 campaign rerun (results-20260912-with-k/). K = 1.0000000000 (Q48.16 raw 65536) on every one of 775 heartbeat-tick observations, sd(K) = 0, 100% fleet_conserved, across amd64/aarch64/riscv64, nine identities, three replicates -- zero deviation. Also a free regression check on both recent Stadium fixes (§XVI/§XVII): neither disturbed the reservoir-transfer accounting K depends on. Found and fixed a tooling wrinkle along the way: fleet_conserved, being the CSV row's very last field with nothing after it to bound a regex match, can have a resumed trial digit merge into it with zero separator on the wire -- combine.py now derives it from fleet_k_q48 directly (same epsilon vm_physics_conserved() uses) instead of trusting the raw field. fleet_k_q48 itself is unaffected either way. Full analysis, discussion, and light/dark SVG->PDF figures written up as a proper LaTeX report (report-20260912/report/std79_doe_report.pdf), following experiments/bare_metal/analysis/report/bare_metal_doe_report.tex's established style -- supersedes analysis-20260912/'s markdown-only first pass as the primary deliverable for this dataset (kept, not discarded). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EXieurDfDSsDFdnSyusuWo
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
6573a6d1d5
commit
66ba21adb4
@@ -10,7 +10,7 @@
|
||||
/**
|
||||
* doe_log.c — DoE CSV logger for the LithosAnanke kernel
|
||||
*
|
||||
* Emits 18-column CSV rows to the serial log once per heartbeat tick.
|
||||
* Emits 20-column CSV rows to the serial log once per heartbeat tick.
|
||||
* Each row is prefixed with a cyan [HADES][DOE ] tag so it can be
|
||||
* extracted cleanly:
|
||||
*
|
||||
@@ -35,6 +35,17 @@
|
||||
* 16. hera_heat_q48 uint64 — VM fleet physics: Hera's execution_heat_q48
|
||||
* 17. hermes_heat_q48 uint64 — VM fleet physics: Hermes's execution_heat_q48
|
||||
* 18. artemis_heat_q48 uint64 — VM fleet physics: Artemis's execution_heat_q48
|
||||
* 19. fleet_k_q48 uint64 — "K": vm_physics_fleet_heat_sum() over ALL live
|
||||
* VMs (not just the 3 named Tripod members above --
|
||||
* this is the genuine conservation invariant, which
|
||||
* should read Q48_ONE (65536) whenever conservation
|
||||
* holds). Requested 2026-09-12 alongside the 3x9
|
||||
* factorial analysis in experiments/std79-doe/ --
|
||||
* columns 16-18 alone cannot reconstruct this since
|
||||
* they omit every identity VM's own heat.
|
||||
* 20. fleet_conserved uint32 — vm_physics_conserved() as 0/1: whether
|
||||
* |fleet_k_q48 - Q48_ONE| < VM_PHYSICS_EPSILON_Q48
|
||||
* at the moment this row was captured.
|
||||
*
|
||||
* Note: avg_word_heat and estimated_jitter_ns are stored as double in the
|
||||
* snapshot but the freestanding snprintf has no %%f support. avg_word_heat
|
||||
@@ -71,7 +82,8 @@ static const char *doe_header =
|
||||
"hot_word_count,avg_word_heat_q48,"
|
||||
"window_width,actual_window_size,predicted_label_hits,jitter_bits,"
|
||||
"apic_ticks,time_trust_q48,variance_q48,vm_call_depth_max,"
|
||||
"hera_heat_q48,hermes_heat_q48,artemis_heat_q48";
|
||||
"hera_heat_q48,hermes_heat_q48,artemis_heat_q48,"
|
||||
"fleet_k_q48,fleet_conserved";
|
||||
|
||||
/* Looks up a Tripod VM's fleet heat by name; 0 if not currently registered
|
||||
* (e.g. between KILL and rebirth). */
|
||||
@@ -110,7 +122,7 @@ void doe_log_tick_row(VM *vm, const HeartbeatTickSnapshot *snap)
|
||||
jitter_bits.d = snap->estimated_jitter_ns;
|
||||
uint64_t jitter_raw = jitter_bits.u;
|
||||
|
||||
/* Format the 18-column CSV row into a local buffer.
|
||||
/* Format the 20-column CSV row into a local buffer.
|
||||
* Use %llu (unsigned long long) for all uint64_t fields — %lu is unreliable
|
||||
* for values > 2^32 on aarch64 due to mixed-width varargs ABI behaviour. */
|
||||
unsigned vm_call_depth_max = (vm && vm->call_stack_max > 0) ? (unsigned)vm->call_stack_max : 0;
|
||||
@@ -118,10 +130,12 @@ void doe_log_tick_row(VM *vm, const HeartbeatTickSnapshot *snap)
|
||||
uint64_t hera_heat_q48 = doe_log_heat_by_name("Hera");
|
||||
uint64_t hermes_heat_q48 = doe_log_heat_by_name("Hermes");
|
||||
uint64_t artemis_heat_q48 = doe_log_heat_by_name("Artemis");
|
||||
uint64_t fleet_k_q48 = vm_physics_fleet_heat_sum();
|
||||
unsigned fleet_conserved = vm_physics_conserved() ? 1u : 0u;
|
||||
|
||||
char buf[DOE_BUF_SIZE];
|
||||
snprintf(buf, sizeof(buf),
|
||||
"%u,%llu,%llu,%u,%u,%u,%llu,%llu,%u,%u,%u,%llu,%llu,%llu,%llu,%u,%llu,%llu,%llu",
|
||||
"%u,%llu,%llu,%u,%u,%u,%llu,%llu,%u,%u,%u,%llu,%llu,%llu,%llu,%u,%llu,%llu,%llu,%llu,%u",
|
||||
snap->tick_number,
|
||||
(unsigned long long)snap->elapsed_ns,
|
||||
(unsigned long long)snap->tick_interval_ns,
|
||||
@@ -140,7 +154,9 @@ void doe_log_tick_row(VM *vm, const HeartbeatTickSnapshot *snap)
|
||||
vm_call_depth_max,
|
||||
(unsigned long long)hera_heat_q48,
|
||||
(unsigned long long)hermes_heat_q48,
|
||||
(unsigned long long)artemis_heat_q48);
|
||||
(unsigned long long)artemis_heat_q48,
|
||||
(unsigned long long)fleet_k_q48,
|
||||
fleet_conserved);
|
||||
|
||||
console_puts(DOE_PREFIX);
|
||||
console_puts(buf);
|
||||
|
||||
Reference in New Issue
Block a user