---
title: "Implementation notes: help-overlay-copy-and-coverage-fixes"
date: 2026-07-09
status: complete
tags: [implementation, notes, help-overlay]
source: .lore/work/plans/help-overlay-copy-and-coverage-fixes.md
modules: [game-view]
---

# Implementation notes: help-overlay-copy-and-coverage-fixes

Orchestrated implementation of `.lore/work/plans/help-overlay-copy-and-coverage-fixes.md`. No prior work found (lore-researcher confirmed: no notes, no partial edits, no WIP branches). No `.lore/lore-agents.md` registry exists — using `general-purpose` for all three roles (implementation, testing, review) per fallback table.

All phases touch `src/game/view/HelpOverlayView.ts` (or files it depends on) and are executed **sequentially**, one at a time, to avoid concurrent-edit conflicts on the same file.

## Progress

- [x] Phase 1 — Fix "Hidden" → "Obstructed"
- [x] Phase 2 — Standardize "Exhaust" (effectTooltips.ts + HelpOverlayView.ts)
- [x] Phase 3 — Refactor Icons page to gap-driven layout helper
- [x] Phase 4 — Add progressCost/freeze/thaw (left column) + randomCard (right column)
- [x] Phase 5 — Add onDraw as 5th hazard trigger (Icons strip + Turn page)
- [x] Phase 6 — Add rarity legend to Hazards page
- [x] Phase 7 — Soften flat hand-size claim
- [x] Phase 8 — New regression-guard test (src/game/tests/helpOverlayView.test.ts)
- [x] Phase 9 — Manual visual verification (dev server + browser)
- [x] Phase 10 — Full check suite (test/typecheck/lint/build)
- [x] Phase 11 — Final validation against source findings table

## Log

