Commit graph

30 commits

Author SHA1 Message Date
Mike Conley
6705cadd11
Infra: Add CMake presets for every platform, and one home for AI assistant skills (#9742)
#### Brief overview of PR changes/additions

- Adds `CMakePresets.json` with configure, build and test presets for
macOS, Linux and Windows, including sanitizer and static-analysis
variants. Each is gated on the host system, so a listing only offers
what the current machine can build.
- Consolidates the AI assistant skills into `.agents/skills/`, which
Claude Code, GitHub Copilot and Cursor all read, replacing two copies
that had drifted into contradicting each other.
- Corrects the build documentation: the Windows toolchain is CLANG64
rather than MinGW64, and the previous "no need to specify number of
jobs" advice holds only for Ninja.

#### Motivation for adding to Mudlet

The instructions presented platform-specific build advice as though it
were universal, so following them on the wrong platform produced either
an unbounded parallel build or a toolchain the setup scripts refuse to
run.

#### Other info (issues closed, discussion etc)

`windows-debug` has been exercised on Windows: `CI/setup-windows-sdk.sh`
in an MSYS2 CLANG64 shell, then configure and build both to completion
against Qt 6.11.1 and Clang 22.1.7. `cmake --list-presets` correctly
offered only `windows-debug` there.

Note that `windows-debug` is a Debug configuration, whereas
`CI/build-mudlet-for-windows.sh` builds Release, so the two are not
equivalent.

`.claude/skills` is a symlink to `.agents/skills`, following the
existing pattern used by `CLAUDE.md`, `AGENTS.md` and `.cursorrules`. On
Windows checkouts without `core.symlinks` it lands as a plain file, in
which case Copilot and Cursor still read `.agents/skills` directly.

**Test case:** `cmake --preset macos-debug && cmake --build --preset
macos-debug`, then `ctest --preset macos-debug`. `cmake --list-presets`
should offer only the current platform's presets, and a variant such as
`macos-debug-nosan` should build into `build-macos-debug-nosan/` while
leaving `build/` untouched.

---------

Signed-off-by: Michael Conley <sousesider@gmail.com>
2026-08-12 21:28:13 +02:00
Vadim Peretokin
9a9710b229
fix: new profiles process game text about twice as fast (#9705)
#### Brief overview of PR changes/additions

- The starter UI armed **77 always-active PCRE triggers** (12 chat + 65
vitals) at package load, so every line a game sent was matched against
all of them - and every line one matched was then re-walked in Lua with
all 77 patterns **recompiled from source**, because `rex.match` given a
pattern string compiles it afresh on every call. They are now fronted by
4 triggers (3 chat-routing groups + 1 vitals prefilter) and compiled
once. The 65 vitals shapes and 12 chat shapes are byte-identical and
still do all the reading.
- The plain-text vitals layer now retires itself once GMCP or MSDP holds
the source lock, since `applyVitals` discards its readings from that
point anyway, and re-arms on disconnect.
- `PipelineBenchmark` created its profile through the production
new-profile path, so the starter UI was **inside** the
`text_lines_per_sec` baseline backing the "no more than 10% throughput
loss" gate for #9011 - the guard built to catch this class of regression
could not see it. Pipeline metrics now come from a profile with default
packages suppressed; the shipped configuration is reported separately as
`defaults_*` and gated in its own right.

#### Motivation for adding to Mudlet

Every new 5.0 profile was paying roughly half its text throughput to a
default package, and the perf guard had the cost baked into its own
baseline so nothing flagged it.

#### Other info (issues closed, discussion etc)

Findings C17 and C18 of the 5.0 QA sweep. Bisected there to `69cd06b1c`
- "add: starter interface with health bars, map and chat for new
players" (#9454); the benchmark half is the interaction of that with
`7d67d4bfb` - "infrastructure: perf baseline" (#9509).

Measured on a quiet 16-core box, Release, no ASan, alternating paired
runs so drift is shared between arms:

| workload | before | after | |
| --- | --- | --- | --- |
| `TelnetBenchmark` `benchLargeData`, 1000 lines that match nothing |
22.25 ms `[22.1-22.6]` | 12.0 ms `[11.9-12.2]` | **1.85x** |
| `PipelineBenchmark`, 25k lines of realistic game output, new-user
profile | 9,998 lines/s `[9,856-10,072]` | 16,503 lines/s
`[16,257-16,632]` | **1.65x** |

Complete separation in both (21 and 9 pairs; within-arm spread ±1.7% and
±1.5%, so ~3% is the smallest effect distinguishable from noise - the
effect is 85% and 65%). The bare pipeline measures 116,000 lines/s, so
the starter UI's remaining cost on that corpus is 7.0x, down from 11.6x;
the residual is the capture layer doing its designed work on a corpus
where 1 line in 11 is a tell and another 1 in 11 a vitals prompt.

Two notes for reviewers:
- `config.lua` is bumped to 1.1.0, so mpkg offers the update - but
default packages are installed at profile creation, so **profiles
already created on a 5.0 PTB keep the old copy** until they update it.
- Touches `src/mudlet.cpp` / `src/mudlet.h` /
`test/functional_tests/CMakeLists.txt`, which #9695 also touches; the
CMakeLists hunk will likely conflict trivially (both append a test
file).

**Test case:** create a fresh profile against any game without GMCP,
confirm the health/mana gauges and chat tabs still appear from prompt
and chat lines, then `ctest -R StarterUiTriggerCostTest`.

Assisted-by: Claude:claude-opus-5
2026-08-08 09:04:14 +00:00
Vadim Peretokin
f7da6ca3da
improve: ship every default package as an mpackage (#9626)
#### Brief overview of PR changes/additions

- Every package Mudlet preinstalls now lives in `src/packages/<name>/`,
holding its `config.lua`, `.xml` and the `.mpackage` built from them -
previously they were scattered across `src/` and `src/mudlet-lua/lua/`,
and four had no metadata at all.
- The game loaders (Carrion Fields, Icesus, MorgenGrauen, Medievia) and
the two `mudlet.org` dev packages shipped as bare xml, so the Package
Manager showed them with no version, author or description. They are
packaged now, keeping their existing package names so nothing renames on
upgrade.
- New `DefaultPackagesTest` walks the preinstall table for seven games,
checks every queued path is really compiled in, and installs all 15
archives.

#### Motivation for adding to Mudlet

An mpackage carries Mudlet's metadata and a bare xml cannot. Keeping
each package's sources next to its archive also makes the Lua reviewable
in diffs, which a committed zip on its own is not.

#### Other info

Stacked on #9624, whose check now covers all 15 packages. The IRE mapper
stays an xml because upstream publishes it that way and
`update-3rdparty.yml` overwrites it weekly. Package repository PR
Mudlet/mudlet-package-repository#746 updates the sync paths and must
merge right after this.

#### Test case

`ctest` 66/67 locally (`TKeySequenceEditTest` is the known headless
flake - passes under openbox); `DefaultPackagesTest` 28/28; `python3
CI/check-mpackage-sync.py --base-ref origin/development` clean.

Assisted-by: Claude:claude-opus-5

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-08-04 10:18:48 +02:00
Vadim Peretokin
7d67d4bfb9
infrastructure: add performance baseline benchmark for the text and trigger pipeline (#9509)
#### Brief overview of PR changes/additions

- Adds `test/functional_tests/PipelineBenchmark.cpp` - a headless,
deterministic, report-only benchmark. It feeds a fixed 25,000-line
corpus (plain text, ANSI SGR colour, UTF-8, and long wrapping-heavy
prose adopted from the Stressinator display package) through the
production `cTelnet -> TBuffer -> TConsole -> TriggerUnit` path via
`loopbackTest()`, and prints `METRIC` lines: text-pipeline throughput,
trigger-engine throughput with a realistic ~34-trigger set, derived
trigger overhead, and peak RSS.
- Adds `test/compare-perf-baseline.py` - the primary workflow. Given an
older and a newer build run on the **same machine**, it parses their
`METRIC` output, prints per-metric deltas, and exits non-zero on a
PASS/FAIL against the 10% gate.
- `test/functional_tests/CMakeLists.txt` builds the benchmark **always**
but keeps it **out of the default ctest suite**; it is report-only and
slow, so it should not run on every CI pipeline. Opt in with
`-DREGISTER_PERF_BENCHMARK=ON` to also register it with ctest.
- Adds `docs/libmudlet-perf-baseline.md` documenting the before/after
workflow. **No canonical, machine-specific numbers are committed** - the
figures in the doc are explicitly illustrative.

#### Motivation for adding to Mudlet

The libmudlet refactor's "no more than 10% throughput loss" gate is
unenforceable without a reproducible way to measure it. Absolute numbers
are meaningless across machines, so this provides a deterministic
harness plus a same-machine before/after comparison tool that turns the
gate into a mechanical PASS/FAIL.

#### Other info (issues closed, discussion etc)

Part of the libmudlet refactor (#8681, #9011) - referenced, not closed.

- **Report-only**: it makes no timing assertions (absolute speed varies
wildly between machines and CI runners), but it does assert the pipeline
genuinely processed data - console buffer fill, every trigger
compiled/registered, and an untimed sentinel trigger firing - so a
silently-disconnected pipeline fails instead of reporting inflated
numbers.
- Each phase feeds the corpus 6 times and reports the **fastest pass**:
the least-disturbed pass isolates intrinsic speed from transient CPU
contention, keeping run-to-run spread ~2% even on a loaded machine.
- **Companion, not a replacement, for the live-GUI path.**
`PipelineBenchmark` runs offscreen and covers the telnet -> buffer ->
trigger core (the piece the refactor moves). The **Stressinator display
benchmark** covers the on-screen render/echo path on a live build; its
wrapping-heavy prose has been adopted into this corpus. Between them
they cover bytes-off-the-socket to pixels-on-screen.

Assisted-by: Claude:claude-fable-5

**Test case:**

Primary workflow - build an older and a newer tree on the same machine,
then compare:

```
flock /tmp/mudlet-functional-tests.lock \
  test/compare-perf-baseline.py --run \
    ../mudlet-before/build/test/functional_tests/PipelineBenchmark \
    build/test/functional_tests/PipelineBenchmark
```

Or run the benchmark once directly (it is built even without the ctest
opt-in):

```
QT_QPA_PLATFORM=offscreen ASAN_OPTIONS=detect_leaks=0 \
  ./build/test/functional_tests/PipelineBenchmark
```

Illustrative output (absolute values vary per machine; nothing is
asserted on timing):

```
METRIC text_corpus_lines 25000
METRIC text_corpus_bytes 1436934
METRIC text_lines_per_sec 4281.46
METRIC text_mb_per_sec 0.41
METRIC text_best_pass_ms 5839.12
METRIC trigger_count 34
METRIC trigger_lines_per_sec 3323.25
METRIC trigger_mb_per_sec 0.32
METRIC trigger_best_pass_ms 7523.40
METRIC trigger_overhead_ms 1683.64
METRIC peak_rss_kb 1402384
```

To drive it through ctest instead, configure with
`-DREGISTER_PERF_BENCHMARK=ON`, then `ctest -R PipelineBenchmark -V`.
2026-07-27 22:01:25 +02:00
Vadim Peretokin
2d4d9b9ca5
infrastructure: harden the Widgets audit script and refresh its baseline (#9516)
#### Brief overview of PR changes/additions

Follow-up to #9508. Hardens `cmake/audit-core-widgets.sh` against five
silent-wrong-count failure modes (each reproduced by running the script
against crafted inputs), and refreshes the committed baseline/report to
the current count.

- **CMakeLists parser** now strips `#` comments and a trailing `\r`, and
tracks multi-line `list(APPEND mudlet_SRCS ...)` blocks. Previously a
`)` inside a comment truncated the file list, a commented-out filename
got audited, a wrapped `APPEND` dropped its continuation lines, and a
CRLF checkout only partially parsed.
- **Comment/string stripper** now matches a `/* ... */` comment whose
body contains `*` (the `/** ... */` one-liner that used to latch the
scanner into comment mode and silently swallow the rest of a file), and
hard-fails (exit 2) on an unterminated comment at EOF rather than
under-counting.
- **`--enforce`** is now a real gate: a source file listed in
`CMakeLists.txt` but missing from disk is fatal, and the baseline is
strict-parsed (bare integer on line 1). The old `tr -cd 0-9` pooled
every digit in the file, so a `# updated 2026-07-20` comment produced a
baseline like `20260720158` that out-ranked any real count and passed
forever.
- **Qt sanity**: if the `QtGui`/`QtCore` header listings come out empty
while `QtWidgets` is non-empty (a partial/broken Qt), the script aborts
instead of miscounting relocated forwarder headers (`qaction.h`,
`qshortcut.h`, ...) as Widgets dependencies.
- **Baseline + report refreshed** from `160` to `158`: #9507 decoupled
the telnet engine from UI dialogs after the original report was
generated, so `ctelnet.cpp`/`ctelnet.h` are now clean.

The script stays POSIX `sh`, deterministic (`LC_ALL=C`), and fast
(~0.2s). The parser change is count-neutral: old and new parsers produce
an identical 392-file list on the current `src/CMakeLists.txt`.

#### Motivation for adding to Mudlet

The audit becomes a CI gate once the count reaches 0 (#8681, #9011).
Before that, it must never report a wrong number quietly - every one of
these paths could have made the count drift (up or down) with no visible
error, which would erode trust in the gate. Loud failure beats a
silently passing check.

#### Other info (issues closed, discussion etc)

Follow-up to #9508. No build required (shell + docs only). Self-tested
with a 17-assertion harness that crafts each proven failure input and
confirms the fixed script returns the correct count or exits 2, while
the pre-fix script mis-parses.

**Test case:**

```
bash cmake/audit-core-widgets.sh --summary
# expected: mudlet_core Qt Widgets audit: 158 of 392 files depend on Qt Widgets

bash cmake/audit-core-widgets.sh --enforce
# expected: mudlet_core Qt Widgets audit: 158 offending files (baseline 158).  (exit 0)
```

Assisted-by: Claude:claude-opus-4-8
2026-07-26 18:05:59 +02:00
Vadim Peretokin
7c4ee8bef2
infrastructure: slim down the AI assistant instructions (#9511)
#### Brief overview of PR changes/additions
- Remove content from docs/ai-instructions.md that any coding agent can
derive from the repo itself (directory layout, dependency versions,
generic code examples)
- Move macOS/Windows build steps and debugging defines to a new
docs/platform-builds.md, referenced by a pointer line, so they load only
when needed
- Fix the debugging-defines usage note to name the actual CMake target
and a couple of typos

#### Motivation for adding to Mudlet
Every AI-assisted session loads these instructions into its context
window; trimming the derivable ~40% leaves more room for actual work,
and works for all agents (Claude Code, Codex, Cursor, Copilot) since
they all read this same file via symlinks and can follow a plain docs/
path.

#### Other info (issues closed, discussion etc)
Newer models can be trusted to discover more and require less hand
holding, which can even limit them, see
https://claude.com/blog/the-new-rules-of-context-engineering-for-claude-5-generation-models.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Vadim Peretokin <vadim.peretokin@mudlet.org>
2026-07-26 15:23:14 +02:00
Vadim Peretokin
113d1fe930
infrastructure: add Qt Widgets dependency audit for the core library (#9508)
#### Brief overview of PR changes/additions

- Adds `cmake/audit-core-widgets.sh`: measures how many `mudlet_core`
source files depend on Qt Widgets (direct QtWidgets includes plus
class-symbol references, with the QtWidgets header/class sets derived
from the installed Qt's module layout).
- Commits the generated `docs/libmudlet-widgets-report.md` (per-file
breakdown, regenerated via the script) and
`cmake/core-widgets-baseline.txt`.
- Script modes: Markdown report (default), `--summary` one-liner,
`--enforce` ratchet that fails if the count rises above the baseline.

#### Motivation for adding to Mudlet

Gives the libmudlet split a measurable metric - files in `mudlet_core`
still coupled to Qt Widgets - and a future CI ratchet to stop that
number from creeping back up as it is driven down.

#### Other info (issues closed, discussion etc)

Part of the libmudlet refactor discussed in #8681 and #9011. Current
baseline: 160 of 392 `mudlet_core` files depend on Qt Widgets.
`--enforce` is intended to become a CI guard in a follow-up once wired
into a workflow; output is byte-deterministic (pinned C locale) so the
committed report regenerates identically on any machine.

Assisted-by: Claude:claude-fable-5

**Test case:**

```
bash cmake/audit-core-widgets.sh --summary
```

Expected output: `mudlet_core Qt Widgets audit: 160 of 392 files depend
on Qt Widgets`. Also `bash cmake/audit-core-widgets.sh >
docs/libmudlet-widgets-report.md` should leave the committed report
unchanged, and `bash cmake/audit-core-widgets.sh --enforce` should exit
0.
2026-07-26 10:32:26 +02:00
Vadim Peretokin
69cd06b1c2
add: starter interface with health bars, map and chat for new players (#9454)
#### Brief overview of PR changes/additions
- New "Mudlet base UI" package auto-installed for new players on every
game: adjustable right-side dock with map (placeholder until the game is
mapped), tabbed chat (All/Tells/Channels with unread badges) and themed
HP/MP/MV/XP gauges - only ever built from data the game actually
provides
- Chat capture: GMCP Comm.Channel.Text when available, otherwise a
generic additive trigger layer (line shapes distilled from an audit of
all 216 packages in the Mudlet package repository); nothing is ever
gagged, and the trigger layer retires itself the moment GMCP chat
appears
- Vitals ladder for the gauges: GMCP (several dialect spellings) > MSDP
(negotiated automatically) > self-sufficient prompts (labeled cur/max or
percents) > score-screen harvesting; when a prompt only shows bare
currents, Mudlet sends `score` once - visibly, with an announcement - to
learn the maxima. Maxima are never guessed. An enemy-health bar appears
during fights on games that report it
- `baseui hide` / `baseui show` opt-out persists across restarts;
first-run announcement defers to the UI tour; experienced players never
get the package
- Plays nice with games that provide their own interface: profiles for
games whose bundled loader installs the game's official UI (flagged in
TGameDetails: Carrion Fields, Icesus, MorgenGrauen, Medievia) skip the
starter UI entirely, and when a game pushes a `Client.GUI` package the
starter UI quietly stands aside (via the new `sysServerGuiInstalled`
event) - `baseui show` brings it back for players who prefer it
- `docs/package-capture-audits/` records the chat + vitals capture
audits (with provenance) behind the design

#### Motivation for adding to Mudlet
New players currently get a bare text screen; this gives every game -
GMCP-rich, MSDP-only or plain telnet - an immediate, honest starter UI
out of the box.

#### Other info (issues closed, discussion etc)
Progresses #3071 and #3070 (phase 1 - not closing them).

**Test case:** Fresh install → create a profile for any game → connect.
On GMCP/MSDP games the dock builds with ticking gauges and tabbed chat;
on a game whose prompt carries cur/max values, gauges appear once the
prompt repeats; on a bare-number prompt, `score` is sent once
(announced) to size the gauges; on pure chat games, tells/says/channels
are captured with no gauges invented. `baseui hide` removes it and
survives restart.



https://github.com/user-attachments/assets/56d207cc-5bad-4464-867c-1a810d41cf2f

---------

Signed-off-by: Vadim Peretokin <vadim.peretokin@mudlet.org>
2026-07-26 08:43:21 +02:00
Vadim Peretokin
17a44b91ad
infrastructure: document how to record before & after demo videos (#9482)
#### Brief overview of PR changes/additions
- New `docs/demo-videos.md`: agent-neutral guide for recording before &
after demo videos of fixes headlessly on Linux
(Xvfb/openbox/xdotool/ffmpeg), with a reference recording script, a
trimming/labelling recipe, and the known gotchas
- `docs/ai-instructions.md` (shared by CLAUDE.md, AGENTS.md and the
Copilot instructions) now points at it

#### Motivation for adding to Mudlet
The demo videos accompanying recent PRs were made from workflow
knowledge that lived outside the repo; documenting it lets any
contributor or AI assistant produce them.

#### Other info (issues closed, discussion etc)
Linux-only for now - macOS and Windows additions to the workflow are
welcome.

**Test case:** Have an AI agent (or a human) follow only the document to
produce a sample video. Already QA'd this way once: an agent given
nothing but this document produced a correctly labelled before/after
video on the first try, and its documentation findings are folded in.

---------

Signed-off-by: Vadim Peretokin <vadim.peretokin@mudlet.org>
2026-07-22 09:29:30 +02:00
Vadim Peretokin
7bb0b5ead8
infrastructure: align CLAUDE.md et all with contributing guidelines (#9265)
<!-- Keep the title short & concise so anyone non-technical can
understand it,
     the title appears in PTB changelogs -->
#### Brief overview of PR changes/additions
Mirrors the AI Coding Assistants policy from docs/CONTRIBUTING.md into
the agent instructions so AI assistants apply it on every commit, not
only when CONTRIBUTING.md is consulted. Also makes explicit that the
human must build and test the change before signing off.
#### Motivation for adding to Mudlet
AI agents weren't reading CONTRIBUTING.md, but they do read CLAUDE.md
and all other files.
#### Other info (issues closed, discussion etc)

---------

Signed-off-by: Vadim Peretokin <vadim.peretokin@mudlet.org>
Co-authored-by: Vadim Peretokin <vadi2@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-05-12 11:39:51 +02:00
Vadim Peretokin
8d2f8597a7
Infrastructure: update CONTRIBUTING.md with AI coding guidelines (#9224)
<!-- Keep the title short & concise so anyone non-technical can
understand it,
     the title appears in PTB changelogs -->
#### Brief overview of PR changes/additions
Added guidelines for AI coding assistants, including licensing,
attribution, and responsibilities for human submitters.

Inspired by Linux Kernel rules for the same:
https://github.com/torvalds/linux/blob/master/Documentation/process/coding-assistants.rst?plain=1
#### Motivation for adding to Mudlet
Clarify Mudlet stance on AI agents
#### Other info (issues closed, discussion etc)

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-04-29 06:57:35 +02:00
Vadim Peretokin
5de0ed8a06
Fix link to CONTRIBUTING.md in ai-instructions.md (#9225)
<!-- Keep the title short & concise so anyone non-technical can
understand it,
     the title appears in PTB changelogs -->
#### Brief overview of PR changes/additions
Updated link to the CONTRIBUTING.md file in the documentation.
#### Motivation for adding to Mudlet
Missed it in the move
#### Other info (issues closed, discussion etc)
Also added a note on `is` prefix

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-04-28 09:39:11 +02:00
Vadim Peretokin
ea57a6dc1c
infrastructure: apply clang-format style to tests too (#9201)
#### Brief overview of PR changes/additions
Move `.clang-format` from `src/` to the repo root so it applies to
`test/` as well.

#### Motivation for adding to Mudlet
Test files were not being formatted with the project's clang-format
style, leading to inconsistent style drift when editors auto-format
them.

#### Other info (issues closed, discussion etc)
None.

**Test case:** Run `clang-format --dry-run
test/functional_tests/TelnetTextDisplayedTest.cpp` from the repo root
and confirm it reports Mudlet-style violations (i.e. config is
discovered).
2026-04-20 11:56:29 +02:00
Morquin
3036e1f3d7
improve: Give players full control over Discord Rich Presence (#9116)
## Summary

Players had no clear way to control what Discord shows about their
Mudlet activity. The old checkbox in the connection pane only gated
server GMCP data but didn't prevent Discord from showing "Playing
Mudlet", and the privacy controls were confusing. This PR replaces all
of that with three straightforward modes via radio buttons in Profile
Preferences > Chat:

- **Show full game details (if supported)** - full game integration with
server-provided presence (default)
- **Show Mudlet only** - only shows "playing Mudlet", game server is not
told about Discord
- **Disabled** - Discord shows nothing about Mudlet

Players pick the mode that matches their comfort level, and the existing
privacy checkboxes (hide detail, hide state, etc.) remain available in
Game details mode for finer control.

### What changed

- **Three-mode radio buttons** in Profile Preferences > Chat with a
two-column layout (modes on the left, privacy controls on the right),
replacing the old connection-pane checkbox
- **Server-origin tracking** so privacy checkboxes only gate data sent
by the game server - Lua API calls always pass through (only Disabled
mode blocks Lua entirely)
- **Mid-session mode switching** via dynamic GMCP negotiation
(Core.Supports.Add/Remove + External.Discord.Hello/Get)
- **Deferred RPC init** - Discord RPC now starts when a profile loads,
not on app launch
- **Username restriction improvements** - takes effect immediately,
case-insensitive (Discord usernames are lowercase-only since 2023),
shuts down RPC when mismatched
- **Shows logged-in Discord user** in preferences next to the
restriction field, with a tooltip explaining the desktop app requirement
when not connected
- **Presence fix** - empty string fields now send nullptr so Discord
hides them instead of showing blanks
- **Memory leak fix** - presence allocations are now freed in the
destructor regardless of RPC state

### Cleanup

- Removed obsolete discriminator field
(`mRequiredDiscordUserDiscriminator`) - Discord removed discriminators
in 2023
- Removed dead code (`getDiscordUserDetails()`, never called)
- Restored `Discord_ClearPresence` function pointer for potential future
use
- Use proper `Host::DiscordOptionFlags` types instead of raw `int`
(thanks @SlySven)

### Known quirks

- The "Hide timer" checkbox correctly omits timestamps from presence
data, but Discord's client starts its own activity timer for any
presence without a timestamp - this is Discord client behavior outside
our control.
- The "Hide large icon" setting clears the image key, but some Discord
clients fall back to the application's default icon instead of hiding it
entirely.

### Test plan

- [ ] Open Profile Preferences > Chat tab
- [ ] Switch between the three radio button modes and verify Discord
presence updates accordingly
- [ ] In Game details mode, toggle privacy checkboxes and verify fields
are hidden/shown
- [ ] Use Lua API (e.g. `setDiscordDetail("test")`) in Mudlet only mode
- should work. Try in Disabled mode - should fail with error
- [ ] Set a username restriction and verify presence clears immediately
if mismatched
- [ ] Run unit tests: `cd build && ./test/DiscordTest`
- [ ] Run functional tests: `cd build && ctest -R TDiscordModeTest -V`

Closes #6967. Supersedes #7438.

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: SlySven <slysven@virginmedia.com>
2026-04-08 13:33:09 +02:00
Mike Conley
706419784b
Improve: Add macOS clang-format path to AI instructions (#8926)
#### Brief overview of PR changes/additions

Adds macOS-specific guidance for running clang-format using the
Homebrew-installed LLVM version.

#### Motivation for adding to Mudlet

On macOS, the system `clang-format` command may not be available or may
be an older version. This update helps AI assistants and developers use
the correct full path to the Homebrew LLVM clang-format, ensuring
consistent code formatting.

#### Other info (issues closed, discussion etc)

Documentation-only change to `docs/ai-instructions.md` (symlinked to
`AGENTS.md` and `.github/copilot-instructions.md`).
2026-02-09 11:48:25 +01:00
Mike Conley
6d90a1e56f
Improve: macOS build instructions use absolute path (#8860)
#### Brief overview of PR changes/additions

Updated the macOS build instructions to use an absolute path when
running Mudlet, making it clearer and more reliable.

#### Motivation for adding to Mudlet

Using a relative path requires being in the correct directory, which can
cause confusion. An absolute path works from anywhere and matches the
pattern that has been successful in practice.

#### Other info (issues closed, discussion etc)

This is a documentation-only change that improves clarity for developers
building on macOS.
2026-02-01 21:49:13 +01:00
Vadim Peretokin
e6ea808bbb
infrastructure: add clang-format instructions to AI guidelines (#8806)
#### Brief overview of PR changes/additions
Add instructions for running clang-format after editing C++ files.

#### Motivation for adding to Mudlet
After the recent clang-format pass, AI assistants need clear guidance on
when to format code to avoid future merge conflicts.

#### Other info (issues closed, discussion etc)
N/A
2026-01-22 07:07:18 +01:00
Mike Conley
3d780e9c71
Fix: Improve build documentation clarity for terminal execution (#8774)
#### Brief overview of PR changes/additions

Combines the `cd` and execution commands into a single line in the macOS
build instructions, ensuring commands run in the correct directory
context.

#### Motivation for adding to Mudlet

When AI assistants help with building and running Mudlet, they start
fresh terminal sessions that don't retain directory context. By
combining the directory change with the executable path in a single
command, the instructions ensure the command always executes from the
correct location without requiring additional navigation steps.

This reduces the number of self-prompts AI assistants need to locate the
executable, improving efficiency and reducing unnecessary token
consumption during development assistance.

#### Other info (issues closed, discussion etc)

No issues closed. Minor documentation improvement to enhance AI
assistant workflow efficiency.
2026-01-11 16:59:06 +01:00
Vadim Peretokin
e7f22e5dbc
Infrastructure: reduce Mudlet build times by 30s (#8403)
<!-- Keep the title short & concise so anyone non-technical can
understand it,
     the title appears in PTB changelogs -->
#### Brief overview of PR changes/additions
Reduce Mudlet build times
#### Motivation for adding to Mudlet
Address #6765, and give developers a better experience.
#### Other info (issues closed, discussion etc)
  Benchmark Results

=== Testing: development (before) (development) ===
Run 1 of 3...
  Time: 226.071397436s
Run 2 of 3...
  Time: 216.059263209s
Run 3 of 3...
  Time: 221.592760908s

=== Testing: PR #8403 (after) (pr-8403) ===
Run 1 of 3...
  Time: 191.112400957s
Run 2 of 3...
  Time: 193.975717783s
Run 3 of 3...
  Time: 196.569316252s


[benchmark-mudlet-build.sh](https://github.com/user-attachments/files/24466717/benchmark-mudlet-build.sh)

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Vadim Peretokin <vadi2@users.noreply.github.com>
2026-01-08 21:04:24 +01:00
Vadim Peretokin
f51b5513e4
infrastructure: Simplify build system by removing unused QMake files (#8731)
#### Brief overview of PR changes/additions

Removes the legacy QMake build system (`src/mudlet.pro`) since CMake is
now the only supported build method.

#### Motivation for adding to Mudlet

- Eliminates unmaintained code
- Removes need to keep version in sync between two build systems
- Simplifies CI scripts and documentation

#### Other info (issues closed, discussion etc)

**Test case:** Build Mudlet using CMake as documented at
https://wiki.mudlet.org/w/Compiling_Mudlet - should work unchanged.
2026-01-05 09:07:33 +01:00
Mike Conley
6912c65d6c
Improve: AI assistant guidance for modern C++ loops (#8741)
#### Brief overview of PR changes/additions

Adds guidance for AI assistants to use range-based for loops instead of
older iterator or index-based loops.

#### Motivation for adding to Mudlet

Following PR #8733, this ensures AI assistants write more readable and
modern C++ code that aligns with current project practices.

#### Other info (issues closed, discussion etc)

Inspired by #8733
2026-01-04 14:32:07 +00:00
Mike Conley
f06096fd0e
Add: Optional static analysis during build (#8708)
#### Brief overview of PR changes/additions

Adds optional static analysis integration to the CMake build system.
Developers can now enable clang-tidy and cppcheck during compilation by
passing `-DENABLE_STATIC_ANALYSIS=ON` to cmake. The analysis runs
automatically during builds and helps catch bugs, performance issues,
and code quality problems.

**Changes:**
- New `cmake/StaticAnalysis.cmake` module with clang-tidy and cppcheck
configuration
- Enabled by default in `CMakeLists.txt` but requires opt-in flag to
activate
- Updated AI assistant instructions with wiki reference
- Performs performance-*, bugprone-*, and clang-analyzer-* checks

#### Motivation for adding to Mudlet

Static analysis helps developers catch issues early without requiring
manual code review:
- **Bug detection**: Identifies null pointer dereferences, memory leaks,
and logic errors
- **Performance**: Finds unnecessary copies and inefficient patterns
- **Code quality**: Enforces best practices and consistent patterns
- **Developer experience**: Optional feature - doesn't impact regular
builds

Mudlet already uses static analysis in CI, but this makes it available
locally for faster feedback during development.

#### Other info (issues closed, discussion etc)

- Static analysis is **disabled by default** - developers opt-in with
the cmake flag
- Build output can be captured and filtered to focus on Mudlet-specific
issues
- Uses existing `.clang-tidy` configuration already in the repository
- Wiki documentation will be added at
https://wiki.mudlet.org/w/Compiling_Mudlet#Static_Analysis
2025-12-28 23:12:20 +01:00
Vadim Peretokin
a66e9a56e2
Infrastructure: Update AI instructions with comments and git guidelines (#8531)
<!-- Keep the title short & concise so anyone non-technical can
understand it,
     the title appears in PTB changelogs -->
#### Brief overview of PR changes/additions
Added guidelines for comments and git practices based on my experience
in using coding agents.
#### Motivation for adding to Mudlet
Better fit for Mudlet's development.
#### Other info (issues closed, discussion etc)

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-11-18 08:09:13 +00:00
Kebap
f25d4aa099
Infra: Improve documentation to hide ui strings from translation (#8524)
#### Brief overview of PR changes/additions
- Document the a bit arcane "notr" option in .ui files

#### Motivation for adding to Mudlet
- Some UI text do not need translation after all

#### Other info (issues closed, discussion etc)
- Follow-up to #8506 as requested in there
2025-11-14 10:31:49 +01:00
Kebap
db88f8cde8
Infra: Improve documentation to hide ui strings from translation (#8506)
#### Brief overview of PR changes/additions
- Document the a bit arcane "notr" option in .ui files

#### Motivation for adding to Mudlet
- some UI text do not need translation after all

#### Other info (issues closed, discussion etc)
- Was searching for this option quite a while
2025-11-11 12:03:55 +00:00
Vadim Peretokin
f6e50b5d23
Infrastructure: improve instructions for AIs & humans (#8377)
<!-- Keep the title short & concise so anyone non-technical can
understand it,
     the title appears in PTB changelogs -->
#### Brief overview of PR changes/additions
Some light clarifications on Mudlet's infrastructure
#### Motivation for adding to Mudlet
Better use of coding agents
#### Other info (issues closed, discussion etc)
2025-10-21 09:14:54 +01:00
Vadim Peretokin
7f58d98b3c
Infrastructure: update info for LLM agents (#8245)
<!-- Keep the title short & concise so anyone non-technical can
understand it,
     the title appears in PTB changelogs -->
#### Brief overview of PR changes/additions
update info for LLM agents -

1. move `.ai` folder to the new `docs` folder that we have gained since
2. add mention of context for translators
3. improve compiling instructions on Linux

#### Motivation for adding to Mudlet
Improve agentic experience when developing Mudlet code
#### Other info (issues closed, discussion etc)

---------

Co-authored-by: Vadim Peretokin <vadi2@users.noreply.github.com>
2025-09-23 07:06:06 +02:00
Kebap
5c56d968b8
Infra: Remove dead link to source (#8233)
#### Brief overview of PR changes/additions

Remove a dead link

#### Motivation for adding to Mudlet

Less confusion

#### Other info (issues closed, discussion etc)

Link was http://blog.qt.io/blog/2014/06/13/qt-weekly-13-qstringliteral/

Searched through blog history of
[2014-06](https://www.qt.io/blog/archive/2014/06) and
[2014-05](https://www.qt.io/blog/archive/2014/05) alright
Found [QT Weekly Blog Post
11](https://www.qt.io/blog/2014/05/20/qt-weekly-11-getting-started-with-winrt-2)
and
[14](https://www.qt.io/blog/2014/06/20/qt-weekly-14-testing-accessibility-on-os-x)
easily
However 13 seems depublished
2025-09-17 14:11:53 +00:00
Vadim Peretokin
1461a543b5
Infrastructure: update contribution instructions for humans/LLMs (#8132)
<!-- Keep the title short & concise so anyone non-technical can
understand it,
     the title appears in PTB changelogs -->
#### Brief overview of PR changes/additions
Update contribution instructions for humans/LLMs with a few things I
found relevant: compilation time timeouts and Mudlet's C++ style.
#### Motivation for adding to Mudlet
Better time when coding with an LLM
#### Other info (issues closed, discussion etc)
2025-08-30 11:40:03 +02:00
Kebap
9a527a4e04
Infra: Move developer documentation to /docs (#8120)
#### Brief overview of PR changes/additions
- Create a /docs folder for prose info for developers
- Move a few files in there including /.github/README.md, it was taking
precedence over the /README in Github's rendering

#### Motivation for adding to Mudlet
Fix #8107

#### Other info (issues closed, discussion etc)
- Alternative to #8108 simply removing the info file
- Follow-up to #1348 which moved the file from / to /.github
-
https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions/creating-a-default-community-health-file
suggests a list of relevant files, and explains how .github folder will
take precedence over root, then /docs folders.
2025-08-27 10:22:23 +02:00