#### Brief overview of PR changes/additions
- Stop importing settings from the pre-4.19 NativeFormat store (macOS
plists / Windows registry) into a freshly created Mudlet.ini
- On those platforms the old store ignores HOME/XDG overrides, so any
machine that ever ran Mudlet <= 4.18 made every fresh install inherit
stale keys and classify as an experienced player - skipping the starter
UI, tour and hints, and failing two functional tests
- Add tripwire asserts so any future write into a fresh Mudlet.ini
before init() fails with a self-explaining message
#### Motivation for adding to Mudlet
A fresh install must be recognised as a new player; anyone who ran 4.19+
was already migrated, and a direct <= 4.18 upgrade only loses UI
preferences (window geometry, appearance, storePasswordsSecurely,
deletedDefaultMuds), never profiles.
#### Other info (issues closed, discussion etc)
Fixes#9741
**Test case:** ExperiencedPlayerGateTest (18/18) and DefaultPackagesTest
(28/28) pass; on a Mac that ran Mudlet <= 4.18 (check with `defaults
read com.mudlet.Mudlet pos`), both suites now pass and a fresh profile
gets the starter UI.
Assisted-by: Claude:claude-opus-5
#### Brief overview of PR changes/additions
- An empty `$XDG_CONFIG_HOME/mudlet` silently beat a populated
`~/.config/mudlet`, so a stray `mkdir` hid every profile and Mudlet ran
its first-launch onboarding as though the user were new. It also stuck:
the first such launch wrote `Mudlet.ini` into that directory, which then
kept it winning.
- The two candidate roots are now ranked (`profiles/` > `Mudlet.ini` >
exists > absent) and the stronger claim wins, with
`$XDG_CONFIG_HOME/mudlet` taking ties so a fresh install and a
deliberate opt-in both still land there. A directory that cannot be
listed counts as populated rather than empty, so a permission bit cannot
re-enter the bug.
- Creating `profiles/` is now the opt-in a test harness uses; the
`mudlet` directory alone is not, because other tooling creates that by
accident. Where both roots hold profiles, `setupConfig()` names the one
it is ignoring instead of leaving those profiles apparently gone.
#### Motivation for adding to Mudlet
Data-loss-shaped regression from #9552 "improve: honor XDG_CONFIG_HOME
for Mudlet's config directory" (`e6c268cb0`). The profiles are orphaned
rather than destroyed, but a returning user sees "5.0 wiped my
profiles". `src/mudlet-lua/tests/README.md` itself instructed `mkdir -p
"$CONFIG_DIR/mudlet"`, so following Mudlet's own test docs triggered it.
#### Other info (issues closed, discussion etc)
Test case: create `~/.config/mudlet/profiles/{AlphaGame,BetaGame}`,
`mkdir -p $XDG_CONFIG_HOME/mudlet`, launch. Before: no profiles and the
onboarding dialog. After: both profiles listed.
`ConfigDirOverrideTest` covers the resolution table including the sticky
`Mudlet.ini` state, both-populated, symlinked and unreadable
directories; each new guard was mutation-checked. The busted suite
passes 2422/0 against an isolated `$XDG_CONFIG_HOME/mudlet/profiles`
root.
Not fixed here, and pre-existing rather than 5.0 regressions:
`CredentialManager` stores passwords and the OAuth reconnect token under
`AppConfigLocation` while the config root is `confPath`, so exporting
`XDG_CONFIG_HOME` strands them, and the plaintext-password migration
reads one path, writes the other and deletes the original. Both
reproduce identically on the 4.22.0 binary and need their own migration
path.
Assisted-by: Claude:claude-opus-5
#### Brief overview of PR changes/additions
- Comment-only follow-up to #9695 "fix: stop treating long-time Mudlet
users as brand new players" - no code line changes at all.
- Removes every passage describing what the gate used to do; git history
and the #9695 body carry that, and in source it goes stale the moment
someone touches the line.
- Cuts what remains to the constraints a reader cannot derive from the
code: the `init()` ordering requirement, why no filesystem timestamp can
substitute for the recorded date, and why the fallback deliberately errs
towards 'experienced'.
#### Motivation for adding to Mudlet
Applies the house comment standard to code that landed a few hours
earlier: 112 comment lines out, 33 shorter ones in.
#### Other info (issues closed, discussion etc)
Test names carry the intent in `ExperiencedPlayerGateTest`, so
per-assertion narration went; the `QVERIFY2` failure messages already
say what each case is asserting. What was kept there: the permissions
restore-before-assert ordering, the `$XDG_CONFIG_HOME/mudlet` opt-in
marker, and the note that the live-singleton case must run last because
`experiencedMudletPlayer()` memoises.
**Test case:** `ctest --output-on-failure` - 79/79, unchanged.
Assisted-by: Claude:claude-opus-5
#### Brief overview of PR changes/additions
- `experiencedMudletPlayer()` decided veteran status from profile
**directory** mtimes. The per-profile data writes (url, port, password,
`profile.ini`, command history) all land straight in that directory and
bump its mtime every session, so only a profile *abandoned* for six
months ever looked old - the more you use Mudlet, the more certainly it
called you new. All 13 profiles on the maintainer's machine classified
as "brand new player".
- Mudlet renewed those timestamps itself: the connection dialog rewrites
`url`/`port`/`description` for the selected profile at startup, so
merely launching Mudlet reset the value the gate read.
- Replaced with a `firstLaunchDate` key recorded in QSettings on a
genuinely fresh install (written in `init()`, before anything can create
a profile or save a setting). An installation with any trace of earlier
use - a profile, or any other setting already on file - has no
recoverable start date and is treated as experienced; timestamps cannot
recover one, since a copied or restored profile keeps its modification
times only if the tool used happened to preserve them, and loses its
birth time regardless.
#### Motivation for adding to Mudlet
In 4.22.0 this gate only suppressed three one-line hints, but 5.0 hung
the full-window "Welcome to Mudlet! New here?" tour (#9385, 69d7d4169
"Add: UI tour to complement the Mudlet tutorial") and the starter UI
package (#9454, 69cd06b1c "add: starter interface with health bars, map
and chat for new players") off it, so essentially every active 4.22.0
user upgrading to 5.0 would get a beginner tour dropped on top of their
session.
#### Other info (issues closed, discussion etc)
The heuristic dates back to ae0564e6e "Improve: revise splitscreen
tutorial (try 2)" (#7341); the two 5.0 consumers above are what turned
it into a release blocker. New `ExperiencedPlayerGateTest` (18 cases)
covers fresh install, upgrader with freshly-written profiles, settings
restored without profiles, the six-month boundary, a profile restored
from backup, future-dated, unparseable and unwritable records, and two
live-singleton cases that pin the `init()` call site and the memoised
read. Both directions were mutation-tested: dropping the `init()` call
and restoring the old mtime heuristic each fail the suite. When in doubt
the gate errs towards *experienced* - a veteran shown a new-user tour is
a much worse outcome than a newcomer who misses it.
**Test case:** Seed a HOME that looks like an existing user (one
profile, `Mudlet.ini` without `uiTourShown`), launch Mudlet and connect
- before, the 6-step "Welcome to Mudlet!" tour appears; after, it does
not. A HOME whose `Mudlet.ini` has a recent `firstLaunchDate` still gets
the tour, and a genuinely empty HOME records one.
Assisted-by: Claude:claude-opus-5