Loads turtle.4th and doe.4th, defines SDK-VERSION/SDK-HELP into an SDK vocabulary, then calls FENCE once everything is loaded -- protecting the base wordset and both cookbook capsules from FORGET. Kernel-only (EXEC doesn't exist hosted), REPL-invoked via S" sdk.4th" EXEC, not part of init.4th's boot sequence. Verified before writing the capsule, not assumed: VOCABULARY/DEFINITIONS does not actually scope word visibility in this interpreter -- vm_find_word is a flat dictionary scan that never consults CONTEXT/CURRENT. Documented plainly in the HOWTO so this isn't mistaken for namespace isolation later. Block range 5109-5115 -- discovered along the way that user-block space is capped at [2048, 5120) by mkcapsule, tighter than expected. Verified: mkcapsule --lint clean, hosted-build trace runs SDK-HELP with zero attributable VM errors, zero build warnings and identical 1012/0/0 POST results with matching dict_hash on all three kernel architectures. HOWTO: docs/working/architecture/SDK-HOWTO-20260819.md Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
5.0 KiB
SDK HOWTO — capsules/sdk.4th
Status: WORKING. Part of the v1.9.0 scoping work (FABRIC-2.md section K).
Loads the two cookbook capsules (turtle graphics, DoE library) and adds an
SDK vocabulary entry point plus FENCE protection on top of them.
Loading it
Kernel-only (it loads other capsules via EXEC, which does not exist in
the hosted build), REPL-invoked — not part of init.4th's boot sequence,
matching turtle.4th's own choice:
S" sdk.4th" EXEC
This loads turtle.4th and doe.4th, defines an SDK vocabulary with two
introspection words (SDK-VERSION, SDK-HELP), then calls FENCE to
protect everything loaded so far — the base wordset, both cookbook
capsules, and sdk.4th's own words — from FORGET. Prints a one-line
confirmation and hint on load; run SDK-HELP for the full word list.
What VOCABULARY actually does here — read before assuming isolation
sdk.4th defines its own words (SDK-VERSION, SDK-HELP) into a named
SDK vocabulary via SDK DEFINITIONS. This is organizational, not
isolating: this VM's primary word lookup (vm_find_word, used by the
ordinary interpreter loop) is a flat, first-character-bucketed scan of the
whole dictionary — it does not consult CONTEXT/CURRENT at all. Verified
directly before writing this file: a word defined while CURRENT targeted
a custom vocabulary remained globally callable immediately after switching
back to FORTH DEFINITIONS, exactly as if no vocabulary had been involved.
The VOCABULARY/DEFINITIONS/CONTEXT/ORDER/(FIND) machinery is real,
standard FORTH-79, and useful for anything that explicitly walks vocabulary
chains ((FIND), ORDER) — it just isn't what makes SDK words reachable
day to day. Don't build anything on the assumption that loading a second
vocabulary hides or scopes its words from the rest of the system.
FENCE — and the bug it surfaced
FENCE ( -- ) is new (this scoping pass) — it raises the dictionary's
FORGET boundary to whatever is currently the newest word, so anything
defined afterward can be safely FORGETten without reaching back into
protected territory. sdk.4th calls it once, at the very end of loading.
Building a direct test for FENCE surfaced a real, severe, pre-existing
bug in FORGET itself — completely independent of FENCE, reproducible
with the original boot-time fence alone. Forgetting the single newest
word wrongly destroyed every other word back to the fence too; forgetting
an older word (which correctly cascades to remove newer words, per
FORTH-79 semantics) crashed with a SIGSEGV — a use-after-free in the
dictionary relink logic. Found and fixed as part of this work; full
root-cause writeup in FABRIC-2.md section K. Three POST cases were added to
dictionary_manipulation_words_test.c (Module 14) alongside FORGET's
own, including the exact regression scenario, so it can't silently return.
Vocabulary
| Word | Effect |
|---|---|
SDK-VERSION |
Prints the release tag (SDK v1.9.0 (scoping)). |
SDK-HELP |
Prints the full word list for both cookbook capsules, with HOWTO pointers. |
FENCE |
(Not SDK-specific — a base word, used by this capsule.) Raises the FORGET boundary to the current dictionary top. |
Everything from turtle.4th and doe.4th is also available after loading
— see their own HOWTOs (TURTLE-GRAPHICS-HOWTO-20260819.md,
DOE-LIBRARY-HOWTO-20260819.md) for their vocabularies.
Verification performed
mkcapsule --lint capsules/clean (block range5109–5115, clear ofturtle.4th's5100–5108).- Hosted-build logic trace:
fabric.4th's core blocks +turtle.4th+doe.4th+sdk.4th's own blocks (with its twoEXEClines stripped, sinceEXECdoesn't exist hosted — the capsules they'd load were concatenated directly instead) piped into the hosted binary.SDK-HELPruns and prints correctly; zero VM errors from any of this content (all errors present in the log are the built-in POST suite's own deliberate error-injection cases, confirmed by cross-checking against the same baseline used for the cookbook capsules' own verification). - Built cleanly (zero warnings) and baked into the capsule set on all
three kernel architectures (amd64/aarch64/riscv64); boot verified clean
through POST on all three,
1012 passed / 0 failed / 0 errorsidentically,dict_hashunchanged from the pre-sdk.4thbaseline on all three (expected —sdk.4thisn't autoloaded, so it cannot affect boot-time dictionary content). - Not yet driven interactively through a live REPL — same practical
limitation as
turtle.4th's own HOWTO documents (the DoE campaign that auto-runs on every kernel boot blocks the REPL for ~25–30 minutes before serial commands can reach it). The FORTH logic is verified; the interactive load-and-run experience is not.