Haven

✅ 可玩

havenmud

更新 fdf581a 2026-09-12 源码 下载 ZIP 上游 brainface/havenmud

▶ 开始游玩 · Play Now

A long-running, genuinely large Dead Souls/Nightmare-lineage production game self-titled 'Haven,' set in the world of Kailie -- 13,589 source files (7,328 under domains/ alone), not a near-stock demo like this collection's sibling dshakkard. New characters begin 'in the skies above Kailie,' a staging room where reading a newbie book awards a real quest completion before descending into one of several playable hometowns. Kailie has its own pantheon (the Lord of Balance Duuktsaryth, and the Primal Gods Amelia, Balishae, Syra, Morgoth, Zaxan, and Ahriman), a creation-myth timeline, and its own calendar counting years from Haven's own founding. Playable races span humans, elves, dwarves, half-elves, orcs, half-orcs, sprites, skaven, lamrani, dark-elves, and wild-elves, with goblins, kobolds, gelflings, nosferatu, drughkor, and meuzzin appearing as lore/NPC races. 21 custom domains make up the live world -- averath, baria, crystal_reaches, estergrym, frostmarches, gurov, havenwood, innersea, islands, namatar, peninsula, southern_coast, tairi, valley, westwood, xandria, and yozrath among them -- towns, wilderness, and dungeons built up over years of individual wizards' work, plus a marriage/chapel system, player estates, a crafting subsystem, an in-game newsgroup daemon, and a wizard FTP daemon. 25 personal wizard workrooms sit under realms/ (Duuk, Zaxan, Mahkefel, Alessandra, Laoise, Torak, and others), several holding real in-progress building projects alongside old scratch files. Makes a real outbound Intermud-3 connection on boot.

README

A long-running Dead Souls-based game called Haven, set in the world of Kailie. New characters begin in "the skies above Kailie" -- a staging area where you read the newbie book (Type read book, then go down) before descending into the real world through your chosen hometown.

Source: git clone https://github.com/brainface/havenmud. Slug havenmud, number 947, port 40249.

The world

Kailie has its own pantheon (the Lord of Balance Duuktsaryth and the Primal Gods Amelia, Balishae, Syra, Morgoth, Zaxan, and Ahriman), its own creation-myth timeline, and its own calendar counting years from the opening of Haven for player testing. Playable races include humans, elves, dwarves, half-elves, orcs, half-orcs, sprites, skaven, lamrani, dark-elves, and wild-elves -- with several more (goblins, kobolds, gelflings, nosferatu, drughkor, meuzzin) appearing in the lore and as NPCs.

21 custom domains make up the live world: averath, baria, crystal_reaches, estergrym, frostmarches, gurov, havenwood, innersea, islands, namatar, peninsula, southern_coast, tairi, valley, westwood, xandria, and yozrath, among others -- towns, wilderness, dungeons, and quest lines built up over years. On top of the world content, Haven has a marriage/chapel system, player estates, a crafting subsystem (clothing, at least), an in-game newsgroup daemon, and an FTP daemon for wizards. realms/ holds 25 personal wizard workrooms (Duuk, Zaxan, Mahkefel, Alessandra, Laoise, Torak, and others), several containing real in-progress building projects alongside old scratch files and backups.

Status

Boots clean under this project's native FluffOS driver and plays through the full flow: name -> confirm -> email -> password (with confirmation) -> gender -> real name -> race (list/pick) -> town (list/pick) -> arrival in the newbie staging room -> read book (awards a real quest completion + development points) -> go down into your hometown's real content (verified reaching Haven town's "Above the Elven Charity"). look/score/quit all produce correct output, and reconnecting (name + password) restores the same character in the same room with inventory intact.

See NOTES.md for the full restoration log, including several driver- compatibility bugs found and fixed -- most notably a single off-by-one slice bug in the shared command dispatcher that silently broke every non-verb player command (including score) game-wide.

Live network note: this lib's daemon/intermud preloads and makes a real outbound connection to the public Intermud-3 network on boot (confirmed live, same router this collection's other Dead Souls-family libs connect to) -- don't sweep this lib into high-frequency automated re-boot loops.

WASM status: playable. Shared WASM driver. New-character registration (wasmhav / Mud@2026 / pick human / pick haven) into "In the skies above Kailie", plus look / score ("You are Wasmhav, a level 0 Human.") / quit, verified with scripts/wasm_client.js. FTP/socket_* compile failures are graceful preload skips. Play: https://mudlibs.fluffos.info/havenmud/

