Skip to content

fix(ui): restore the two rebrand legacy localStorage keys (#7782) - #7849

Closed
galuis116 wants to merge 1 commit into
JSONbored:mainfrom
galuis116:fix/rebrand-legacy-localstorage-keys
Closed

fix(ui): restore the two rebrand legacy localStorage keys (#7782)#7849
galuis116 wants to merge 1 commit into
JSONbored:mainfrom
galuis116:fix/rebrand-legacy-localstorage-keys

Conversation

@galuis116

Copy link
Copy Markdown
Contributor

Summary

Closes #7782.

#5405 gave useLocalStorage a legacyKey param so a user's pre-rebrand gittensory_* localStorage value is read once and migrated forward to the new loopover_* key. Two days later, #5743's blanket gittensory -> loopover substitution ran across ~480 files and rewrote two string literals that were supposed to stay on the old prefix, leaving legacyKey identical to the current key:

  • app-panels/onboarding-preview-card.tsx - LEGACY_DISMISS_KEY
  • notification-readiness-card.tsx - the notification opt-in legacy key

When both keys are equal, useLocalStorage's fallback branch re-reads the exact key it just missed, so the migration is a no-op: a maintainer who dismissed the onboarding-preview card, or opted into notifications, before the rebrand silently loses that preference (the card reappears / they are defaulted back to notifications-off).

This restores both literals to their pre-rebrand values, verified against git show 112bc4a83:

  • gittensory_maintainer_onboarding_preview_dismissed
  • gittensory_notification_opt_in

matching the uncorrupted shape still present at api/try-it.tsx (STORAGE_KEY = "loopover.session_token" / LEGACY_STORAGE_KEY = "gittensory.session_token"). Every other rebrand-migrated legacy key (try-it.tsx, app.workbench.tsx, app.runs.tsx, app.index.tsx) was already genuinely distinct and is left untouched.

Regression tests

One per component, extending each component's existing test file and harness:

  • onboarding-preview-card.test.tsx - a dismissal stored only under the legacy key keeps the card hidden (and skips the API call), and the value is written forward to the current key.
  • notification-readiness-card.test.tsx - an opt-in stored only under the legacy key renders "opt-in enabled" and is written forward; plus the negative case (neither key set stays "opt-in required").

Both new tests were confirmed to fail against the pre-fix literals and pass after - i.e. they genuinely pin this bug rather than restating current behavior.

Scope

  • The PR title follows type(scope): short summary Conventional Commit format.
  • This PR is focused and does not mix unrelated backend, UI, MCP, docs, dependency, and deploy changes.
  • This follows CONTRIBUTING.md and does not reintroduce GitHub Pages, VitePress, site/, or CNAME.
  • I linked a currently open issue this PR resolves (Closes #7782).

Validation

  • git diff --check
  • npm run actionlint - no workflow files touched.
  • npm run ui:typecheck (clean across both UI workspaces)
  • Full @loopover/ui suite: 81 files / 550 tests pass, including the 3 new ones.
  • Negative control: with the two literals reverted, exactly the 2 new migration tests fail and the other 10 in those files still pass.
  • npm run test:coverage / test:workers / build:mcp / test:mcp-pack / ui:openapi:check - not run: this changes two string literals plus tests under apps/loopover-ui/ and touches no backend, worker, MCP, or OpenAPI surface.
  • npm audit --audit-level=moderate - no dependency changes.
  • New or changed behavior has unit tests for new branches and fallback paths.

If any required check was skipped, explain why:

  • No src/** lines are modified, so codecov/patch has no changed lines to score (apps/** is outside Codecov's coverage.include).
  • ui:lint could not be run meaningfully on this Windows checkout: core.autocrlf=true makes prettier report Delete CR on every file in the repo (including files this PR never touches), so its output is not a signal here. Excluding that CRLF noise, eslint reports no issues on the four changed files, and the committed diff is LF-normalized (48 insertions / 3 deletions, no whole-file rewrite).

Safety

  • No secrets, wallet details, hotkeys, coldkeys, user PATs, private keys, raw trust scores, private rankings, or private maintainer evidence are exposed.
  • Public GitHub text stays sanitized and low-noise.
  • Auth, cookie, CORS, GitHub App, Cloudflare, or session changes include negative-path tests - n/a: this is a browser-local preference key, not auth or session state. (try-it.tsx's session-token key is deliberately untouched.)
  • API/OpenAPI/MCP behavior is updated and tested where needed - n/a.
  • UI changes use live API data or real empty/error/loading states, not production mock/demo fallbacks - unchanged; both components keep their existing loading/error/ready paths.
  • Visible UI changes include a UI Evidence section - n/a: there is no visual diff. Nothing about layout, copy, or styling changes; for any given stored state the rendered output is identical. The only behavioral difference is which localStorage key is read during the one-time migration, which is why this is pinned by the two regression tests above rather than by a screenshot.
  • Public docs/changelogs are updated where needed - n/a.

Notes

  • The onboarding card stores an object ({ dismissed: boolean }) while the notification card stores a bare boolean, so each regression test seeds the legacy key with that component's own serialized shape.

…7782)

JSONbored#5405 gave useLocalStorage a legacyKey param so a pre-rebrand gittensory_*
value is read once and migrated forward to the loopover_* key. Two days
later JSONbored#5743's blanket gittensory->loopover substitution rewrote two string
literals it should not have, leaving legacyKey identical to the current key:

- onboarding-preview-card.tsx's LEGACY_DISMISS_KEY
- notification-readiness-card.tsx's notification opt-in legacy key

With both keys equal, useLocalStorage's fallback re-reads the same key it
just missed, so a maintainer who dismissed the onboarding card or opted into
notifications before the rebrand silently loses that preference.

Restores both literals to their pre-rebrand gittensory_* values, matching the
uncorrupted shape still present in api/try-it.tsx. Every other rebrand-migrated
legacy key was already distinct and is left untouched.

Adds a regression test per component asserting a value stored only under the
legacy key is read AND written forward to the current key; both fail against
the pre-fix literals and pass after.
@galuis116
galuis116 requested a review from JSONbored as a code owner July 21, 2026 15:00
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 21, 2026
@loopover-orb

loopover-orb Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Caution

🛑 LoopOver review result - fixes required

Review updated: 2026-07-21 15:06:48 UTC

4 files · 1 AI reviewer · no blockers · CI failing · blocked

🛑 Suggested Action - Fix Blockers

Review summary
This restores two legacy localStorage key literals (`gittensory_maintainer_onboarding_preview_dismissed` and `gittensory_notification_opt_in`) that a prior blanket rebrand rename had incorrectly overwritten to match the current key, which broke the migration fallback path in `useLocalStorage`. The fix is narrowly scoped, matches the verified pre-rebrand values cited against `git show 112bc4a` and the still-correct `try-it.tsx` pattern, and each component gets a regression test exercising the legacy-key-only read and forward-migration write plus a negative case. The change is a clean, well-targeted two-line fix with matching tests; the CI failures are unexplained by the diff itself.

Nits — 2 non-blocking
  • The two `validate-code`/`validate` CI failures show no detail, and given the branch is 2 commits behind the default branch, they may stem from unrelated upstream drift rather than this diff — worth confirming after a rebase.
  • Consider a shared constant or lint rule (e.g. a codemod exclusion list) to prevent future blanket rebrand/find-replace scripts from re-clobbering intentional legacy-key literals, since this is the second incident of that class.

CI checks failing

  • validate
  • validate-code

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #7782
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 1946 registered-repo PR(s), 1275 merged, 53 issue(s).
Contributor context ✅ Confirmed Gittensor contributor galuis116; Gittensor profile; 1946 PR(s), 53 issue(s).
Improvement ✅ Minor risk: clean · value: minor · LLM: moderate
Linked issue satisfaction

Addressed
The PR restores both LEGACY_DISMISS_KEY and the notification legacy key to their distinct gittensory_-prefixed values, matching the try-it.tsx pattern, and adds regression tests for both components verifying the legacy-key migration path works.

Review context
  • Author: galuis116
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: JavaScript, Python, Dart, TypeScript, HTML, MDX, Rust, C++
  • Official Gittensor activity: 1946 PR(s), 53 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Triage stale or unlinked PRs.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask <question> answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat <question> answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://loopover.ai/docs/loopover-commands

🧪 Experimental — new and may change.

Visual preview
Route Viewport Before (production) After (this PR's preview) Diff
/ desktop before /
before /
after /
after /
/ mobile before / (mobile)
before / (mobile)
after / (mobile)
after / (mobile)

Click any thumbnail to open the full-size screenshot. Before = production · After = this PR's preview deploy.

Scroll preview
Route Before (production) After (this PR's preview)
/ before / (scroll)
before / (scroll)
after / (scroll)
after / (scroll)

A short scroll-through clip (desktop) — click either thumbnail to open the full animation. Evidence for scroll-linked behavior a single screenshot can't show.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@loopover-orb

loopover-orb Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

This pull request changes UI/visual code but its screenshot evidence is incomplete. Every required viewport × theme combination needs its own before/after image pair in a labeled table row (e.g. "Desktop · Light | before | after"). Still missing: Desktop · Dark, Tablet · Dark, Mobile · Dark.

Please resubmit with the remaining rows filled in.

See https://github.com/JSONbored/loopover/blob/main/.claude/skills/contributing-to-loopover/SKILL.md for the exact format and examples. This is an automated maintenance action.

@loopover-orb loopover-orb Bot closed this Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Two rebrand legacy-key fallbacks were silently destroyed by the gittensory->loopover blanket rename

1 participant