Files
Robert Allan JamesandClaude Sonnet 5 3e0966095c Stadium: real VM-patron admission + real COOL dispatch at KILL (FABRIC-3.md §B)
capsule_vm_kill() had zero Stadium involvement (vm_cleanup()/sf_free()
only), and child-VM birth only ever called stadium_grant_quota() -- a
resource pool for the VM's own future word/block patrons, never
stadium_admit() for the VM itself. stadium_birth_hera() looked like a
precedent but admits Hera into her own quota as a permanently pinned
cell 0, which can never reach stadium_evict() -- not a working example
of COOL firing for a VM.

Adds size_t stadium_patron_cell to VMRegistryEntry. At birth, right
after the existing stadium_grant_quota() call, admits a candidate into
the new VM's own quota mirroring stadium_birth_hera()'s shape
(identity=0, mass=1, behaviour=COOL) but deliberately unpinned --
pinning would need a new "unpin" primitive (none exists) to ever evict
it later, and unpinned costs nothing since nothing wires COOL's
dispatch body to kill anything; the worst case of an unrelated natural
eviction is stale bookkeeping, tolerated the same way
stadium_word_forget() already tolerates staleness elsewhere. At
capsule_vm_kill() and capsule_vm_kill_all_nonmama(): stadium_evict()
the tracked cell if still resident, silently tolerating refusal
(already gone). stadium_dispatch()'s COOL case needed no new payload
body -- same as it already is for words, where COOL has no defined
extra action beyond stadium_evict()'s own universal reservoir credit.

On investigation this turned out not to be entangled with the
still-iterating Tripod/Zuse/messaging vision after all -- birth and
kill already funnel through two single choke points, so the earlier
deferral (previous commit) was overcautious.

Verified live: a second, new "Stadium: dispatch cell=... behaviour=
COOL" now fires immediately before every PARITY:KILL line, for both
Hermes and Artemis, distinct from the pre-existing COMMON-CH
word-eviction self-test's own COOL print. Conservation
(resident_sum + reservoir == Q48_ONE) intact throughout. Clean
zero-warning compile and clean boot on all three architectures.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXjAPTEKrgY2Mrk25KoLDn
2026-08-26 02:53:56 -04:00