NOTES · 移植与修复记录

Haven ("havenmud") -- porting notes

Source: git clone https://github.com/brainface/havenmud (a single- commit snapshot from 2023, cloned 2026-08-28). Repo top level: bin/ (driver-config scaffolding, ignored -- this project uses its own driver), ansible/, scripts/, smb.conf, Vagrantfile, and lib/ (the real mudlib root, confirmed via bin/haven.cfg's master file : /secure/daemon/master and mudlib directory : /home/haven/haven/lib). secure/daemon/master.c's header credits "Descartes of Borg 940910" and other file headers cite "Nightmare IVr2"/"Nightmare IVr3" and "Dead Souls" lineages by name -- this is the same MudOS/FluffOS- compatible Dead Souls/Nightmare family already represented in this collection by ds386, dsI/dsII/dsIII, dshakkard, and deadsouls_fluffos. Slug havenmud, number 947, port 40249.

Unlike dshakkard (a closed-alpha game with almost no bespoke content beyond three domains) or the various near-stock Dead Souls ports, this is a large, long-lived production game: 13,589 .c files (7,328 under domains/ alone), 21 custom domains, 25 personal wizard realms under realms/, and its own pantheon/history/calendar (doc/help/players/timeline). Unlike dshakkard, this repo commits its own secure/ tree in full -- no engine-layer gap to fill from a sibling.

1. Conversion

