Commit graph

10 commits

Author SHA1 Message Date
Stephen Dennis
9beb938412 Fix WorldBuilder attribute escaping and verify coverage 2026-04-10 19:33:57 -06:00
Stephen Dennis
1db57e843e Robust dbref capture in WorldBuilder live executor
The live adapter used to parse free-form @dig/@open/@create response
text with a plain "#NNN" regex (extract_dbref) to recover the newly
created object's dbref. That broke whenever the server output format
shifted — the tracker's open item flagged this as
version-fragile. Thing creation also silently dropped its dbref
entirely, leaving state entries unindexed for later reconciler runs.

Replace the parsing path with a sentinel-wrapped `think` round-trip:

  think WB1[<expr>]WB2

`think` emits its evaluated argument verbatim on the executor's
output stream, so the response buffer contains the literal bytes
`WB1<value>WB2`. `parse_think_response()` takes the *last* match so
we land on the evaluated output rather than the command echo, which
also carries the sentinel bytes in its un-evaluated form. On top of
that helper, `query_last_created(conn, kind)` wraps
`lastcreate(me, R|E|T|P)` to deterministically pull the just-created
object's dbref without any parsing assumptions.

executor.py's three create paths (rooms, exits, things) now use
query_last_created instead of extract_dbref(resp). Thing creation
also captures its dbref + objid into state, which was missing.
extract_dbref() is removed as dead code. The live_adapter module
docstring documents the one remaining server-format dependency
(`%L`, a MUX core invariant).

test_worldbuilder.py (72), test_diff_v3.py, and test_reconciler.py
(36) still pass. Top-level ISSUES.md index updated to move
WorldBuilder into the fully-closed trackers list.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 15:52:25 -06:00
Stephen Dennis
a6a1159bec Enable TLS verification in WorldBuilder 2026-04-04 17:44:10 -06:00
Stephen Dennis
869da8df45 WorldBuilder: wire code through three-piece architecture end-to-end
- Deduplicate mux_escape/mux_unescape into live_adapter.py (single source)
- Executor now consumes Operation objects from the planner instead of
  walking spec directly; phased execution (rooms/exits/things/destroys)
- Add query_live_object() and query_live_snapshot() to live_adapter for
  producing reconciler-compatible normalized snapshots from a running game
- Add normalize_imported_room/exit helpers; importer generate_state() now
  produces reconciler-compatible output with proper flag lists and exits
- Add test_reconciler.py (36 tests covering all 7 reconciliation states)
- Add ISSUES.md tracking the integration gaps and their resolution

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 19:14:33 -06:00
Stephen Dennis
3d38167962 Refactor worldbuilder around reconcile architecture 2026-03-19 18:50:18 -06:00
Stephen Dennis
13a1864071 WorldBuilder v3: objid() identity, known defects audit, deferred destroy
Replace Virtual ID / &WB_ID design with objid() for identity tracking.
State file bumped to v4 with objid stored alongside dbref. Executor,
importer, and verify all capture and validate objid to detect dbref
recycling.

Add Known Defects section (D1-D8) documenting architectural gaps in v2
code that must be resolved before v3 features: attribute escaping
ambiguity, Things not tracked, teleport/here fragility, lossy exit
identity, silent command failures, missing zone creation, inconsistent
description escaping, and dry-run state pollution.

Document deferred @destroy semantics — GOING flag, @undestroy race,
pending_destroy state tracking, re-creation race conditions.

Restructure implementation order into three phases: fix foundations,
complete object model, then build v3 features.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 16:10:55 -06:00
Stephen Dennis
b34d01a8d3 WorldBuilder v3: Attribute-level diffing and destructive changes
- Upgrade StateFile to v3: stores description, flags, and attributes.
- Enhance diff_spec to compare specific fields with old/new values.
- Refactor compile_incremental to emit surgical MUX commands.
- Implement room destruction in incremental compiler.
- Update importer to generate v3 state files.
2026-03-19 15:27:05 -06:00
Stephen Dennis
7bb3b66d90 WorldBuilder: fix 5 known issues, add @decomp import, output formats
Issue fixes:
  1. mux_escape() — proper %r/%t/%%  escaping, replaces naive \n→%r
  2. Full exit model — lock, desc, succ/osucc/fail/ofail/drop/odrop, flags
  3. Reliable dbref capture — think %L primary, @dig parse fallback
  4. Content hashing in state — sha256 of name+desc+attrs+flags
  5. Auto _instance_id param — components can use ${_instance_id}

@decomp integration:
  Importer tries @decomp/tf first (one command, all attrs)
  Falls back to lattr+get if @decomp unavailable
  Parses &ATTR #dbref=value format

Output formats (--format flag):
  default — comments + commands (human-readable)
  upload — unformat-compatible .mux format (TF /quote)
  raw — commands only (pipe to telnet)

Exit property compilation:
  @lock, @desc, @succ, @osucc, @fail, @ofail, @drop, @odrop, @set
  emitted after @open when exit spec has those fields

All 4 valid test specs pass DRC.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:40:21 -06:00
Stephen Dennis
b086f22298 WorldBuilder: procedural grids, verify, rollback, things, components
Procedural generation:
  Grid generator creates WxH rooms with cardinal exits
  Seeded-random description selection (deterministic)
  Density parameter controls connectivity (0.0-1.0)
  Edge ports for wiring grid to external rooms
  forest_area.yaml — 7 description variants
  street_grid.yaml — 5 description variants

Verify command (executor.py verify):
  Connects to live game, checks rooms match spec
  Validates names, descriptions, attributes against state
  Reports discrepancies

Rollback command (executor.py rollback):
  Destroys objects in reverse order (exits first, then rooms)
  Clears state file after destruction
  Dry-run mode supported

Thing support:
  Thing model (name, location, description, flags, attrs, parent)
  Parsed from spec YAML and component definitions
  Compiled to @create + @desc + &attr + @parent commands
  Shown in plan output
  Component things expand with parameter substitution

New components:
  tavern.yaml — 3 rooms + barkeeper NPC thing
  street_grid.yaml — procedural city block grid

Test specs:
  town.yaml — combines tavern + street_grid + manual rooms/things
  forest.yaml — 4x4 procedural forest with edge connection

Zone support:
  @chzone emitted in compiler for all rooms
  @parent emitted when room has parent field

All 4 test specs pass DRC.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:28:34 -06:00
Stephen Dennis
d0b1a6a80c WorldBuilder executor: telnet bot with state tracking
executor.py — connects to a MUX and applies compiled specs:

MuxConnection class:
  Synchronous telnet with IAC stripping
  SSL/TLS support, login with character/password
  Send commands, read responses with quiet-timeout

Execution engine:
  Phase 1: create rooms via @dig/teleport, capture dbrefs from output
  Phase 2: create exits via @open with resolved dbrefs
  Sets descriptions, flags, attributes per room
  Handles existing rooms (teleport + update instead of recreate)

State file (.worldbuilder/<zone>.state.yaml):
  Tracks spec_id → dbref mapping across runs
  Enables incremental updates and dbref resolution
  YAML format for human readability

Safety:
  DRC validation before any commands sent
  Dry-run mode (--dry-run) logs commands without executing
  Optional log file (--log) for full audit trail
  Sequential execution with response capture

CLI: worldbuilder executor.py <spec> --host --port --character --password
  [--ssl] [--dry-run] [--log] [--state]

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:07:56 -06:00