chore: bump version to 1.4.7, sync changelog and forge post

- csproj <Version> -> 1.4.7
- repo.json AssemblyVersion + TestingAssemblyVersion -> 1.4.7.0
- repo.json DownloadLink{Install,Update,Testing} URLs -> /v1.4.7/
- repo.json + HellionChat.yaml changelog: prepend v1.4.7 block, retire
  v1.4.3 (slim rule keeps the last 3-4 versions)
- docs/CHANGELOG.md + docs/ROADMAP.md: v1.4.7 section, next-cycle
  pointer flipped to v1.4.8 Hook-Layer-Cycle
- README.md release badge + version stamps + Project Status block
  rewritten for v1.4.7
- .github/forge-posts/v1.4.7.md (new): DE body with subtitle
  "Backlog Cleanup and Mid-Features" / versionsnatur "Mid-Feature-Patch"
- Pin diagnostic logs (RehydratePinnedTabs / TryPin / Unpin /
  PromoteToPermanent) downgraded from Info to Debug so non-debug
  console stays quiet on release builds
This commit is contained in:
2026-05-13 11:00:25 +02:00
parent d5735d8dcc
commit f4ea460644
8 changed files with 167 additions and 48 deletions
+29
View File
@@ -0,0 +1,29 @@
---
subtitle: Backlog Cleanup and Mid-Features
versionsnatur: Mid-Feature-Patch
---
Achter Sub-Patch der v1.4.x Polish-Sweep-Serie. Erstes User-sichtbares Feature-Bundle seit v1.4.5 — angepinnte Tell-Tabs
die Relog überleben, opt-in Honorific-Glow, plus eine konfigurierbare Sidebar.
- **TempTell anpinnen**: Rechtsklick auf einen TempTell-Tab in der Sidebar → „Tab anpinnen". Angepinnte Tabs überleben
Plugin-Reload und Char-Logout, behalten ihre Konversations-Historie (wird beim Rehydrate aus dem MessageStore
nachgeladen) und bleiben an die gleiche /tell-Person gebunden. Hard-Cap 5 angepinnte Tabs in einem separaten Pool —
die normalen Auto-Tell-Tabs (15er Cap) sind davon entkoppelt, Gesamt-Decke 20. Die Sidebar gruppiert angepinnte Tabs
in einer eigenen „Angepinnt"-Sektion mit eigenem Trenner.
- **Honorific Glow-Outline**: rendert jetzt eine 8-Richtungs-DrawList-Outline wenn der Honorific-Titel eine Glow-Farbe
trägt. Opt-in via **Settings → Integrationen → Glow-Outline rendern (Honorific)** (Default OFF). Gradient (Color3 /
GradientColourSet / Wave / Pulse) wird geparst und im DTO weitergereicht, rendert aktuell aber statisch als
Primärfarbe — der volle Gradient-Port (Animations-Algorithmus + Pride-Palette) kommt als eigener Cycle nach.
- **Sidebar-Breite konfigurierbar**: in **Theme & Layout** ein Slider 44160 px. Default bleibt 44 px (icon-only), aber
breiter machen damit Sektion-Header wie „Aktive Tells (3)" oder „Angepinnt (2)" nicht abgeschnitten werden.
- **Settings-Save Channel-Fix**: ein Save mit aktivem Party- oder Linkshell-Tab konnte den Chat-Input zurück auf
`/tell <angepinnte Person>` springen lassen. `Configuration.UpdateFrom` bewahrt jetzt den Runtime-`CurrentChannel`
über den persistent-Tab-Merge hinweg, und `TabSwitched` deep-cloned den Seed-Channel statt sich den `UsedChannel` mit
dem vorigen Tab zu teilen.
- **Internal**: `IPluginLogProxy`-Indirektion vor Dalamud's `IPluginLog` über alle ~91 `Plugin.Log`-Call-Sites. Damit
läuft `MessageStore.Migrate0` voll-isoliert in xUnit (F12.1-Lücke aus v1.4.6 geschlossen). Plus: TempTab-Counter als
abgeleitete Property statt gecachtes Interlocked-Feld — die neuen Pin/Unpin-Übergänge sind Cold-Path, kein
Lock-Free-Vorteil mehr. Migration v16 → v17 ist rein additiv (neues `Tab.IsPinned`-Bool, Default false).
Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
+6 -6
View File
@@ -67,7 +67,7 @@ internal sealed class AutoTellTabsService : IDisposable
private void RehydratePinnedTabs() private void RehydratePinnedTabs()
{ {
var pinned = Plugin.Config.Tabs.Count(TabLifecycleHelpers.IsInPinnedPool); var pinned = Plugin.Config.Tabs.Count(TabLifecycleHelpers.IsInPinnedPool);
Plugin.LogProxy.Info($"[Pin] Rehydrate scan: {pinned} pinned tab(s) found"); Plugin.LogProxy.Debug($"[Pin] Rehydrate scan: {pinned} pinned tab(s) found");
foreach (var tab in Plugin.Config.Tabs) foreach (var tab in Plugin.Config.Tabs)
{ {
@@ -93,7 +93,7 @@ internal sealed class AutoTellTabsService : IDisposable
// sees the recent conversation, not a blank tab. // sees the recent conversation, not a blank tab.
PreloadHistory(tab, tab.TellTarget.Name, tab.TellTarget.World, Guid.Empty); PreloadHistory(tab, tab.TellTarget.Name, tab.TellTarget.World, Guid.Empty);
Plugin.LogProxy.Info( Plugin.LogProxy.Debug(
$"[Pin] Rehydrated '{tab.Name}' -> Tell target {tab.TellTarget.Name}@{tab.TellTarget.World}" $"[Pin] Rehydrated '{tab.Name}' -> Tell target {tab.TellTarget.Name}@{tab.TellTarget.World}"
); );
} }
@@ -456,7 +456,7 @@ internal sealed class AutoTellTabsService : IDisposable
{ {
if (!tab.IsTempTab || tab.IsPinned) if (!tab.IsTempTab || tab.IsPinned)
{ {
Plugin.LogProxy.Info( Plugin.LogProxy.Debug(
$"[Pin] TryPin skipped: IsTempTab={tab.IsTempTab} IsPinned={tab.IsPinned}" $"[Pin] TryPin skipped: IsTempTab={tab.IsTempTab} IsPinned={tab.IsPinned}"
); );
return false; return false;
@@ -472,7 +472,7 @@ internal sealed class AutoTellTabsService : IDisposable
} }
tab.IsPinned = true; tab.IsPinned = true;
Plugin.LogProxy.Info( Plugin.LogProxy.Debug(
$"[Pin] Pinned tab '{tab.Name}' target={tab.TellTarget?.Name}@{tab.TellTarget?.World}" $"[Pin] Pinned tab '{tab.Name}' target={tab.TellTarget?.Name}@{tab.TellTarget?.World}"
); );
_plugin.SaveConfig(); _plugin.SaveConfig();
@@ -495,7 +495,7 @@ internal sealed class AutoTellTabsService : IDisposable
} }
tab.IsPinned = false; tab.IsPinned = false;
Plugin.LogProxy.Info($"[Pin] Unpinned tab '{tab.Name}'"); Plugin.LogProxy.Debug("[Pin] Unpinned tab '{tab.Name}'");
_plugin.SaveConfig(); _plugin.SaveConfig();
} }
@@ -509,7 +509,7 @@ internal sealed class AutoTellTabsService : IDisposable
tab.IsTempTab = false; tab.IsTempTab = false;
tab.IsPinned = false; tab.IsPinned = false;
tab.TellTarget = TellTarget.Empty(); tab.TellTarget = TellTarget.Empty();
Plugin.LogProxy.Info( Plugin.LogProxy.Debug(
$"[Pin] Promoted tab '{tab.Name}' to permanent (tell-binding dropped)" $"[Pin] Promoted tab '{tab.Name}' to permanent (tell-binding dropped)"
); );
_plugin.SaveConfig(); _plugin.SaveConfig();
+1 -1
View File
@@ -1,7 +1,7 @@
<Project Sdk="Dalamud.NET.Sdk/15.0.0"> <Project Sdk="Dalamud.NET.Sdk/15.0.0">
<PropertyGroup> <PropertyGroup>
<!-- Independent versioning; see yaml changelog for upstream Chat 2 base --> <!-- Independent versioning; see yaml changelog for upstream Chat 2 base -->
<Version>1.4.6</Version> <Version>1.4.7</Version>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<!-- Use lock file to pin exact versions --> <!-- Use lock file to pin exact versions -->
+43 -15
View File
@@ -35,6 +35,49 @@ tags:
- Replacement - Replacement
- Privacy - Privacy
changelog: |- changelog: |-
**v1.4.7 — Backlog Cleanup and Mid-Features (2026-05-13)**
Eighth sub-patch of the v1.4.x polish-sweep series. First
user-visible feature bundle since v1.4.5 — pinned tell tabs that
survive relog, opt-in Honorific glow rendering, and a configurable
sidebar.
- TempTell Pin: right-click a TempTell tab in the sidebar to pin
it. Pinned tabs survive relog, keep their conversation history
(loaded on demand from the message store), and stay bound to
the same /tell partner. Hard cap of 5 pinned tabs in a pool
separate from the 15-tab auto-tell pool — total ceiling is 20
tabs. New 'Pinned' section in the sidebar with its own divider
header
- Honorific Glow outline now renders when the title carries a
Glow colour. Opt-in via Settings → Integrations → 'Render glow
outlines (Honorific)' (default off, dodges the per-frame
DrawList overhead on low-end hardware). Gradient (Color3 /
GradientColourSet / Wave / Pulse) is parsed but rendered
statically — a later cycle will port the full animation
- Sidebar width is now configurable in Theme & Layout (range
44160 px). Default stays icon-only; widen to fit section
headers like 'Active Tells (3)' without truncation
- Settings Save no longer pops the chat input back to /tell with
a pinned partner — Configuration.UpdateFrom now preserves the
runtime CurrentChannel across the persistent-tab merge, and
TabSwitched deep-clones the seeded channel instead of sharing
the previous tab's UsedChannel
- Util/ImGuiUtil.cs DrawArrows IconButton id now uses
(id + 1).ToString() instead of the operator-precedence quirk
id + 1.ToString() — generated IDs stay numerically stable
- Internal: IPluginLogProxy indirection over Dalamud's IPluginLog
routes all ~91 Plugin.Log call sites through a testable proxy.
MessageStore.Migrate0 can now run in xUnit without loading
Dalamud.dll, closing the gap F12.1 left in v1.4.6
- Internal: TempTab counter switched from an Interlocked cached
field to a derived Tabs.Count(predicate) — pin-state transitions
are cold-path and don't need lock-free reads
Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
---
**v1.4.6 — Code Hygiene and Refactor (2026-05-12)** **v1.4.6 — Code Hygiene and Refactor (2026-05-12)**
Maintenance patch. No user-visible behaviour changes; tightens the Maintenance patch. No user-visible behaviour changes; tightens the
@@ -117,19 +160,4 @@ changelog: |-
--- ---
**v1.4.3 — Faster plugin load + new repo (2026-05-08)**
Heavy startup work (migrations, hooks, windows) now runs async so
Dalamud's UI stays responsive during load. Load time is comparable
to v1.4.2 — this is the foundation for v1.4.4 optimisations.
- Two-phase async load via IAsyncDalamudPlugin
- Schema-gate replaces the v9→v16 migration chain; old configs
require a v1.4.2 install first
- AutoTranslate cache loads on first use instead of every startup
- Custom font (Hellion-Exo2) appears with a brief pop after load
- Repo moved to gitea.hellion-forge.cloud — update your custom-repo URL
---
Full history: https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases Full history: https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases
+19 -16
View File
@@ -2,7 +2,7 @@
[![Build](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/actions/workflows/build.yml/badge.svg?branch=main)](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/actions/workflows/build.yml) [![Build](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/actions/workflows/build.yml/badge.svg?branch=main)](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/actions/workflows/build.yml)
[![License: EUPL-1.2](https://img.shields.io/badge/License-EUPL--1.2-blue.svg)](LICENSE) [![License: EUPL-1.2](https://img.shields.io/badge/License-EUPL--1.2-blue.svg)](LICENSE)
[![Latest release](https://img.shields.io/badge/release-v1.4.6-brightgreen)](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/latest) [![Latest release](https://img.shields.io/badge/release-v1.4.7-brightgreen)](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/latest)
[![Dalamud API](https://img.shields.io/badge/Dalamud-API_15-purple)](https://github.com/goatcorp/Dalamud) [![Dalamud API](https://img.shields.io/badge/Dalamud-API_15-purple)](https://github.com/goatcorp/Dalamud)
[![.NET](https://img.shields.io/badge/.NET-10.0-512BD4)](https://dotnet.microsoft.com/) [![.NET](https://img.shields.io/badge/.NET-10.0-512BD4)](https://dotnet.microsoft.com/)
[![FFXIV](https://img.shields.io/badge/FFXIV-Dawntrail-c3a37f)](https://www.finalfantasyxiv.com/) [![FFXIV](https://img.shields.io/badge/FFXIV-Dawntrail-c3a37f)](https://www.finalfantasyxiv.com/)
@@ -11,7 +11,7 @@
<img src="docs/images/hellion-forge.png" alt="Hellion Forge" width="180" /> <img src="docs/images/hellion-forge.png" alt="Hellion Forge" width="180" />
</p> </p>
**Version 1.4.6** — Privacy-first chat plugin for FINAL FANTASY XIV / Dalamud, built on **Version 1.4.7** — Privacy-first chat plugin for FINAL FANTASY XIV / Dalamud, built on
[Chat 2](https://github.com/Infiziert90/ChatTwo) (EUPL-1.2). [Chat 2](https://github.com/Infiziert90/ChatTwo) (EUPL-1.2).
Hellion Chat is a privacy-first plugin built on the Chat 2 foundation. The majority of the engine comes from Chat 2 Hellion Chat is a privacy-first plugin built on the Chat 2 foundation. The majority of the engine comes from Chat 2
@@ -286,20 +286,23 @@ An optional submission to the Dalamud main plugin repo (in addition to the custo
## Project Status ## Project Status
**Version 1.4.6**Maintenance patch. No user-visible behaviour changes; tightens the development feedback loop and **Version 1.4.7**Backlog cleanup and the first user-visible feature bundle since v1.4.5. TempTell tabs can now be
pulls in two ChatTwo upstream bugfixes. `scripts/preflight.sh` gains a csharpier reflow check and a markdownlint pass at pinned via right-click; pinned tabs survive relog, keep their conversation history (loaded on demand from the message
the pre-push gate. `FontManager`'s font-fallback catch-filter now covers `InvalidOperationException` and store), and stay bound to the same `/tell` partner. A hard cap of 5 pinned tabs lives in a pool separate from the 15-tab
`ArgumentException` on top of the IO triad, so a corrupted font config no longer takes down the atlas build. auto-tell pool, so the total ceiling is 20 tabs. The sidebar groups pinned tabs into their own section with its own
`BrandingLinks` and `IntegrationLinks` URLs validate themselves on plugin load — a typo in a future URL rotation throws divider header. Honorific glow outlines now render when the title carries a Glow colour — opt-in via **Settings →
at startup instead of failing silently when a user clicks the broken button. Cherry-picked from ChatTwo upstream Integrations → Render glow outlines (Honorific)**, default off, so v1.4.6 visuals stay untouched for users who don't
`f35b7d3`: `Chat.SetChannel` no longer leaks the native `Utf8String` when the linkshell check rejects the channel, and care and the per-frame DrawList overhead is skipped on low-end hardware. Honorific gradient (Color3 / GradientColourSet
`Tab.Clone` now deep-clones `UsedChannel` and `TellTarget` (the previous reference copy let PopOut and Temp tabs mutate / Wave / Pulse) is parsed and stashed for a later cycle, but currently renders as the primary colour. Sidebar width is
each other's channel state). The active-tab underline pill scales with DPI and rounds to physical pixels for crisp configurable in **Theme & Layout** between 44 and 160 px; default stays icon-only so existing users see no layout
rendering above 100 % DPI. Internal items: `HellionStyle` ChildBgAlpha extracted to a testable helper, change. `Configuration.UpdateFrom` now preserves the runtime `CurrentChannel` across the persistent-tab merge, and
`Plugin.SaveConfig` clones only the temp-tab subset, `SettingsOverview` caches the draw-list per frame, `TabSwitched` deep-clones the seeded channel — together they fix a Settings-Save regression where the chat input could
`Dalamud.Utility.Util` static surface routed through an `IPlatformUtil` indirection (`MessageStore`'s `IsWine` probe is pop back to `/tell <pinned-partner>` after touching settings while on a Party or Linkshell tab. Internal items:
now testable in isolation). No schema bump, no migration. Seventh sub-patch of the v1.4.x polish sweep series (as of `IPluginLogProxy` indirection over Dalamud's `IPluginLog` routes all ~91 `Plugin.Log` call sites through a testable
2026-05-12). proxy, closing the test-isolation gap F12.1 left in v1.4.6 (`MessageStore.Migrate0` now runs in xUnit without loading
`Dalamud.dll`). `Util/ImGuiUtil.cs`'s `DrawArrows` IconButton id gets explicit parentheses on the increment. Migration
v16 → v17 is additive (new `Tab.IsPinned` flag, default false). Eighth sub-patch of the v1.4.x polish sweep series (as
of 2026-05-13).
Hellion Chat is a standalone plugin, no longer a fork in the repository sense. Fully completed: Hellion Chat is a standalone plugin, no longer a fork in the repository sense. Fully completed:
+39
View File
@@ -10,6 +10,45 @@ to the release pages for details.
--- ---
## Hellion Chat 1.4.7 — Backlog Cleanup and Mid-Features (2026-05-13)
Eighth sub-patch of the v1.4.x polish-sweep series. First user-visible feature bundle since v1.4.5 — pinned tell tabs
that survive relog, opt-in Honorific glow rendering, a configurable sidebar, plus a Settings-Save channel-preservation
fix surfaced during smoke testing.
- TempTell Pin: right-click a TempTell tab in the sidebar and choose "Pin Tab" / "Tab anpinnen". Pinned tabs survive
plugin reload and character logout, keep their conversation history (loaded on demand from the message store on
rehydrate), and stay bound to the same `/tell` partner. Hard cap of 5 pinned tabs in a pool separate from the 15-tab
auto-tell pool — total ceiling is 20 tabs. The sidebar groups pinned tabs into their own section with a divider header
- Honorific glow outlines now render via an 8-direction DrawList pre-pass when the title carries a Glow colour. Opt-in
via **Settings → Integrations → Render glow outlines (Honorific)** (default off). Honorific's gradient surface
(`Color3`, `GradientColourSet`, `GradientAnimationStyle`) is parsed and stashed for a later cycle but renders as the
primary colour until then — the v1.4.7 DTO already mirrors all four extra fields so the JSON roundtrip doesn't
silent-drop them
- Sidebar width configurable in **Theme & Layout** (44160 px, default 44 stays icon-only). The icon button stretches
with the configured width so a widened sidebar looks intentional, not a 36 px icon floating in empty space
- `Configuration.UpdateFrom` now preserves the runtime `CurrentChannel` across the persistent-tab merge alongside
`Messages` and `LastSendUnread`. `TabSwitched` deep-clones the seeded channel from the previous tab instead of sharing
the same `UsedChannel` instance. Together these fix a regression where Settings-Save on a Party or Linkshell tab
popped the chat input back to `/tell <pinned-partner>` on the next interaction
- `Util/ImGuiUtil.cs` `DrawArrows` IconButton id uses `(id + 1).ToString()` with explicit parentheses instead of the
operator-precedence quirk `id + 1.ToString()` (which resolved to `id.ToString() + "1"`). Single live caller is
`Ui/DbViewer.cs:227` page-navigation
- Internal: `IPluginLogProxy` indirection over Dalamud's `IPluginLog` routes all ~91 `Plugin.Log` call sites through a
testable proxy. `MessageStore.Migrate0` can now run in xUnit without loading `Dalamud.dll`, closing the gap F12.1 left
in v1.4.6. Production wrapper `DalamudPluginLogProxy` and Build-Suite `FakePluginLogProxy` mirror the full
`IPluginLog` surface (`Verbose`/`Debug`/`Information`/`Info`/`Warning`/`Error`/`Fatal`) with single-string,
`Exception+string`, and `params object[]` overloads
- Internal: TempTab counter switched from an `Interlocked` cached field to a derived `Tabs.Count(predicate)`. Pin-state
transitions (TryPin / Unpin / Promote) are cold-path and don't need lock-free reads; counter mutation surface dropped
from 5 to 0 sites. Build-Suite floor 688 → 710 (+22)
- Schema bump v16 → v17 is additive: new `Tab.IsPinned` bool, default false. Existing v16 configs load cleanly and get
their `Version` stamp bumped after the gate check
Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
---
## Hellion Chat 1.4.6 — Code Hygiene and Refactor (2026-05-12) ## Hellion Chat 1.4.6 — Code Hygiene and Refactor (2026-05-12)
Maintenance patch. No user-visible behaviour changes; tightens the development feedback loop, fixes two Maintenance patch. No user-visible behaviour changes; tightens the development feedback loop, fixes two
+24 -4
View File
@@ -10,14 +10,34 @@ the plugin's privacy-first scope during brainstorming.
--- ---
## Next Cycle (v1.4.7) ## Next Cycle (v1.4.8)
**Backlog Cleanup.** Roll up the remaining audit items deferred from v1.4.0v1.4.6 and the new entries surfaced during **Hook-Layer Cycle.** Receive-suppressed-tells toggle (cross-reference XIVIM #73 bubble-layer sub-task), Database Viewer
v1.4.6 (notably the `Plugin.Log` indirection that would unlock fully isolated `MessageStore` construction tests, plus full-text search via SQLite FTS5, plus preparation for the later Ad-Block cycle. Hook-layer investigation is shared
follow-up scope hinted at in the ChatTwo upstream f35b7d3 cherry-picks). Scope is consolidated during brainstorm. across these items so they cluster naturally in one sub-patch.
--- ---
## v1.4.7 — Backlog Cleanup and Mid-Features (released 2026-05-13)
Eighth sub-patch of the v1.4.x Polish Sweep series. First user-visible feature bundle since v1.4.5. TempTell tabs can
now be pinned via right-click; pinned tabs survive plugin reload and character logout, keep their conversation history
(loaded on demand from the message store on rehydrate), and stay bound to the same `/tell` partner. A hard cap of 5
pinned tabs lives in a pool separate from the 15-tab auto-tell pool, total ceiling 20. The sidebar groups pinned tabs
into their own section with a divider header, and the sidebar width itself is now configurable in **Theme & Layout**
between 44 and 160 px. Honorific glow outlines render when the title carries a Glow colour, opt-in via **Settings →
Integrations → Render glow outlines (Honorific)** (default off). Honorific's gradient (Color3 / GradientColourSet / Wave
/ Pulse) is parsed but rendered statically — a later cycle will port the full animation algorithm or land an upstream
IPC PR for the resolved frame colour. `Configuration.UpdateFrom` now preserves the runtime `CurrentChannel` across the
persistent-tab merge, and `TabSwitched` deep-clones the seeded channel instead of sharing the previous tab's
`UsedChannel` — together they fix a Settings-Save regression where the chat input could pop back to
`/tell <pinned-partner>` after touching settings on a Party or Linkshell tab. Internal items: `IPluginLogProxy`
indirection over Dalamud's `IPluginLog` routes all ~91 `Plugin.Log` call sites through a testable proxy, closing the
F12.1 test-isolation gap (`MessageStore.Migrate0` runs in xUnit now). TempTab counter switched from `Interlocked` cached
field to derived `Tabs.Count(predicate)`. Migration v16 → v17 is additive (new `Tab.IsPinned` flag). Build-Suite floor
688 → 710 (+22 tests across Pin-lifecycle predicates, pool limits, Tab.Clone roundtrip, MessageStore Migrate0
construction, and Honorific TitleData JSON roundtrip).
## v1.4.6 — Code Hygiene and Refactor (released 2026-05-12) ## v1.4.6 — Code Hygiene and Refactor (released 2026-05-12)
Seventh sub-patch of the v1.4.x Polish Sweep series. Maintenance patch — no user-visible behaviour changes; tightens the Seventh sub-patch of the v1.4.x Polish Sweep series. Maintenance patch — no user-visible behaviour changes; tightens the
+6 -6
View File
File diff suppressed because one or more lines are too long