feat(log): LOG-FLUSH -- a VM's log records reach Artemis's log ring; and the ring keeps its order when it grows

FABRIC-3 SXXXII.4's deferred LOG-FLUSH, built to the 2026-10-14 rulings
(SXXXVIII): everything a VM logs, at or above the log level, goes into its
own buffer; it goes to Artemis on LOG-FLUSH, when full, and at once on an
ERROR, as one kernel-Hermes LOG_BATCH message she writes on her own turn,
the source being the sender the kernel stamped.  Records that cannot go yet
are counted and reported with the next flush.  LOG-SHOW (Hera only) reads
the ring back -- it had no reader.

Found by the first test that filled it: ring growth overwrote the oldest
record and put blank slots inside the live range.  Fixed test first.

Three ISAs: POST 1052 passed; new parity baseline word_count=526
hash=0x82f4ae7cb2e2d424 (deliberate).  CLAUDE.md: Phase 8 PKI closed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-14 12:10:01 -04:00
co-authored by Claude Opus 5.5
parent 5e26fad30d
commit 4da370f492
35 changed files with 91102 additions and 15 deletions
+46
View File
@@ -49,6 +49,7 @@
#include "starkernel/capsule_mint.h"
#include "starkernel/user_identity_seed.h"
#include "starkernel/vm_identity.h"
#include "starkernel/log_region.h" /* LOG-SHOW */
#include "starkernel/capsule_loader.h"
#include "starkernel/capsule_run.h"
#include "starkernel/capsule_loader.h"
@@ -1379,6 +1380,49 @@ static void mama_word_name_to_xt(VM *vm)
vm_push(vm, (cell_t)(uintptr_t)e);
}
/**
* @brief LOG-SHOW ( n -- )
* Prints the newest n records of Artemis's log ring, oldest of them first:
* source, level, text (2026-10-14, FABRIC-3.md SXXXVIII). Hera's only --
* it shows every VM's records, and Hera's console is Zuse's.
*/
static void mama_word_log_show(VM *vm)
{
static const char *names[] = { "ERROR", "WARN ", "INFO ", "TEST ", "DEBUG" };
static log_slot_t slot; /* 1 KiB: static, not on the stack */
static char text[LOG_SLOT_MSG_MAX + 1];
cell_t n;
int32_t back;
if (vm->dsp < 0) {
console_println("LOG-SHOW: expects a count -- nothing on the stack");
vm->error = 1;
return;
}
n = vm_pop(vm);
if (n > 128) n = 128;
for (back = (int32_t)n - 1; back >= 0; back--) {
int rc = log_region_read_recent((uint32_t)back, &slot);
uint32_t len;
char src[LOG_SLOT_SOURCE_MAX + 1];
if (rc < 0) {
console_println("LOG-SHOW: no log ring -- Artemis's disk not attached");
return;
}
if (rc > 0) continue; /* fewer records than asked for */
len = slot.msg_len < LOG_SLOT_MSG_MAX ? slot.msg_len : LOG_SLOT_MSG_MAX;
memcpy(text, slot.msg, len);
text[len] = '\0';
memcpy(src, slot.source, LOG_SLOT_SOURCE_MAX);
src[LOG_SLOT_SOURCE_MAX] = '\0';
console_puts(src);
console_puts(" ");
console_puts(names[slot.level <= 4 ? slot.level : 0]);
console_puts(" ");
console_println(text);
}
}
/**
* @brief RUNCAP-TEST ( caddr u -- ok? rc )
* Diagnostic-only word (FABRIC-2.md §F.6/§F.18): calls
@@ -2275,6 +2319,7 @@ void register_mama_forth_words(VM *vm)
register_word(vm, "WORKER-BIRTH", mama_word_worker_birth);
register_word(vm, "UNATTENDED-BIRTH", mama_word_unattended_birth);
register_word(vm, "CONSOLE-ATTACH", mama_word_console_attach);
register_word(vm, "LOG-SHOW", mama_word_log_show);
register_word(vm, "NAME>XT", mama_word_name_to_xt);
register_word(vm, "RUNCAP-TEST", mama_word_runcap_test);
register_word(vm, "PAIR-TEST", mama_word_pair_test);
@@ -2337,6 +2382,7 @@ void register_mama_forth_words(VM *vm)
register_word(vm, "WORKER-BIRTH", mama_word_worker_birth);
register_word(vm, "UNATTENDED-BIRTH", mama_word_unattended_birth);
register_word(vm, "CONSOLE-ATTACH", mama_word_console_attach);
register_word(vm, "LOG-SHOW", mama_word_log_show);
register_word(vm, "NAME>XT", mama_word_name_to_xt);
register_word(vm, "RUNCAP-TEST", mama_word_runcap_test);
register_word(vm, "PAIR-TEST", mama_word_pair_test);