233 lines
7.6 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
StarForth — Steady-State Virtual Machine Runtime
Copyright (c) 20232025 Robert A. James
All rights reserved.
This file is part of the StarForth project.
Licensed under the StarForth License, Version 1.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
https://github.com/star.4th@proton.me/StarForth/LICENSE.txt
This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND,
express or implied, including but not limited to the warranties of
merchantability, fitness for a particular purpose, and noninfringement.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* capsule_run.h - DoE Run Logging (M7.1)
*
* Structures for logging capsule execution runs and VM births.
* Supports provenance tracking and experiment reproducibility.
*/
#ifndef STARKERNEL_CAPSULE_RUN_H
#define STARKERNEL_CAPSULE_RUN_H
#include <stddef.h>
#include <stdint.h>
#include "starkernel/vm_uuid.h" /* VMUuid -- FABRIC.md item 3.8 */
#ifdef __cplusplus
extern "C" {
#endif
/*===========================================================================
* Run Log Configuration
*===========================================================================*/
/** Phase A: Fixed ring buffer size */
#define CAPSULE_MAX_RUN_RECORDS 1024
/*===========================================================================
* Result Codes
*===========================================================================*/
typedef enum {
CAPSULE_RUN_OK = 0,
CAPSULE_RUN_ERR_INVALID, /* Invalid capsule */
CAPSULE_RUN_ERR_NOT_ELIGIBLE, /* Capsule not eligible for operation */
CAPSULE_RUN_ERR_EXEC_FAIL, /* Execution failed */
CAPSULE_RUN_ERR_HASH_MISMATCH, /* Post-run hash mismatch */
CAPSULE_RUN_ERR_STILLBORN, /* VM birth failed */
CAPSULE_RUN_ERR_FLEET_FULL, /* Outer Stadium at stadium_max_vm_count() (FABRIC.md item 1.5/2.2) */
} CapsuleRunResult;
/*===========================================================================
* CapsuleRunRecord - DoE Execution Log Entry
*===========================================================================*/
typedef struct {
uint64_t run_id; /* Sequential run identifier */
VMUuid vm_id; /* Which VM executed this (item 3.8) */
uint32_t reserved; /* Padding */
uint64_t capsule_id; /* Which capsule was run */
uint64_t capsule_hash; /* Hash at time of execution */
uint64_t pre_dict_hash; /* Dictionary state before run */
uint64_t post_dict_hash; /* Dictionary state after run */
uint64_t started_ns; /* Monotonic start time */
uint64_t ended_ns; /* Monotonic end time */
uint32_t result_code; /* CapsuleRunResult */
uint32_t flags; /* Run flags (mode, etc.) */
} CapsuleRunRecord;
/*===========================================================================
* VM Registry Entry
*===========================================================================*/
/** Maximum length of a VM symbolic name, including null terminator */
#define VM_NAME_MAX 64
typedef enum {
VM_STATE_EMBRYO = 0, /* Allocated but not yet born */
VM_STATE_LIVE, /* Successfully born, operational */
VM_STATE_STOPPED, /* Suspended — execution state saved */
VM_STATE_STILLBORN, /* Birth failed */
VM_STATE_DEAD, /* Terminated */
} VMState;
typedef struct {
VMUuid vm_id; /* Assigned at birth, immutable (item 3.8) */
uint32_t state; /* VMState */
uint64_t birth_capsule_id; /* Which capsule birthed this VM */
uint64_t birth_timestamp_ns; /* When VM was born */
uint64_t birth_dict_hash; /* Dictionary hash after birth */
uint32_t flags; /* VM flags */
VMUuid parent_vm_id; /* Who birthed this VM. Set once at birth,
* never rewritten. Hera's own entry is
* self-referential (parent_vm_id == vm_id
* == vm_uuid_hera(), all-zero) -- the
* sentinel a heat-fanout walk up the
* parent chain stops at. */
void *vm_ptr; /* Pointer to live VM object; NULL when dead */
char name[VM_NAME_MAX]; /* Symbolic name, e.g. "Hera", "Hermes" */
size_t stadium_patron_cell; /* FABRIC-3.md SS B, VM-COOL: this VM's own
* Stadium cell index (STADIUM_CELL_NONE,
* i.e. (size_t)-1, if never admitted or
* already reaped) -- admitted into the VM's
* own quota at birth, explicitly evicted at
* KILL. Not Hera's; she is pinned and never
* reaches this field's purpose. */
} VMRegistryEntry;
/*===========================================================================
* Run Log Functions
*===========================================================================*/
/**
* capsule_run_log_init - Initialize run log
*/
void capsule_run_log_init(void);
/**
* capsule_run_log_record - Log a run record
*
* @param record Record to log
* @return Run ID assigned, or 0 on failure
*/
uint64_t capsule_run_log_record(const CapsuleRunRecord *record);
/**
* capsule_run_log_get - Get a run record by ID
*
* @param run_id Run ID to retrieve
* @param out Output record
* @return 0 on success, -1 if not found
*/
int capsule_run_log_get(uint64_t run_id, CapsuleRunRecord *out);
/**
* capsule_run_log_count - Get number of logged runs
*/
uint32_t capsule_run_log_count(void);
/*===========================================================================
* Parity Logging
*===========================================================================*/
/**
* capsule_parity_log_birth - Log VM birth parity record
*
* Output format:
* PARITY:BIRTH vm_id=N capsule_id=X mode=p capsule_hash=H dict_hash=D
*/
void capsule_parity_log_birth(
VMUuid vm_id,
uint64_t capsule_id,
uint64_t capsule_hash,
uint64_t dict_hash
);
/**
* capsule_parity_log_birth_failed - Log failed birth
*
* Output format:
* PARITY:BIRTH_FAILED vm_id=N capsule_id=X error=E partial_dict_hash=H
*/
void capsule_parity_log_birth_failed(
VMUuid vm_id,
uint64_t capsule_id,
CapsuleRunResult error,
uint64_t partial_dict_hash
);
/**
* capsule_parity_log_run - Log DoE run parity record
*
* Output format:
* PARITY:RUN vm_id=N run_id=R capsule_id=X mode=e pre_dict=P post_dict=Q
*/
void capsule_parity_log_run(
VMUuid vm_id,
uint64_t run_id,
uint64_t capsule_id,
uint64_t pre_dict_hash,
uint64_t post_dict_hash
);
/**
* capsule_parity_log_mama_init - Log Mama init parity record
*
* Output format:
* PARITY:MAMA_INIT capsule_id=X mode=m capsule_hash=H dict_hash=D
*/
void capsule_parity_log_mama_init(
uint64_t capsule_id,
uint64_t capsule_hash,
uint64_t dict_hash
);
/**
* capsule_parity_log_kill - Log VM kill parity record
*
* Output format:
* PARITY:KILL vm_id=N name=X
*/
void capsule_parity_log_kill(
VMUuid vm_id,
const char *name
);
/**
* capsule_parity_set_output - Set output hooks for parity logging
*
* @param putc_fn Function to output a single character
* @param puts_fn Function to output a string
*/
void capsule_parity_set_output(
void (*putc_fn)(char),
void (*puts_fn)(const char *)
);
#ifdef __cplusplus
}
#endif
#endif /* STARKERNEL_CAPSULE_RUN_H */