diff --git a/.github/forge-posts/v1.4.4.md b/.github/forge-posts/v1.4.4.md new file mode 100644 index 0000000..01bcfff --- /dev/null +++ b/.github/forge-posts/v1.4.4.md @@ -0,0 +1,35 @@ +--- +subtitle: Threading- und IPC-Sicherheits-Politur +versionsnatur: Wartung und Robustheit +--- + +**Hellion Chat 1.4.4 — Threading- und IPC-Sicherheits-Politur** + +Fünfter Sub-Patch der v1.4.x Polish-Sweep-Serie. Threading-Annahmen werden explizit pro Methode dokumentiert, ein +Hot-Path-Lock im Auto-Tell-Tab-Counter fällt weg, IPC-Cleanup wird sichtbar wenn er fehlschlägt und der Privacy-Filter +spricht jetzt bei unbekannten ChatTypes. + +- **AutoTellTabsService Hot-Path-Lock entfernt.** `ActiveTempTabCount` hat bisher pro Render-Frame ein LINQ-Count unter + einem Lock gemacht. Jetzt läuft das über einen Interlocked-Counter der parallel zur Tabs-Liste mitgeführt wird, + inklusive Resync-Hook für den Snapshot-Restore-Pfad in `SaveConfig`. Plus Pure-Helper-Test-Mirror in der Build-Suite + damit die Atomicity-Semantik nicht versehentlich wegrefactored wird +- **HonorificService selbst-dokumentierende Threading-Banner.** Statt eines Block-Comments am Klassen-Ende hat jede + IPC-Callback-Methode jetzt einen 1-Zeilen-Banner darüber, der den Thread-Kontext direkt am Call-Site benennt + (framework only, framework scheduled, any). Mehr Hilfe für künftige Reviews als ein abstraktes Threading-Kapitel +- **Unsubscribe-Failure ist jetzt sichtbar.** `TryUnsubscribe` hat ein Honorific-Unsubscribe-Failure bisher als Debug + geloggt, was bei Standard-Loglevel verschluckt wurde. Eine geleakte Subscription kann den Service über + Plugin-Reloads hinweg leben lassen, also läuft der Log jetzt auf Warning +- **AutoTranslate-Warmup blockiert den Plugin-Unload nicht mehr.** Der Cache-Warmup-Thread war ohne `IsBackground=true` + unterwegs, was den Unload um 100-300 ms verzögern konnte. Pattern-Match zu MessageManager und RetentionSweep + (beide seit v1.4.0) +- **Privacy-Filter loggt unbekannte ChatTypes.** Wenn FFXIV durch einen Patch einen neuen ChatType einführt der weder + in der Whitelist noch in den Defaults steht, wird er bisher silent durch den Failsafe geleitet. Jetzt loggt der + Filter einmalig pro Runtime eine Warning mit dem Type und dem Failsafe-Wert. Dedup über ein NonSerialized-HashSet, + also kein Log-Spam +- **Default-Flip für neue Installationen.** `PrivacyPersistUnknownChannels` startet bei neuen Configs jetzt auf `true`, + damit ein Patch-bedingt neuer ChatType nicht stillschweigend gedroppt wird bevor der User entscheiden kann. + Bestehende Configs behalten ihre Wahl, weil der Deserializer den Initializer überschreibt. Keine Migration, kein + Schema-Bump + +Keine User-sichtbaren Funktions-Änderungen außer dem Default-Flip für neue Installationen. Settings, Themes, Tabs und +das Privacy-Verhalten für Bestand bleiben unangetastet. diff --git a/HellionChat/HellionChat.csproj b/HellionChat/HellionChat.csproj index 67d73d1..570db82 100644 --- a/HellionChat/HellionChat.csproj +++ b/HellionChat/HellionChat.csproj @@ -1,7 +1,7 @@ - 1.4.3 + 1.4.4 enable enable diff --git a/HellionChat/HellionChat.yaml b/HellionChat/HellionChat.yaml index 13034d1..7fbb1f8 100755 --- a/HellionChat/HellionChat.yaml +++ b/HellionChat/HellionChat.yaml @@ -35,6 +35,26 @@ tags: - Replacement - Privacy changelog: |- + **v1.4.4 — Threading and IPC safety polish (2026-05-12)** + + Fifth sub-patch of the v1.4.x polish-sweep series. Threading + assumptions are documented per-method, a hot-path lock falls + away, and the privacy filter speaks up when an unknown ChatType + shows up. + + - AutoTellTabs hot-path getter uses an Interlocked counter + instead of taking the lock on every read + - Honorific integration: per-method threading banners, plus + Warning-level log on unsubscribe failure + - AutoTranslate warmup thread marked IsBackground so plugin + unload doesn't wait for it + - PrivacyFilter logs once per unknown ChatType so a future + patch's added channel doesn't drop off the radar + - New installs persist unknown channels by default; existing + configs keep their explicit choice + + --- + **v1.4.3 — Faster plugin load + new repo (2026-05-08)** Heavy startup work (migrations, hooks, windows) now runs async so diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 8b4c171..7f880f4 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -10,6 +10,38 @@ to the release pages for details. --- +## Hellion Chat 1.4.4 — Threading and IPC Safety Polish (2026-05-12) + +Fifth sub-patch of the v1.4.x polish-sweep series. Threading assumptions are documented per-method, a hot-path lock +falls away in `AutoTellTabsService`, IPC-cleanup failures become visible, and the privacy filter now speaks up when an +unknown ChatType shows up. + +- `AutoTellTabsService.ActiveTempTabCount` switches from a lock-protected LINQ `Count` to an `Interlocked` counter kept + in sync with `Config.Tabs` from inside the existing mutation paths. `Initialize()` seeds the counter from the + persisted Tabs list, and `SaveConfig`'s snapshot-restore path calls a new `ResyncTempTabCounter()` so the mid-step + `RemoveAll` doesn't leave the counter drifting. Pure-helper test mirror lives in the Build-Suite repo +- `HonorificService` per-method threading banners replace the block comment at the bottom of the file. Each IPC + callback (`TryInitialPull`, `OnTitleChanged`, `OnReady`, `OnDisposing`, `TryUnsubscribe`) and the `CurrentTitle` + field carry a one-line `// Thread:` annotation so the framework-thread invariant is visible at the call site +- `TryUnsubscribe` log-level upgraded from `Debug` to `Warning`. A silent unsubscribe failure leaks a live subscription + across plugin reloads, which is exactly the kind of issue that should not be at Debug +- `AutoTranslate.PreloadCache` thread now has `IsBackground = true` and a thread name. Without `IsBackground` the + warmup blocks plugin unload (typically 100-300 ms). Pattern-match to `MessageManager` (F6.1) and `Plugin.RetentionSweep` + (F9.3), both since v1.4.0 +- `Configuration.IsAllowedForStorage` adds a one-line `Plugin.Log.Warning` for the first occurrence of any ChatType + that isn't in `PrivacyPersistChannels`. Dedup via a `NonSerialized` `HashSet`, so the warning fires once + per runtime — not once per frame, not once per install. Failsafe routing through `PrivacyPersistUnknownChannels` + is unchanged +- `PrivacyPersistUnknownChannels` field default flipped from `false` to `true` for new installs via a constant in + `PrivacyDefaults`. Existing configs keep their explicit choice — the deserializer overrides the initializer. No + schema bump, no migration, no first-run banner + +Modding & support: join Hellion Forge — + +Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2). + +--- + ## Hellion Chat 1.4.3 — Plugin-Load Async-Init + Repo-Cutover (2026-05-08) Plugin lifecycle migrated to Dalamud's `IAsyncDalamudPlugin` API. The constructor now does only the bootstrap-essentials diff --git a/repo.json b/repo.json index d616320..bc26225 100644 --- a/repo.json +++ b/repo.json @@ -3,7 +3,7 @@ "Author": "Jon Kazama (Hellion Forge)", "Name": "Hellion Chat", "InternalName": "HellionChat", - "AssemblyVersion": "1.4.3.0", + "AssemblyVersion": "1.4.4.0", "Description": "A Hellion Forge plugin — privacy-focused chat replacement for FINAL FANTASY XIV, built for EU, US and JP data rules.\n\nBy default only your own conversations are stored. Public chat, NPC dialogue, system messages and battle logs are discarded at the storage layer unless you opt in. Retention windows are configurable per channel, history can be wiped retroactively, and everything can be exported on demand.\n\nFeatures:\n- Channel whitelist with a Privacy-First default\n- Per-channel retention with a daily background sweep\n- Retroactive cleanup with preview and Ctrl+Shift confirm\n- Export to Markdown, JSON or CSV\n- First-run wizard with three profiles: Privacy-First, Casual, Full History\n- Bilingual UI (EN/DE) with live language switching\n- Own config and database — no shared state with other plugins\n\nBased on Chat 2 by Infi and Anna (EUPL-1.2).\nSupport: https://discord.gg/X9V7Kcv5gR", "ApplicableVersion": "any", "RepoUrl": "https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat", @@ -14,12 +14,12 @@ "CanUnloadAsync": false, "LoadPriority": 0, "Punchline": "A Hellion Forge plugin. Privacy-first chat for FFXIV, built to stay out of your way.", - "Changelog": "**v1.4.3 — Faster plugin load + new repo (2026-05-08)**\n\nHeavy 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.\n\n- Two-phase async load via IAsyncDalamudPlugin\n- Schema-gate replaces the v9→v16 migration chain; old configs require a v1.4.2 install first\n- AutoTranslate cache loads on first use instead of every startup\n- Custom font (Hellion-Exo2) appears with a brief pop after load\n- Repo moved to gitea.hellion-forge.cloud — update your custom-repo URL\n\n---\n\n**v1.4.2 — Smoother frames in the chat log**\n\nPer-frame allocations in the chat-log render path eliminated. 2–5% frame-time recovery in typical scenes, more on pop-out-heavy setups.\n\n- Card-mode: theme/border invariants hoisted out of the per-message loop\n- Auto-tell tab tint and icon cached per tab\n- Status bar aggregation runs on ~1% of frames instead of every frame\n\n---\n\nFull history: https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases", + "Changelog": "**v1.4.4 — Threading and IPC safety polish (2026-05-12)**\n\nFifth sub-patch of the v1.4.x polish-sweep series. Threading assumptions are documented per-method, a hot-path lock falls away, and the privacy filter speaks up when an unknown ChatType shows up.\n\n- AutoTellTabs hot-path getter uses an Interlocked counter instead of taking the lock on every read\n- Honorific integration: per-method threading banners, plus Warning-level log on unsubscribe failure\n- AutoTranslate warmup thread marked IsBackground so plugin unload doesn't wait for it\n- PrivacyFilter logs once per unknown ChatType so a future patch's added channel doesn't drop off the radar\n- New installs persist unknown channels by default; existing configs keep their explicit choice\n\n---\n\n**v1.4.3 — Faster plugin load + new repo (2026-05-08)**\n\nHeavy 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.\n\n- Two-phase async load via IAsyncDalamudPlugin\n- Schema-gate replaces the v9→v16 migration chain; old configs require a v1.4.2 install first\n- AutoTranslate cache loads on first use instead of every startup\n- Custom font (Hellion-Exo2) appears with a brief pop after load\n- Repo moved to gitea.hellion-forge.cloud — update your custom-repo URL\n\n---\n\n**v1.4.2 — Smoother frames in the chat log**\n\nPer-frame allocations in the chat-log render path eliminated. 2–5% frame-time recovery in typical scenes, more on pop-out-heavy setups.\n\n- Card-mode: theme/border invariants hoisted out of the per-message loop\n- Auto-tell tab tint and icon cached per tab\n- Status bar aggregation runs on ~1% of frames instead of every frame\n\n---\n\nFull history: https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases", "AcceptsFeedback": true, - "DownloadLinkInstall": "https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/download/v1.4.3/latest.zip", - "DownloadLinkUpdate": "https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/download/v1.4.3/latest.zip", - "DownloadLinkTesting": "https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/download/v1.4.3/latest.zip", - "TestingAssemblyVersion": "1.4.3.0", + "DownloadLinkInstall": "https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/download/v1.4.4/latest.zip", + "DownloadLinkUpdate": "https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/download/v1.4.4/latest.zip", + "DownloadLinkTesting": "https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/download/v1.4.4/latest.zip", + "TestingAssemblyVersion": "1.4.4.0", "IconUrl": "https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/raw/branch/main/HellionChat/images/icon.png", "ImageUrls": [ "https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/raw/branch/main/HellionChat/images/chatWindow.png",