Skip to content

Fix review findings: readout occlusion, contrast, date bounds, disposal#7

Merged
veillette merged 1 commit into
mainfrom
claude/simulation-review-a54rsw
Jul 27, 2026
Merged

Fix review findings: readout occlusion, contrast, date bounds, disposal#7
veillette merged 1 commit into
mainfrom
claude/simulation-review-a54rsw

Conversation

@veillette

Copy link
Copy Markdown
Contributor

A review of the planetarium turned up ten issues. Each was reproduced against a production build driven in Chromium (not just read off the source), and each fix was re-verified the same way.

User-visible defects

The Selected Object readout was unreadable. It anchors bottom-left, but the Location + Time panels fill the left column at common window sizes and the Time panel paints over it — only a ~14 px sliver showed at both 1280×720 and 900×600. Since "click to identify" is a core feature, its primary output being hidden is the most serious item here. updateChromeLayout now slides the readout clear to the right of that column when they would overlap, mirroring the existing Reset All vs. Display panel avoidance.

Worth a second look in review: this runs re-entrantly from selectionPanel.boundsProperty, so left must be computed once and assigned once. My first attempt assigned it twice (default, then shifted) and recursed forever.

Search results were invisible. Result rows and the "no matches" line sit on the dark panel fill but used LIGHT_SURFACE_TEXT_FILL (near-black) — 1.04:1 contrast. The highlighted row was white on the light accent at 1.81:1. Both now take the correct side of that pairing (~15:1 and ~9.6:1). ZenithButtonOptions.ts already warned about this mixup in the opposite direction; the rule is now written down in CLAUDE.md so it does not recur.

?date= rendered a different sky than it named. The parameter accepted any parseable timestamp while the UI is bounded to 1900–2100, so ?date=1850-01-01 silently showed 1900 and ?date=2150-06-01 showed 2100 — a shared classroom link quietly resolving to the wrong epoch. It is now validated against a new CIVIL_TIME_MS_RANGE (derived from CIVIL_YEAR_RANGE) and falls back to the documented default with the standard invalid-parameter notice. Civil time is held inside the same range at runtime through setCivilTimeMs(), so playback stops at the edge instead of leaving the Year spinner displaying 2101.

The epoch combo always read "Custom time". The timer starts playing, so the first step() advanced civil time by a few milliseconds and marked the preset CUSTOM while the minute-precision readout still showed the preset epoch. It now flips only once the clock is a full minute off, matching the readout — so the selector can actually display a preset, including right after one is chosen.

Correctness and hygiene

  • Locale parity only asserted en↔fr, so a key missing from strings_es.json was not a build error despite CONVENTIONS.md §4 requiring it. Both directions are now asserted for es too — verified by deleting a key and watching npm run check fail.
  • SelectedObjectReadout never released its axon graph — a Multilink, ~20 DerivedPropertys and their pattern Properties stayed subscribed to the model and the shared StringManager after teardown. It now disposes in dependency order and ZenithScreenView.dispose() calls it.
  • Dropped the empty credits block, which rendered blank labelled rows in Help → About.
  • Replaced two literal rgba(0,0,0,0) hit-target fills with Color.TRANSPARENT.
  • Removed the unused ZenithPreferencesModel.reset(), which invited wiring preferences into Reset All against the documented "preferences outlive Reset All" contract.
  • Documented the "Use my location" third-party IP fallback (get.geojs.io, ipapi.co) in the README and model doc — it was explained in code but nowhere a teacher would look.

Verification

npm run lint, npm run check, npm run build, and npm test all pass. Tests: 154 → 163, adding coverage for the epoch tolerance, the civil-time clamp, out-of-range date links, and readout disposal (GC reachability plus no-throw-after-dispose).

Re-driving the production build in Chromium confirms the readout is fully legible at both window sizes, search results are readable, the epoch combo shows the preset, and ?date=1850-01-01 falls back to 2024-06-21 18:00. The Sirius readout also checks out astronomically — RA 6.75 h, Dec −16.7°, mag −1.46, transiting in 1h 43m from LST 5.03 h.

Not addressed

The invalid-parameter dialog renders joist's own untranslated Property#464{...} placeholders. That is pre-existing framework string loading, unrelated to these changes, and left for a separate look.

🤖 Generated with Claude Code

https://claude.ai/code/session_01P93K8JHzi5ytJDsGm1w1K9


Generated by Claude Code

Review of the planetarium surfaced several defects, verified against a
production build driven in Chromium.

Selected Object readout was unreadable. It anchors bottom-left, but the
Location + Time panels fill the left column at common window sizes and the
Time panel paints over it — only a ~14 px sliver showed at 1280x720 and
900x600. updateChromeLayout now slides the readout clear to the right of
that column when they would overlap, mirroring the existing Reset All vs.
Display panel avoidance. `left` is computed once and assigned once because
this runs re-entrantly from selectionPanel.boundsProperty.

Search results were invisible. Result rows and the "no matches" line sit on
the dark panel fill but used LIGHT_SURFACE_TEXT_FILL (near-black), giving
~1.04:1 contrast; the highlighted row was white on the light accent at
1.81:1. Both now take the correct side of that pairing, and the rule is
written down in CLAUDE.md so the mixup does not recur.

The `date` deep link accepted any parseable timestamp while the UI is bounded
to 1900-2100, so ?date=1850-01-01 silently rendered 1900 and ?date=2150-06-01
rendered 2100 — a shared link showed a different sky than it named. The
parameter is now validated against CIVIL_TIME_MS_RANGE (derived from
CIVIL_YEAR_RANGE) and falls back to the documented default. Civil time is
held inside the same range at runtime via setCivilTimeMs(), so playback stops
at the edge instead of leaving the Year spinner displaying 2101.

The epoch combo always read "Custom time": the timer starts playing, so the
first step advanced civil time a few milliseconds and marked the preset
CUSTOM while the minute-precision readout still showed the preset epoch. It
now flips only once the clock is a full minute off, matching the readout.

Locale parity only asserted en<->fr, so a key missing from strings_es.json
was not a build error despite CONVENTIONS.md sec. 4 requiring it. Both
directions are now asserted for es as well (verified by deleting a key).

Also: dispose SelectedObjectReadout's axon graph (a Multilink, ~20
DerivedProperties and their pattern Properties stayed subscribed to the model
and StringManager after teardown) and call it from ZenithScreenView.dispose;
drop the empty `credits` block that rendered blank rows in Help > About;
replace literal rgba(0,0,0,0) hit-target fills with Color.TRANSPARENT; remove
the unused ZenithPreferencesModel.reset(), which invited wiring preferences
into Reset All against the documented contract; and document the "Use my
location" third-party IP fallback in the README and model doc.

Tests: 154 -> 163. npm run lint, check, build, and test all pass.
@cursor

cursor Bot commented Jul 27, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@veillette
veillette merged commit 0002889 into main Jul 27, 2026
8 checks passed
@veillette
veillette deleted the claude/simulation-review-a54rsw branch July 27, 2026 08:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants