Immortal Companions' Bond (Early Test Build)

✅ 可玩

仙侣情缘(早期测试版)

xlqy_early

🔑 fluffos / Mud@2026 更新 5782147 2026-09-02 源码 下载 ZIP

▶ 开始游玩 · Play Now

仙侣情缘(早期测试版)是一部以《西游记》取经旅程为背景的仙侣题材 MUD,讲述人与妖、仙与凡之间跨界的门派恩怨与情缘故事;内容尚不完整,但核心的登录、探索、战斗流程都能正常运作,而且这一快照独有其它姊妹版本都没有的特色——开服后 100 个自动游走的"人造人"NPC 会在几分钟内把地图上的房间逐一触发编译一遍;经逐字节比对确认,本档案与"新仙侣情缘之飘渺纪元"(xlqy_new2007)、"浙大版"(xlqyzdb)其实是同一位作者笔下同一个世界观的三个开发快照,公共路径下 84%-86% 的文件完全相同,关系远比"共享引擎"这种说法暗示的要紧密;据存档自带说明文件记载,这是作者当年用来测试驱动兼容性的半成品,是三者中最粗糙的一版,而本站另收录的 2001 年"知秋"存档(xianlvqiyuan)虽是更远的同源近亲,文件层面的重合度却只有约 10%。

English

A Journey-to-the-West-flavored immortal/mortal romance MUD: the world is built around the pilgrimage to the West, with sect rivalries and love stories crossing the boundary between human, demon, and immortal. Content is incomplete, but the core login/explore/combat loop works, and this snapshot has one feature not found in its own siblings: 100 auto-walking "artificial person" NPCs that wander the map and compile every room within minutes of the server booting. A byte-level file comparison confirms this is genuinely the same authored game world as "New Immortal Companions' Bond: Age of Mist" (xlqy_new2007) and the "Zhejiang University edition" (xlqyzdb) — 84-86% of common-path files are identical across all three, making this a much closer three-way family than a shared-engine label alone would suggest. Per the archive's own included notes, this was originally the author's half-finished build for testing driver compatibility, the roughest of the three snapshots. A more distant relative in this collection, the 2001 "Zhiqiu" snapshot (xianlvqiyuan), shares the same setting and engine lineage but only about 10% file-level overlap.

README

内容亮点

在线试玩

https://mudlibs.fluffos.info/xlqy_early/

管理员账号 / Admin account

警告:这是一个公开的默认密码,仅供本地/浏览器试玩。正式对外开服前
请务必修改此密码。

本地运行

cd libs/xlqy_early
~/src/fluffos/build-debug/src/driver config.fluffos

游戏端口:40076

NOTES · 移植与修复记录

xlqy_early — 仙侣情缘 (early/incomplete "driver test" snapshot)

