Skip to content

History / Pack Entity Reference

Revisions

  • Round 48: SRD items/chargen/plumbing — the last engine wave of #505 (#512/#514-#519/#548) Eight primitives closing the SRD engine register. Two stale claims corrected (chargen array/roll "not implemented"; the Wearer "affix sums" only). - Pack-Entity-Reference: chargen array_assign + roll step kinds now implemented (roll is server-authoritative, forged client values ignored); wearable gains static `modifiers` (#514) and `equip_affects` (#515, on-equip magic + OnHit procs, item-keyed derived state). - Abilities-and-Effects: worn static modifiers compose through the Wearer modSource (mulMod was hardwired to identity); teleport/push same-zone relocation ops (#516, forced-move harm-gated, same-zone structural, instance- entrance refused); the polymorphic dice_num + one-of conflict rejection (#517) and the `fixed` op flag (#515). - Combat-System: item procs = an equip-affect subscribing OnHit, with the OnHit self-loop guard + `fixed` rider; the prevents:move WALK fix (#548, a confirmed bug — attemptMove never consulted prevents:move, voiding the whole immobilize system). - Builder-Commands + Player-Reference: carrying capacity (carry_capacity derived attribute, enforced at acquisition, get-all-takes-what-fits); the `credits` verb (#519); rest short/long. - Pack-MUD-Settings: manifest license/attribution (accumulate per pack; a later pack can't erase an earlier notice). - Pack-Lua-Hooks: OnRest now live + OnShortRest/OnLongRest (distinct kinds, NOT the mag argument which would double a handler's heal). - Pack-Lua-Scripting: h:move now harm-gates forcing another player (was an ungated grief hole) — the safe co-move primitive for mounts/grapple-drag. Store field-drop trap again: #519 pack license needed BOTH fold loops (mergePacks file->Pack AND Merge Pack->LoadedContent) plus the pack_meta round-trip; #514/#515 ride existing wholesale-marshaled bodies.

    @yfronto yfronto committed Jul 26, 2026
  • Round 47: SRD engine primitives batch 2 (#536/#539/#541-#547) Nine composable SRD primitives, threaded into the combat/effect/schema pages. - Combat-System: #547 OnEnterCombat (the initiative checkpoint, seeded-rng, per entry); #544 crit dice-doubling (crit_dice doubles the dice term vs crit_mult the whole roll; reaches swing + check-band crits; set-not-multiply, no leak); #543 heterogeneous multiattack routine (replaces attacks, shares one to_hit, same dealDamage path per swing, capped); #536 absorb buffer in the funnel (after the OnDamageTaken reaction, before the vital; instance-set capacity, no max_attr, set_resource op). - Abilities-and-Effects: #541 highest-wins stacking + graded rungs, and the HIGH harm-classifier fix (affectIsDetrimental / respawn-strip now fold in RUNG modifiers/prevents — the 6th blind spot; decrement_rung gated cross-player); #545 duration_kind: indefinite + level/dispel-by-level (indefinite room-field lease kept finite); #546 prevents_source source-relative CC (a targeting gate, not a can't-harm firewall; fail-open across load); #539 concentration single slot (the cross-zone single-writer fix: expireConcentration gated on holder.zone==z + break-before-detach on transfer/quit); #542 richer if predicate (comparators + formula RHS; indeterminate operand fails to FALSE, not 0; unknown comparator rejected at parse); the set_resource / increment_rung / decrement_rung ops; the absorb resource fields. - Pack-Entity-Reference: resource absorb/fronts; affect level/concentration/ duration_kind/rungs/prevents_source + stacking: highest; combat_profile multiattack. - Pack-Lua-Hooks: OnEnterCombat + OnAffectBlocked added to the live event enum. Store field-drop trap hit TWICE this round (absorb/fronts on resource_defs; multiattack on combat_profiles) — both round-tripped through Postgres by the reflection test; noted as JSONB-body fields needing no migration.

    @yfronto yfronto committed Jul 26, 2026
  • Round 46: SRD engine primitives (#511/#513/#537/#538/#540/#535 + #557/#562) The capstone SRD-primitive round. Six composable primitives plus a fold-clamp fix and the check subject selector, threaded into the effect/combat pages. - Check pipeline (Combat-System + the check op in Abilities-and-Effects): * #511 boon/bane — a net-sign channel selecting among boon_dice/bane_dice/ neutral dice (NOT keep-high synthesis, which inverts the demo's roll-UNDER ladder); 5e cancellation falls out of sign-netting; composes through ordinary attribute modifiers, no new state/DTO. * #513 band `when` — a forcing fifth band axis (auto-crit / auto-fail-save) with no engine crit/fail vocabulary; truthiness is non-zero AND finite (NaN != 0 in Go); replaces an affine sentinel hack that broke on stacking. * #562 subject selector — subject: target is the saving-throw idiom (target rolls, narrates to the saver, OnCheck subject = saver, caster rides as other); does NOT rebind band-op target vocabulary (authoring trap noted). - Damage/death (Combat-System): * #537 per-target damage_taken_mult — an affect-granted map, product-composed like prevents (absence = identity-1 structurally), consulted after soak; per-FACTOR normalization at composition closes the "two {fire:-3} buffs compose to a 9x amplifier" cross-player harm-gate bypass. * #535 downed/dying — a third onPoolDepleted disposition: an active suspends_death affect holds the victim at 0 (no die/corpse/respawn); regen pauses, auto-swings stop (swingGatesPass now refuses a prevents:[act] attacker); the resolution is a content affect. die() keeps its one call site. - Reactions/affects (Combat-System + Abilities-and-Effects): * #540 incapacitation gate — canReact = canAct && !preventsTag("react") on every reaction checkpoint; gates reactions only, never the plain bus (passive on_event still fires while stunned). * #538 incoming-affect trait immunity — grants_immunity vetoes an incoming affect BEFORE attach on {ref}u{category}u tags; a separate multiset from prevents; the veto sits after the reattach branch so a load is never vetoed. * #557 attribute-fold clamp — the (base+flat)*mul fold saturates (+/-Inf -> +/-1e12, NaN -> pre-mod base); screen runs BEFORE min/max since NaN passes every range; the reachable consumers read attr() directly (resourceMax -> an unkillable bottomless pool, the OPPOSITE of the panel's claimed one-shot). - Pack-Entity-Reference affect schema: tags, grants_immunity, suspends_death, damage_taken_mult rows + the conventional act/react/cast prevents tags.

    @yfronto yfronto committed Jul 24, 2026
  • Round 43: the three review-bundle follow-ups (#397/#399/#401) Refinements to systems already documented (spawn-protection, comms history, the audit trail); each thread lands in its existing home. - Abilities-and-Effects (#397): the sourceless-ambient exemption. A room field with no applier ticks at actor==target, which guardHarmful treats as an exempt self-effect, so it kept damaging a just-respawned occupant. A sourcelessAmbient flag fires ENFORCEMENT even at actor==target while CANCELLATION stays actor!=target-gated, so the field never drops the occupant's own shield; threaded into all four such harm sites. - Combat-System (#397): a swing at a spawn-protected target is short-circuited BEFORE the pipeline, not zeroed inside it. Narration ran before dealDamage, so the target saw a phantom hit each round; the pre-gate also drops a still- protected attacker's own shield. - Builder-Commands + Pack-Entity-Reference (#401): a sent tell is recorded at the CONFIRMED-echo point, so no phantom entry on a resolve-miss or publish-failure; history channel appends a shard-local partial-view footer on a multi-shard fleet; the channel history ring is reaped on channel removal, and the schema now warns that loosening hear_access retroactively exposes buffered lines. - Persistence-and-Durability (#399): the async auditor now coalesces up to 64 events into one pgx.Batch round-trip, with per-row fallback under the same bounded ctx; newest-first reads order by at DESC, seq DESC for true insertion order incl. within a shared-now batch; and staff audit-by-name now folds in the target account tier_changed rows, scoped to the owning account.

    @yfronto yfronto committed Jul 24, 2026
  • Round 42: depletion hooks on any pool, damage-type pool routing, the depletion arithmetic Updates the builder-facing reference for #405/#406/#407: - resources: `vital` now means only "emptying this causes death"; every pool runs its own on_depleted. Documents the level-trigger and the two authoring rules it forces (make the hook idempotent; never reward from one), and the $depletion.overflow/.applied/.amount scalars with the carry-over idiom. - damage_types: target_resource, the three-tier routing precedence, why a capacity-less target is immune by construction (and how to use a 0-base capping attribute as an opt-in lever), and the never-retrofit rule. - Combat System: the same two corrections where it described the seam as vital-only and the routing as op-level-only.

    @MrG0rd0x MrG0rd0x committed Jul 23, 2026
  • Round 41 milestone: director & durable-bus reliability (#354/#355/#356/#390 + the forged-event fix) Corrects a stale claim: Orchestration said "No region directors are deployed, so signal_region currently has no consuming director". #356 shipped them. - Orchestration-and-Directors (new section) + Pack-Entity-Reference: per-region director scripts (#356). Region scope had been WRITE-DEAD — content published durable region signals and zones applied region deltas, but nothing consumed the subject or wrote region state. Records the three hazards found building it (an omitted ref minted a PHANTOM WORLD director sharing the world lease, instance id and consumer name; the consumer id was not injective across . and :; the tier hardcoded the demo pack) and the disproved premise that a director losing leadership leaks its VM — the proposed fix would have crashed the process on a late signal. - Orchestration-and-Directors: a signal is NAK d when its scope-state write never landed (#354). The ack consumed the event FLEET-WIDE because every director binds the same durable consumer name. Widened to any store error, recorded at the single write chokepoint (a handler return is defeated by pcall, by closure composition, and by the schedule-state path). Includes the prerequisite defect that inverts intuition: a restarted director CASed on a cold cache version of 0, so ErrCASLost meant "cold cache" far more often than "concurrent writer" and NAKing on it would have requeued on every restart. - Orchestration-and-Directors: the down-broadcast carries the store version and replicas fence on it (#355) — with the issue s framing corrected in two directions (churn does not reproduce; and there is NO re-read, so a stale replica stays wrong until the next write or a reseed). Why the version must be the store s, and the three easily-inverted rules (0 = unversioned, unknown key applies, deletes record too). - Scoped-Event-Bus + Pack-Lua-Scripting: a zone script could forge a director-only event, because signal-up and broadcast-down share one subject and shards core-subscribe it. #355 made it worse — a forged high version permanently freezes a key fleet-wide. Notes why boss.died is deliberately NOT in the shared reserved list, and the residual (a NATS-credentialed publisher still reaches it; needs the subjects split). - Running-at-Scale + Sysadmin-Reference + Scoped-Event-Bus: durable_stalled_total (#390) — the recoverable window before a park. Explains why it is an orchestration outage rather than a delayed message (MaxAckPending=1 blocks the whole per-scope consumer) and carries the known miss: a wedged handler never reaches the counter, so the park alarm can fire with no early warning.

    @yfronto yfronto committed Jul 20, 2026
  • Round 40 milestone: instance residuals + operator tunables (#436/#438/#435/#429/#425) Corrects claims from the Round 37 sync: "nothing caps memory" (three places) and the #340 eviction guidance, whose stated prerequisite now exists. - Lua-Sandbox-Internals (new section) + Sysadmin-Reference + Pack-Lua-Scripting: the per-call string-allocation budget (#438). Documents why the filed premise was impossible — bytes-per-instruction spans FIVE orders of magnitude (25 instructions, 63MB), so no instruction budget bounds memory, and heap sampling cannot work because a neighbour goroutine s noise floor would let a player quarantine content they do not own. The real vector is the `..` OPCODE (every string BUILTIN was already capped; an opcode has no wrapper): at shipping defaults `s = s .. s` reaches 64 GB. Charged in the fork BEFORE the join. Also the misclassification fix — a memory bomb used to land in AbortDeadline (weight 0.1, "transient host load"); new AbortAlloc weighs with AbortBudget. Keeps the review lesson that "does not amplify" != "does not allocate". - Sysadmin-Reference + Deployment: redis.directory_addr splits coordination from cache (#429). The eviction check is now shape-dependent — SHARED stays warn-only, DEDICATED is FATAL — which supplies the prerequisite the previous guidance said was missing, so the advice changes from "flip the policy" to "declare the split". Periodic re-check stays warn-only on both shapes (exiting over a live CONFIG SET would cause the outage it prevents), and a configured-but-unreachable coordination Redis is fatal rather than falling back onto the evicting instance. - Instanced-Zones + Sysadmin-Reference: the instance caps are operator-tunable (#436), with the two ENFORCED cross-field invariants that disproved the issue s "no ordering invariant" premise (instances_per_shard vs the drain eject barrier; burst validated with its window as a rate), plus the corrected claim that per-account bounds churn — it does not. - Instanced-Zones + Building-Instanced-Zones + Pack-Entity-Reference + Pack-Lua-Scripting: the declared instance entrance (#435). Documents why option 2 (relaxing self-only) was rejected — standing in a room is not consent, greet/enter share an actor, and the mint bills the VICTIM s account — and why entrances live in their own map so no push-the-player path can traverse a door it cannot see.

    @yfronto yfronto committed Jul 20, 2026
  • Document instanced zones across all three audiences (#422) Round 36 shipped instanced zones (#72) and Round 37 changed four things about them; only the engine-developer page existed, and it predated the Round 37 work. Builder — new page, Building Instanced Zones: - the `instanceable: true` opt-in and why it is opt-in (a mint runs the zone's boot resets, so every copy is a generation faucet that also routes around every in-world gate: a private copy has no doorman) - the start_room requirement, enforced at mint, and both reasons for it - mud.send_to_instance is self-only, and what "the invoking actor" actually resolves to per attach point: a custom command or an ability acts as the PLAYER, but on("enter")/on("greet") act as the room/mob, so an entity trigger cannot send the entrant in. The dungeon-door idiom is a verb the player types - mud.zone() and why `ev.zone ~= "darkwood"` matches inside every copy - the exhaustive does-not-work list with the why for each: persistent resets (durable item dupe), timed repop (farmable), signal_region / signal_world (the envelope drops source), reserved director schedule events, nesting, the reload freeze - the engine-owned player-facing lines, and the caps to design around Sysadmin — a new section in Running at Scale plus the prune-guard remedy in Content Pack Operations: - the caps ARE PER PROCESS, so an account gets perAccount x shards; and they are not config knobs today (compile-time defaults + a Go option, no TELOS_INSTANCE_* env var wires them) - shard-local and unleased: not in the placement pool, never rebalanced, never a handoff destination, and they die with the shard - metrics label by template because an instance id is unbounded, player-driven cardinality; logs go the other way and keep the id. Adds the missing telos.zone.instances gauge to the metrics table - drain step 0 ejects occupants to their exit anchor - the reload freeze and the pinned-instance advisory - Round 37: a mint builds from the live content snapshot and refuses an incomplete build (#418); the TTL'd dir:tmplinuse claim, so a content pull can be REFUSED while parties are inside copies and clears ~45s after the last one (#416); the concurrent bounded reaper sweep (#419); and the up-to-3-minute rebalance deferral with its "rebalance deferred" log lines (#421) Mudlib — Instanced Zones: - the routing-vs-isolation rule spelled out (the room map is the isolation boundary; the zone-segment test is only a pre-filter), and what the build-failing lint actually covers - the "never mint on a zone goroutine" contract with the reason, the three-hop entry, why the request carries the origin zone POINTER, and why abandonInstance is a flag rather than a record deletion - minting from the live snapshot, and the incomplete-build refusal - the concurrent reaper: the detached per-teardown context, and why the bound is a smoothing bound rather than a correctness one - the dir:tmplinuse claim as the cheapest possible analogue of a lease, its own goroutine, and the mint kick - the anchor's invariant DECAYS, the pre-handoverZoneTo guard and why the placement of that guard is the load-bearing property, why the anchors are queried rather than maintained, and why it fails open

    @MrG0rd0x MrG0rd0x committed Jul 19, 2026
  • Round 36 milestone: instanced zones (#72) New deep-dive page Instanced-Zones, plus corrections to two pages that asserted "instancing is deferred / not implemented". - NEW Instanced-Zones: template-vs-id identity and the ownsZoneRef locality chokepoint (with the build-failing AST lint); why the id is <template>#<128-bit random> (# outside the ref charset, unguessable so it is not a farming oracle); unleased by construction; async 3-hop mint + quiescence reaper; the instanceable content opt-in; the isolation exclusions (persistent resets fail closed vs a durable item dupe, per-mint RNG salting, withheld director schedule events, refused signal_region/world, drain/reload/off-box-ingress); THE ANCHOR (template projection was killed because placement is the gate ROUTING key); exit paths; and the security posture. - Distributed-Systems-Model + Running-at-Scale (x2): instancing now exists but is ISOLATION, not transparent load-sharding — the public hot-zone ceiling stands. - Zone-Runtime: quiescence gains the third `incoming` counter for in-flight intra-shard transfers, claimed under the same mutex teardown checks. - Cross-Shard-Handoff + RPC-and-Protobuf: signed-snapshot optionals now written UNCONDITIONALLY — a second append-if-non-empty optional made digest(tier="",account=X) == digest(tier=X,account="") (length prefixes solve boundaries, not presence); instances rejected at every off-box ingress. - Persistence: an instance is never a durable location; the anchor + COALESCE. - Pack-Entity-Reference: zone `instanceable` flag, start_room respawn semantics. - Pack-Lua-Scripting: mud.zone(), mud.send_to_instance (self-only). - Orchestration: instances withheld from reserved schedule fan-out. - Sidebar + Engine-Developer-Reference index entries.

    @yfronto yfronto committed Jul 19, 2026
  • Round 35 milestone: multi-vital support (#71) Corrects a now-stale claim: Abilities-and-Effects asserted "multi-vital is unsupported (only the lowest-ref pool damages and kills)". - Abilities-and-Effects: multiple independently-lethal vital pools, each with its own on_depleted; deal_damage routes via `resource` (empty = the new `primary` vital, so existing content is unchanged); `primary` replaces the implicit lowest-ref rule; max<=0 is natural immunity; non-vital pools are damageable but never lethal. - Combat-System: damage now subtracts from the ROUTED pool; documents the per-pool vitalDepleted predicate (def.vital && max>0 && cur<=0) and why the max>0 term is load-bearing (a zero-max pool would read as already-depleted and instantly kill); the death-generation guard is ordered BEFORE the pool-local cancel re-check so a cross-pool cascade yields exactly one die(). - Pack-Entity-Reference: vital row updated, new `primary` row (rides the resource JSONB body, no migration), per-pool on_depleted, and the LintVitalResources / LintDealDamageResources lints. - Pack-Lua-Scripting: h:damage gains `resource=` for the routed pool.

    @yfronto yfronto committed Jul 18, 2026
  • Round 34 milestone: spawn-protection window, audit trail, comms history - Combat-System + Abilities-and-Effects: the actor-agnostic post-respawn spawn-protection window shipped (#394) — updates the #318 "deferred" note. respawnPlayer opens a pulse-deadline protectedUntil; guardHarmful refuses harmful ops aimed at a protected player AHEAD of the !isPlayer no-op so a MOB attacker is covered (safe-room cannot be); drops when the player acts. - Persistence-and-Durability (new section) + Accounts-and-Auth-Internals: the append-only character_audit trail (#350) — world emits died/attr/track via an async per-shard auditor (saver twin, drains on shutdown), account emits create/tier_changed in-transaction; idempotent on (subject,kind,dedup_key) with a DURABLY-UNIQUE key (died = per-death UUID, not the transient deaths counter that collided across relogs); audit self-view scoped by stable pid, audit <name> staff-only. - Builder-Commands + Player-Reference: tells/replay session tell history (#349, structural pair-privacy, skips ignored authors, resets on relog) and history <channel> scrollback (#348, fetch-time canHear gate, shard-local partial view); Pack-Entity-Reference channel_defs.history row enriched.

    @yfronto yfronto committed Jul 18, 2026
  • Round 33 milestone: staff visibility pair + respawn hostile-affect strip - Pack-Entity-Reference: help_defs gains an optional per-topic min_rank; a gated topic is invisible in both the index and a direct lookup (falls through to "no help on ..." so existence never leaks), see_also is filtered per-viewer, and the gate fails open (a dropped field un-gates text, never a capability) (#351). - Combat-System: document the "no hostile effect survives respawn" invariant at the respawnPlayer chokepoint — whitelist inversion (provably-benign is closed/checkable, unknown ops fail toward stripping), hard removal with no on_expire hooks, and the tickOnce re-entrancy guard for a lethal DoT (#318). - Builder-Commands + Accounts-and-Auth-Internals + RPC-and-Protobuf + Trust-Tier-Model: promote/demote now have the wiz-command posture for non-staff (plain Huh?, no refusal, no account-service round-trip) via a manage_tiers visibility bit on IssueSessionAssertion; the service stays authoritative, the bit is defense-in-depth visibility only (#369).

    @yfronto yfronto committed Jul 17, 2026
  • Overworld map, content-defined toggles, and the demo-strip release model Cross-repo changes (gomud engine+demo, telosMUD-content, telosMUD-infra): Overworld / minimap (gomud #358/#360/#361/#367): - Pack-Entity-Reference: new toggle_defs def table (on/off player preference, verb-flipped, delta-from-default override, never a trust signal); the room display surface (return nil to fall back → own the render for some rooms only) - Pack-Lua-Scripting: coord(), has_room_flag (room content flags, vs has_flag = Living flags), long(), toggle() handle reads - Builder-Commands + Player-Reference: enter/exit/out named-exit verbs + the Exits: line order; toggle verbs - Demo-Pack: the 4th zone (overworld 'The Open Plains', 6x20 grid) + the opt-in minimap (overworld toggle → room display template); the plains route vs the kept-for-parity direct market->grove exit Demo-strip release model (gomud release-images + telosMUD-content/-infra): - Deployment: published images built with nofixture ship core-only; the world is pulled from the external content store; telos-pull added to the published matrix (telos-seed keeps the demo embed for local stacks) - Content-Packs-Intro + Content-Pack-Operations: the demo is a dev fixture, not a shipped world; a deployed fleet (e.g. live staging) pulls the reference pack

    @yfronto yfronto committed Jul 11, 2026
  • Round 29: help system (#64) + world-director script (#47) Round did not self-document. Two LARGE features: #47 content-defined Lua world-director script (the headline — closes the 'director-script unauthored' gap the Orchestration + Engine-Dev-landing pages carried): - Orchestration-and-Directors: new 'The world-director script' section — the director host table (get/set/broadcast/log), on_signal delivered per non- boss.died signal, the four guards (guard-your-own-events, idempotent derived writes, reserved key/down-event refusal); rewrote the stale 'unauthored' note. - Lua-Sandbox-Internals: the sandbox core is now a shared internal/luasandbox package used by both the zone VM and the director VM, cross-checked by a build-failing parity test. - Scoped-Event-Bus: signal-up is now consumed by the content on_signal handler. - Pack-MUD-Settings: world_script manifest field. - Pack-Lua-Hooks: builder-facing 'The world-director script' authoring section. #64 builder-defined help system: - Pack-Entity-Reference: help_defs def table (ref/title/category/keywords/body/ see_also; auto-includes the command set; honors CmdHidden+MinRank). - Builder-Commands + Player-Reference: the help command; fixed the stale 'CmdHidden has no help/listing consumer yet' note.

    @yfronto yfronto committed Jul 10, 2026
  • Close the Round 24 doc gaps: roam field, salvage pity, #205 validation Most of Round 24 was documented as it shipped (on("spawn")/witness_leave hooks, the state.x reload-guard idiom, the shared-def rolling-reboot readout). Remaining: - Pack-Entity-Reference: add the missing roam reset field (zone-wide population) - Loot-Spawns-and-Crafting: salvage pity no longer compounds across over-skill bonus passes (was listed as a latent bug); only the base pass advances pity - Content-Loading-and-Hot-Reload: scoped reloads now validate against the whole merged graph, rejecting only findings whose last-writer pack is in scope (provenance-by-last-writer; avoids the migration trap) - Demo-Pack: the wandering wisp + chasing stalker, and the reload-safe greeter seed

    @yfronto yfronto committed Jul 10, 2026
  • Builder Reference: pack format, entities, and Lua - Pack-Authoring: directory-tree format, merge semantics, ingestion paths - Pack-MUD-Settings: pack.yaml manifest + pack_meta scalars - Pack-Entity-Reference: exhaustive world-entity + 23 def-table field reference - Pack-Lua-Scripting: sandbox model, curated handle/global API, self.state - Pack-Lua-Hooks: full lifecycle/event/reaction/trigger + EventKind catalog All grounded in code (content loader, world Lua runtime); reserved/unused surface flagged honestly (class_defs, unwired formulas, stub globals).

    @yfronto yfronto committed Jul 9, 2026
  • Scaffold wiki + author About and Getting Started - 48-page skeleton across all audiences (flat files + grouped _Sidebar) - Every page carries an Audience + Status banner (Ready/Draft/Placeholder) - About: Overview, History of MUDs (Ready) - Getting Started: Getting-Started, Running-Locally, First-Admin-Setup, Content-Packs-Intro (Ready) — dev bypass, local GitHub OAuth, bootstrap admin, promote/demote, content-pack model, all grounded in code - SRD5/WoW/D6 pack pages are honest placeholders (packs not yet built)

    @yfronto yfronto committed Jul 9, 2026