FENCE ( -- ) exposes the dict_fence_latest/dict_fence_here state FORGET
already honored internally, letting callers (e.g. a future SDK capsule)
raise the boundary after loading their own content -- no new VM fields,
no policy logic beyond exposing existing state.
Writing a direct test for it surfaced a real, severe, pre-existing bug in
FORGET's relink logic, unrelated to FENCE itself and reproducible with the
original boot-time fence alone:
- Forgetting the single newest word incorrectly destroyed every other word
back to the fence too, not just the target.
- Forgetting an older word (correctly cascading to remove newer words too,
per FORTH-79 semantics) crashed with SIGSEGV.
Root cause: the relink code's target_prev pointer was, by construction,
always inside the range the preceding loop had just freed whenever target
wasn't vm->latest -- so writing through it was a use-after-free every time
that branch executed. Fixed by removing the target_prev tracking and both
branches entirely; vm->latest unconditionally becomes target_next (target's
own captured, still-valid link) after the free loop, correct in every case.
Added a FENCE test suite to dictionary_manipulation_words_test.c (Module 14)
including the exact regression case (forgetting the newest word must not
disturb an older one). Verified zero warnings and identical POST/dict_hash
results across all three kernel architectures.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
TestCase gained a trailing `contract` field (WordContract) at some point
after all 20 test-module files' compound literals were written -- every
single TestCase/WordTestSuite initializer in the tree (sentinels, real
entries, and per-suite entries) omitted it, producing ~3010 warnings on
every build. CLAUDE.md's own documentation claimed this was isolated to
one file (vocabulary_words_test.c); a full audit found it systemic
across all 20 files.
Fixed mechanically: added the missing `{0}` trailing initializer
everywhere. Semantically a no-op -- C99 already zero-fills unlisted
trailing struct fields, so this only silences the diagnostic, changes
no behavior. Verified: all three architectures (amd64/aarch64/riscv64)
build clean, remaining warning count unchanged (30, matching the other
three known -Wno-error-exempted classes: unused-parameter, sign-compare,
plus mkcapsule.c's stringop-truncation which was never actually gated
by this policy -- it's a separate host tool with no -Werror at all).
.claude/CLAUDE.md corrected to describe the actual -Wno-error= exemption
list (four classes, not "build with -Wall -Werror" unconditionally) and
the real current warning inventory.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>