Crystal Resonance polish, Banishment greybox, and asset QA / design docs#2
Merged
Conversation
forced the proxy, decorative lane, orb stack, and vignette to use the same explicit playfield height in iOSDungeonResonancePlayView.swift, instead of letting inner layers expand independently. For the next device run, the key thing to check is whether these lines stabilize: UIKit proxy: layoutSubviews bounds.height ... UIKit proxy: updateContentHeight ... scrollRange ...
Improve VoiceOver interaction and control state for the dungeon resonance game: - Remove automatic objective announcements (.onAppear) in iOSDungeonDescentView to avoid redundant prompts on navigation. - Increase iOSResonanceAlignment.lockedMaxPoints to 52 (with comment) so coarse VoiceOver scrolls can settle into the locked state. - Add computed VoiceOver scroll status in iOSDungeonResonancePlayView (selected lane name + alignment band) and wire it into the scroll proxy's accessibility status. - Consolidate playfield controls: make playfieldControlsContent accept an isEnabled flag, disable the seal button when target is not reachable, and update accessibility hints accordingly (remove the hidden fallback view). - Update iOSResonanceVoiceOverScrollProxyCoordinator to conform to UIScrollViewAccessibilityDelegate, expose accessibilityScrollStatus(for:), and adjust accessibility notification posting (use UIScrollView as argument, tweak timings and re-post layoutChanged) to improve announcement reliability. - Wire accessibilityScrollStatusText through the UIViewRepresentable coordinator. Also includes an updated Xcode user workspace state file.
Emit multimodal feedback when VoiceOver scroll proxy snaps between lane slots: introduce laneSlot intent/input and laneSlotTick, map reducer input to a new tick intent, and add laneSlotCue to QuestFeedbackProfile with sensible defaults and tests. Wire iOS UI to notify the coordinator (onLaneSlotChanged handler, view model notifyResonanceLaneSlotChanged) and invoke the callback when the proxy snaps; adjust lane spacing/stride math and intrinsic heights to improve three-finger VO scrolling. Add localized VoiceOver names for resonance items and several UI visual/background tweaks to better contrast playback panels.
Add agent guidance and tooling notes, asset pipeline utilities, and accessibility/visual/audio improvements for the Crystal Resonance feature. - Add .cursor rule and CLAUDE.md to require following AGENTS.md and document agent toolchain (allowed/forbidden CLI/runtime use). - Update AGENTS.md with maintainer agent boundaries, Cursor/Codex/Claude behavior, and utility notes. - Ignore PNG backup files in .gitignore; add utility/ensure_png_rgba.py and update remove_white_background.py. - Replace/update numerous Assets.xcassets PNGs (asset updates for resonance/room art and icons). - iOS feedback: iOSAudioFeedbackRenderer: special-case laneSlotStep for VoiceOver and engine-fallback system sound, add laneSlotStep tone, tweak amplitudes for several cues. - iOSHapticFeedbackRenderer: add UISelectionFeedbackGenerator and selectionChanged handling; prepare generators before use. - Resonance UI: introduce iOSResonanceWideCanvasImage helper and iOSResonanceReticleDonutMask; replace direct Image usage with wide-canvas handling to preserve visual weight of centered wide masters; tune opacities/shadows and remove blur that caused artifacts. - Accessibility & VoiceOver: localize orb labels, add voiceOver trailing slack & stable room identity, snap selection to target row on room changes, mirror scroll state between VO proxy and lane, use main-queue dispatching for some state updates. - Misc: small comments, layout tweaks, and test/Scoring/RankThresholds adjustments. Overall: improves asset handling, visual fidelity for wide-canvas PNGs, and VoiceOver/audio/haptic accessibility behavior while documenting agent policies and adding pipeline tooling.
Introduce The Banishment feature and wire it into navigation: add iOSBanishmentQuestView and BanishmentQuestViewModel (phases, trap overlay, VO escape handling, scoring/timer/session flow) and map GameKind.banishment through iOSAppRouter and iOSRootView. Remove the legacy Rogue Gauntlet view. Update the Basics sequence and routing to include the Banishment step instead of the Rogue game. Refine Dungeon Resonance visuals and layout math: elliptical reticle hole sized to Moonstone aspect ratio, tuned orb masking/gradients, selection scaling/tilt behavior, and more accurate lane/aim-line scrolling/snapping calculations. Also update localization, screenshots/docs, memlog entries, and related tests to reflect these changes.
Add deterministic lane seeding, decoy-first behavior, and UI/VO improvements for Crystal Resonance. View changes: pass continue button titles and initialLaneIndexOverride into resonance play view; prefer a decoy start unless an override is provided. ViewModel: add resonanceInitialLaneIndexOverride, reset it at level transitions, rename/randomize helpers for lane layout, and seed randomized rooms for L1–L3. Accessibility: tweak VoiceOver scroll coordinator (remove duplicate announcement, shorten follow-up delay) and ensure layoutChanged is re-posted. Visuals: replace destinationOut reticle mask with an even-odd Shape to avoid compositing artifacts, adjust Lights-Off presentation (black playfield + lane-only blackout, hide center orb), and make the L1 gesture tip scrollable. Localization: add continue-to-* strings and copy tweaks. Tests/docs/tools: add a unit test for randomized room pool; add image-gen prompt template and a new PNG QA script (utility/qa_crystal_resonance_png_assets.py), update design/research docs, and extend ensure_png_rgba asset prefixes. These changes improve determinism for screenshots, accessibility reliability, visual masking stability, and introduce automated PNG QA for asset correctness.
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.
Summary
This PR ships The Banishment greybox flow, improves Crystal Resonance (Lights Off, seal/copy, VoiceOver scroll landing, lane randomization), adds automated PNG QA and a generative image prompt template, and updates design / memlog docs so art and LLM workflows stay aligned with what works in-app.
The Banishment (the-banishment)
Greybox quest: ward trap → timed towers → dark tower; accessibilityAction(.escape) for two-finger scrub teaching; GameSession / coordinator for scored run; localized strings, routing, basics sequence, result copy.
Routing: AppRoute.theBanishment, hub/play integration.
Fixes: Swift access for Banishment types; ra11yTitle3 in RA11yCore for trap typography.
Tests: Hub / catalog / scoring coverage; HubViewModelTests includes banishment when checking stored results.
Crystal Resonance (gameplay & accessibility)
L3 Lights Off: Enchanter-style black playfield, ra11yLightsOffGameplayBlackout on the glyph lane only, orb/reticle hidden in L3; removed vignette-only approach for the final trial.
Seal / flow copy: “Activate the Seal”; contextual continue: “Continue to Rising Challenge” / “Continue to Final Trial”; hint string aligned.
VoiceOver scroll proxy: Two layoutChanged posts (timing) for reliable iPad landing; removed redundant .announcement to avoid double-speak with label + hint.
Reticle: Even–odd donut mask instead of destinationOut compositing (reduces grey flash on seal).
L1 tip UI: Scrollable tip card + shorter VO-focus copy.
Lane replayability: L1 & L2 use randomizedRoomsPreservingPool when randomization is allowed; initial scroll slot prefers a decoy (not pre-aligned Moonstone); resonanceInitialLaneIndexOverride for screenshot determinism (dungeonFirstAttempt).
Checkerboard / art: Reverted experimental ra11yGameFallbackBackground backdrops behind wide-canvas PNGs (regressed other art; did not fix moonstone checkerboard — fix at source PNG / pipeline).
Tooling
utility/qa_crystal_resonance_png_assets.py: Validates Crystal Resonance catalog PNGs (presence, RGB vs RGBA for sprites, coarse halo/empty heuristics); --strict-warnings, --verbose-ok, --llm-snippet prints the ImageGen template.
utility/ensure_png_rgba.py: dungeon_target_ and dungeon_decoy_ included in edge sprite normalization.
Documentation
memlog/requirements/Design/CrystalResonance-ImageGen-PromptTemplate.txt: Generative image prompts only (global + per-asset); no engineering “run this script” inside model-facing text.
memlog/requirements/Design/DesignProcess.md: Phase 4 generative tools + Phase 5 PNG QA vs ImageGen split; artefact checklist; revision note.
memlog/research/CrystalResonance-Asset-And-Scroll-QC.md: §5 QA script, §6 commands, L3 blackout row, ImageGen vs QA cross-links.
memlog/research/CrystalResonance-VoiceOverScrollProxy-Investigation.md: Status + coordinator behavior revision table.
memlog/requirements/Phase2-Roadmap.txt: M6 / M7 marked IN PROGRESS with short implementation notes.