Repository navigation
Pin renderedstep/engine#99's head (e5c28ab): stock a floor with safe rooms and healing things when it is laid out - #375
Merged
Merged
Conversation
…rooms and healing things when it is laid out
Stage 7 of the dungeon plan, server half ("Floor supplies: healing items
and safe rooms"). A floor that says `safe_rooms:` and `healing:` is stocked
when the engine lays it out, once, for the world (VISION.md principle 7): its
safe rooms are laid out safe, with no hazard and nobody born in them
(`locations.sanctuary`), and its healing things are world rows lying one to a
room, with the supply marker and no `kit_key`. The player learns a room is
safe from the engine's line on the room panel; no model is told. A world
without the keys plays as before; no checked-in story world turns them on.
- Migration 20261031150000 AddSuppliesToFloors, the engine's version and
declaration. schema.rb moves to 2026_10_31_150000.
- Floor validates safe_rooms and healing_count as whole numbers from 0, and
requires healing_name and healing_description when healing_count > 0.
Item gains SUPPLIES, validates supply in it or nil, and #supply?;
Item.bespoke leaves supply rows out, so neither registry cap counts them.
Factory traits :supply (item) and :sanctuary (location), neither rolling.
- Character::Registry#slots draws nobody for a sanctuary and throws no die,
the engine's realize.rs `slots`.
- Loader reads floor `safe_rooms` and `healing: {count, name, description}`
in both directions (absent writes 0 / 0, nil, nil), and a generic
`sanctuary: true` on any location (absent writes false). It refuses a
non-integer or negative safe_rooms, safe_rooms above rooms - 2, a healing
that is not a map or has another key, a non-integer or negative count, and
a blank name or description when count > 0. A re-seed never matches,
moves or removes a supply row (the item finders skip them, and a file row
is written with no supply), nor unsets a laid-out floor room's sanctuary.
Item::TemplateRefresh skips copies of a supply.
- Exporter writes safe_rooms and healing when their counts are not zero, and
sanctuary: true on a location that has it; a floor's laid-out rooms are
still not written.
- Story::Doctor: sanctuary_with_a_hostile_resident (world or game),
supply_with_a_kit_key and floor_stocked_to_another_count, all warnings,
reported and never repaired. Supply rows join kit rows outside
duplicate_items and the story cap count: the layout leaves one name in
several rooms by design.
- The extension's glance_json, Playthrough::Glance::Room (and its console
line) and Protocol::V1#glance carry the room's `safe`; openapi.json and
v1.md add it as revision 1.8.
- Sweep: world a-stocked-floor, script a-floor-stocked-at-layout, golden
vendored and checks file written. test/engine_vectors re-exported: the
recorded rows gain items.supply and locations.sanctuary.
calebl
added a commit
to renderedstep/engine
that referenced
this pull request
Oct 30, 2026
… b696798 The game's pin PR (renderedstep/server#375) reads safe_rooms: and healing:, so the dump is now the one its own loader writes from a schema load: the supplies are written by the loader rather than by hand. The rows are the same; only timestamps, the schema digest and the order the dump lists them in moved. No golden or records file moves.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stage 7 of the dungeon plan, server half: floor supplies, healing items and safe rooms. The engine half is renderedstep/engine#99. This PR pins its head (
e5c28ab) and does every item of its "What the server pin PR must change" section.floors.safe_rooms, plusfloors.healing_countwithhealing_nameandhealing_description.locations.sanctuaryset, and nobody is born in it.items.supply = 'floor'. Neither the room's cap nor the story's cap counts it.glance.room.safe. No model is told, and no prompt template changed.No model was called. Every command ran with
OPENROUTER_API_KEYandTYPESAFE_API_KEYunset.What changed
20261031150000AddSuppliesToFloors. The version and declarations are the engine's, so its world dumps stay byte-true.db/schema.rbmoves to2026_10_31_150000. That version is still the latest against a freshly fetchedmain.Floorvalidatessafe_roomsandhealing_countas whole numbers from 0. It requireshealing_nameandhealing_descriptionwhenhealing_count > 0.ItemgainsSUPPLIES = %w[floor], validatessupplyagainst it (nil allowed), and gains#supply?.:supply(item) and:sanctuary(location). Neither rolls dice.floor: safe_rooms:andfloor: healing: {count, name, description}in both directions on every load. An absent key writes 0, or 0, nil, nil.sanctuary: trueon any location; absent writes false.safe_rooms;safe_roomsaboverooms − 2;healing:that is not a mapping, or that has another key;count;nameordescriptionwhencount > 0;sanctuary.find_item,find_renamed_item,room_item) skip supply rows, and a file's item is always written withsupply: nil. So a file thing that shares a draught's name is a different thing, and the supply row stays where the layout put it. A laid-out floor room keeps itssanctuary.Item::TemplateRefreshskips copies of a supply.safe_roomsandhealing:only when their counts are non-zero, andsanctuary: trueon any location that has it. A floor's laid-out rooms are still not written. Round-trip test included.Item.bespokeis nowportable.where(kit_key: nil, supply: nil), soItem::Registry#room_for_itemsand#story_item_countleave supplies out.Character::Registry#slotsdraws nobody for a sanctuary and throws no die, as the engine'sslotsdoes.things_limit: 1, with two supply rows lying in the room.Story::ForkandStory::Snapshotgo through the exporter's document, so they carry the floor's keys andsanctuary; there is a new fork test.Playthrough::SqlitePackagecopies rows withSELECT *; its test now pins both columns.Item::NOT_COPIEDleavessupplyout, so a game's copy keeps the marker.sanctuary_with_a_hostile_resident: a living hostile person in the world, or someone a game has provoked (Playthrough#foes_in).supply_with_a_kit_key.floor_stocked_to_another_count: compares what is on record with the row's counts, clamped the way the engine'sfloor.rsclamps them.glance_jsonadds"safe"toroom.Playthrough::Glance::Roomgains:safe, and the console prints it on its ownsafeline.Protocol::V1#glancesendsroom.safe.openapi.json:safeis required on the room object, appears in every example, and is described as the engine PR specifies.v1.mdadds it as revision 1.8.a-stocked-floorand scripta-floor-stocked-at-layoutare copied from the engine PR with their comments andwhy:notes. The script's stripped form matches the engine'sparity/scripts/byte for byte.engine:vendoredpasses.engine:checks.test/ruby_loop_coverage.ymldid not need to change.test/engine_vectorswas re-exported. The recorded rows only gain"supply": nulland"sanctuary": false, as the stage 3 pin re-export did withposted_to_id.Things a reviewer should know
duplicate_itemsor the story-cap count. This is the one change beyond the engine PR's list. On the firstengine:checksrun, the new script's two draughts were reported asduplicate_items("one thing to a re-seed"). That stopped being true once the loader stopped matching supply rows by name. Kit rows were already left out of both for the same reason. The checks file now says "playable, 2 warnings" (no_arc,room_without_a_layout), the same as every other floor sweep world.errorseverity inStory::Doctor(SEVERITIESisfatalandwarning). Sosupply_with_a_kit_key, which the engine PR calls an error, is a warning here. It is not fatal: the story still plays, its room just reads as furnished.parity/worlds/a-stocked-floor.sqldoes not need rebuilding. I rebuilt it with this branch's loader (scratch copy,db:schema:load, the README'sload_world.rb,sqlite3 .dump). Every row matches the engine's dump. The only differences arecreated_at/updated_attimestamps and where theschema_migrationsrow sits in the dump (a schema load puts it in order; the engine migrated its dump, which appends it).Gates
All ran with both provider keys unset, at
b696798:bin/rails test(includesgame:sweep): 5487 runs, 0 failures, 0 errors, 0 skips.bin/rails engine:rust_gates: PASSED for all 113 scripts (goldens, invariants, doctor and audit).bin/rails engine:vendored: VENDORED, ate5c28ab.bin/rails engine:kept_requests: the engine reproduces every golden vector and kept request this checkout exports (45 passed).bundle exec rubocop,bin/rails zeitwerk:checkandbin/brakeman: clean.ext/renderedstep,cargo fmt --checkandcargo clippy --release --locked -- -D warnings: clean.Post-update: no new
Update::REGISTRYstep.bin/updatealready migrates and rebuilds the extension when the pin moves.After renderedstep/engine#99 merges, this PR moves the pin to its merge commit.