Polishing the edges: Epic 23
A focused standards-and-I/O round that took antforth to v3.1.0 : named values, port words, honest environment queries, and a banking bug the review refused to let ship.
Polishing the Edges: antforth Epic 23

Phase 4 taught our Z80 Forth to address half a megabyte through one banked window. That was the big, rocky climb. Epic 23 is the opposite: a single, focused epic that sands the edges of the wordset, closes a handful of ANS conformance gaps, and adds the small ergonomic words you reach for every day.
It ships as antforth v3.1.0 — the first minor release since v3.0, and the close of Phase 5.
What landed
Five feature stories:
- Named values (
VALUE/TO). You can now define a mutable named cell and assign to it by name —42 VALUE LIVES, thenLIVES .prints 42, and99 TO LIVESupdates it. This is the standard ergonomic middle ground between aCONSTANT(immutable) and aVARIABLE(you fetch and store through an address). It was the biggest single piece of the epic, because making it bank-aware meant a full resolve/map/unmap trio so aVALUEdefined in any bank reads and writes correctly. - Port I/O (
IN/OUT). Direct Z80 port reads and writes, surfaced as Forth words for talking to hardware. - Honest environment queries (
UD.andENVIRONMENT?rows).UD.prints an unsigned double. More interestingly, the newENVIRONMENT?rows tell the truth: queries for wordsets antforth only partially implements answerfalse("recognised but incomplete") rather than a flatteringtrue. - An assembler operand-order fix. The Z80 assembler's immediate-operand path was corrected to the Zilog destination-source convention. Byte-neutral, but a real correctness fix.
- A banking guard the review caught (
23.6). More on this below.
A bug that never shipped
The most valuable thing Epic 23 produced is a bug that didn't reach silicon.
antforth's code review runs adversarially, in a fresh context. The standing rule is that a review which finds nothing is suspect, not reassuring. On the named-values and port-words stories, that review surfaced a silent correctness defect: a banked colon definition whose body grew past $C000 would have its runtime read through the wrong bank window. No crash, just quietly wrong results, the worst kind of bug.
That finding became its own story (23.6): a window-top overflow guard. Its own review then caught a second one: a 16-bit wraparound in ALLOT. Both would have shipped silently. Neither did.
Why this matters. The temptation in a "polish" epic is to relax the adversary. The work feels low-risk, the reviews feel like ceremony. Epic 23 is the counter-argument: the one story that mattered most for correctness existed only because the review refused to relax.
The byte ledger
Every byte is measured from a clean rebuild and accepted at its story's close. The epic grew the kernel by +563 bytes, and free RAM measured on real hardware (24,954 B) independently corroborates that ledger.
| Story | What | Δ bytes |
|---|---|---|
| 23.1 | Assembler operand-order fix (Zilog dst-src) | 0 |
| 23.2 | VALUE / TO (bank-aware) |
+317 |
| 23.3 | IN / OUT port words |
+19 |
| 23.4 | UD. + honest ENVIRONMENT? rows |
+112 |
| 23.6 | Banked window-top overflow guard | +115 |
| antforth v3.1.0 total | +563 |
The original estimate was ~300 B, so the epic ran about 1.9× over, squarely inside the ~2.4× "cross-bank plumbing always undershoots" multiplier we learned to budget for in Phase 4. The single biggest overrun (VALUE/TO) is exactly where the bank-aware machinery lives. The pattern keeps confirming itself.
Where this leaves antforth
v3.1.0 is a tidier, more conformant Forth than v3.0.7: named mutable values, hardware port access, and environment queries that don't oversell themselves. All of it bank-aware, all of it verified on real hardware.
The big platform shifts (a cooperative multitasker, counting semaphores, full ANS locals) are recorded for a future phase. Epic 23 did quieter, equally necessary work: making the foundation strong before further building on top of it.