Improvement punch list
Improvement punch list — rolling polish-audit log
Section titled “Improvement punch list — rolling polish-audit log”Staging area for the 2026-10-02 improvement loop (one investigation every 10 min for 6 h).
Nothing here gets fixed by the loop itself — Chris triages items onto
docs/RELEASE-1.0.1.md before any fix, per project rules.
Run protocol (each loop run follows this):
- Read the newest run section below to learn the last category covered.
- Pick the NEXT category in this cycle:
- Asset-fiction mismatch (marketing/icon vs real in-game assets)
- Snap-vs-ramp effects (boolean/threshold-driven feedback for continuous quantities)
- UI pattern inconsistency (same job, different pattern across screens)
- Invisible progression / undifferentiated abilities (upgrade tiers the player can’t perceive)
- Render ignores sim data (unread fx_event fields, undrawn sim state, hardcoded colours)
- Telemetry-driven improvement (real death/hitch/behaviour data suggests a fix)
- Run the sweep per the polish categories in
.claude/skills/bh-overnight-audit-loop/references/polish-categories.md. Investigation only — no code changes without sign-off. Dedupe against every previous section below. - Append a new
## Run N — <category> — <timestamp>section: concrete findings with file:line evidence, or “no new findings” plus exactly what ground was covered (so later runs don’t repeat it). - Commit just this file (
docs(polish): loop run N — <category> — <n> findings),git pull --rebasethen push; if push is blocked, leave the commit local. - If it is past 2026-10-02 06:50 BST, do not run a sweep — cancel this loop (Loop tool → list → cancel) and post a closing summary of total findings.
Run 1 — Asset-fiction mismatch — 2026-10-02 01:00 BST
Section titled “Run 1 — Asset-fiction mismatch — 2026-10-02 01:00 BST”6 findings. Method: git-history freshness audit of every player-facing static asset vs the overhaul dates that changed its subject (2026-07-03 HUD polish, 2026-07-22 glow rework, 2026-09-24 icon re-bake, 2026-09-28 weapon FX v2). No pixels judged — evidence is last-modified commits.
marketing/appstore/{iphone,ipad,tv}/*.png— last touched 2026-09-24 (b44d4d1e): live App Store 1.0 screenshots show pre-FX-v2 flat weapon visuals.marketing/appstore/mac/01–06_*.png— 2026-06-30 (731a1c79): stalest set, predates the HUD polish pass, glow rework AND FX v2 (3 overhauls behind).marketing/appstore/icon/icon_60.png/icon_120.png— 2026-06-30 (0210374c), sourced from the OLD genericicon.png; the real icon re-bake (bdc7122b, 2026-09-24, real Nova hull) never flowed into these thumbs.marketing/appstore/press/hero.png,one-sheet.png— 2026-06-30: press key art predates every visual overhaul.marketing/trailer/cards/*.png— 2026-06-30: trailer frames predate glow rework + FX v2.docs-site/public/images/**— all 2026-07-05 (69175d91/fca91eaa): every “real game frame” on the docs site shows the pre-rework look; weapon-icon set covers only 7 of bible’s 16 weapons.
Ground covered / FRESH (don’t re-audit): platform/tvos/icon* + xcassets (2026-09-24 re-bake, real hull); marketing site repo ~/Claude/bullet-heaven-site (rebuilt 2026-10-01 f3d156b, post-FX-v2 images, 16-weapon table matches data/bible.json, roster gap already documented in its AUDIT-2026-10-01.md); concept-art/ (labelled concept); marketing/raw/ (untracked).
Suggested triage order: device screenshot sets (1) → Mac set (2) → icon thumbs (3) → press kit (4) → trailer cards (5) → docs-site images (6). All are re-captures/re-bakes, not code changes.
Run 2 — Snap-vs-ramp effects — 2026-10-02 01:10 BST
Section titled “Run 2 — Snap-vs-ramp effects — 2026-10-02 01:10 BST”5 findings. Method: grep of render/fx/ui/main.gd for boolean setters + hard-threshold call sites gating feedback whose underlying quantity is continuous; the fixed ScreenFeedback.set_hp_fraction case is the fix template.
- HUD HP-bar danger pulse snaps at 30% —
ui/hud.gd:232(P1) /:285(P2): pulse depth is afrac < 0.3ternary while colour ramps continuously; also out of sync withScreenFeedback.LOW_HP_START_FRAC = 0.5(fx/screen_feedback.gd:36). Fix: amplitude = eased low-HP ramp, start 0.5. - HUD HP-block visibility two-steps at 50% —
ui/hud.gd:251-254/:296:above_half_hpbool switches baseline alpha between hard 1.0 and the hit-flash curve. Fix: continuous floormaxf(flash, ramp(frac)). - Warden boss colour flips WHITE→full crimson in one frame —
main.gd:2257-2258:if enraged: return vivid; return WHITE; enrage latches at 40% HP (sim/boss_warden.gd:100). Fix: continuous lerp like other boss renderers’hurt = 1 - hp_frac; keep the latch only for cadence. - Graviton lens enrage term is a +0.25 step —
main.gd:2718-2722:enr := 1.0 if enragedjumps the swirl instantly at the latch (sim/graviton.gd:74) whilepullramps. Fix: drive from thehp_fracalready exposed atsim/graviton.gd:71. - Boss2 enrage aura snaps on at fixed intensity —
render/boss2_renderer.gd:73(if enraged:; latchsim/boss2.gd:115). Fix: alpha-ramp with1 - hp_frac. (Same-shaped branches inrender/eye_renderer.gd:80,render/graviton_renderer.gd:73,render/funzo_renderer.gd:76already carry a continuous hurt ramp alongside — borderline, lower priority.)
Ground covered / fine (don’t re-sweep): set_hp_fraction + eased ramp (fx/screen_feedback.gd:185, fed main.gd:2065); player heal/tilt, weapon_fx_layer.set_dim(d) (main.gd:2686), screen_punch damage scaling (main.gd:2054), audio_manager.set_weapon_load (audio/audio_manager.gd:394), touch-ability charge fractions, gold/shop-affordability glows (binary facts), graviton/eye/funzo sim-side escalation already continuous.
Run 3 — UI pattern inconsistency — 2026-10-02 01:20 BST
Section titled “Run 3 — UI pattern inconsistency — 2026-10-02 01:20 BST”4 findings — all design-judgment calls for Chris, no clear defects. Key discovery: the convention itself has forked. The full start_menu carousel no longer exists (replaced 2026-09-24 by a vertical glass row list, ui/start_menu.gd:1-10), so the game now has FOUR picker idioms: hero-card carousel, all-visible card strip, vertical list, confirm-to-cycle rows.
- Start-menu mode picker vs ship picker — modes/actions are a vertical
VBoxContainerofGlassPanelrows with up/down nav (ui/start_menu.gd:80-88,:447-448) while the equivalent ship picker uses the hero-card carousel (ui/ship_config_panel.gd). Same job, two patterns — but appears deliberate (2026-09-24 redesign). - Death Results vs Pause menu action lists — Results: horizontal 3-button row, LEFT/RIGHT nav (
ui/results_panel.gd:36-37,:529-533); Pause: vertical button column, UP/DOWN (ui/pause_menu.gd:32,:505-509). Two orientations/nav axes for the same “pick 1 of N actions” job. Carousel removal on Results was Chris-directed 2026-09-26 (phone paging hid options). - Drone Bay third idiom — per-slot “pick 1 of N” via confirm-to-cycle rows (
ui/drone_bay_panel.gd:118,:140,:279). Arguably right for slot-fitting, but confirms the fork. - Stale exemplar in our own docs — skill
bh-polish-audit+DESIGN.mdconventions still citestart_menu.gd’s drag-physics carousel as the pattern exemplar; it’s gone. LevelUpPanel + DimensionChoice now form a consistent all-visible card-strip pair (ui/level_up_panel.gd:244-248,ui/dimension_choice_panel.gd:157-200) that just doesn’t match the doc. Doc should record which idiom is canonical going forward.
Decision needed from Chris: which picker idiom is canonical (hero-card carousel / all-visible card strip / list / cycle-rows), then re-align docs + outliers. Past confirmed cases (Dimension Choice, Results actions) were deliberately redesigned away — not defects.
Ground covered / fine: codex (browse), debug settings (toggles), stats sheet, meta shop (tabs+grid, hulls delegated to SHIP panel :67), all HUD/overlay panels, dialogue box, level_up_panel_legacy (retained variant).
Run 4 — Invisible progression — 2026-10-02 01:30 BST
Section titled “Run 4 — Invisible progression — 2026-10-02 01:30 BST”3 grouped findings (17 items). Method: FX v2 coverage cross-ref of all 17 weapons vs V2_LOOKS; manifest 0-score cards; threshold/evolution table completeness; meta-upgrade render consumers.
- 11 weapons still have NO progression visual — pulse, beam, turret, scatter, chalice, railgun, scar_tissue, momentum_core, chronowell, thunder_wake, wildfire. FX v2 is 6-of-17 merged (batches 1-2 at
4ebccfcc/50ca79b5); notably batch 2 shipped Beam/Railgun mechanics under the v1 look — noV2_LOOKSentry (fx/fx_manager.gd:38), Railgun v2 look still unpromoted infx/weapons/candidates/. Fix pattern: entry + look readingWeaponVfx.power/rungs/evolved(asfx/weapons/blade_slash_look.gd:22-28). Beam width bug was fixed but beam still has no per-level/per-evolve look; wildfire/thunder_wake zones drawn but binary, not tiered. - 5 sim states confirmed still invisible (manifest 0-score MISSING cards,
tools/vfx_library/library_manifest.gd:124-136):elemental_aura(stack counts affect damage, no renderer),railgun_mark(damage-amplifying mark invisible),disruptor_field(slow/suppress field has no visible radius),wisp_phase(untargetable phase looks solid),scar_tissue_meter(stack buildup invisible until discharge). - Meta-shop upgrades apply stats with no in-run perception —
data/bible.json.data.meta_upgradestiers (armor, fire_rate, pickup_radius, move_speed, e.g. vitality lvl 5) applied stat-only viasim/meta_run_setup.gd:24; only max_hp is perceivable (HP bar). Needs a call: addvisual_tier()-style consumers (pickup ring, thruster intensity) or accept menu-only.
Table completeness fine (don’t re-sweep): sim/weapon_thresholds.gd (16) + sim/weapon_evolutions.gd:15-31 (17) cover the full roster, no gap rows; drones have no tier table by design.
Run 5 — Render ignores sim data — 2026-10-02 01:40 BST
Section titled “Run 5 — Render ignores sim data — 2026-10-02 01:40 BST”10 new findings across the 3 mechanical sweeps (ignored event fields / undrawn sim state / hardcoded colour). Prior confirmed cases verified: blade arc FIXED (fx/fx_manager.gd:696); wildfire/thunder_wake zones now drawn (render/zone_renderer.gd:166-174); beam width still ignored by the legacy path (fx/fx_manager.gd:662-668, only v2 candidate looks read it) — partial fix.
- Halo-chain tethers + their buffs are completely invisible —
sim/halo_chain_director.gd:53_active_tethers(explicitly “for render/debug”) has zero render readers; the +15%/member damage mult (sim/sim.gd:3110) and knockback immunity (sim/elemental_system.gd:147) mean enemies near packs hit up to +45% harder with no visual cue. Highest-impact finding of the run. beam.hits(sim/weapon_beam.gd:66) — no consumer infx/at all.mark_popignoreshits+element(sim/weapon_railgun.gd:144→fx/fx_manager.gd:678-684reads only pos/radius).reactionslam ignoresradius— elite brute slam sendsELITE_BRUTE_SLAM_RADIUS(sim/enemy_attacks.gd:598) but fx draws fixedREACTION_BURST_RING = 120.0(fx/fx_manager.gd:42,:769).ignitecarrieselement(sim/weapon_wildfire.gd:66) but fx hardcodes orange (fx/fx_manager.gd:756).turret_firehardcodes amber + producer stamps no element (fx/fx_manager.gd:715,sim/weapon_turret.gd:65) — turret is element-selectable.scatter_firesame pattern (fx/fx_manager.gd:717,sim/weapon_scatter.gd:57).wildfire_popsame pattern (fx/fx_manager.gd:729,sim/weapon_wildfire.gd:104).MARK_POP_COLfixed light-gold ignores railgun’s selectableelement_idx(fx/fx_manager.gd:26) — overlaps finding 3.momentum_charged_firehardcodes (fx/fx_manager.gd:748) on an element-bearing weapon — borderline; chronowell’s pale cyan is fixed zone identity by design (fine).
Fix pattern for all: read the field / derive from ElementPalette, then pin with a GUT test. Ground covered clean: death.type_id (audio-consumed), accum_warn.radius, dmgnum.big, thunder_wake from/radius, turret positions, eye laser targets, elite beams/warps.
Run 6 — Telemetry-driven improvement — 2026-10-02 01:50 BST
Section titled “Run 6 — Telemetry-driven improvement — 2026-10-02 01:50 BST”4 findings from live D1 (human runs n≈308, ATV samples build≥235, hitches build≥235). Method: death-cause + run-length funnel from runs (is_auto=0/NULL, charger label merged), hitch/fps from hitches/samples.
- The first 2 minutes are a cliff: 63% of human runs (193/346) end <2m, and swarmer alone causes 44% of all human deaths (136 deaths, avg level 3.9, avg 81s). The early swarm wall dominates everything else; charger is the secondary wall (73 deaths, lvl 12.4, 226s). Improvement candidate: early-game pacing audit (spawn curve/forgiveness in the first 90s) —
docs/RELEASE-1.0.1.mdearly-game items should be weighed against this. - 12 runs flagged human have
weapons_listNULL and absurd dps (1,858,568 avg — attract/dev sessions predating or bypassingis_auto), plus 12 NULL + 11 emptydeath_causerows — the funnel/death numbers above include this contamination (~7%). Improvement: fix the run-report path sois_auto/weapons_listare always set, or exclude these from future queries. - A build id 9001 session is writing ATV samples at 46.4 fps (n=254) — an out-of-range build id (dev-spoofed?) polluting per-build perf stats. Hygiene: make DevFlags builds report a distinguishable real BUILD.
- Perf verified healthy on current builds — no new work needed: builds 236-240 averaged 105-181ms play hitches (243 peaked at ~1.5s with pipeline compiles), but 244-246 show no play-state hitches in the top rows and hold ~59 fps / 16.9-17.1ms with sim_ms 1.2-3.0 — the shader-bake/PSO-prewarm arc reads as landed. 238’s 38.7 fps low is the known late-run collapse already triaged in RELEASE-1.0.1 §1.
Weapon diversity (Q5): blade-only 64 runs (starter/tutorial-heavy), blaster-centric lists dominate after — consistent with the funnel, not a separate finding. Ghost/accumulator deaths occur late (lvl 20-36) = healthy curve.
Run 7 — Asset-fiction mismatch (deep: data + copy) — 2026-10-02 02:00 BST
Section titled “Run 7 — Asset-fiction mismatch (deep: data + copy) — 2026-10-02 02:00 BST”3 findings. Cycle 2 went past run 1’s image-freshness pass into data/copy that claims to describe the game: bestiary vs bible, App Store copy, web-demo build. Tutorial/help-text sweep came back clean (token-driven, matches real bindings).
sentinelbestiary stats block is dead-stale —data/bestiary.jsonentries.sentinel.stats: hp 1800 vs bible 3400, speed 45 vs 60, contact_damage 44 vs 22, armor 0 vs 5, elementkineticvsvoid. Not player-visible today (BestiaryLoader_merge_oneprefers live bible stats,content/bestiary_loader.gd:66-80), but it’s a fallback that silently becomes the displayed source if the bible entry is removed. Warden block (concurrent fix) verified correct; all 30 keys have bible entries; codex has no hardcoded copy.- App Store copy version framing + feature gaps —
marketing/appstore/copy.md“What’s New (v0.1): First release…” while the store build is 1.0/37 (SUBMIT.md §3 still points at the v0.1 label); description never mentions Story mode (“Ascent: The Spectrum”), the codex/bestiary, or gold-shop meta-unlocks. No FALSE claims found (elemental/dimension/boss/drone claims all verified 2026-09-23, 30b6ffd8). - Public web demo is 1.0-era and docs say otherwise — live
bullet-heaven-play.lumara.digitalindex.pck= 2026-09-28 21:23 GMT export (byte-identical to last local export), predating the Warden rebuild/FX v2-era main (BUILD 242+);docs/architecture/dev-tools.md:82still claims the demo is “CURRENT at build 78”. Re-deployscripts/deploy-demo.shafter the next merge and fix the doc line.
Ground covered clean (don’t re-sweep): bestiary↔bible full 30-key diff + codex render path; store copy claims vs sim (2026-09-23 pass held); tutorial/help/dialogue control tokens vs input/input_router.gd and touch UI — no drift.
Run 8 — Snap-vs-ramp (cycle 2) — 2026-10-02 02:10 BST
Section titled “Run 8 — Snap-vs-ramp (cycle 2) — 2026-10-02 02:10 BST”3 new findings; all 5 run-2 findings re-checked — NONE fixed. Warden enrage snap NOT fixed by the rebuild, just MOVED: now fx/boss/warden_fx.gd:101, :182 (_tint = HOSTILE_BODY.lightened(0.2) if enraged else HOSTILE_BODY — still a binary lightening at the 40% latch; supersede run-2 finding 3’s old main.gd:2257 location). HP pulse (ui/hud.gd:238/:290), above_half_hp (:251-252/:296-297), graviton enr step (main.gd:2749, :2752-2754), boss2 aura (render/boss2_renderer.gd:73-75) all still live.
- Area warp is a frozen 1.2s beat with no VFX, then an instant background swap —
main.gd:2780-2787_begin_warp→_finish_warp; comment says “Streak/fade VFX is a noted polish follow-up”. Fix: drive dim/flash off the_warp_timer / WARP_DURATIONfraction — the warp-dash path (main.gd:2697-2717,set_dim(t),set_warp_smear) already shows the pattern. - Damage numbers are binary big/small —
fx/damage_numbers.gd:81-82:font_size 36 if big else 20+ gold-vs-white on thebigbool (dealt >= DMGNUM_BIG), hiding the continuousamount. Fix: remap font 20→36 and lerp colour toward gold. Same two-state split in the fx_managerdmgnumspark. - Boss enrage audio is a one-shot sting, never a swelling state —
audio/audio_manager.gd:63-64maps ENRAGED → a sharedgraviton_singularityone-shot; below the latch nothing escalates. Fix: low-intensity looping enrage bed on the boss voice with pitch/volume ramped from boss HP frac, sting as latch accent.
Ground covered clean (don’t re-sweep): zone renderers (render/zone_renderer.gd — all fades + radii continuous, incl. funzo growth); boss telegraphs (bomb/lancer/graviton rings + warden tele/fire_charge 0..1 looks, fx/boss/warden_charge_look.gd:5-9); drone dock cooldowns, touch ability rings, decoy durability fade; warden rebuild FX beyond the enrage tint (charge convergence, missile flicker, body spin 1→4x flare).
Run 9 — UI pattern inconsistency (cycle 2: DESIGN.md conventions) — 2026-10-02 02:20 BST
Section titled “Run 9 — UI pattern inconsistency (cycle 2: DESIGN.md conventions) — 2026-10-02 02:20 BST”4 drift findings. This pass swept the non-picker DESIGN.md conventions across ui/ (anchoring, typography, glass family, bars, colour discipline, MenuNav, motion). Run 3’s picker-idiom fork not re-swept.
- Glass spec has drifted codebase-wide — DESIGN.md says translucent bg alpha 0.6-0.66; the only literal complier is
ui/weapon_panel.gd:203(0.6). Every other panel sits at 0.82-0.97 opaque:ui/level_up_panel.gd:608(0.82),ui/ship_config_panel.gd:441(0.85),ui/codex_overlay.gd:71+ui/meta_shop_panel.gd:249(0.92),ui/dialogue_box.gd:92(0.95),ui/pause_menu.gd:459+ui/debug_settings_panel.gd:882(0.97). Doc or panels need re-pinning — Chris’s call which direction (the Nova look at 0.94 was Chris-requested, so “opaque” may be the real convention now). - Dialogue box glass outlier —
ui/dialogue_box.gd:92-94: 2px border at full-strength cyan (family: 1-2px at ~0.22-0.42 alpha) + shadow_size 10 (family: 3-7). - Meta-shop tab chrome breaks the single-cyan pillar —
ui/meta_shop_panel.gd:1723-1728_cat_color(): purple/orange/green/pink per category. Categories aren’t weapons/elements, so this reads as decorative multi-hue chrome — unless Chris calls it category identity (drone class colours indrone_dock.gd:26ARE identity and fine). - Stats sheet hand-rolls the only non-family bar-like style —
ui/stats_sheet.gd:585-590scrollbar (white 0.06 track, accent 0.55 grab, corner_radius 2) unrelated tohud.gd:365-384_bar_*family. Borderline (it’s a scrollbar).
Verified compliant (don’t re-sweep): anchoring (no hardcoded-position bug class anywhere), typography (all via NeonTheme fonts), bars (HP+boss share _bar_*), MenuNav (raw keycodes found are additive keyboard shortcuts, not parity breaks), motion timings (idle breaths 0.55-1.4s, level-up 0.22s + 0.8s failsafe, low-HP pulse reuses the semantic ramp).
Deliberate outliers (confirm, don’t fix): ui/debug_overlay.gd:25 absolute positioning (dev-only); ui/ship_config_panel.gd:363-429 viewport-math layout inside FULL_RECT root (resize-safe, not the bug class); Nova dual style family (Chris-requested, VisualLook.nova); level_up_panel_legacy.gd retained variant.
Run 10 — Invisible progression (cycle 2: non-weapon systems) — 2026-10-02 02:30 BST
Section titled “Run 10 — Invisible progression (cycle 2: non-weapon systems) — 2026-10-02 02:30 BST”4 new findings. Pass-1 re-checks post-warden-merge: ALL still open — V2_LOOKS still only 5 weapons (fx/fx_manager.gd:38), the 5 invisible states still score 0 in tools/vfx_library/library_manifest.gd:30-31, meta-shop stats still consumer-less. This pass swept drones/abilities/hulls/elites/mods/career/audio.
- Weapon dock draws NO progression at all — no level, no mod, no evolve state —
sim/upgrade_system.gd:323apply_weapon_mod()alters power/rate butui/weapon_icon.gdreads none of it; evolved names only appear on the end-run results panel (ui/results_panel.gd:396). Fix: level pips + mod ring segment on the dock icon frompilot.arsenal. - Drone class-upgrade tiers invisible —
sim/meta_state.gd:149_apply_class_upgrades()scales dmg/durability/radius/speed perdrone-<class>-<attr>level, butsim/drone_director.gd:523-528drones_render_info()exposes no tier/power field andrender/decoy_renderer.gd:38uses a fixed render size. Fix: addpowerto render info, scale size/glow. - Weapon audio never escalates —
audio/audio_manager.gd:213play()takes only key/volume/pitch; no level/evolved parameter anywhere (only per-shot random pitch:102and load density:394). An evolved weapon sounds identical to level 1. Fix: pass a tier/pitchMult from the fx event weapons already emit. - Warp-cooldown upgrade tier invisible —
sim/sim.gd:2437(dash_cd *= pilot.dash_cooldown_mult); HUD ring shows fill fraction only, so a faster warp is perceivable only by timing it. Fix: tier pip/rim brightness fromdash_cooldown_mult.
Borderline: career/meta has end-run reflection only (banked gold + shop pulse, ui/results_panel.gd:250, :258-270), zero mid-run.
Fine (don’t re-sweep): ship hulls — render/player_renderer.gd:20-58 renders 5 per-tier bands, hue ascent, ascension ring pop; elites — distinct shapes (render/archetype_renderer.gd:14, :56), dedicated HP bars + attack FX.
Run 11 — Render ignores sim data (cycle 2: render-info dicts + player-side state) — 2026-10-02 02:40 BST
Section titled “Run 11 — Render ignores sim data (cycle 2: render-info dicts + player-side state) — 2026-10-02 02:40 BST”6 new findings. Pass-1 re-checks: all 10 still open (one partial: mark_pop now reads radius at fx/fx_manager.gd:684 but still hardcodes MARK_POP_COL, ignores hits/element; beam legacy still drops width at :674). This pass swept render-info dicts, player-side statuses, HUD ambient state, armour/element identity, audio.
- Player-side DoT and slows are completely invisible — the most damaging class (changes player decisions, not just polish):
pilot.burn_timer(elite burn, setsim/elite_kit.gd:341, ticked:351) has zero render/HUD/fx consumers — the player takes ticking damage with no on-ship visual;pilot.kite_slow_timer(sim/elite_kit.gd:343/345,sim/sim.gd:3127) andpilot.beam_slow_timer(:298) slow with no status visual;player.move_mult(sim/sim.gd:816) sources render but the slowed state itself is unread. Fix: ship-heat tint/sparks for burn, vignette/tint for slow keyed onmove_mult < 1. Good precedent exists:warp_scramble_timerIS drawn (render/elite_fx_renderer.gd:54). - Active Dimension is invisible after the choice popup —
main.gd:681-689_apply_area_changeonly retints bg/border; nothing in ui/render readsAreaDefsduring play. Hidden: dimension name + its modifier (reward ×, enemy buff, element override). Fix: HUD chip on arrival. - Warden
render_info()["strafing"](sim/boss_warden.gd:542) has zero render/fx consumers — the rebuild spec (2026-10-01-warden-rebuild.md:296) named it as a render contract. No lean/thrust cue while the boss orbits. Fix:warden_fxreads it, adds drift thrust. boss2.render_info()["charge_pos"](sim/boss2.gd:253) unread — renderer usescharge_dironly (minor; boss2 is dev-only today).- Post-warp invulnerability frames render nothing —
RESUME_IFRAMESgrant (main.gd:684); minor (short window) but free forgiveness the player can’t exploit knowingly. - Audio is purely event-driven — zero sim-state reads in
audio/(no boss-proximity or swarm-density ambient layering); verdict logged, overlaps run 10’s weapon-tier finding.
Ground covered clean (don’t re-sweep): eye/graviton/funzo/elite/lancer render-info dicts fully consumed (only the known drone power gap remains); wave pressure (spawn_banner + threat_radar); boss bar name+HP; enemy element tint (render/archetype_renderer.gd:296) + armour silhouettes.
Run 12 — Telemetry (cycle 2: encounters, picks, iOS, quality ladder) — 2026-10-02 02:50 BST
Section titled “Run 12 — Telemetry (cycle 2: encounters, picks, iOS, quality ladder) — 2026-10-02 02:50 BST”4 new findings from live D1. New ground vs run 6: encounters table (n=2,274), build_picks weapon-token aggregation, iOS session coverage, adaptive-quality engagement.
- Warp dash is a panic button, not a skill tool — on CLEARED dash encounters players dashed only 5-11% of the time (charger 0.11, spider 0.05, accumulator 0.07); on CONTACT (hit) outcomes dash_rate jumps to 0.26-0.42. Players clear telegraphs by walking and only dash once it’s too late. Accumulator has the worst clear rate (79% vs charger 89%, spider 95%) and longest contact duration (0.96s). Improvement candidates: dash teaching/incentive, accumulator telegraph readability.
- Weapon picks are heavily concentrated on the visible-progression weapons — nova 134, beam 108, orbit 102, turret 93, pulse 90 vs chalice 5, scythe 5, thunder_wake 5, momentum_core 5, scar_tissue 6, scatter 14, railgun 4, wildfire 3, chronowell 0 (blade/blaster are starters, excluded). The near-zero weapons are exactly run 4’s no-progression-visual list — telemetry now supports the invisible-progression suppresses-picks hypothesis.
- Adaptive quality ladder engagement looks broken/threshold-mismatched — build 238 averaged 40.4 fps / 33.8 ms across 750 sample windows with ZERO degraded windows (quality=0 throughout); build 9001 (the anomalous dev-id build from run 6 finding 3) engaged the ladder in 189/254 windows (avg_q 1.49) at similar-or-better fps (46.4 avg, min 28). Either the ladder is DevFlags-gated, or its engage threshold sits below 238’s collapse. Needs a code-level threshold audit (
render/QualityManager). - Zero iOS device sessions in the recent build range — last iPad sample build 230, last iPhone 206 (the store 1.0 build); everything since (236-246, incl. the warden rebuild + PSO-prewarm arc) has no iPhone/iPad validation at all. Install a dev build on both before the next release.
Ground covered: death-cause funnel/run-length/hitch/fps (run 6, not re-queried); encounters outcome/dash/duration per type; per-weapon pick frequency; iOS session coverage; quality-tier engagement per build.
Run 13 — Asset-fiction mismatch (cycle 3: player-facing strings + audio) — 2026-10-02 03:00 BST
Section titled “Run 13 — Asset-fiction mismatch (cycle 3: player-facing strings + audio) — 2026-10-02 03:00 BST”4 findings. Cycles 1-2 covered images and data; this pass swept naming consistency, the Decoy/Sentinel rule, audio↔content match, and privacy labels. Name chain (project.godot, CFBundleDisplayName, ASC, marketing site) fully CLEAN — zero player-facing “Bullet Heaven”; Decoy/Sentinel rule fully CLEAN (only code comments + legit boss name).
- Warden lunge telegraph is silent and untracked —
boss_swing_startfx (sim/boss_warden.gd:285,:321,:395) has no audio_manager case AND noaudio/sound_map.jsonentry (swing hit + missiles are mapped); every other silent thing is honestly catalogued with"status": "silent"(sound_map.json:179-249— chalice, chronowell, momentum, scar_tissue). - Elemental Dimension hazard rifts emit nothing at all —
sim/dimension_hazards.gd:259,:696-703(drawn byrender/dimension_hazard_renderer.gd) produce no fx_events → no possible audio, no sound_map row. Rift appearance is silent and untracked. - Privacy page’s “No other third party receives it” has a dormant exception — the iOS build embeds the Sentry SDK (no DSN, dormant; declared to ASC in
marketing/appstore/compliance.md). True today, but unlike compliance.md, the site privacy page (~/Claude/bullet-heaven-site/privacy/index.html) has no note that a DSN-config change must update the page in the same change. - Privacy page omits the build-channel probe (App Store/TestFlight receipt existence check) that compliance.md lists — minor, arguably covered by “app build number”.
Borderline (internal convention, Chris’s call): project.godot:6 custom_user_dir_name keeps “Bullet Heaven” in macOS Finder save paths. Chalice/chronowell/momentum/scar_tissue weapon silence is PRE-TRACKED (sound_map “silent”) — not new.
Run 14 — Snap-vs-ramp (cycle 3: spawn/despawn, bars, focus, transitions) — 2026-10-02 03:10 BST
Section titled “Run 14 — Snap-vs-ramp (cycle 3: spawn/despawn, bars, focus, transitions) — 2026-10-02 03:10 BST”6 new findings. Pass 3 swept snap classes passes 1-2 didn’t touch. (The 8 prior findings not re-checked; all were open at last check.)
- Enemy death: corpse vanishes in one frame —
_sweep_deadend-of-tick removal leaves only a 0.16s additive spark (fx/fx_manager.gddeath case); no dissolve/shrink. Fix: render-side dying-ghost pass (last-known pos/colour, scale+alpha out ~0.12s), mirroringrender/funzo_dash_afterimage.gd’s pooled-ghost pattern. - No lagging damage chip on HP/boss bars —
ui/hud.gd:222and:337: fill width tracks HP exactly each frame; damage drops instantly, healing pops. Fix: ghost-fill lerp toward frac at fixed rate (classic chip), both bars. - Focus glow snaps between rows —
ui/theme/glass_panel.gd:35focussetter +ui/results_panel.gd:245-246,ui/drone_bay_panel.gd:234-235:focus = 1.0/0.0assigned directly. Fix: ~0.10s ease-out tween. - Element override recolours everything in one frame —
main.gd:2403_proj_colors()+render/zone_renderer.gd:326-327: when a dimension/mod flips the active element, all in-flight projectiles and live zones snap to the new colour; no lerp on the path. Fix: per-instance colour lerp ~0.15s or fade old-colour instances out. - Pause/codex/panel opens are instant —
main.gd:405,565,573,594visible = true,ui/codex_overlay.gd:111,124; no modulate fade. Fix: 0.15s alpha fade-in/out, consistent with level-up’s entry. - Enemy spawn pop-in at full size —
render/archetype_renderer.gd:765-833: drawn atradius[i]with no spawn-age. Fix: spawn-time column + 0.1s scale ramp.
Ground covered clean: FxManager primitives (rings/beams/slashes fade+grow via tick()); level-up card stagger; ship-config slide+crossfade; start-menu staggered reveal. No combo/streak system exists (F — nothing to ramp).
Run 15 — UI pattern inconsistency (cycle 3: formatting, empty states, settings, hints) — 2026-10-02 03:20 BST
Section titled “Run 15 — UI pattern inconsistency (cycle 3: formatting, empty states, settings, hints) — 2026-10-02 03:20 BST”6 findings. Pass 3 swept number/time/gold formatting, empty/locked states, player-facing settings, hint conventions, iconography. (Picker idioms and DESIGN.md styling already covered.)
- Store players cannot mute the game — no shipped volume/audio control: mute exists only in
ui/debug_settings_panel.gd:396-445, which is DevFlags dev-only. Meanwhile the telemetry opt-out IS player-facing (ui/pause_menu.gd:22,:30,:156-165). Asymmetric settings surface — a shipped game needs at least volume in pause/start menu. - Headline DPS isn’t compacted while sibling rows are —
ui/results_panel.gd:258raw%.0f(e.g.12400 DPS) vs the same panel’s_short()compaction (12.4k,:432-435,:400). Also two time idioms coexist (M:SSat:257vs raw%dsinui/hud.gd:323,ui/drone_bay_panel.gd:164— minor) and gold casing drifts (%d GOLD/GOLDvs"0 gold"inui/meta_shop_panel.gd:225). - All-maxed shop category has no designed state — only fully-empty categories auto-hide (
ui/shop_categories.gd:16-20); a category with everything maxed just sorts last (meta_shop_panel.gd:12), showing a wall of grey MAXED pills. Needs an “all maxed” empty-state treatment. - Zero-kill/zero-gold death run renders bare zeros —
results_panel.gd:257,:267(0 KILLS · 0 GOLD); only the zero-damage case has designed copy (:447). - Run tips violate DESIGN.md twice — objective-panel tips sit top-center (
ui/objective_panel.gd:46-48, fedmain.gd:2592-2644) where the convention is bottom-center transient; and they re-show EVERY run (main.gd:51, reset:1261) instead of being seen-once onboarding. Either the doc or the tips need re-pinning (Chris’s call — tips re-showing may be intentional teaching). - Mixed separators inside one stat string —
ui/stats_sheet.gd:494-503mixes→,/,·in single value lines. Micro.
Handled well (don’t re-sweep): codex locked ??? entries (ui/codex_overlay.gd:153-158), drone bay — empty —, stats sheet +N empty slots, empty-category auto-hide, LOCKED ships; iconography is one clean procedural family (ui/shop_icons.gd, ui/weapon_icon.gd, ui/drone_panel.gd:57, codex live previews — no font-glyph/emoji strays). Damage numbers raw vs _short() — acceptable (live hits), noted only.
Run 16 — Invisible progression (cycle 3: decision-time readability) — 2026-10-02 03:30 BST
Section titled “Run 16 — Invisible progression (cycle 3: decision-time readability) — 2026-10-02 03:30 BST”4 findings. Pass 3 swept readability at the moment of choice (level-up cards, evolution readiness, crystal wallet, story progress) rather than render consumers. Prior items unchanged (one-line re-checks in the log below).
- Evolution fires with zero announcement —
_apply_weapon_thresholds(sim/sim.gd:991-1008) applies crystal rungs including a full evolve with nofx_eventspush anywhere (grep: no evolve/threshold fx event). The only tell is the weapon’s look changing. Fix: push an fx_event (banner + sound) per newly-met rung; minimal version = pickup blip on card confirm. (Crystals are never field pickups — the wallet only changes at card-pick time, silently; same fix covers it.) - Crystal wallet is invisible outside the level-up sheet — only
ui/stats_sheet.gd:58-96readssim.crystals.counts; no HUD counter, no dock rung/evolve-ready indicator (run 10’s dock gap still holds). Between level-ups the player can’t see holdings or evolve-readiness. Fix: HUD wallet row or evolve-ready glow on the dock slot. - No LV n → n+1 on upgrade cards —
weapon_levelstracked (sim/upgrade_system.gd:407-412) but read only bycan_evolve/dev tools; awm:card shows “+50% damage” but not how many Power picks you’ve stacked or that the weapon is 1 pick from evolve-eligible (REQUIRES_LEVEL). Fix: “LV n → n+1” sub-line fromweapon_level(). - Story mode has no chapter/beat number —
ui/hud.gd:261-263,:318-336renders “Region — objective” live (good) but never chapter n-of-m;story.current_room+ region list exist unsurfaced. Fix: add n/m to_story_objective.
Clean (don’t re-sweep): upgrade-vs-new card distinction (why-tag pills ui/level_up_panel.gd:383-402), real stat deltas (ui/upgrade_copy.gd:31-126, upgrade_preview sim/upgrade_system.gd:479-516), crystal-card rung progress (“EVOLVE → name”, 3/5 rows :487-491), no wasted MAXED picks (wm: mods uncapped by design, capped ones pre-filtered :107-112, mod_eligible:247, one-pick Fork :256), no reroll/ban mechanic exists.
Run 17 — Render ignores sim data (cycle 3: coverage + capacity + attribution) — 2026-10-02 03:40 BST
Section titled “Run 17 — Render ignores sim data (cycle 3: coverage + capacity + attribution) — 2026-10-02 03:40 BST”3 findings. Pass 3 swept entity-type→renderer coverage completeness, projectile→fx consumer coverage, MultiMesh/LUT capacity vs telemetry max, mid-run UI staleness, kill attribution.
- Death recap mis-categorizes dimension-hazard damage as melee — hazards damage with source
"hazard"(sim/dimension_hazards.gd:409,414,422,475,574,631) butui/death_recap.gd:13-16_ZONElist is only["funzo","orbiter","burn"], sosuggest_counterstells players to buy armor/kite the swarm for what was a fire/poison zone. Fix: add"hazard". Minor sibling:"funzo_dash"/"brute_slam"also fall to melee — switch to prefix match. - No completeness-guard test for enemy shape coverage — all 32 TYPE_ constants have
_TYPE_SHAPErows today (render/archetype_renderer.gd:87-141) butshape_for(:722-727) silently falls back to a generic triangle for any type_id beyond the table, and no GUT test pins_TYPE_SHAPE.size() == TYPE count(only Nova buckets are pinned,tests/test_nova_units.gd:45). This is exactly the bh-add-content invisible-entity trap, unpinned. Fix: one-line assert. - Boss bar shows one boss via priority chain —
main.gd:2007-2021(Warden→Boss2→Funzo→Graviton→Eye); directors are mutually exclusive in practice and Boss2 dev-only, so noting as design intent — confirm only.
Ground covered clean (don’t re-sweep): every emitted fx kind has a consumer (~30 in fx/fx_manager.gd:640-871, warden kinds in fx/boss/warden_fx.gd, funzo/eye from sim-state readers, audio-only kinds intentional); capacity — ENEMY_CAP 6000 with EntityPool.add() returning -1 at cap + grow-only SwarmRenderer.fit_capacity (render/swarm_renderer.gd:70-76), telemetry max 5246 < cap, no type-indexed colour LUT; pause genuinely freezes sim.tick (main.gd:1415-1425) so mid-run panels can’t go stale; death-recap damage contract otherwise holds (all _hurt_player sites pass a source).
Run 18 — Telemetry (cycle 3: v2 events table) — 2026-10-02 03:50 BST
Section titled “Run 18 — Telemetry (cycle 3: v2 events table) — 2026-10-02 03:50 BST”4 findings. New ground: the v2 events table (now LIVE and populated — 26,720 samples, 3,150 hitches, 476 shop_buys; the bh-telemetry skill’s “events does not exist live” note is stale). Death funnel/fps/encounters/picks already covered in runs 6+12.
- 80% of recorded exits are reason=“crash” (48 of 60 prev_exit events) — builds 211-228, mixed states incl. mid-play at run_time 0.25s and post-gameover at 359s. CAVEAT: Chris’s devicectl-terminate fresh-process test recipe likely masquerades as crash, so some/many of these are test kills. Action: make the client distinguish a dev-kill/SIGTERM from a real crash (or cross-check MetricKit) before treating this as a stability signal — right now the exit-health metric is unusable.
- Tutorial lesson “wake” started 5× and never advanced past step 0; “riftbolt” also stalls at step 0 — every other lesson shows symmetric step 0→2/3 progression (n small: 51 events, mostly one clean completion). Candidate stuck lesson-gate — exactly the harness/gate class CLAUDE.md warns about. Watch/verify with a story_trace run before trusting.
- The legacy
runstable is nearly dead on recent builds — only 1 row (attract) for build ≥236 while 84run_endevents exist; death-cause/build analysis must move toeventsor it silently reads an empty set (run 6’s funnel queries predate this and still work on old builds, but any build-236+ analysis onrunsreturns nothing). - Shop purchases: 80% from the results screen (381) vs 20% from menu (95), all out-of-run (
in_run: 0) — the death→shop funnel is where spending happens; recent id mix is drone-upgrade-heavy (decoy-power, drone-disruptor-*, unlock-drone-bomber). Informational; economy-sim calibration input.
Payload gotchas logged for future queries: event keys are $.id/$.from/$.reason/$.lesson (not item/build/dev); ts is not a usable date column (use marker_ts in data).
Run 19 — Asset-fiction mismatch (cycle 4: prose claims) — 2026-10-02 04:00 BST
Section titled “Run 19 — Asset-fiction mismatch (cycle 4: prose claims) — 2026-10-02 04:00 BST”5 findings. Pass 4 audited prose that claims to describe behavior: bestiary descriptions/counters vs sim, docs-site “current” claims, ASC metadata, display-name consistency.
- Codex tells players skirmishers “drop a powerup when killed” — powerups are disabled —
data/bestiary.json:22-24desc + counter advise chasing a drop that can’t spawn (sim/sim.gd:93POWERUPS_ENABLED := false, off since 2026-09-27). The drop roll happens, nothing spawns. Player-facing fiction in the codex. - Tank’s “armored fire wall… wear the armor down” counter is fiction —
data/bestiary.json:8-9vsdata/bible.json:859"armor": 0; no armor special-case exists insim/. Sustained-fire advice is moot. - Two stale “current” claims in live public docs —
docs/architecture/enemies-bosses-survival.md:12saysSim_Const.BUILD“currently 14” (it’s 242);docs/architecture/art-asset-pipeline.md:130describesADAPTIVE_QUALITY := falsegated on the v0.1 release — the const moved toQualityManager.ENABLED(render/quality_manager.gd:16), v0.1 shipped, and it’s now remote-tunable. (docs/ symlinks into the live docs site, so these are public pages.) - Tank missile name mismatch — bible
data/bible.jsoncalls it “Fireball”, bestiary/codex shows “Tank Missile” (desc says “fired by Tanks” so the bestiary side reads intentional — the bible name looks stale). - VFX library labels the weapon “Pulse” where the player-facing name is “Electricity” —
tools/vfx_library/library_manifest.gd; dev tool only, but it’s the polish-audit reference surface.
Verified accurate (don’t re-check): fleet_kite slow bolt, glass_wisp phase-negate, coil ring-reset, leech knockbreak, accumulator growth, warden range-banded deck + 40% enrage, swarmer fragility. ASC metadata clean (keywords/subtitle/age-rating all match shipped reality). Dialogue only names Blaster/Nova, both accurate.
Run 20 — Snap-vs-ramp (cycle 4: big moments + hit feedback) — 2026-10-02 04:10 BST
Section titled “Run 20 — Snap-vs-ramp (cycle 4: big moments + hit feedback) — 2026-10-02 04:10 BST”6 findings. Pass 4 swept the moments no prior pass touched: boss death, player death, enemy hit feedback, gem magnet, thruster, XP anticipation.
- Boss death pops into a ~54px generic disc — the biggest moment in the game reads small: body removal + all fx are same-tick (
sim/sim.gd:2825-2863), and the dissolve is a FIXED size —fx/death_dissolve.gd:12SIZE := 0.85(~54px),consume()(:39-46) ignores thetype_idthe sim already sends (sim.gd:2772). A screen-filling boss becomes a small disc in one frame. Fix: scale the dissolve (or multi-burst) fromtype_id, 3-4× for bosses. Surrounding layers (shockwavemain.gd:1802, hero lights, victory sting) are fine. - Player death is a hard cut to the results card —
main.gd:1606-1621→_show_results_when_drawn()(:1630-1635) awaits ONE drawn frame then shows results: no slowdown, desaturation, zoom, or fade — in sharp contrast to the ramped level-up convention. Fix: ~1s_time_scalelerp to 0 + fullscreen desat/fade, then results. - Thruster ignores actual speed —
render/player_renderer.gd:199takes no velocity param; the plume (:212-222) varies only with the binarydash_ready(16/9 Hz, ×1.2/×0.8). Identical at full speed and a dead stop. Fix: plume size+alpha 0→1 eased from move magnitude. - Gem magnet is flat 520 px/s —
sim/sim.gd:2929constant velocity inside the fixed 240px radius (:222-223); no acceleration as it closes. Fix:lerp(speed, speed*2.5, 1 - d/RADIUS). - Zero anticipation moment at XP-full —
pending_levelupsopens the panel the same tick (main.gd:1596-1601); no HUD charge pulse, dock flash, or beat before it appears (and the live HUD has no run timer in survival — pause menu only,ui/pause_menu.gd:324-327— design choice, noted). - Enemy hit: colour flash only, no scale pulse — whitening is good (
main.gd:233-237,render/hit_flash_tracker.gd:11, 0.09s); body is otherwise rigid. Optional polish: ~1.05 scale pulse riding the same tracker (knockback would be sim-side, out of scope).
Clean: enemy hit-flash system; story countdown cadence (ui/hud.gd:323 re-derived per frame); boss-death supporting layers.
Run 21 — UI pattern inconsistency (cycle 4: interaction behavior) — 2026-10-02 04:20 BST
Section titled “Run 21 — UI pattern inconsistency (cycle 4: interaction behavior) — 2026-10-02 04:20 BST”5 findings. Pass 4 swept how panels BEHAVE: transient messages, back handling, selection memory, confirms, touch parity, death flow.
- “Quit to menu” is the only unconfirmed destructive action — abandons the whole run instantly (
ui/pause_menu.gd:183) while harmless-ish RESET PROGRESS gets a full confirm dialog (ui/meta_shop_panel.gd:136,:1530-1617) and shop buys are deliberately no-confirm (:20). The most destructive action in the game is the only unconfirmed one. Fix: reuse the reset-dialog pattern. - Four ad-hoc transient-message systems — wave banner (
ui/hud.gd:163-176,:266-277, top-center gold 40px, sim-driven seconds, no fade), objective tip (ui/objective_panel.gd:14, top-center gold 14px, hard 6s cutoff), shop toast (ui/meta_shop_panel.gd:34,:364-376, centered glass plate, 3s + 0.4s fade — the only one that fades), damage numbers (own system). Same job, four lifetimes/positions/styles. Fix: one shared helper (text, position, lifetime, fade). - Dimension choice swallows the universal “back” —
ui/dimension_choice_panel.gd:216-231has noui_cancel/B branch; every other panel closes on B. (Results panel:508-541also ignores B — minor, nothing to go back to.) - Codex browse rows are nav-only — Labels with no per-row tap handler (
ui/codex_overlay.gd:145-163,:205); tapping anywhere just closes, so touch players can’t tap to inspect. Fix: row gui_input → select+show. All other panels have proper tap targets. - Selection-memory policy is split and undocumented — shop/codex/results/dimension all reset to index 0 on reopen; pause menu alone remembers (
ui/pause_menu.gd:415,:460). Pick one policy (remember-last is friendlier for shop/codex) and apply uniformly.
Clean: ui_cancel/B/ESC consistent on drone bay, ship config, shop, stats sheet; forced-choice panels (level-up, dimension) intentionally non-cancellable and consistent with each other; death flow is one family by construction (DeathRecap renders inside ResultsPanel).
Run 22 — Invisible progression (cycle 4: value/identity perception) — 2026-10-02 04:30 BST
Section titled “Run 22 — Invisible progression (cycle 4: value/identity perception) — 2026-10-02 04:30 BST”4 findings. Pass 4 swept perception of VALUE differences the sim computes: gem worth, enemy elemental states, reward multipliers, time-based enemy tanking. (Player-burn overlap with run 11 noted, not re-reported.)
- Gem values are pixel-identical — a 400-XP boss gem and a 5-XP swarmer gem look the same:
main.gd:1971gem_renderer.syncpasses one fixed colour and NO scale array, thoughrender/swarm_renderer.gd:103-142supports per-instance colours/scales; boss biomass 400 vs ~5 land in the same pool (sim/sim.gd:2724-2730,:228). Gold has no entity at all (awarded invisibly atsim.gd:2810-2858). Fix: per-gem colour+scale keyed to value tiers, distinct boss-gem colour. - Burning/shocked enemies have no element-specific tell —
main.gd:2317_enemy_colors()reads base_element/is_elite/hit-flash but neveraura_element/aura_remaining/stacks(sim/elemental_system.gd:280-281,:249,:449); a burning enemy shows no flame tint, a shocked one no arcs. Only tell is the element-agnostic white flash. Fix: lerp instance colour toward the element palette in_enemy_colors()(enemy-side; the PLAYER burn DoT was run 11’s finding). - Reward multipliers are invisible once the run starts —
area_reward_mult1.25-1.5 (sim/area_defs.gd:68-147, appliedsim.gd:2724,:2810-2858) has exactly one consumer: the pre-run choice panel (ui/dimension_choice_panel.gd:173). In-run, boosted gems look identical and gold just increments faster with no blip. Fix: warm gold-shift tint on boosted-area gems + gold-counter pulse. - Late-run enemy tanking is invisible —
difficulty_mult()+50% HP/contact per minute (sim/spawn_director.gd:25-31, appliedsim.gd:1538,:1658) never reaches render:render/archetype_renderer.gd:135sizes byradius[i]only. A minute-15 swarmer with 10× HP is pixel-identical to a minute-2 one. Fix: per-enemy spawn-diff scale/tint lerp.
Common fix shape: the per-instance colour/scale channels SwarmRenderer.sync/ArchetypeRenderer.sync already support, but nothing populates from the sim data. Verified fine: drone class identity (distinct tints render/decoy_renderer.gd:26-32 + per-class Nova sprites render/drone_sprites.gd:20).
Run 23 — Render ignores sim data (cycle 4: hitbox vs visual) — 2026-10-02 04:40 BST
Section titled “Run 23 — Render ignores sim data (cycle 4: hitbox vs visual) — 2026-10-02 04:40 BST”5 findings (3 in the harmful direction). Pass 4 compared every damage radius against its drawn radius. Correction to run 22 finding 1: AUTO_COLLECT_XP = true (sim/sim.gd:226) banks XP on kill — no physical gems spawn in the shipped config, so the “pixel-identical gem values” gap is config-mooted (fix stays valid if physical gems return).
- Eye boss hitbox 28% bigger than its drawn body — contact at full
enemies.radius(sim/sim.gd:3129) vs body disc drawn aterad * 0.78(render/eye_renderer.gd:65,eradfull at:45). You get hit standing clear of the drawn eye. Fix: draw at ≥1.0× or shrink the pool radius. - Boss2 artillery blast 25% bigger than its telegraph — damages within full
BOSS2_ARTILLERY_BLAST_RADIUS = 80(sim/boss2.gd:34,:96); telegraph circle drawn at*0.8 = 64(render/boss2_renderer.gd:142). Hits land inside the unmarked ring. Fix: draw telegraph at 1.0×. - Boss2 body hitbox 12% bigger than visual — full
bradcontact (sim.gd:3129) vsbrad*0.88disc /0.92ring (render/boss2_renderer.gd:59-60). Same class, milder. - Graviton satellites: visual 40-60% BIGGER than hitbox (forgiving) — collision
GRAVITON_SAT_HIT_R = 8(sim/graviton.gd:39,:175) vs drawn 11.2/12.8 (render/graviton_renderer.gd:115-116). Cosmetic only. - Web capsule hitbox leads its visual by 0.25s — sim tests the full capsule on landing (
sim/elemental_system.gd:314-321); renderer grows drawn length overWEB_GROW_S = 0.25(render/zone_renderer.gd:96-99). Far end slows you before it’s drawn. Minor — plausibly intended landing animation.
Clean (don’t re-sweep): swarm contact vs draw (scale by construction, render/archetype_renderer.gd:135); every drawn zone radius = damage radius (webs, weapon zones, funzo, chalice, chronowell, reaction); bomb telegraphs at full radius; warden body; arena bounds fully rendered (glowing edge at exactly ±ARENA_HALF, render/arena_border.gd:20-22, :49-56; story walls via StoryMapRenderer); elite-kit status scan — all four pilot fields have consumers; pause/attract render behaviour clean.
Run 24 — Telemetry (cycle 4: v2 run lifecycle) — 2026-10-02 04:50 BST
Section titled “Run 24 — Telemetry (cycle 4: v2 run lifecycle) — 2026-10-02 04:50 BST”4 findings. New ground: run_start/run_end lifecycle analysis on the events table (119 starts vs 84 ends), level-at-death distribution, quit behaviour, perf_seg rows.
- Death-cause data is being LOST going forward — v2
run_endpayloads carry kills/level/mode/reason/run_time but NO cause (verified across all 84 rows); the legacyrunstable that haddeath_causeis dead on build ≥236. Run 6’s funnel (44% swarmer, charger wall) is the LAST measurement of its kind — the 1.0.1 early-death work is flying blind on new builds. Fix: addcauseto the run_end payload (and abuild/devkey — run_start has neither, so per-build lifecycle analysis on events currently can’t group). - Level-at-death is bimodal — the wall is real — 0-9: 22, 10-19: 22, 20-29: 10, 30-39: 5, 40+: 14. Players either die early (avg lvl 10.1 for quitters) or break through and run long (survival deaths avg lvl 22.5 / 438s; several lvl-40+ runs 490-1049s). Get past the mid-game and you thrive. Corroborates run 6’s early-pacing finding from a different angle.
- 29% of started runs never record an end (119 starts vs 84 ends) — with 48-of-60 exits reading “crash”, most of the gap is probably the devicectl-kill masquerade (run 18 finding 1), not rage-quit. Direct quit data that DOES exist: 8 survival quits (avg lvl 10.1, 320s) + one 2-second tutorial quit. Fix path remains: distinguish dev-kill from crash.
- The soak/perf A-B harness writes to the production DB — 21
perf_segrows (scenario ids, A/B sides, presets like “nova_shockwave” vs “webs”, p50/p95) are harness-generated test data in prod, same contamination class as the build-9001 rows (run 6 finding 3). Minor hygiene: tag harness rows or route them elsewhere.
Ground covered: run_end/run_start payload schemas; level-at-death buckets; quit vs death split; tutorial_cap (2 completions); no new device samples landed during the loop itself (no sessions since ~21:23 UTC 2026-09-28 era beyond the ones already counted).
Run 25 — Asset-fiction mismatch (cycle 5: preview reality + store media) — 2026-10-02 05:00 BST
Section titled “Run 25 — Asset-fiction mismatch (cycle 5: preview reality + store media) — 2026-10-02 05:00 BST”3 findings. Pass 5 traced preview-vs-reality pipelines and store media. Hull preview verified CLEAN — config screen and in-run renderer load the identical baked PNGs via the identical PlayerRenderer.nova_hull_base() helper (ui/ship_config_panel.gd:221-225 = render/player_renderer.gd:181-190); no bake-vs-live divergence class exists there (cosmetic only: preview shows body PNG without glow/tilt). Console deployment current, no drift signal.
- Trailer videos are 3 months stale while SUBMIT.md says “still being produced” —
marketing/appstore/previews/{iphone,ipad,tv}.mp4(12-17MB each) last changed 2026-06-30 (0210374c), predating the glow rework, Nova look, and 1.0 content freeze — yet SUBMIT.md §5 claims trailers are still being produced. Fiction both ways. Fix: recapture viamarketing/trailer/build_trailer.sh+ update §5 to reference the existing files. - No TestFlight what-to-test text exists — grep of marketing/docs/copy finds none; SUBMIT.md has no TestFlight section at all. Gap (not drift): write a
marketing/appstore/testflight.mdmatched to 1.0.1’s real scope. - Mac screenshots are 2880×1800, not the required 2560×1600 —
marketing/appstore/mac/(dead weight: never uploaded, Mac listing uses the iPad set as “Designed for iPad”, per SUBMIT.md §4). Delete or regenerate only if a native Mac submit ever happens. iPhone 6.9“ (2868×1320), iPad 13“, tvOS sizes all correct.
Run 26 — Snap-vs-ramp (cycle 5: readiness + transitions) — 2026-10-02 05:10 BST
Section titled “Run 26 — Snap-vs-ramp (cycle 5: readiness + transitions) — 2026-10-02 05:10 BST”6 findings. Pass 5 swept readiness transitions, boss entrances, music switches, counters, banner text.
- Bosses spawn with no entrance ceremony — every boss emits a spawn reaction (name + ring + sting:
sim/sim.gd:1086,sim/graviton.gd:64,sim/eye.gd:70,sim/boss2.gd:51,sim/funzo.gd:94) but the BODY pops in via the generic pooled spawn, in plain sight under the BOSS APPROACHING banner. Fix: aboss_spawnfx event driving a 0.5-1s materialize ramp/telegraph ring. - Music switches are hard cuts —
audio/audio_manager.gd:423-436play_music()swaps the stream on one player,stop_music()(:456-459) hard-stops (gameover → abrupt silence); no tween exists anywhere in the file. Fix: twin-player crossfade ~0.8s. - Warp readiness is diegetic-only AND discontinuous — no HUD indicator exists (the old icon was removed; stale comment
ui/touch_controls.gd:148), and the thruster pulse hard-flips rate 9→16 Hz / amp at the ready edge (render/player_renderer.gd:213-219). Fix: lerpdash_readystrength over ~200ms + a one-shot ready ring (mirroring touch’sREADY_PULSE_MS,ui/touch_controls.gd:530-533). - Drone dock ready-state snaps 14% scale —
ui/drone_dock.gd:76-77_apply_ready_state()sets scale 1.0→1.14 instantly; glow pulse starts abruptly. Fix: ~150ms tween on the ready edge. - Boss bar pops at full size —
ui/hud.gd:311_boss_group.visible = true. Fix: modulate+fill tween ~300ms on first sight. - Gold counters show final numbers instantly — results tiles (
ui/results_panel.gd:267-270) and shop header (ui/meta_shop_panel.gd:610) set the final int directly; no count-up on the payoff moment. Fix: 0.6s count-up tween (results at minimum). Banner/reaction text also snap in at full size (ui/hud.gd:275,fx/fx_manager.gd:343-352— out-fade only).
Clean: touch ability ready pulse (expanding ring + halo, ui/touch_controls.gd:530-533); codex/stats scrolling reads fine linear for tvOS (nit: codex row-highlight rebuild is instant where ship-config tweens EASE_OUT — same family, different motion language, low priority).
Run 27 — UI pattern inconsistency (cycle 5: text + token discipline) — 2026-10-02 05:20 BST
Section titled “Run 27 — UI pattern inconsistency (cycle 5: text + token discipline) — 2026-10-02 05:20 BST”4 grouped findings. Pass 5 swept casing, safe-area coverage, colour-token discipline, scaling mechanisms.
- Safe-area insets ignored on four live HUD surfaces (shared helper
Platform.safe_insets_unitsexists,platform.gd:42-64, and most panels use it):ui/hud.gd:72-73HP group at hardcoded y=22 (inside TV-overscan/Dynamic-Island band),ui/objective_panel.gd:46-48fixed TOP_Y,ui/level_up_panel.gd:123-126,338-340,175-177bottom strip/hint/STATS (home-indicator band),ui/dimension_choice_panel.gd:193bottom hint. Real device bug class. Fix: add insets on all four. - Button/hint casing is three-way mixed — titles are reliably ALL-CAPS, but buttons: start-menu CAPS (“SHIP”, “SHOP”,
ui/start_menu.gd:75-86) vs pause Title Case (“Ship stats”, “Shop”,ui/pause_menu.gd:142-155) on back-to-back screens; “STATS” CAPS vs Title siblings (ui/level_up_panel.gd:174); hints three-way (“TAP A RIFT TO ENTER” vs “Tap to select · swipe to browse” vs “tap to continue”). Fix: one button casing + one hint casing. - Colour tokens exist but five semantic roles drift — TEXT_DIM has 6 variants (
ui/tokens.gdvsui/results_panel.gd:129,ui/codex_card.gd:8,ui/weapon_detail_view.gd:11,ui/stats_sheet.gd:131, +ui/dimension_choice_panel.gd:24shadows the token); GOLD has 5 values (ui/results_panel.gd:180vsui/theme/gold_pulse.gd:10etc.); SUCCESS 4 variants;ui/feedback_panel.gd:22redefines ACCENT as a hue-drifted cyan; Tokens.BG (0,0,0,0.55) matches neither DESIGN.md’s (0.02,0.03,0.06,0.6-0.66) nor the 0.9+ panels actually use (ties to run 9’s glass-drift finding — the token itself needs re-pinning). Fix: migrate to tokens, retokenize BG per the real convention. - start_menu runs its own second scaling mechanism —
ui/start_menu.gd:29-31,:201-204_scale()against a 1280×720 DESIGN basis, duplicatingTokens.ui_scale()/content-scale (can compound with the touch 1.3 CSF). Other families: meta_shop’slayout_for, measured 720p fitting with tests. Fix: collapse to the shared model or document why it’s separate.
Clean: identity-colour tables (weapon/drone/codex) by design; death_recap, boss_edge_indicator, region_title.
Run 28 — Invisible progression (cycle 5: long-horizon meta) — 2026-10-02 05:30 BST
Section titled “Run 28 — Invisible progression (cycle 5: long-horizon meta) — 2026-10-02 05:30 BST”4 findings. Pass 5 swept cross-run progression visibility: personal bests, collection counters, account numbers.
- Personal-best records don’t exist —
sim/meta_state.gdpersists only banked_gold/gold_spent/levels/flags/loadout/seen_enemies — no best time/kills/level/gold field anywhere;ui/results_panel.gd:251-270shows this run’s tiles with no comparison and no NEW RECORD moment; nothing in the start menu either. The retention lever is absent entirely. Fix: best_* fields in MetaState + BEST tile + record flash in results. - Codex completion is tracked but never shown —
ui/codex_overlay.gd:96-104hasentry_count()/seen_count()used only by a test, never rendered; title is just “BESTIARY” with per-entry ??? but no “12 / 30 discovered”. Fix: title counter. Players can’t chase what they can’t count. ✅ DONE (COMMIT, branchcodex-counter): claim verified accurate. BROWSE mode now renders a right-aligned “n / m DISCOVERED” counter (JetBrains Mono 24, soft blue-grey so the cyan BESTIARY title keeps the accent) on the title row; hidden on the NEW ENEMY card. Lives inside the full-screen overlay (layer 24, 56px margins), so no HUD collision. Tests:test_codex_overlay.gd×2. Windowed look at Apple TV distance not checked here;codex.pngin the UI sweep will drift and needs a bless. - No account-level career numbers at all — no career level, total runs, or lifetime kills field exists in meta_state; the only account number ever rendered is banked_gold (
ui/meta_shop_panel.gd:610,ui/results_panel.gd:259-270); the start menu shows no gold readout either (ui/start_menu.gd:40-44,:71-83). Fix: persist runs_played/lifetime_kills, surface a line on the start menu. - Ship collection has no count framing — LOCKED tag + dim treatment per hull exists (
ui/ship_config_panel.gd:82,:226-228) but no “n of m hulls owned”. Fix: header counter from ShipBonuses roster vsmeta.owns_ship.
Clean (don’t re-sweep): empty weapon/drone slots DO render as visible empty boxes (ui/weapon_panel.gd:218-222, max slots always built; ship config renders “Empty slot / not yet owned” cards) — progression space is readable; locked abilities hide entirely but are tutorial-stage gates only — nothing unowned to tease.
Run 29 — Render ignores sim data (cycle 5: overflow + z-order) — 2026-10-02 05:40 BST
Section titled “Run 29 — Render ignores sim data (cycle 5: overflow + z-order) — 2026-10-02 05:40 BST”3 findings. Pass 5 audited load behavior and layering. The fx queue itself is clean (plain arrays, no cap, drained per frame); damage numbers clean (fixed 72-pool + merge); aim indicators clean (Rift Bolt is stick-directed, no reticle needed).
- Boss reaction events can be silently dropped under a hitch backlog — per-consume caps count in event order (
fx/fx_manager.gd:12-47: REACTION_CAP=6, ring pool 24, global JUICE_FRAME_CAP=48);reaction(shared by boss ENRAGED/SUMMON/BLAST rings+labels fromsim/graviton.gd/sim/eye.gd/sim/boss2.gd) andaccum_warn(accumulator kill-priority warning) appended after weapon spam can vanish. Boss telegraph SHAPES are safe (state-reading renderers, not events). Fix: exempt named reactions + accum_warn like ESSENTIAL_KINDS. - Bomb telegraphs render UNDER the swarm (z=-1) while lancer/ghost telegraphs sit at z=1 —
render/bomb_renderer.gdz=-1 vsrender/dash_telegraph_renderer.gdz=-1 and ghost/lancer at z=1 (deliberately promoted “visible over enemies”). A dense horde can bury the bomb blast zone the player must dodge. Fix: raise bomb telegraph to z=1. (DoT/web zones at z=-1 are deliberate large translucent fields — acceptable, but worth one eyeball check under a 5000-enemy swarm in the vfx harness.) - Audio PER_FRAME_CAP=4 drops priority cues — the cap is checked BEFORE priority in
audio/audio_manager.gd(~:25 + mapped-sound gate), so a boss_missile_launch/eye_laser arriving after 4 ordinary sounds in the same consume is dropped despite the BOSS_RESERVED_VOICES=3 steal protection existing. Fix: letPRIORITY_FX_KINDSpast the cap (or reserve a cap slot).
Run 30 — Telemetry (cycle 5: economy + prewarm verification) — 2026-10-02 05:50 BST
Section titled “Run 30 — Telemetry (cycle 5: economy + prewarm verification) — 2026-10-02 05:50 BST”3 findings. New ground: shop-economy health from shop_buy payloads, gold accumulation, first-use-stall verification on current builds.
- Gold over-accumulates — sinks are far too weak vs income — 476 shop_buys across 62 distinct items: avg cost only 112 gold, avg
gold_after14,115, only 28/476 buys left the player under 200 gold, 234 left them over 5k; and 65 of 119 runs START with 5k+ banked (26 start under 100). Players are hoarding with nothing meaningful to spend on. Data-backed economy imbalance — feed into the economy-sim calibration (bh-economy-sim/docs/RELEASE-1.0.1.mdpricing items): prices need scaling or new sinks for 1.0.1. - First-use shader stalls: ZERO on builds 244-246 — no
pipelines > 0hitch rows exist for any build ≥244 (hardest cut). The shader-bake/PSO-prewarm arc is fully verified — run 6 finding 4’s “reads as landed” is now confirmed; no further work. - Launch events carry no timestamp —
marker_tsexists only onprev_exitpayloads;launch/run_start/run_end/shop_buyhave no time key, so play-frequency/retention-over-time analysis is impossible (and the events table’stscolumn isn’t a usable date). Fold amarker_ts(or fixts) into the same payload-keys fix as run 24 finding 1.
Run 31 — Asset-fiction mismatch (cycle 6: long-tail prose) — 2026-10-02 06:00 BST
Section titled “Run 31 — Asset-fiction mismatch (cycle 6: long-tail prose) — 2026-10-02 06:00 BST”6 findings. Pass 6 verified the remaining ~20 bestiary prose entries, unverified story dialogue, credits, and export metadata.
- Sentinel boss “five attacks” claim includes a removed attack —
data/bestiary.json:41lists “a sweeping cutter beam”; the cutter was removed (sim/boss2_state.gd:14,ATTACK_COUNT := 4at:19-23). Player-facing fiction. Fix: “four attacks — artillery, rings, slam, summons”. - Story dialogue tells players to aim the Beam manually — it auto-targets —
data/story.json:475-477“hold a line and sweep it” vssim/weapon_beam.gd:40-52,:92-106(auto-targets nearest + self-slews; player never aims). Fix: “It seeks the nearest foe on its own…”. - Zapper “fires a bolt mid-charge” is wrong —
data/bestiary.json:27vssim/enemy_attacks.gd:221-246: bolts fire on an independent timer in any phase. Fix: “fires aimed bolts while it rushes”. - Halo-chain “Dash through a tether to break it… collapsing the buff” is doubly wrong —
data/bestiary.json:93vssim/halo_chain_director.gd:171-175(any crossing breaks it) +:31(TETHER_BREAK_COOLDOWN— re-forms in 1.0s, buff only pauses). Fix: “Cross a tether to break it for a moment”. - No credits screen exists anywhere — grep of
ui/clean; start menu has no Credits row. Gap for a shipped store game (not a defect). - Copyright string inconsistent — root
export_presets.cfg:68copyright="Lumara"(bare, no year);platform/tvos/export_presets.cfghas NO copyright field at all. Fix: consistent© 2026 Lumarain both, single-writer style.
Omissions (minor, not fiction): charger entry omits the 0.6s post-lunge recovery (sim/enemy_behaviors.gd:166) + elite chained dash; funzo entry omits jester/confetti mechanics. Support/Marketing/Privacy URLs verified live and real (SUBMIT.md:75-77 → darkcosmos.lumara.digital, deploys confirmed). Checked clean this pass: ghost, rusher, brute, scatterer, bomber, orbiter, spider/weaver, wyrm (shared HP pool real), beacon, mite, tank_missile, graviton, eye, centurion; story: riftbolt, decoy 8s, warp invuln, stand-still regen, homing-missiles-target-drones, crystals, orbit shards, scatter pellets, ember Blaster auto-aim.
Run 32 — Snap-vs-ramp (cycle 6: final corners) — 2026-10-02 06:10 BST
Section titled “Run 32 — Snap-vs-ramp (cycle 6: final corners) — 2026-10-02 06:10 BST”2 findings; category nearing exhaustion. Pass 6 checked the last untouched corners.
- “HOLD %ds” countdown sits flat until zero —
ui/hud.gd:263,:322-323: plain text, no colour shift/pulse/audio tick in the final ~5s, and completion swaps to the next objective with no beat (only incidental mass-kill dissolves,sim/story_director.gd:218-224). Fix: final-5s urgency ramp + completion flash. - Choice-panel confirmations have zero visual animation — level-up
_confirm()(ui/level_up_panel.gd:565-583) plays a nav sound and vanishes: no chosen-card pop, no sibling fade; dimension choice_confirm()(ui/dimension_choice_panel.gd:208-212) the same instant swap. One family fix: chosen-card scale/burst + sibling fade (~0.2s).
Verified clean (don’t re-sweep): drone deploy materializes over ~0.45s (render/decoy_renderer.gd:23-26); shop purchase flash tweens (ui/meta_shop_panel.gd:905-910); all fx/ pooled classes ramp from life/max_life, no sibling inconsistencies.
Run 33 — UI pattern inconsistency (cycle 6: final corners) — 2026-10-02 06:20 BST
Section titled “Run 33 — UI pattern inconsistency (cycle 6: final corners) — 2026-10-02 06:20 BST”2 mild findings; category exhausted. Pass 6 swept layer stacking, modal dim, focus treatments, hint footers, onboarding tips.
- Level-up and dimension choice dim differently for the same job — both are mid-run freeze-and-pick-card modals, but level-up ramps a vertical 0→0.88 veil (
ui/level_up_panel.gd:102) while dimension choice is flat 0.9 (ui/dimension_choice_panel.gd:23). Level-up’s ramp is the odd one out among card modals (unless deliberate — Chris’s call). - Ship config has no hint footer, no first-open tip, nothing — while every sibling has at least one: drone bay a full contextual hint bar (
ui/drone_bay_panel.gd:114), shop a persisted first-3-opens tip (ui/meta_shop_panel.gd:1492-1509); ship config only has a top-left BACK + ‹/› glyphs (ui/ship_config_panel.gd:91,95,110). Results panel likewise has no exit hint (weaker case — buttons self-labelled).
Verified clean (don’t re-sweep): CanvasLayer stacking fully consistent and documented (HUD 5 < modals 10 < codex 24 < touch 30 < menus 60-82 < toast 200; the one same-layer pair feedback/shop at 80 never co-opens; touch suppressed while codex open, main.gd:2660); focus treatments are ONE GlassPanel family across level-up/dimension/drone/results/shop; dim tiers otherwise consistent (0.55 light veil, 0.86-0.9 heavy, 1.0 opaque-HDR).
Run 34 — Invisible progression (cycle 6: unlock discoverability) — 2026-10-02 06:30 BST
Section titled “Run 34 — Invisible progression (cycle 6: unlock discoverability) — 2026-10-02 06:30 BST”No new findings — category exhausted. Pass 6 swept unlock discoverability and all four corners came back clean or deliberate:
- Shop shows unowned items (priced unlock cards render, just sort first —
ui/meta_shop_panel.gd:468,:1251-1286; no ownership filtering anywhere). No invisibility. - Tutorial progress IS visible — “LESSON %d OF %d” + per-step progress line (
ui/objective_panel.gd:92,:97-102). - Dimension choice has no silent gating — exclusions are only already-visited rifts (
sim/sim.gd:2976,:2995), with a failsafe re-admit; card count is honest. - Borderline design choice (Chris’s call, not a defect): the drone-bay slot cycle filters to owned classes only (
ui/drone_bay_panel.gd:133-138_options()), so a new player cycling the bay never sees that Bomber/Interceptor/Disruptor/Logistics exist — discoverability rests entirely on the shop’s Drones tab blurbs (ui/shop_categories.gd:67-86). Locked placeholders in the cycle would close it if wanted.
Run 35 — Render ignores sim data (cycle 6: interpolation + final corners) — 2026-10-02 06:40 BST
Section titled “Run 35 — Render ignores sim data (cycle 6: interpolation + final corners) — 2026-10-02 06:40 BST”1 finding. Pass 6 audited sim→render temporal smoothing, camera, shader uniforms, and “for render” fields.
- No sim-to-render interpolation — 60Hz stepping is visible on 120Hz ProMotion displays — sim ticks in
_physics_process(main.gd:1412, tick at:1506), renderers draw rawposper_processframe (main.gd:1725); no prev-position columns in any pool, no tick-fraction lerp anywhere (grep-verified). On iPhone/iPad Pro/Mac 120Hz displays, fast movers step at 2-render-frames-per-tick. Partially masked by the rigid player-follow camera (fixed-offset child of the player,main.gd:1231-1233) — whether interpolation is warranted is a design call, but the mechanism doesn’t exist today.
Verified clean (don’t re-sweep): camera responds only to player transform by design; live-game shaders’ only uniforms (dim, accent_codes) are both set live; the “for render” comment census found only graviton satellites (consumed, render/graviton_renderer.gd:112) and the KNOWN still-open halo-chain tethers (sim/halo_chain_director.gd:53 — punch-list run 5 finding 1, still zero consumers at HEAD).
Run 36 — Telemetry (cycle 6: confirmations) — 2026-10-02 06:40 BST
Section titled “Run 36 — Telemetry (cycle 6: confirmations) — 2026-10-02 06:40 BST”2 findings, both confirmations of earlier candidates. New ground: hitch-free verification on current builds, dash-rate trend, wake-lesson recheck, purchase spread.
- Tutorial “wake” lesson stall CONFIRMED — still 5× step 0 with zero progressions (riftbolt 2× step 0 likewise), no new completions since run 18’s flag. Upgrade from “candidate”: worth a
story_traceverification pass before trusting, but the stall is stable in the data. - Builds 244+ are hitch-free in event data — zero rows of ANY kind (no pipeline stalls per run 30, now no non-pipeline stalls either on this cut). Combined with 244-246 holding ~59fps: the perf thread from runs 6/12/30 is fully closed. No action.
Trend note (no action beyond run 12’s finding): dash rate on cleared encounters roughly DOUBLED across builds — 0.04-0.07 on builds 207-212 vs 0.17-0.18 on 230/243/244 (encounter tuning or tester skill; still ≤0.18, so “dash as panic button” holds). Purchase spread: all 476 buys are 1-2 per item across 62 items — no must-buy concentration; consistent with run 30’s cheap-prices/hoarding picture (players buy a bit of everything, bank the rest).
Closing summary — 2026-10-02 06:50 BST — loop complete
Section titled “Closing summary — 2026-10-02 06:50 BST — loop complete”36 runs over 6 hours, 148 logged findings, all committed and pushed. Six audit categories × 6 passes each; nothing was fixed (per protocol) — everything above awaits triage onto docs/RELEASE-1.0.1.md.
Triage guide — highest-value first:
- Gameplay fairness (player getting hit by invisible things): eye hitbox +28% vs drawn body (r23), boss2 artillery +25% past telegraph (r23), player burn/slow DoT invisibility (r11), halo-chain +45% damage buff with zero visual (r5), bomb telegraph buried under swarm (r29), audio priority cues dropped by PER_FRAME_CAP (r29), boss reaction events dropped under load (r29).
- Retention + economy (data-backed): first-2-minutes cliff — 63% of runs die <2m, swarmers cause 44% of deaths (r6, r12, r24 bimodal); gold over-accumulation — avg 14k banked vs 112 avg cost (r30); personal bests don’t exist (r28); tutorial “wake” lesson stalled 5× (r18, r36 confirmed); death-cause no longer captured on new builds (r24).
- Store hygiene for 1.0.1: screenshots/trailers/press kit 3 overhauls behind (r1, r25), “What’s New” still v0.1-framed + missing Story/codex/gold-shop mention (r7), no TestFlight text (r25), privacy-page Sentry note (r13), copyright fields missing/inconsistent (r31), no credits screen (r31), stale docs claims (r7, r19).
- In-fiction fictions (player-told lies): skirmisher “drops a powerup” (disabled) (r19), sentinel “five attacks” (cutter removed) (r31), story “hold a line” Beam (auto-aims) (r31), zapper/halo-chain prose (r31), death recap calls hazard damage “melee” (r17).
- Juice for the big moments: boss death = 54px disc (r20), player death hard cut (r20), bosses spawn with no entrance (r26), music hard cuts (r26), HP/boss bars no damage chip (r14), gold count-up absent (r26), card-confirm animations absent (r32), 60Hz stepping on 120Hz displays (r35).
- UI hygiene: store players can’t mute (r15), quit-run unconfirmed (r21), HUD safe-area gaps on TV/iPhone (r27), save-area + colour-token + casing cleanups (r27), run tips violate DESIGN.md placement (r15), 4 ad-hoc transient-message systems (r21).
- Progression visibility (supports r12’s pick-concentration data): 11 weapons without progression visuals — and they’re exactly the unpicked ones (r4, r12), weapon dock shows no level/mod/evolve (r10), crystal wallet + evolve announcement invisible (r16), meta-stat upgrades imperceptible (r4).
- Guard rails to add: shape-coverage GUT test (r17), death-cause/build keys in run_end (r24), devicectl-kill vs real-crash distinction (r18), codex counter render (r28).
Verified healthy (no action): ATV perf fully landed (zero hitches, ~59fps on 244-246), arena bounds rendered, drone class identity, hull pipeline, enemy shape coverage today, tutorial progress + codex locked states, back handling, glass focus family, layer stacking, privacy labels vs reality, Dark Cosmos naming chain, Decoy naming rule.