sprint 024: playtest quick wins (combat feel, gear polish, item properties UI)#38
Merged
Conversation
Reformulated after code recon: the "budget not consumed" premise was wrong — the dispatcher already charged movement via action_cost(MOVE)=MOVEMENT, gated by check_budget. The real issue was split accounting: MOVE charged requested ft in the dispatcher while MOVE_TO/DASH charged actual distance in their handlers, causing latent diagonal undercharge and blocked-step overcharge. - MOVE -> cost_type=FREE; remove CostType.MOVEMENT. handle_move now checks and decrements the distance actually walked, atomically (no partial placement on rejection). - Add check_movement_available so a spent-out creature is still not offered MOVE (check_budget no longer gates a FREE action). - handle_move_to distinguishes "no path" from "not enough movement". - Surface movement_remaining + reachable targets to the LLM prompt (player and RuleBrain already had it). Updated dispatcher/multi-action/session-awareness tests to the new contract; new i18n strings translated to ru.
…og, build faction relation fn once per awareness rebuild
…ull health', not 'regaining 0 HP'
… 9/9, mark phase complete
… gear from inventory
…tions Add 10 slot labels (equip_armor..unequip_ring) plus a short 'use' key to en/ru game.json; route InventoryPanel USE/EQUIP literals through t(). Add RU translations for the 12 equip/unequip ActionDef descriptions to the .po and recompile the .mo, so a Russian player sees Russian labels and tooltips instead of raw ids and English base strings. Web contract of the 12 ActionType is untouched.
…k phase complete E2E surfaced pre-existing ac-stale-on-unequip bug (unequip armor raises AC), logged to backlog. Not a phase-2 regression.
…all phases complete
Rename private _reaction_to_dict to public reaction_to_dict (was imported across the transport_payloads/session module boundary). Drop the dead check_faction_hostility wrapper left without production callers by the relation-fn refactor; tests now exercise _hostility_from_relation through a helper that mirrors the production path.
item-properties-ui closed by phase 3, leftover split to loot-panel-item-props; second-wind-zero-heal narrowed to use_item perceptor; new: round-stop-timeout-on-disconnect, nearby-shows-raw-id, ru-duplicate-condition-label, combat-panel-weapon-summary-truncated, master-player-brain-label
Full review of all managed docs against current code, first since 2026-07-14. Sprint 024 changes reflected: movement budget ownership (MOVE/MOVE_TO are FREE at the dispatcher, handlers charge actual distance), structured item props in player-facing payloads, SRD prices on catalog items, item details card and equip i18n scenarios in the e2e playbook. Stale claims found and fixed beyond the sprint delta: - master/ was documented as a live LLM orchestrator; it has been an empty stub since the first commit and nothing imports it - CLI/Telegram adapters described as existing; only adapters/api/ exists - xp_for_kill -> xp_for_cr, perform_level_up moved to its own module - rules/ docstring listed physics/economics (nonexistent), omitted six modules, and claimed all functions are pure - CLAUDE.md put effective_speed/attack_advantage in rules/conditions.py; they are in rules/modifiers.py (attack_advantage does not exist) - README claimed make serve auto-builds the frontend - e2e-playbook: 7 scenarios asserted UI behavior that does not match the code (clock location, move buttons, prone speed, log rendering, depleted action buttons, combat inspect fields, encounter roll trigger) BACKLOG: 7 sprint-024 items marked fixed, use-item-zero-heal split out of second-wind-zero-heal. ROADMAP: sprint 024 Done entry.
…em properties UI) Eight items from the 2026-07-15 live session, closed across three phases: combat movement budget accounting unified, other creatures' technical errors gated out of the player log, faction_hostility_check INFO->DEBUG, Second Wind at full HP no longer reads "0 HP", SRD prices on all catalog items, equip and unequip buttons localized, item properties card in inventory and trade (RU+EN). Backend 2573 unit, frontend 299, integration 166. Post-audit E2E 26/26, no blockers. Audit triaged: 2 quick-fixes applied, the rest already tracked. Also fixes a pre-existing flake in test_timeout_preserves_lifecycle_until_same_ thread_stops: the test lowered the round-stop deadline to 10ms to exercise the timeout path and never restored it, so the later stop_round and the fixture teardown raced a live round thread against a 10ms join. Restore the default once the timeout assertions are done. Verified over 12 consecutive runs.
vladmesh
enabled auto-merge
July 16, 2026 17:06
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.
Closes sprint 024. Eight items from the live session of 2026-07-15, picked for maximum effect per line of code. Does not advance the simulation-core epic; this was an operator-requested UX sprint.
Phase 1 — combat readability and tactics
MOVE→CostType.FREE,handle_movecharges the distance actually moved atomically,CostType.MOVEMENTremoved. The dispatcher owns action/bonus/reaction; movement handlers ownmovement_remaining.build_action_resultgateserror/budgeton the player).faction_hostility_checkINFO → DEBUG, and the relation fn is built once per awareness rebuild instead of once per pair. That single event was 70.8% of the backend log in the live session.Phase 2 — trading and equipment polish
priceon all 31 catalog entries, so starting gear can be unequipped and sold. No code changes needed; the plumbing already carried price through.Phase 3 — item properties UI
propsbuilt from the typed defs across all four player-facing channels (inventory, equipment, merchant, loot).ItemDetailscard renders localized properties in inventory and trade, RU and EN, for all five item kinds.Notable
The premise of
combat-move-budget-not-consumed("budget is never charged, kiting is infinite") turned out to be wrong. Code recon before the fix showed the dispatcher was charging the budget correctly and speed=30 stopped at 30 ft. The real defect was the split accounting, where the latent bugs lived: diagonals charged a flat 5 ft instead of 5/10, and a blocked or partial step charged the request rather than the distance travelled. The task was reformulated rather than implemented as written.hide-world-travel-in-combatwas found already fixed since sprint 009 and marked superseded.Verification
Closing also ran a full
/update-docs, which found documentation drift wider than this sprint's delta:master/was documented as a live LLM orchestrator (an empty stub since the first commit that nothing imports), CLI/Telegram adapters described as existing,xp_for_killvs the realxp_for_cr, and 7 e2e-playbook scenarios that disagreed with actual behavior. Also fixes a pre-existing flake intest_timeout_preserves_lifecycle_until_same_thread_stops(a 10ms round-stop deadline was never restored, racing the fixture teardown against a live round thread).Produced autonomously.