chore: comments say what the code does, not which task produced it

A comment that reads "MUST stay in lockstep with TryGetActiveCrossfade (K8)"
helps nobody outside the plan that used to have a K8 in it, and the plans are
not in this repo. Same for "Spec FR-4", "plan §B.2", "Sub-Task 4.4" and the
F/R/M/A/S round codes scattered through the style engine and the self-tests.

Personal names go too. "tester feedback from Jin (v1.4.7)" and "Flo decision
2026-06-15" carry the reason fine without naming anyone -- the version and the
reason are the parts a reader can act on, and a public repo should not need a
cast list to be read.

The rule applied throughout: keep the why, drop the reference. Version numbers
stay, since those resolve through the changelog. 77 files.

ChunkUtil also carried 281 lines of commented-out code -- an older ToChunks
variant and two helpers with no callers, inherited and never removed. Deleted;
git remembers them.
This commit is contained in:
2026-08-19 21:50:31 +02:00
parent 52237fda7e
commit 5b738e6885
48 changed files with 113 additions and 397 deletions
+2 -2
View File
@@ -18,7 +18,7 @@ internal sealed class CommandHelpWindow : Window
// Setter-injected post-ctor to break the InputBar -> CommandHelpWindow ->
// MainWindow -> InputBar singleton cycle (MS.DI does not detect cycles
// through FactoryCallSite registrations). Wired in
// CommandHelpWindowInitHostedService.StartAsync, same §6.2 pattern as
// CommandHelpWindowInitHostedService.StartAsync, same setter-injection pattern as
// MessageList.AttachPayloadHandler.
private Windows.MainWindow? _mainWindow;
@@ -41,7 +41,7 @@ internal sealed class CommandHelpWindow : Window
RespectCloseHotkey = false;
DisableWindowSounds = true;
// Logger injected for future diagnostic hooks (no call-sites yet in R2).
// Logger injected for future diagnostic hooks; no call sites yet.
_ = _logger;
}
+1 -1
View File
@@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace HellionChat.Ui.Components;
// B2 (PERF-B2): variable-height clip plan. ImGuiListClipper needs a constant
// row height, and since v1.10.0/A2 neither density has one (compact rows wrap
// row height, and since v1.10.0 neither density has one (compact rows wrap
// too), so both compute a plan from the cached per-row heights: a lead dummy
// for the rows above
// the viewport, the [first..last] index range that overlaps the viewport, and
+2 -2
View File
@@ -118,7 +118,7 @@ internal sealed class InputBar
// Note: when MainWindow is closed, DrawInputField never runs, so
// _isFocused keeps the last value written by the previous draw pass.
// The consumer that actually pushes this state across the IPC boundary
// (TypingIpc.BuildState, see F3 Step 2) gates on Plugin.MainWindow.IsOpen
// (TypingIpc.BuildState) gates on Plugin.MainWindow.IsOpen
// itself, so the stale backing-field never leaks to subscribers. Mirroring
// the gate here would require an extra Plugin-backref in InputBar that the
// rest of the component doesn't need.
@@ -1183,7 +1183,7 @@ internal sealed class InputBar
}
// DTO for an in-flight auto-translate completion. Lives as a companion type
// in this file because it is only consumed by InputBar (see v1.7.1 Fix #4 plan §2.4).
// in this file because it is only consumed by InputBar.
internal sealed class AutoCompleteInfo
{
// ToComplete MUST be a mutable field (not an auto-property), because the
+4 -4
View File
@@ -38,7 +38,7 @@ internal sealed class MessageList
private readonly Action<Message, string?> _drawCardRow;
// Reused across frames: at MessageManager.MessageDisplayLimit a fresh array
// per frame is 40 KB of garbage, and A2 put the default density on this
// per frame is 40 KB of garbage, and A later cycle put the default density on this
// path. The old comment named MaxLinesToRender and its 2500 default, a
// config field that had stopped bounding anything.
private float[] _heightScratch = [];
@@ -49,7 +49,7 @@ internal sealed class MessageList
private bool _stampVisible;
private float _metaDrop;
// §6.2: setter-injection breaks the PayloadHandler → MainWindow → MessageList → PayloadHandler 3-cycle.
// Setter-injection breaks the PayloadHandler → MainWindow → MessageList → PayloadHandler 3-cycle.
// Wired by PayloadHandlerInitHostedService.StartAsync after both singletons exist.
internal void AttachPayloadHandler(PayloadHandler handler)
{
@@ -88,7 +88,7 @@ internal sealed class MessageList
// SelfTest hook (B2): drives the live invalidation, returns the tab's remaining
// cached-height count so the step can assert the drop. nowMs is a parameter so
// the step can step past the settle window without sleeping (v1.10.0/A1).
// the step can step past the settle window without sleeping (v1.10.0).
internal int RunHeightCacheInvalidationForSelfTest(Tab tab, float contentWidth, long nowMs)
{
InvalidateHeightCacheIfLayoutChanged(tab, contentWidth, nowMs);
@@ -569,7 +569,7 @@ internal sealed class MessageList
// B2-1/B2-2: sender via DrawChunks (name-aware path), on its own line
// with content below — 1.5.6 card parity (ChatLogWindow.cs:1913, no
// SameLine after the sender). The 1.5.6 channel-colour push on the
// sender is deferred styling polish (masterplan §6 -> v1.9.0); plain
// sender is deferred styling polish (deferred to v1.9.0); plain
// text here.
// A system message has no sender, so a header row would be a stamp on a
// line of its own -- an empty gesture. Those stay single-line in both
@@ -20,7 +20,7 @@ internal sealed class LivePreviewPanel : IDisposable
private static uint Abgr(StyleEngine.Token token, ThemeColors colors) =>
ColourUtil.RgbaToAbgr(Tokens.Resolve(token, colors));
// Static counter for S5 reload-stress verification: after 10 reloads the
// Static counter for reload-stress verification: after 10 reloads the
// counter must read 0 (plugin disabled) or 1 (plugin enabled). Anything
// higher signals a Dispose skip and a subscriber leak against ThemeRegistry.
internal static int InstanceCount;
@@ -254,7 +254,7 @@ internal sealed class DataPrivacyTab
)
{
// Read-only statement, not a switch. Do not promote it to one
// without an explicit Sub-Spec change: a toggle implies there is
// without an explicit design change: a toggle implies there is
// something to turn off.
ImGuiUtil.HelpText(HellionStrings.Settings_Telemetry_None);
}
@@ -173,8 +173,7 @@ internal sealed class ThemeImportExportRow
// Slug sanitisation BEFORE BeginEditing — SaveEditingBuffer would
// reject too, but rejecting here means an unsafe slug never enters
// the editing buffer. Shared helper ThemeRegistry.IsSafeThemeSlug
// keeps the rule set in sync with F1's save-side guard (see
// ThemeRegistry.IsSafeThemeSlug shared helper).
// keeps the rule set in sync with the save-side guard.
var importSlug = theme.Slug;
if (!ThemeRegistry.IsSafeThemeSlug(importSlug))
{
@@ -186,9 +185,9 @@ internal sealed class ThemeImportExportRow
return;
}
// Pragmatic deviation from §1.6 wording ("File.Copy into themes/"):
// BeginEditing+SaveEditingBuffer produces the same end-state and
// reuses the validated F1 save pipeline. Trade-off: destination
// Not a plain File.Copy into themes/: BeginEditing+SaveEditingBuffer
// produces the same end state and reuses the validated save
// pipeline. Trade-off: destination
// filename becomes the theme's slug, not the original filename.
//
// Slug-collision handling:
+1 -1
View File
@@ -54,7 +54,7 @@ internal sealed class InputPreview : Window
DisableWindowSounds = true;
IsOpen = true;
// TODO Polish-Sweep: remove discard once logging call-sites exist
// TODO: remove discard once logging call sites exist
_ = _logger;
}
@@ -12,7 +12,7 @@ namespace HellionChat.Ui.StyleEngine;
// ABGR before delegating to ImDrawList.
internal static class DrawListExtensions
{
// A1 accent-tint (Variante A): how far the white sweep is pulled toward
// Accent tint: how far the white sweep is pulled toward
// the element's accent hue. Kept low so the sheen reads as a tinted
// highlight, not a saturated accent flash (effect level "subtle").
private const float SheenTintStrength = 0.35f;
+2 -2
View File
@@ -9,7 +9,7 @@ namespace HellionChat.Ui.StyleEngine;
// compare an unscaled value (Sidebar.GetWidth, the width slider bounds).
//
// Deliberately NOT part of ThemeLayout: that record is serialised into theme
// JSON, and layout customisation is out of scope per the master spec.
// JSON, and layout customisation is deliberately out of scope.
internal static class Metrics
{
// --- Sidebar ---
@@ -65,7 +65,7 @@ internal static class Metrics
return _cachedScale;
// Safe variant: GlobalScale throws while the interface manager is
// still coming up, and Block F pulls Metrics into more call sites.
// still coming up, and Metrics reaches more call sites than it did.
_cachedScale = ImGuiHelpers.GlobalScaleSafe;
_cachedFrame = frame;
return _cachedScale;
+1 -1
View File
@@ -23,7 +23,7 @@ internal enum TypeRole
// exactly Body and never be pushed -- a value with no call site, which is the one
// thing this whole style track exists to stop.
//
// The factors are defaults, not constants. The master spec puts typography under
// The factors are defaults, not constants. Typography is meant to sit under
// theme control rather than user control, and ThemeTypography already exists as
// the extension point for exactly that. A const would wall it off. What is
// deliberately absent either way is a user-facing slider per role.
@@ -18,8 +18,8 @@ namespace HellionChat.Ui.StyleEngine.Widgets;
//
// So: no plate, but a tint. A tenth-opacity accent wash falling from the top
// edge -- colour as atmosphere rather than as a box, which is what the plate got
// wrong. Flo picked it from the lab over the rule-only variant; at this strength
// it survives the violet themes that killed the filled bar.
// wrong. Picked from the lab over the rule-only variant; at this strength it
// survives the violet themes that killed the filled bar.
//
// Which face draws what is not a style choice here, it is a constraint. The meta
// face has a glyph range of ASCII plus a middle dot, so only the world name and
+2 -2
View File
@@ -7,7 +7,7 @@ namespace HellionChat.Ui.Windows;
// windows via the injected factory, all registered once in the WindowSystem
// (PluginLifecycle.RegisterWindows, framework thread). Open/Close is IsOpen +
// Bind/Unbind only — NEVER runtime AddWindow/RemoveWindow (v1.4.9 Stage-2
// freeze lesson). Pure DI-sink: no PayloadHandler in the ctor (plan §B.2).
// freeze lesson). Pure DI-sink: no PayloadHandler in the ctor.
internal sealed class ChannelPopoutPool
{
private readonly List<ChannelPopoutWindow> _instances;
@@ -30,7 +30,7 @@ internal sealed class ChannelPopoutPool
// Route each window's in-body close through the pool so closing releases
// the slot. Wired here (post-construction) rather than via ctor to avoid
// a Window->Pool edge that would re-enter pool resolution (plan §B.2).
// a Window->Pool edge that would re-enter pool resolution.
foreach (var window in _instances)
window.CloseRequested = TryClose;
}
@@ -13,7 +13,7 @@ namespace HellionChat.Ui.Windows;
// One pre-allocated pop-out window bound to a single Tab. Pure DI-sink: the
// PayloadHandler arrives via AttachPayloadHandler (post-build setter), NEVER
// via ctor — see plan §B.2. The ###id carries the slot index so all N
// via ctor. The ###id carries the slot index so all N
// instances are unique for WindowSystem.AddWindow and ImGui state is stable
// per slot (not per bound tab).
internal sealed class ChannelPopoutWindow : Window, IFocusableChatWindow
@@ -66,10 +66,10 @@ internal sealed class ChannelPopoutWindow : Window, IFocusableChatWindow
// Wired post-build by ChannelPopoutPool so closing routes through the pool
// (which owns the slot map). The window can't reach the pool by ctor without
// a DI cycle, so the pool sets this after construction. See plan §B.2.
// a DI cycle, so the pool sets this after construction.
public Action<Guid>? CloseRequested { get; set; }
// Post-build setter — see plan §B.2. Wired by ChannelPopoutInitHostedService.
// Post-build setter. Wired by ChannelPopoutInitHostedService.
public void AttachPayloadHandler(PayloadHandler handler) =>
_messages.AttachPayloadHandler(handler);
@@ -78,7 +78,7 @@ internal sealed class ChannelPopoutWindow : Window, IFocusableChatWindow
Bound = tab;
var isTell = tab is { IsTempTab: true, TellTarget: { } target } && target.IsSet();
// Master §4.3 default sizes: Tell is the more compact conversation window.
// Default sizes: Tell is the more compact conversation window.
Size = isTell ? new Vector2(380f, 320f) : new Vector2(420f, 320f);
SizeCondition = ImGuiCond.FirstUseEver;
+2 -2
View File
@@ -13,8 +13,8 @@ namespace HellionChat.Ui.Windows;
// Variants of UI elements, drawn side by side so decisions are made by looking
// rather than by imagining. Reachable with /hellion lab.
//
// Permanent, by Flo's call: a dev playground for seeing ideas in-game against
// the live theme. The radios default to whatever shipped, so the window also
// Permanent: a playground for seeing ideas in-game against the live theme.
// The radios default to whatever shipped, so the window also
// documents which variant won and what it beat.
//
// It exists because the alternative was drawing mockups, and mockups are what