Archive: xlqy-解压看readme.rar (archive #27). Port: 40076. Status: done (boots clean, full registration flow verified end-to-end multiple times incl. real Chinese names, score/look/quit all confirmed working post-login).

What this is / lineage confirmation vs xlqy_new2007 (#26)

Extracts cleanly (no password/special step needed despite the xlqy-解压看 readme.rar "unzip and read the readme" filename) to a root xlqy/ directory. readme.txt's own text (translated): *"start with startxlqy64.bat... this lib is very incomplete, mainly used to test the driver... you can open the rzr channel, it's mostly rzr [artificial NPCs] running around... configure the number of rzr in /adm/daemons/manmade_npcd's max_npcs... the underlying engine has been heavily rewritten, many things are incompatible, no tech support provided."* — an unpolished, pre-#26 snapshot of the same "仙侣情缘" codebase, explicitly shipped for driver-compatibility testing rather than play.

Lineage confirmed via diff, not assumed from the shared title (this project's own repeated lesson: similar Chinese titles are not a reliable lineage signal — see xianlvqiyuan vs xlqy_new2007, sjpl2 vs shujian2008):

Net conclusion: same base engine/authorship (bugbug & alading @ 缥缈水云间, 2003-4-5 credited in nearly every file header), an earlier development snapshot with a rougher/smaller logind.lpc/chinesed.lpc, NOT a duplicate archive. xlqy_new2007's proven master.lpc/chinese.lpc fixes ported directly and worked unchanged; logind.lpc's check_legal_name needed its own independent §15h fix since that file's content differs.

Fixes applied

1. AGENTS.md §15h (chinese.lpc): is_chinese()'s GBK lead-byte range check (str[0] > 160 && str[0] < 255, strlen(str) >= 2) replaced with a CJK Unicode codepoint range check (str[0] >= 0x4e00 && str[0] <= 0x9fff, strlen(str) >= 1). Ported the same shape already proven on xlqy_new2007. 2. AGENTS.md §15h (logind.lpc check_legal_name): byte-calibrated bound strlen(name) < 2 || > 12< 1 || > 6 (message already says "必须是一到六个中文字" — 1 to 6 Chinese characters — halving the byte bound just makes the code match what the message already promised); dropped the i%2==0 && GBK-lead-byte-alternation gate from the sliding-window loop so every character position is checked, not every other one. 3. AGENTS.md §14 (valid_override): upgraded from the 2-arg (file, name) signature to the documented 3-arg (file, name, main_file) form, checking main_file == SIMUL_EFUN_OB/MASTER_OB too — free insurance for #include-composed simul_efun fragments (confirmed this specific gap causes an lpcc-sweep-only failure on adm/simul_efun/object.lpc, see lpcc section below; never actually surfaces on a real boot). 4. AGENTS.md §8d/§15o (get_include_path()): added to master.lpc (was entirely absent) — prepends the compiling file's own directory to the include search path so #include "local.h"-next-to-its-user resolves for compiles triggered live mid-connection (this lineage has several such local headers: d/city/workroom.h, d/obj/misc/ message.h, d/obj/quest/quest.h, d/*/npc/reporting.h, d/city/misc/banned.h). 5. AGENTS.md §15w (log_error): gated the player-facing broadcast on the message NOT containing "warning:" (this driver funnels every compile *warning* — e.g. the harmless nosave-function warnings that staticnosave renaming produces — through the same apply as real fatal errors; without the gate, any lazily-compiled file with a cosmetic warning would flash the scary default-error message at whichever player happened to be online). 6. AGENTS.md §8h (convertd.lpc Greek-table typo): one instance, line 258, "α\","α", (plain LF file, verified with cat -A before choosing the non-CRLF sed pattern per the documented lesson). 7. niu.lpc disallowed ..-relative include (§15t #2): d/ourhome/honglou/npc/niu.lpc had #include "../honglou.h" — this driver disallows .. in #include paths outright. Fixed to the real absolute quoted path "/d/ourhome/honglou/honglou.h". 8. eventd.lpc fixed-width extension-strip bug (AGENTS.md §2's [0..<3][0..<5] nitan-family-shaped variant, found independently here in a non-nitan-lineage lib): collect_all_event()'s map_array(get_dir(EVENT_DIR+"*.lpc"), (: $1[0..<3] :)) was correct for stripping the original 2-char .c extension but left a stray trailing .l after the .c.lpc rename ("emei.lpc"[0..<3]"emei.l", not "emei") — every event failed to resolve (call_other() couldn't find object '.../emei.l', one per preload, non-fatal since wrapped in the daemon's own catch()). Widened to [0..<5] per the established +2 formula. 9. d/city/workroom.h broken __FILE__ usage (new finding, not yet in AGENTS.md): this header is #included (not inherited) into 3 sibling rooms (workroom1/2/3.lpc), and used __FILE__ inside a start_busy() closure intending "the room that's actually running this code" — but __FILE__ is a preprocessor macro that expands to whatever file is textually being *scanned* at that point, which for a #included fragment is always the header's own path (/d/city/workroom.h, never a loadable object on its own), not whichever of the 3 rooms actually included it. This produced ~130+ call_other() couldn't find object '/d/city/workroom.h' runtime errors per test session (the highest-volume error category by far, generated continuously by autonomous NPCs' "work for money" AI behavior in these rooms). Fixed by replacing both __FILE__ uses with file_name(this_object()) (resolves correctly at runtime regardless of which of the 3 rooms is actually executing). Worth adding to AGENTS.md as a new catalog entry — this is a generic trap for any lib with a #included (not inherited) fragment that uses __FILE__ expecting "the including object," since standard C-style preprocessor semantics (this driver's __FILE__ genuinely matches plain C here, confirmed by reading lexer_rules_pp.cc) never behaved that way. 10. daemon/skill/dao/taijitu.lpc — AGENTS.md §15aa-shaped same-file forward-reference bug (new instance, different mechanism than §15aa's original "same name as a real efun" trap): cast_person() (defined early in the file) calls remove_effect_using(me, target) before the file's OWN 2-arg (object me, object target) override of that name is defined later in the file. Because the base class std/sserver.lpc (reached via inherit FAMILYSKILL) already defines an INHERITED remove_effect_using(object me, string file), the compiler bound the early call to that inherited (wrong-arity) version instead — error: Bad type for argument 2 of remove_effect_using ( string vs object ). A first attempt at a fix (changing the call site to pass __FILE__ instead of target, matching every sibling skill file's convention) compiled but was WRONG: it silently changed behavior to call the generic inherited cleanup instead of this file's own invisibility-removal/room-restoration logic. Corrected fix: moved the actual function body (not just a prototype — a bare forward *declaration* alone was insufficient here, still bound to the wrong inherited version) to appear before cast_person()'s first call to it. Confirmed clean via lpcc before and after. This skill is only reachable via actual "太极图" (taijitu) spell casting in combat, not the registration/boot path, but was a real semantic bug worth fixing correctly rather than papering over. 11. adm/daemons/cndd.lpc — THREE separate undeclared-variable/ forward-reference bugs in the condition-tracking daemon, found via the lpcc sweep, all pre-existing in the raw archive (confirmed by grepping the raw .c file directly — none of these declarations were ever present, not something our conversion dropped): - clear_condition(object me, string cnd) used a bare conditions mapping throughout with NO declaration/fetch at all. Every sibling function in the same file (query_entire_conditions() right above it) fetches the equivalent value via me->query_temp("conditions") — added the same fetch as a local declaration at the top of the function (unambiguous fix, not a guess, matching an existing sibling idiom in the same file). - clear_conditions_by_type(string required_type) had the identical conditions-undeclared bug, but this function takes NO me parameter (unlike clear_condition) — fixed via this_object()->query_temp("conditions") instead. - A SEPARATE, parallel hb_conditions mapping (heartbeat-scoped condition store, used by update_hb_condition()/ apply_hb_condition()/query_hb_condition()/ clear_hb_condition()) was used identically across all four functions with no declaration anywhere in the file at all (not even a query_temp fetch — this one is genuinely meant to be a persistent per-object global, since it needs to survive across calls with no explicit save-back). Added nosave mapping hb_conditions; as a real file-level global, resolving all four call sites at once. - Bonus: clear_condition() calls clear_hb_condition() (defined much later in the same file) before that definition appears — "Undefined function clear_hb_condition" (AGENTS.md §8b's classic "same-file forward reference" shape). Fixed with a one-line forward declaration near the top of the file (this one DID work as a bare declaration — unlike the taijitu.lpc case above, since there's no competing inherited function of the same name to shadow it). - Verified compiles clean via lpcc after all four fixes. 12. Uppercase .C rename (AGENTS.md's "watch for uppercase .C" check): 3 files missed by convert_lib.sh's lowercase-only glob (d/obj/drug/YUNDAN.C, d/guzhanchang/obj/{DIAMOND,BAG}.C) — manually renamed to .lpc; all three were already UTF-8 (not GBK), so no additional encoding pass was needed. Confirmed no dangling .c/ .C-suffixed string references to these three basenames anywhere else in the lib (only stale .bak/timestamp-suffixed backup copies reference the related zone, none of them live .lpc code). 13. Created missing save-data directories (not present anywhere in the raw archive — data/ shipped completely empty): data/{login, user,npc,fabao,gold,pet}/{a..z}/ — this driver's save_object() (vm/internal/base/object.cc) does a plain fopen() with no mkdir, so saving to a nonexistent sharded directory throws an uncaught error() ("Could not open ... for a save"). Since enter_world()'s user->save(); ob->save(); calls have no catch() around them, this would have silently killed every new registration right after gender selection (the same failure shape as AGENTS.md §15ah, just for save_object() rather than log_file()). Also created log/nosave/ (referenced by master.lpc's crash handler and several log_file("nosave/...") calls, same §15ah pattern, lower-impact since only reachable on an actual crash).

Confirmed NOT needed (checked via source reading, not assumption)

>= 0 checks in logind.lpc` are already written correctly.

Interactive test results — full registration + post-login commands

Registration shape (read from logind.lpc's actual callback chain, not inferred from prompt text): GB/BIG5 selection → "are you a student" age-gate (any non-"no" ends the session) → English id prompt (new must be typed literally) → English id → no y/n confirmation step → Chinese name prompt → password → password confirmation → email → gender (m/f) → an always-instant, non-interactive "gift allocation" step (the d/wiz/ init.lpc room's own input_to("get_input", ...) line is commented out in the source, so get_start() calls do_finish() synchronously via a call_out(0) right when the player enters — no real stat customization ever happens, matching the archive's own "not fully finished" nature) → drops the new character into an actual starting room (聚见亭, chosen at random from several candidates per d/wiz/init.lpc's own logic).

Verified successfully in FOUR independent full continuous sessions, each incl. a real Chinese name reaching the actual game world and at least one post-login command producing correct output:

One recurring, understood-and-benign cosmetic quirk: get_name() in logind.lpc has a leftover debug statement, printf("%O\n", ob);, printed right after a Chinese name is accepted — shows the raw login object reference (e.g. /obj/login#16) to the player. Pre-existing in the original source (not something this pass introduced), purely cosmetic, does not block anything. A second cosmetic-only artifact seen once: sending an early command (9/look) in the split-second window between entering d/wiz/init and its call_out(0)-triggered do_finish() firing can get silently swallowed by d/wiz/init.lpc's own add_action("do_block", "", 1) catch-all (which only allows look/ help/story/say while in that room) and shows the driver's generic default fail message ("什么?") once — harmless, and the very next line in every affected transcript is the correct room entry/gift completion; not a registration or command-dispatch defect.

Known characteristic, not a bug: heavy CPU load from autonomous "rzr" NPC roaming

This archive ships with adm/daemons/manmade_npcd.lpc's max_npcs = 100 — per the readme's own description, up to 100 autonomous "rzr" (人造人/ artificial-human) NPCs wander the ~9,177-file map continuously from boot, lazily compiling every room/NPC/item file they touch for the first time. Observed: driver CPU climbed from ~7-20% right after boot to a sustained 75-85% within a few minutes and stayed there for the ~12+ minutes this pass kept the driver running, visible in debug.log as a continuous stream of "In file included from ..." compile-cascade lines across every zone in the map. This is a genuine, intentional feature of this particular "for driver testing" snapshot (explicitly what the readme describes), not a conversion defect — no crash, no fatal error, the driver stayed fully responsive to new connections throughout (confirmed: a fresh registration completed correctly even while this was happening, just with higher latency on some responses since this driver's game-tick processing is single-threaded and a heavy background lazy-compile pass competes for the same thread). Two of the six test connections in this pass hit this slowdown directly (the qinbao/qinchuan/qinhuai runs issued in the middle of this pass, while the storm was in full swing, never actually completed within their allotted test-script timeout budgets — confirmed via the absence of a corresponding data/user// data/login/ save file for those three ids, i.e. these were test-harness timeouts, not silent registration failures). Not fixed/tuned down since it's original game-balance content, not a driver-compat defect; flagging here so a future session isn't surprised by it.

lpcc sweep

9177 files, 9070 pass / 107 fail (98.8%) (libs/xlqy_early/ lpcc_batch_raw.log / lpcc_fail.log, both left in place per the established per-lib convention). Triaged by category rather than fixing all 107 blind, per AGENTS.md §6b:

Suggested new AGENTS.md catalog entries (not added — instructed not to edit AGENTS.md directly)

2026-07-23: driver rebuild retest + LPC formatter + WASM check

WASM-enablement pass (loopback-allow / gate bypass / admin seed)

Standard WASM-first pass per AGENTS.md §1.3b/e and §1.5. Gates patched:

- logon() reconnect-flood throttle (last_ip==ip && time+5>time, ~line 79) — now !is_loopback_conn(ob) && ..., loopback exempt. - logon() "too many from this IP" cap (logon_cnt > 10, ~line 98) — loopback exempt. - encoding() !ip_name destruct + the dotted-quad char-loop format validator (~lines 163-173) — whole block now guarded by if (!is_loopback_conn(ob)) { ... }, so loopback/garbage-IP connections skip both. This was the WASM-fatal gate (query_ip_name/number return garbage under WASM). - No uptime() < N startup-grace *destruct* gate exists in this lib; the uptime() use at ~line 132 is the newid registration-throttle window (game content) — left intact.

Admin account seeded: id fluffos, pw Mud@2026, name 浮浮, granted (admin) by adding fluffos (admin) to adm/etc/wizlist. Verified via real registration flow (gb/no/new/fluffos/浮浮/Mud@2026/.../m → entered world) then relogin + update /adm/daemons/logind → "成功" and status line shows (admin). Retest: fresh normal registration still works, zero new debug.log errors. Save file: work/data/user/f/fluffos.o (tracked, NOT gitignored — no force-add needed).

Fail-closed retrofit for the loopback-allow gate (2026-07-24)

The loopback helper above was originally written matching the project-wide convention at patch time (AGENTS.md §1.3b), which also treated an empty/non-string/malformed query_ip_number() result as loopback, defensively, because the WASM driver used to return garbage there. That underlying driver bug is now fixed (fluffos commits e33bb5da "fix: query_ip_number() returned uninitialized garbage under WASM" and 007bb863 "feat: synthetic resolve() on WASM instead of raising an LPC error", both 2026-07-23; the locally-built build-debug/build-wasm binaries already postdate both commits), so treating unparseable IPs as trusted is a fail-open gap with no remaining justification. Retrofitted to fail-closed: loopback is now strictly ip == "127.0.0.1" || ip == "::1" || ip[0..3] == "127." (with a stringp() guard before the slice) — a malformed/empty IP now falls through to the NORMAL gate instead of being treated as local. Retested after tightening: fresh driver boot clean, fluffos loopback login and its wizard update command both still work; zero new debug.log errors.

深度功能测试 / Deep functional test (2026-08-06/07)

第一次完整游玩测试(原生驱动 build,ASAN/UBSAN debug 构建)。测试角 色 id xlqytstb,中文名 小仙女。本轮 WASM 未重新验证:emsdk 工具链 下载硬编码指向 storage.googleapis.com,本次会话的出口代理策略性拒 绝该域名(403,已用 curl $HTTPS_PROXY/__agentproxy/status 确认是策 略拒绝而非临时故障),本地无法构建 WASM 驱动。

发现并修复:maximum evaluation cost 过低,开机预载阶段真实崩溃过一次(AGENTS.md §7.90 新实例)

发现并修复:注册流程遗留的 printf("%O", ob) 调试输出(AGENTS.md §7.34 已知模式的又一实例)

adm/daemons/logind.lpc 中文名确认成功分支有一行未加注释的 printf("%O\n", ob);,同一文件里没有找到第二条并行路径的重复实例。 按 §7.34 既定修法直接删除。修复前用第一个测试账号亲眼看到裸露的对象 路径(如 /obj/login#N)夹在提示语之间;修复后第二次注册未再出现。 §9 格式化自检通过。

发现并修复:中文名确认提示里的 GAME_NAME 宏字面量泄漏(新发现的模式,未见于此前任何一份档案的记录)

测试内容与结果

WASM 修复摘要(迁移自 meta.json 的 group_note)

同一套代码库,更早的一份粗糙快照。

§7.86 跨库扫描修复(留言板 post 崩溃)

§7.100 sweep (2026-08-19)

Fixed the corpus-wide inherit ROOM; ... replace_program(ROOM); redundant-replace bug (AGENTS.md §7.100). 332 live occurrences deleted: 331 via scripted sweep (fix_710_room.py), plus 1 hand-fixed roommaker-tool template (obj/roommaker.lpc, simple string-builder variant, same shape as sibling xlqy_new2007). 10 already-commented-out instances left untouched. No real .lpc source found under work/data/. Verified via build-debug driver boot: clean compile, port 40076 listening, zero new "cannot replace"/"cannot bind" debug.log lines.

§7.30 uninitialized-mapping accessor sweep (2026-08-20)

Corpus-wide mechanical sweep of the feature/skill.lpc shared-lineage bug (confirmed independently on xiakexing2017/jqxz2015/haiyang2 via round-four testing): 3 accessor(s) in this file returned a raw never-initialized mapping instance variable (defaults to int 0, not ([]), until first assigned), crashing any unguarded keys()/sizeof()/indexing caller for a fresh/untrained character. Fixed at the accessor level (mapp(x) ? x : ([])) per the documented remedy. Verified via lpcc --batch static compile check only (not a live boot) as part of a large mechanical sweep; not individually functionally re-tested live on this lib.

Round-four follow-up: combat / shop / sect apprenticeship (2026-08-24)

Closed the three gaps flagged as "未覆盖" above. Walking exploration from the starting room again turned up nothing (the only exits are north into a short dead-end path, and out into a fogged teleport) — reachable hostile NPCs, a working shop, and the three real sect masters all live in completely separate map regions (/d/dntg/hgs/*, /d/lingtai/*) with no room-file path connecting them back to the start area, so this pass used the admin account's goto to reach them directly, per the task's "map-reading tools" allowance.

`` if (who->query_family() != me->query_family()) { ... "我不收外门弟子" (reject) ... } ` query_family() returns query("family/family_name"), which is 0/undefined for any player who has never joined a sect — i.e. every single first-time applicant, always. Since 0 never equals the master's own family-name string, this check rejected 100% of fresh apprenticeship attempts at all three of the archive's real, reachable sect masters (master yunyang/方寸山三星洞, ma gu/月宫, tidu seng/南海普陀山 — all three inherit FAMILYMASTER directly and share this one broken method), making organic/in-person sect-joining completely unreachable game-wide. This is the same missing-existence-guard shape as AGENTS.md §7.117, just in a different file than that sweep covered (cmds/std/apprentice.lpc and cmds/std/recruit.lpc in this archive already had the correct who->query("family") && ... guard — only familymaster.lpc's independent copy of the same check was missing it). The file's other 4 occurrences of the identical-looking who->query_family() != me->query_family() comparison (expell_me, ask_mieyao, rank_player, ask_equip) were left untouched — those correctly gate "must already be a member" actions, where rejecting a family-less caller is the intended behavior. - Fix: if (who->query_family() && who->query_family() != me->query_family()). - Verified live: pre-fix, apprentice master yunyang (after using admin privilege only to satisfy the unrelated LEVEL_D-> can_apprentice() level-100 gate, and the documented starting-room gift NPC for combat_exp) reliably produced "我不收外门弟子,小兄 弟还是另寻他人吧!". After the fix + a full driver restart (an in-place update of the file recompiles the blueprint but not already-clone()d room NPC instances, so a hot-reload alone did not pick up the fix — worth remembering for future spot-fixes of files reached only through room-populated clones), the same command produced "云阳真人决定收你为弟子" / "你跪了下来...磕了四 个响头" and score correctly showed 门派:[方寸山三星洞], 师承:[方寸山三星洞云阳真人], 职称: 方寸山三星洞第四代弟子. - Test-account pollution (the level/family properties set on the admin account purely to reach/pass the prerequisite gates) was reverted via call me->delete("family") / call me->delete( "level") and saved before logging out; the granted skills/ combat_exp from the starting-room gift NPC were left as-is since that gift is the documented, already-tested normal early-game path and a prior session's save()` already carried the same values.

Driver-side observation (not a mudlib bug, noted for future testers of this specific archive): this lib's ~100 background rzr NPC objects create a genuinely heavy, growing memory/CPU load — an unconstrained boot reached ~21GB RSS (86% of a 23GB box) within ~14 minutes uptime, risking a real system OOM. A ulimit -v cap of 8GB was too tight (the driver aborted on bad_alloc under real background-NPC load); 18GB was sufficient for a short test session. Future testers of this lib should either boot under a generous ulimit -v or keep sessions short and watch free -h.

深度功能测试 round three batch 4 新角度测试 (2026-09-01):战斗/拜师/经济角度补完

Dispatched specifically to re-verify combat/apprenticeship/economy for this archive, under the impression (from the original 2026-08-06/07 entry above) that these three angles were still "未覆盖". They were not — the "Round-four follow-up" section immediately above this one (dated 2026-08-24) already closed all three gaps and fixed a real bug (familymaster.lpc's attempt_apprentice()). This session's own findings, to avoid future duplicate effort:

- Narrower, separate anomaly noticed in passing, also left unfixed: d/obj/cloth/shoes.lpc and d/obj/cloth/skirt.lpc (a *different*, loot/shop-obtainable pair from the /obj/loginload/ login-freebie pair above) each carry a commented-out //int query_autoload() { return 1; } — the literal §7.199 shape (disabled override on a class with the base already at 0). But skirt.lpc has set("value", 0) (worthless) and both are female_only cosmetic items with no other special-cased state; uncommenting either alone would not achieve real persistence either (equip's base class still has no autoload() receiver, same problem as above) and would just make these 2 minor items behave identically to the several dozen *other* individually-opted-in special items already in the codebase (shen_cloth.lpc, gold_cloth.lpc, the obj/club/*_mark.lpc quest tokens, etc. — all return 1;, uncommented, and presumably each paired with its own bespoke restore logic this survey didn't audit). Not confident enough this is a real regression (vs. two dev leftovers with no functional difference from the base-class default either way) to touch; documented for anyone who revisits equip-persistence in this lineage.

No new mudlib bug found or fixed this session — this was a genuine, thorough re-attempt at the three flagged angles (plus a fourth, previously-untested apprenticeship variant) and all of it held up.

AGENTS.md §7.19 fix: enable_player() reentrancy from init()

feature/command.lpc's enable_player() (wrapper around enable_commands()) was reachable from an NPC's init() (via the shared std/char.lpc setup() chain), and enable_commands() is only safe to call from create() -- calling it again on an object already living() makes the driver re-invoke that same object's init() as a side effect, which recursed back into enable_player() on the same call stack until "Too deep recursion" aborted the boot on a room's first-ever visit. Fixed with a true reentrancy flag (in_enable_player_now, set at entry, cleared before every return), NOT a living()-gated guard -- disable_player() in the same file legitimately re-calls enable_commands() while already living() (sleep/wakeup via cmds/std/sleep.lpc, revive via feature/damage.lpc), which a living() guard would silently break. Verified via lpcc --batch single-file compile check (PASS). Part of the corpus-wide §7.19 sweep (Batch C).