proof/FINDINGS.md's Isabelle/HOL word-source sweep (§1) found the two
defects severe enough to actively corrupt the live Tripod multi-VM fleet:
file-scope C statics standing in for state that belongs on struct VM.
- vocabulary_words.c (highest severity in the sweep): forth_vocab/
context_vocab/current_vocab, context_var_addr/current_var_addr, the
ctx_fc/forth_fc first-char search index, and the `initialized` guard
were all process-wide statics. Only the first VM to touch any
vocabulary word ever ran setup; every VM after that silently shared
VM #1's dictionary-chain pointers and reused VM #1's byte-offset
addresses as if valid in its own vm->memory. One VM's VOCABULARY/
DEFINITIONS/FORTH silently changed where every other VM looked up and
defined words.
- control_words.c: cf_stack/cf_sp/cf_last_mode (IF/THEN/BEGIN/DO/CASE
compile-time nesting) and the LEAVE/ENDOF patch-site bookkeeping
(leave_addrs/leave_sp/leave_mark_*, endof_addrs/endof_sp/endof_mark_*)
were also process-wide statics. Two VMs compiling colon definitions at
overlapping times would corrupt each other's nesting state.
Both moved onto struct VM, following the existing hold_addr/hold_pos
precedent in include/vm.h ("lives in each VM's own memory... so child
VMs never alias Hera's buffer"):
- New VocabularyState struct (vm->vocab): chain heads, VM-cell addresses,
first-char index, initialized flag.
- New ControlFlowState struct (vm->cf): cf_stack/cf_sp/cf_last_mode plus
the LEAVE/ENDOF patch-site stacks. cf_tag_t/cf_item_t/CF_STACK_MAX
moved from control_words.c into include/vm.h since they're now part of
the struct VM field's type.
- Sentinel fields (-1/-999, meaning "empty") explicitly initialized in
both vm_init_with_host() implementations (hosted src/vm_bootstrap.c and
kernel src/starkernel/vm/vm_bootstrap.c) alongside the existing
dsp/rsp = -1 initialization, since the preceding zero-init leaves them
at 0 rather than their empty sentinel.
Every word function in both files already took VM *vm, so no call sites
outside these two files needed to change; cf_push_item/cf_pop_item/
cf_peek_item gained a VM* parameter to reach vm->cf.
Verified: hosted (amd64) and kernel (amd64, __STARKERNEL__) both build
clean with -Wall -Werror after a full clean rebuild (struct VM's layout
changed size, and this Makefile has no header-dependency tracking, so a
stale incremental build would have linked mismatched object layouts).
Hosted POST suite 1012/1012 passing (0 regressions). Manually exercised
VOCABULARY/DEFINITIONS/FORTH/ORDER, and IF/ELSE, DO/LOOP/LEAVE,
BEGIN/WHILE/REPEAT, and CASE/OF/ENDOF/ENDCASE (including nested DO with
I/J) in the REPL -- all correct and unchanged from pre-refactor behavior.
Note: a pre-existing CASE/ENDCASE default-clause bug (the code after the
last OF...ENDOF pair does not correctly become the "default" value once
DROP runs) was found while testing this refactor and confirmed present
on unmodified master too -- not touched here, out of scope for this pass.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Qf6YcnHgaEtEygq3knx19
Maintainability sweep (prompted by "this is getting hard to maintain"):
fixed the remaining three warning classes after the missing-field-
initializers commit -- 2x -Wsign-compare (control_words.c, cast at the
comparison site rather than changing cf_last_mode's type, which
deliberately holds a -999 sentinel outside vm_mode_t's valid range),
2x -Wstringop-truncation (mkcapsule.c, strncpy+manual-null-terminate
replaced with the idiomatic snprintf equivalent), and 26x
-Wunused-parameter (mostly documented stubs, silenced with the repo's
existing (void)param; idiom).
One of the unused-parameter warnings was not a deliberate stub -- a
real bug. restore_vm_state() (test_common.c) is named, documented, and
called by nine real call sites (acl_words_test.c x8 plus its own
internal use) as "restore saved VM state", but ignored all four of its
parameters and hard-reset to a fixed baseline instead, silently not
restoring what any caller actually saved. Fixed to actually assign the
passed-in dsp/rsp/error/mode. Found while fixing warnings, reported
before touching it, fixed/tested/documented/committed on explicit
instruction.
Verified: all three architectures build with zero C-compiler warnings
(amd64: 3040 -> 0; aarch64's one remaining note is lld-link's own
unrelated linker warning, not a C warning). Full amd64 acceptance boot
post-fix: POST 1003/965/0/0/38 (total/passed/failed/errors/stubs),
"ALL IMPLEMENTED TESTS PASSED!", contract checks (A4'/A1) all passed,
dict_hash=0x24b4279f0670aa3a -- an exact match to this document's own
previously-recorded baseline hash.
.claude/CLAUDE.md corrected to describe the real -Wno-error= exemption
list instead of the "-Wall -Werror" oversimplification. FABRIC-2.md
Section J records the full sweep, including doc-tree staleness findings
flagged but not fixed this pass (docs/lithosananke/ROADMAP.md branch
topology, docs/03-architecture/word-acl/DESIGN.md's Phase 7 claim
contradicting CLAUDE.md, top-level ROADMAP.md's stale StarForth-era
status, the Isabelle pipeline-metrics model mismatch).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>