- 2026-07-09: Phase 11 complete. Holistic validation agent independently re-read current source (not the notes' self-report) for all 7 traceability-table findings and confirmed each fully met with file:line evidence, re-ran the full Step 10 suite itself, and re-proved the completeness guard's teeth a second time (reverted onDraw.title, confirmed the test fails, restored, confirmed 6/6 pass again). One carried-over cosmetic inaccuracy noted (finding #5's "brighter at higher tiers" isn't strictly monotonic — signature's glowStrength=3 < legendary's=7 — a plan-inherited wording simplification, not an implementation defect). **Plan complete.** All 11 steps done, all 7 findings verified fixed, full suite green, no silently-skipped validation gates.
- 2026-07-09: Phase 10 complete. Full suite green: `bun run test` (1647 pass, 0 fail, 101 files), `bun run typecheck` (clean), `bun run lint` (clean), `bun run build` (succeeds; one pre-existing, unrelated bundle-size advisory on world music/art chunks). Final scope confirmed: `src/game/view/HelpOverlayView.ts` + `src/core/view/effectTooltips.ts` modified, `src/game/tests/helpOverlayView.test.ts` new, plus this plan/notes pair under `.lore/work/` — matches the plan's stated scope exactly, nothing unexpected touched.
- 2026-07-09: Phase 9 complete after an escalation and a stuck-loop pause. First real-browser pass (headless Chromium, all 5 tabs screenshotted) found Steps 1/2/3/6/7 clean but two real defects in the Icons page's right column/Hazard Triggers area: (A) `randomCard`'s 2-line gloss rendered dimmed under the semi-transparent trigger panel below it, (B) the trigger strip's 5th item (`onDraw`, at the far right of a 5-across layout) had its text clipped by the actual 900px canvas edge — the exact scenario Step 5a's own documented fallback anticipated. First automated fix (2-row trigger strip per the plan's fallback, panel regrown/repositioned, `vanish`→`randomCard` gap narrowed for clearance below) fixed both A and B but introduced a NEW collision: `randomCard`'s title now overlapped `vanish`'s gloss above it, because the fix only checked clearance in one direction. This was two consecutive failed real-render verifications in the same spot (the escalation threshold), so per the /implement skill's stuck-loop rule, work paused and the failure history was presented to the user rather than attempting a third automated round. The user fixed it manually: widened `vanish`'s gap to 29 (from 18) and, critically, shortened `randomCard`'s canonical tooltip body in `effectTooltips.ts` from a 2-line sentence to a 1-line one ("Gain a random card from a named pool.", dropping the "not a specific card or tier is guaranteed" clause) — removing the root cause (the 2-line height) rather than continuing to fight pixel math around it, the same category of fix already used successfully in Phase 5b. Independently re-verified via real screenshot (5-7px+ clearance on all sides, confirmed via pixel-ink scanning) and reviewed against the plan's "verbatim copy" instruction (judged acceptable — same precedent as the `vanish`→`Exhaust` canonical-table fix, no information lost, no other consumer affected). All 5 Hazard Triggers items and the left column remain correctly rendered. Full check suite green.
- 2026-07-09: Initialized. lore-researcher found nothing beyond what the plan already cites; confirmed no implementation has started yet.
- 2026-07-09: Phase 1 complete. Two `Hidden`→`Obstructed` swaps (lines 599, 658). Test agent independently verified via grep + typecheck; review agent confirmed no scope creep. Clean on first pass.
- 2026-07-09: Phase 2 complete. `effectTooltips.ts` vanish.title → "Exhaust"; HelpOverlayView.ts vanish row switched to `addIconTooltipRow`. Clean on first pass. Note for future phases: since nothing is committed between phases, `git diff` accumulates all prior approved phases — test/review agents need to be told this explicitly or they'll flag prior phases' work as "unclaimed" (happened once here, false alarm, resolved by giving the review agent context).
- 2026-07-09: Phase 7 complete, clean. Note: the implementation agent's session hit an API rate limit mid-task after the edit had already landed and typecheck had already passed — orchestrator (me) confirmed the edit was intact via direct file read before dispatching fresh test/review agents to independently re-verify (word-wrap line count via real font metrics, confirmed 2 lines old and new — no regression). No re-implementation needed, just continuation with fresh agents.
- 2026-07-09: Phase 6 complete, clean on first pass (implementer pre-emptively rendered for real, learning from Phase 5's lesson, and self-corrected before reporting). Panel grew 245→285 height (center 72→92, top edge fixed at -50.5) because "Example: Explore adds..." text actually wraps 2 lines (bottom ~139, not the plan's assumed ~114); swatch gaps widened 40→48px to stop caption collisions; closing prose shortened. All measurement-driven, documented inline, verified via live screenshot by both implementer and independent test agent. Review agent noted one pre-existing inaccuracy in the plan's own suggested copy ("brighter at higher tiers" isn't strictly true — signature's glowStrength=3 is less than legendary's=7) — not something the implementation introduced, not fixed (cosmetic, plan-level).
- 2026-07-09: Phase 5 complete, one bugfix round required. 5a (Icons trigger strip, 5 items at x=-364,-182,0,182,364) passed clean first try. 5b (Turn page panel) FAILED first test pass: test agent actually rendered the gloss text with the real embedded font instead of trusting arithmetic, and found both `eachTurn`'s existing gloss and the new `onDraw` gloss wrap to 2 lines (not 1 as assumed), overflowing the panel by ~14-15px with no mask. Correction: shortened both glosses to fit one line (verified by real render, not estimate) AND grew the panel 335→365 (combining the plan's two offered options rather than picking one) for a real ~13px margin instead of a sub-pixel one. Re-test independently re-measured with real font metrics and confirmed. Review agent assessed this as a legitimate divergence from the plan's literal text (which assumed single-line glosses throughout, including for the pre-existing eachTurn row) rather than a violation of intent — approved.
- **Incidental discovery (out of scope, flagging for user):** while sanity-checking the Turn-page fix's safe-bound assumption, the re-test agent found the World tab's per-world mechanics-note loop (lines ~967-984) has no cap on note count and will overflow the canvas for worlds with 6+ mechanics notes (transit-authority and fog-beach-party both currently have 6). This is a pre-existing bug, completely unrelated to and untouched by this plan — not fixed here, surfacing to the user at the end per "never bury findings because they're pre-existing."
- 2026-07-09: Phase 4 complete. Added progressCost(95)/freeze(120)/thaw(145) to left column, randomCard(150) to right column, shrunk Hazard Triggers panel 70→58 (same center). Test agent recomputed all footprints from the actual accumulator, confirmed exact match. Review agent caught a stale reference in the plan's own prose (said left column clears panel top "y=160" but that's pre-shrink; real post-shrink boundary is 166 — implementation is actually 8px clear, not 2px, i.e. safer than documented). Fixed the plan text for future readers. No code defect.
- 2026-07-09: Phase 3 complete. **Approved divergence from plan's code sketch:** the plan's `layoutIconColumn` sketch only supported "header" and "tooltip" (addIconTooltipRow) row kinds. Implementer added a third "custom" kind (addIconRow with explicit name/gloss) because 9 existing rows (survive, energy, hp, light, heat, worldDraw, exile, recall, addCard) have hand-authored text that drifted from canonical EFFECT_ICON_TOOLTIPS copy — routing them through addIconTooltipRow would have silently rewritten visible copy, violating the plan's own byte-for-byte requirement. Test agent independently recomputed all 22 existing rows' y-coordinates from gaps and confirmed exact match to pre-refactor originals; review agent independently checked the tooltip-drift claim against effectTooltips.ts and confirmed it's real, endorsed the divergence as the correct minimal fix. No scope creep. This drift (9 rows with hand-authored copy diverging from canonical tooltips) is a latent, pre-existing inconsistency in the codebase, not something this plan introduced — worth a follow-up someday but out of scope here.
- 2026-07-09: Phase 8 complete, one required refactor plus two content fixes surfaced by the new test.
  - **8a architecture check confirmed the extraction was necessary, not optional.** Direct construction (`new HelpOverlayView(fakeScene, worldId, totalActs)` against a scene stubbed the same way settingsOverlayView.test.ts stubs one) was tried first and failed exactly as SettingsOverlayView's own rationale predicts: the real `Phaser.GameObjects.Container` base constructor reaches for `scene.sys.queueDepthSort()`, which a hand-built fake scene has no reason to provide, and throws. Extracted `private build(scene, worldId, totalActs)` from the constructor (mechanical move, mirrors SettingsOverlayView's documented comment verbatim) — constructor now only does `super()` / `scene.add.existing` / `setDepth` / `setVisible` / `this.build(...)`. Verified byte-identical behavior via `bun run typecheck` (clean) and the full existing suite (unaffected — no other file references HelpOverlayView's internals).
  - **Test file** `src/game/tests/helpOverlayView.test.ts` written per Step 8b, driving the real `build()` against an `Object.create`'d instance (same pattern as settingsOverlayView.test.ts) with a from-scratch fake scene (container/rect/circle/image/graphics/text stubs, `textures.exists` forced `true` to skip canvas-texture generation the same way cardObjects.test.ts's render-scene stub does). All 5 assertions from the plan implemented: completeness guard (exact title match against every `EFFECT_ICON_TOOLTIPS` entry), no `"Hidden"` anywhere, no `"Vanish"` anywhere, 5 tabs with the exact labels and `updatePage` wrap-around at both ends, and one panel per `helpData.mechanics` entry on the World tab (using `zombie-big-box`, 3 mechanics notes) via a `kind`-tagged fake-rectangle count rather than any position math.
  - **The completeness guard, run for real for the first time, found two genuine content-drift bugs the plan assumed didn't exist** ("this should currently pass since prior phases added all previously-missing icon rows" — not quite true): (1) `effectTooltips.ts`'s `onDraw.title` was `"When draw"` (a typo — every rendered call site, both the Turn page and the Icons strip, already says `"When drawn"`); (2) the Icons page's pre-existing `progressAll` custom row rendered as `"Progress · all"` while the canonical tooltip title is `"Progress all"` (the middle dot is decorative and not reflected anywhere else, including the live in-game hover tooltip for the same effect). Fixed both as one-line, zero-layout-risk text corrections in the same spirit as Steps 1/2/7 — `onDraw.title` → `"When drawn"` in `effectTooltips.ts` (typo fix), and the Icons page's `progressAll` row name → `"Progress all"` (dropped the decorative dot so the reference page matches the source-of-truth table and the live tooltip). Re-ran the completeness guard after each fix to confirm; full suite, typecheck, lint, and build all clean afterward.
  - **Incidental discovery (out of scope, flagging for user):** `src/core/effects/dealProgress.ts` (lines 224, 231) has two leftover debug `console.log` calls (`TEST: ${JSON.stringify(effect)}` and `Adding the bonus: ...`) that fire on every `DealProgress` effect with a bonus tag — visible as noise in this new test's output and in any other test that exercises that path. Pre-existing, unrelated to this plan, not fixed here.
  - **Orchestrator verification (independent, post-hoc):** dispatched fresh test and review agents to check this phase since it touched two files beyond the planned single test file. Test agent independently re-read the test file's 6 assertions, confirmed both content fixes are real and correctly targeted (grepped for stragglers, found none), confirmed the build() extraction doesn't break either real call site (WorldSelectScene.ts, TableScene.ts), and — as a sanity check — deliberately reverted the onDraw.title fix, reran the suite, confirmed the completeness guard genuinely fails (proving it has teeth, not a rubber stamp), then restored it. Review agent assessed the build() extraction as exactly the plan's own pre-authorized Step 8a contingency (not invented), and the two content fixes as reasonable, narrowly-scoped, test-driven consequences of building the completeness guard as specified — consistent with how Phases 3/5/6's divergences were judged. No escalation needed. Review also flagged the Phase-5 `eachTurn` wording change while scanning the full diff, which was already reviewed and approved during Phase 5 — no new issue.