scripts/convert_lib.sh against raw/havenmud (16,347 files copied from the repo's own lib/): the content is already almost entirely ASCII/UTF-8 (16,272 of 16,347 files needed no conversion at all; 7 clean re-conversions, 7 lossy, 61 skipped binaries), matching the imud-class precedent for an English-language source rather than the usual GBK/GB18030 corpus. 13,589 files renamed .c->.lpc, 1,188 literal .c"-reference fixups, 37 local angle-bracket includes converted to quotes, 12,234 files touched by the static->nosave sweep. Removed two genuine non-content binaries the conversion pass correctly left alone: a stray macOS .DS_Store (std/mine/) and a 999,992-byte stale secure/tmp/swap.mud.5000 runtime swap file that had been accidentally committed to the original repo.

A tree-wide Python UTF-8 decode scan (per AGENTS.md section 4.1, run against the WHOLE work/ tree, not just .lpc/.h) found the remaining 47 non-UTF-8-decodable files were all genuine binaries (a .bmp, the .DS_Store/swap file above, and ~40 real Microsoft Word .doc design documents under realms/zalbar/oldfiles/projects/ prison_tunnels/ -- a builder's abandoned project notes, left as-is, same "someone's late-night work" class this project preserves rather than discards).

2. Missing runtime scaffolding

This repo's .gitignore excludes the usual set of runtime-written directories that were never committed: /lib/log, /lib/tmp, /lib/secure/save, /lib/ftp, /lib/news, /lib/worlds, /lib/bak, and several named /lib/save/<category> subdirectories (boxes, estates, kills, phouses, pshops, shops, vehicles). All were recreated with the standard placeholder-file convention (foo.txt in otherwise-empty dirs so git tracks the directory shape), following the ds386/dshakkard precedent:

Unlike dshakkard's identical-shaped gap, this repo's own secure/tmp/ was already present and correct (just holding one stale swap file, removed per section 1 above) -- only the top-level runtime trees needed rebuilding.

3. Driver-compat fixes

3.1 secure/daemon/master.lpc -- missing PACKAGE_UIDS applies (AGENTS.md section 7.2)

No get_root_uid()/get_bb_uid()/creator_file() anywhere in this codebase (confirmed zero geteuid()/uid() call sites -- permissions are enforced entirely by the mudlib's own group/wizlist ACL, not the driver's uid system). Added the standard minimal stubs (all objects attributed to "root"), identical in shape to every other lib in this lineage that needed this fix.

3.2 secure/daemon/master.lpc:load_access() -- a local variable named ref collides with this driver's ref keyword

private nosave void load_access(string cfg, mapping ref) {
  ...
  ref[fl] = explode(ac, ":");
}

ref is a genuine lexer keyword on this driver (L_REF, used for pass-by-reference call arguments) -- using it as a plain identifier compiles the parameter declaration fine but hard-errors ("syntax error, unexpected '['") the moment it's used as an lvalue later in the same function, since the driver expects the ref-specific grammar production there instead. This is the FIRST file loaded at boot (load_access() runs from create(), called for read/write/groups ACLs), so it was a hard boot blocker. Renamed the parameter to acc; LPC mappings are reference types already, so nothing about the by-reference-mutation behavior changed.

3.3 lib/rooms/room.lpc -- MudOS-era replace_program() fold (AGENTS.md section 7.141)

The exact same fold documented across this whole lineage (ds386/dsI/dsII/dsIII/dshakkard): create() tried to fold a bare-inherit room's program into its shared parent to save memory, but this driver defers replace_program()'s effect to a periodic backend sweep rather than applying it synchronously -- so any closure built on a freshly-loaded room (this file's own eventHearTalk() TALK_LOCAL filter, reached by ordinary say/ask/tell) would crash for the first several minutes after every boot. Removed the fold entirely, leaving SetNoReplace()/GetNoReplace() in place as harmless unused API, exactly as fixed on every sibling.

3.4 OLD_ED vs. the split editor API (AGENTS.md section 6.2)

lib/users/editor.lpc, lib/users/nmsh.lpc, and secure/cmds/ creators/lsed.lpc all called ed_start()/ed_cmd()/query_ed_mode(), which don't exist under this driver's __OLD_ED__ build (only the single-entry ed() efun exists). Since editor.lpc sits in the player body's inheritance chain, this compile failure would have taken the whole player body down with it. Fixed identically to the established pattern: editor.lpc rewritten against ed(file, exit_fn, restricted); nmsh.lpc's dead custom-prompt branch (already unreachable once an ed session is open, since the driver's own comm.cc intercepts input directly) collapsed to if(0){...}; lsed.lpc's core batch-editing function replaced with a "use ed interactively instead" message, since there's no synchronous scriptable-ed entry point under OLD_ED at all.

3.5 Bare array as a type specifier -- hard parse error, not silent mis-declaration

AGENTS.md section 6.3 describes bare array x; as typically compiling without error but failing to actually declare anything. On this specific driver build it's worse: array used as a type specifier (variable, parameter, or return type) is a hard syntax error (unexpected L_IDENTIFIER), including in a cast position ((string array)expr). 13 files/19 sites fixed (-> mixed */ mixed): lib/npcs/equipper.lpc, lib/livings/race.lpc, lib/users/ history.lpc, daemon/currency.lpc, domains/havenwood/areas/ parvahosp/obj/viallimb_f.lpc (3 sites), domains/westwood/areas/ hiker/obj/fruit.lpc, secure/daemon/newsgroup.lpc (2 sites, including secure/daemon/include/newsgroup.h's matching forward declaration -- newsgroup is preloaded, so this alone blocked one boot-critical daemon), realms/melchezidek/currency.lpc, realms/melchezidek/ armours.lpc, realms/melchezidek/projects/starfire/npc/starfire.lpc (3 sites), realms/melchezidek/projects/starfire/room/room08.lpc (2 sites), cmds/players/armours.lpc.

3.6 The old-MudOS TYPE array NAME two-word dialect (AGENTS.md section 6.3)

356 files / 853 sites, fixed with a masked-text (string/comment-aware) Python regex pass covering every shape this lineage's siblings already documented (simple decl, decl-with-init, multi-name comma lists, function parameters, return types, cast expressions). Verified safe before running corpus-wide: dry-run diffed against hand-picked samples (a function whose OWN return type and OWN parameter were both in the old dialect on one line -- string array SetRestrictLimbs(string array limbs) -- correctly became string *SetRestrictLimbs(string *limbs)) and, after fixing a real bug in the first draft (naive in-place list splicing shifted every later match's offset once an earlier variable-length replacement changed the string's length -- rewritten to build the output left-to-right from a sorted, non-overlapping match list instead), a paren-balance diff between every touched file's raw source and its fixed work/ copy confirmed zero sites where the fixer introduced or removed an unmatched (/) across all 356 files.

3.7 daemon/command.lpc's GetCommand() -- the exact [0..<3] bug already found on ds386, and its wider sibling class

cmd = file[0..<3] while scanning get_dir(path+"/*.lpc") keeps len-2 characters -- correct for stripping the OLD .c MudOS extension (2 characters) but wrong for .lpc (4 characters), turning "score.lpc" into "score.l". Since this daemon is how every non-add_action() player/creator command resolves (cmds/players/*.lpc, cmds/creators/*.lpc, etc.), this broke every single command dispatched through it -- confirmed live: a fresh character's first score command silently fell through to the generic "unrecognized command" fallback with no error message at all, while movement (add_action()-based, a different dispatch path entirely) worked fine. This is the exact same bug, in the exact same file, already found and fixed on ds386 (AGENTS.md/ds386 NOTES.md: "broke the stock score command on every login... the single highest- impact instance of the whole class").

Given the hit, swept the whole corpus for ds386's documented sibling variants of this same "hardcoded old 2-char .c suffix length, should be 4 for .lpc" class and found it recurs far more widely here than on ds386 -- 24 more sites across 20 files:

Three superficially-similar [0..<3]/[<2..] sites were confirmed NOT part of this bug class and left untouched: lib/users/ history.lpc:113 (stripping a literal "/g" 2-char path fragment, unrelated to .lpc), secure/lib/net/ftp.lpc:441 (stripping a trailing "/.", unrelated), and secure/daemon/newsgroup.lpc:76 (genuinely stripping the 2-character .o save-file extension, which IS correctly 2 characters).

3.8 lib/users/player.lpc:SetUndead() -- bare-string calls into a string *-typed API

RemoveAdditionalId(GetUndeadType())/SetAdditionalId(GetUndeadType()) passed a bare string where both functions declare string *. This is the player body class itself -- every single character in the game inherits it -- so this alone hard-blocked all character loading (master.lpc's player_object() reported *No program in object '/lib/users/player'! the moment any registration or login tried to instantiate a new character). Fixed by wrapping both calls in a single-element array (({ GetUndeadType() })), matching the established convention already used correctly at dozens of other call sites in this same codebase.

3.9 SetLong()/SetShort() narrowed to string where the real implementation already accepts mixed (the Dead Souls "SetLong/SetExternalDesc/SetInternalDesc widened to mixed" class, AGENTS.md, already fixed on ds386/dsIII/dshakkard)

lib/common/look.lpc's GetExternalDesc() already handles a function pointer or a ({day, night}) array in ExternalDesc, but its own setters (SetExternalDesc(string desc), SetLong(string str)) were narrowly typed to string only -- widened both to mixed. This was the single largest shared-root-cause cluster in the compile sweep (std/obj/screen.lpc's SetLong((: eventView :)) alone cascaded into 77 reported failures across every object that inherits it). A second, narrower instance: lib/npcs/npc_interactive.lpc's pass-through SetShort(string str)/SetLong(string str) wrappers (used by every NPC) re-narrowed the already-widened base API -- widened to mixed too, fixing domains/valley/towns/jidoor/npc/sentry.lpc's SetShort((: CheckSetShort :)) and two similar NPCs.

3.10 lib/rooms/chapel.lpc -- TYPE * a, b, c; comma-list star-binding bug (AGENTS.md section 6.3)

private string *Classes, Deities, DeityIds;

The * binds to the first declarator only on this driver; Deities/ DeityIds are used as string * everywhere in the file (assigned array literals, indexed with member_array()), so both needed their own *. This file is inherited wherever a marriage/chapel room exists across the world, so the single missing * cascaded into dozens of reported compile failures.

3.11 Author-level content bugs found via the compile sweep (fixed as unambiguous, evidence-backed type/argument-shape corrections, not invented content)

4. Known pre-existing gaps (left undone -- content/archive design, not driver-compat)

5. Live verification

Booted clean under ~/src/fluffos/build-debug/src/driver (Accepting telnet connections on 0.0.0.0:40249., Initializations complete., zero fatal errors, ~290 MB RSS steady-state).

Confirmed a real outbound network connection at boot, same class already documented for ds386/dsIII/dshakkard: daemon/intermud (preloaded) connects to the public Intermud-3 router -- ss -tnp showed ESTABLISHED ... 97.107.133.86:8787 from the driver process, the exact same IMC2/I3 endpoint this lineage's other libs connect to. Do not sweep this lib into high-frequency automated re-boot loops.

Full registration -> world -> reconnect -> quit flow tested with a raw Python socket client (this project's standard admin identity wasn't set up for this lib -- see caveat below):

1. New player registration (Testchartwo, ASCII name -- this archive enforces a strict A-Z a-z name-charset with no digits, confirmed live: Testchar2 was rejected as "not valid or is banished" while Testchartwo was accepted): name -> confirm (y/n) -> email (required, validated non-blank) -> password (6-char minimum) -> confirm password -> gender (male/female) -> real name (blank -> defaults sensibly) -> race (list showed all 11 playable races; pick human) -> hometown (list showed 4 towns; pick haven) -> landed in "In the skies above Kailie", the newbie staging room, correctly wearing starter clothes (threadbare pants/ shirt/socks). 2. The newbie gate: the staging room's down exit is gated behind read book (completing the "Newbie Book" quest, which correctly awarded a real 160 development points and a quest/title credit live). Also confirmed the exit command itself is go down, not bare down (this codebase's core movement dispatch, unlike its cmds/-daemon-based commands, requires the go verb). 3. Reached real custom domain content: go down landed the character in "Above the Elven Charity" in Haven town (domains/southern_coast/towns/haven/) -- a fully-described, bespoke room (sleeping cots, a ticking clock, its own atmosphere text), not a stock/generic placeholder. 4. look/score/quit all produced correct output post-login; score in particular exercises a great deal of the player body class (level, alignment, native town/citizenship, faith, quest/ title counts, in-game birth date and age, development points, wimpy percentage, hunger/thirst/intoxication/temperature status, combat ratings, heart rate, active fears) and came back fully correct and consistent across two separate test characters. 5. Reconnect (name + password, no NetDead state from a live session): restored the SAME character in the SAME room ("Above the Elven Charity") with inventory intact and stats preserved (quest/title/development-point state correctly carried over from the prior session's read book) -- confirmed this is a genuinely distinct code path from fresh registration, not just a re-run of the same logic.

Caveat: this lib has no first-boot admin-install wizard (unlike the ds386-lineage Dead Souls forks) -- it's a live production game whose wizard hierarchy is populated by manual angel/decre promotion commands from an EXISTING admin account, and no such account exists in this fresh checkout. Admin/wizard-level testing (the fluffos/Mud@2026 identity this project normally seeds) was not attempted this session; only ordinary player registration and play were verified. A future session wanting wizard access would need to either hand-edit a save file's group membership or add a bootstrap path -- left undone here as out of scope for the native-boot verification bar.

6. Compile sweep

(ulimit -v 8388608; bash scripts/lpcc_check.sh libs/havenmud/ config.fluffos libs/havenmud/work) -- run under the 8 GB virtual-memory cap per this session's standing caution for large-corpus libs (a prior similarly-sized lib's unguarded batch compile grew to ~15 GB RSS before being killed); this lib's own batch run stayed under ~4 GB RSS throughout, well inside the cap. Iterated four times across this session as fixes landed:

| pass | pass | fail | notes | |------|------|------|-------| | 1 | 9,024 | 4,565 | before any fixes beyond the proactive checklist | | 2 | 9,268 | 4,321 | after the SetReligions/SetId(animate_*)/eventAttack reorder fixes | | 3 | 9,343 | 4,246 | after chapel.lpc/screen.lpc/SetId+SetFriends sweeps, GetInvis/SetPick/SetNoCorpse/VS_SHUTTLE/wound_hamstring | | 4 | 9,344 | 4,245 | after player.lpc, command.lpc, and the full [0..<3] sibling sweep (section 3.7-3.8) |

The remaining failures are overwhelmingly the section 4 classes above (the orphaned std/tower/ bolt-on alone accounts for ~70 files; personal-realm staging/backup copies and unfinished builder templates account for most of the rest) rather than driver-compat gaps -- the live playthrough in section 5 reached real, unrelated domain content with zero runtime errors, which is the stronger signal for this lib's actual playability than the raw batch-compile percentage (see this project's own documented lpcc-batch-vs-live-boot divergence class: a battery of daemon/-preloaded objects can report a bare "Fail to load object" with no visible error text at the point they're reached in a giant batch run, purely as a batch-mode artifact, while compiling and loading perfectly fine standalone or in a real boot -- confirmed directly on this lib for domains/valley/towns/jidoor/npc/ parcil.lpc and domains/crystal_reaches/towns/gwonish/npc/ sneak_trainer.lpc, both of which failed in-batch with no error text at all but compiled clean standalone -- and parcil in particular is a real NPC in the real Haven-adjacent town content, not orphaned or backup content, further confirming this is a batch-tooling ceiling on a 13,589-file lib rather than a real per-file defect).

7. §10.7 deep functional test (2026-08-31)

Round-two pass on the native driver (~/src/fluffos/build-debug/src/ driver, port 40249), building on top of the onboarding playthrough in section 5. Driven via scripts/tmux_mud.sh persistent telnet sessions (three sequential/parallel test characters: Deeptestor, Combattest, Finaltest), plus a ~210s idle long-sit boot watch (python3 scripts/mudclient.py --idle 210 --timeout 215) per AGENTS.md §10.0. One native driver reboot mid-session to pick up the two live fixes below; per section 5's own caution (daemon/intermud's real outbound I3 connection), reboots were kept to the minimum needed.

Two real bugs found and fixed, verified live

1. AGENTS.md §7.191 (new) -- daemon/help.lpc's LoadIndices() crashed on the very first help <topic> command any player ever ran, then stayed silently, permanently degraded for the rest of that boot. tmp = get_dir(DIR_ROOM_VERBS + "/*.lpc") + get_dir(...) + ... + get_dir(DIR_CRAFTING_VERBS + "/*.lpc") + ... -- /verbs/ crafting genuinely never existed in this archive (confirmed absent in raw/ too, not a conversion artifact), and get_dir() on a missing directory returns the driver's own bare integer 0 rather than an empty array, so array + int threw Bad type argument to +. Had array and int. uncaught. Live impact: a fresh character's help vendors (the exact topic that surfaced this) printed only "A runtime error occurred, use \"bug -r\" to report it." Because the crash happened PARTWAY THROUGH a create()-time one-shot function, every category meant to be assigned after that line (verbs, combat actions, immortal commands, player documents, immortal documents, towns, classes, races, religions, lore, library objects) was simply never populated for the rest of the boot -- confirmed by help human (a race) and help sword combat (a verb) both incorrectly returning "Help for the topic ... could not be found", and help index showing only 3 categories (commands, skill documents, stat documents) instead of the real 11. Fixed with a GD(string path) wrapper (mixed r = get_dir(path); return arrayp(r) ? r : ({});) substituted into every get_dir() call feeding a +-concatenation in LoadIndices() -- the correct guarded pattern was already sitting a few lines below in the SAME function for a different set of categories. Verified live twice: before the fix, help vendors/help human/help index all failed exactly as above on a fresh boot's first help invocation; after the fix and a clean reboot, the SAME fresh-boot-first-help sequence returned the real doc/help/players/vendors documentation text (confirmed by its own worked example, "Kelan"/"steel boots"), help human returned the real race blurb, and help index showed all 11 real categories. 2. **domains/averath/towns/averath/npc/chartercaptain.lpc -- SetFirstCommands("board ferry") passed a bare string where the real signature takes string *, so this NPC never compiled at all.** Same self-evident-typo class already catalogued in section 3.11 above (SetReligions/SetId/SetFriends bare-string calls). Impact: domains/averath/towns/averath/room/charter.lpc's SetInventory() tries to new() this NPC to run Averath's ticket-purchase travel feature ("buy a charter to anywhere you've been") -- with the NPC uncompilable, every attempt logs *No program in object '/domains/averath/towns/averath/npc/ chartercaptain'! to log/catch, and the whole charter-travel feature is permanently unusable. This also fires repeatedly and noisily during ordinary play: the stock ferry's own wander/sail logic (lib/npcs/shipcaptain.lpc) passes near/through the charter room while sailing the Haven<->Averath route, so the caught error logs on a recurring basis even for players who never try to charter anything. Fixed by wrapping the argument (({ "board ferry" })). Verified: lpcc standalone-compiles chartercaptain.lpc with zero errors after the fix (zero occurrences of the pre-fix Bad type for argument 1 of SetFirstCommands in a fresh log/errors/averath compile pass), versus the error present before -- not independently re-confirmed via a live charter purchase this session (the charter feature itself needs real travel-history state this session's time budget didn't reach), but the compile-blocking bug itself, which is the actual defect, is conclusively fixed.

Confirmed working live

Minor anomaly observed, not root-caused (flagged, not fixed)

Sibling bug-class check (per AGENTS.md §10.7 item 7)

Checked both catalogued Dead-Souls/Nightmare-lineage sibling findings this session was specifically asked to cross-reference:

Unverified / out of scope for this pass

WASM measurement (2026-09-03)

meta.json was already playable from the 2026-08-31 deploy-unblock; the README had no WASM line. Cold-boot under the shared ~/src/fluffos/build-wasm succeeded with no mudlib-side compile fix (FTP/socket_* failures in secure/lib/net/ are graceful preload skips). Verified with scripts/wasm_client.js: new character wasmhav / confirm / email / Mud@2026 / male / real name / pick human / pick haven. Landed in "In the skies above Kailie" (newbie book visible, down exit), score showed "You are Wasmhav, a level 0 Human" / "Citizen of Haven", quit printed "Please come back another time!" / "Wasmhav logs out." Shop/combat/death were not exercised this pass. The MEMFS copy does not write the throwaway character back to the host. Do not loop-reboot (I3).