promotional bannermobile promotional banner

Ka0s Loot History (Retail)

Records every item you loot, attributes where it came from, and lets you browse and analyze your loot history — account-wide.
Back to Files

1.5.0-release

File nameLootHistory-1.5.0-release.zip
Uploaded
Oct 9, 2026
Downloads
37
Size
7.0 MB
Flavors
Retail
File ID
9110176
Type
R
Release
Supported game versions
  • 12.1.0

What's new

commit 68290f67796385f359ce8d46fb35a8e96a27e40c
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 9 19:23:47 2026 +0530

    Release 1.5.0: version bump, release notes and the gated release run

    Release gate, read from docs/automated-tests/20261009-191728/manifest.json
    (run with --release 1.5.0 at fe1b6cd, clean tree, verdict green):
    - Lint: PASS, 0 warnings / 0 errors in 118 files
    - Tests: PASS, 1523 passed, 0 failed, 1 skipped (sanctioned Kit.skip)
      of 1524
    - Perf: PASS, tests/perf.lua ran (five checks pass); 0 scenarios
      recorded because it writes no perf.json
    - Complexity: PASS, lizard 1.24.0, 32955 NLOC / 4627 functions,
      avg CCN 2.4
    - CCN <= 15: PASS, 0 functions over 15, max CCN 15
    - Sighted: PASS, blindFiles 0

    Files:
    - LootHistory.toc, core/Namespace.lua: 1.4.0 -> 1.5.0
    - docs/module-map.md, docs/slash-dispatch.md: the addon version
      references rolled to 1.5.0
    - README.md: new 1.5.0 row at the top of ## Version History
      (2026-10-09); older rows untouched
    - docs/automated-tests/20261009-191728/: the release run bundle,
      with its ANALYSIS.md
    - docs/automated-tests/RESULTS.md: the run's row; settings/Panel.lua's
      disposition records its third consecutive Accepted release run
      (anti-pattern #53: owed a fix or a tracked deviation ID)

    Left alone: the LibKa0s v1.71.0 provenance line in CLAUDE.md, the
    auto-derived CurseForge badge, smoke-test INSTALL-4's "1.4.0 or
    earlier" (historical), docs/testing.md's "1.4.0 tag" gate sentence,
    libs/, tests/_kit/, frozen bundles and the older history rows.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01J2w6FgfFYw93meWZN9Ahn6

commit fe1b6cde8c8505ee6582452eea025dfee9296956
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 9 18:53:34 2026 +0530

    SD-FIN-03: remove dead exports; fix stale doc citations

    Removes Holdings:ItemCounts and LedgerFormat.Glyph (zero shipped callers; the Glyph test now asserts Color(nil) == DirRGB.IN). Full citation sweep of the living docs: 479 file:line citations read against the tree, 124 corrected; independently re-scanned.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01J2w6FgfFYw93meWZN9Ahn6

commit b57541e54f5b3f1dc670feaa66aa11b3bbe28a86
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Fri Oct 9 17:49:35 2026 +0530

    SD-FIN-02: sync docs to code (collection sync-docs pass 2026-10-09)

    Docs and comment citations reconciled against today's tree: stale counts,
    drifted file:line citations, orphan anchors and toolchain gaps, each verified
    independently before applying. Comment edits are comment-only. Dead-export
    candidates reported, not removed. Green gate run after the edits.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01J2w6FgfFYw93meWZN9Ahn6

commit 627ea9c7e9dc1c385a04ba10f807acc98524e9d6
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 8 00:36:20 2026 +0530

    LED-P2-01: record the owner's passing re-run

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 627ea9c7e9dc1c385a04ba10f807acc98524e9d6
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 8 00:36:20 2026 +0530

    LED-P2-01: record the owner's passing re-run

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 19fc557fae966ce659b70b2452e1c1b615b0b79d
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Thu Oct 8 00:26:01 2026 +0530

    LED-P2-01: re-read the bank on a bag change at an open bank

    A shift-click split dragged from the bank into the bags fires BAG_UPDATE
    for the bags only. The Reconciler waited for the bank's own event, so the
    withdraw stayed one-sided, was committed after the 6 s settle as an
    IN +4 OTHER gain, and the bank's -4 surfaced as UNTRACKED drift on the
    next visit (owner's SavedVariables, 2026-10-08, rows 170/171).

    R:Scan now marks bank and tabs dirty whenever bags are dirty while the
    bank is readable, so both halves meet in one pass and pair as a MOVE.
    A closed bank is still never read.

    Tests: a split withdraw that fires only a bag event is one MOVE bank to
    bags (red before the fix); a bag change with the bank closed never reads
    the bank. docs/test-cases.md regenerated, README badge 1523/1523.

    Also records the owner's LED-P2 results in docs/smoke-tests.md: 02-24
    pass (owner-marked, not every scenario exercised); 01 failed, re-run
    pending on this fix.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 0fea31412cd89b35a229c0d2d15d79656810db9c
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 22:13:03 2026 +0530

    LH-STD: list the owner's LED-P2 release gate; confirm v2.77.0 references

    Standards roll to WowAddonStandards v2.77.0 (WS-11, ffb3d6a on its
    feature branch). The three-place reference is already in the form
    v2.77.0 prescribes and needs no edit: TOC "## X-Standard:" is the bare
    repo URL (toc-file-§1), the README Standard badge is the bare unlinked
    shields.io image (documentation-§1), and CLAUDE.md carries
    "## Standards compliance (read first)" (documentation-§6). All three
    stay version-free, as in the other addons. Sweep: every filename-§N
    citation outside libs/, tests/_kit/ and the frozen bundles (828
    resolved) names a real section file and an existing "### N." heading in
    the v2.77.0 tree; the only non-resolving hits are "spec §5.1-§5.5"
    references to the timeline-ledger design spec, not standard citations.
    No retired notation found. TOC LOAD-BEARING annotations were re-read in
    LH-05.

    Sync-docs check of LH-01..LH-18 and RV-LH: module-map.md, ARCHITECTURE.md
    and browser.md already name modules/BrowserTableGroup.lua and
    modules/BrowserWidgets.lua, the module-map load order matches the TOC
    file for file, CLAUDE.md names LibKa0s v1.71.0, docs/test-cases.md is
    byte-identical to a fresh `lua tests/run.lua --list`, and the README
    badge (1521/1521) equals its Total. Nothing to change there.

    LH-R-03 (review F-003): docs/testing.md now lists the 1.4.0 tag's
    in-client gate. LED-P2-01..24 must all carry a recorded Result before
    the version bump and tag (not the merge), the results are the owner's,
    and on an LED-P2-06 pass the Attribution:OnSendMail comment cites it.
    docs/smoke-tests.md and modules/AttributionOut.lua are untouched.

    No version bump, no CHANGELOG entry, no tag.

    Deviation: the item expected a standards-reference roll; none was
    needed because the reference is version-free and v2.77.0 does not
    require a stamp.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 0fea31412cd89b35a229c0d2d15d79656810db9c
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 22:13:03 2026 +0530

    LH-STD: list the owner's LED-P2 release gate; confirm v2.77.0 references

    Standards roll to WowAddonStandards v2.77.0 (WS-11, ffb3d6a on its
    feature branch). The three-place reference is already in the form
    v2.77.0 prescribes and needs no edit: TOC "## X-Standard:" is the bare
    repo URL (toc-file-§1), the README Standard badge is the bare unlinked
    shields.io image (documentation-§1), and CLAUDE.md carries
    "## Standards compliance (read first)" (documentation-§6). All three
    stay version-free, as in the other addons. Sweep: every filename-§N
    citation outside libs/, tests/_kit/ and the frozen bundles (828
    resolved) names a real section file and an existing "### N." heading in
    the v2.77.0 tree; the only non-resolving hits are "spec §5.1-§5.5"
    references to the timeline-ledger design spec, not standard citations.
    No retired notation found. TOC LOAD-BEARING annotations were re-read in
    LH-05.

    Sync-docs check of LH-01..LH-18 and RV-LH: module-map.md, ARCHITECTURE.md
    and browser.md already name modules/BrowserTableGroup.lua and
    modules/BrowserWidgets.lua, the module-map load order matches the TOC
    file for file, CLAUDE.md names LibKa0s v1.71.0, docs/test-cases.md is
    byte-identical to a fresh `lua tests/run.lua --list`, and the README
    badge (1521/1521) equals its Total. Nothing to change there.

    LH-R-03 (review F-003): docs/testing.md now lists the 1.4.0 tag's
    in-client gate. LED-P2-01..24 must all carry a recorded Result before
    the version bump and tag (not the merge), the results are the owner's,
    and on an LED-P2-06 pass the Attribution:OnSendMail comment cites it.
    docs/smoke-tests.md and modules/AttributionOut.lua are untouched.

    No version bump, no CHANGELOG entry, no tag.

    Deviation: the item expected a standards-reference roll; none was
    needed because the reference is version-free and v2.77.0 does not
    require a stamp.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit e85666fa2420d9bd7ef1498c5237d96b4984eaae
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 22:09:21 2026 +0530

    LH-17: one signpost sentence closes Usage; trim the 1.4.0 history row

    README Usage now closes on a single sentence naming Settings -> AddOns,
    the /lh (/loothistory) shortcut and /lh help, per documentation-§1
    item 5 (LH-A-05). The fact that /lh alone opens the page is not stated
    elsewhere in Usage, so it is folded into the same sentence.

    The 1.4.0 Version History row drops the unprefixed "Released on lint,
    tests and complexity only..." line: contributor gate material does not
    belong in the player-facing table (documentation-§1 item 11, LH-A-07).
    Deleted rather than prefixed, per the verified remediation. No version
    bump.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 2d50e52fdc4f01a29ca89e4d921f045efcdbe14d
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 22:07:12 2026 +0530

    LH-16: drop drifted doc counts; complexity suite command; holdings writers

    Doc-set drift pass after LH-05..LH-15.

    - docs/ARCHITECTURE.md: the LibKa0s vendored version now defers to the
      CLAUDE.md provenance line (was v1.69.0); the module-map paragraph drops
      the hard "Fifty-two"/"Ten" counts; the doc-register rows for
      slash-dispatch.md and compat-layer.md drop "20 verbs" and "47 shims"
      (the grep gives 57) and cite the source/grep instead (LH-A-06).
    - docs/module-map.md: "one of the four files in core/" is count-free (six
      core/ annotations are LOAD-BEARING today); the NS.MakeAutocomplete note
      drops the stale "v1.70.0" (LH-A-06).
    - docs/testing.md: "Forty-four suites ... thirty-nine ... five" becomes a
      count-free sentence pointing at the test-cases.md Totals (LH-R-09).
    - DEPENDENCIES.md and docs/automated-tests/README.md: raw lizard (blind in
      Lua, no -L 1500) replaced by the kit's complexity suite; "The lizard run"
      becomes "The complexity suite" (LH-A-08).
    - docs/schema.md: the holdings Writers bullet names all three writers:
      Reconciler:Flush; Reconciler:ForgetHolder -> Holdings:ForgetHolder (the
      Forget popup, settings/Slash.lua); R.MarkLoginGenesis ->
      Holdings:MarkGenesis (the login scan) (LH-A-10).

    Verified only, no edit: the LootHistory.toc Slash citation and the
    settings/Panel.lua load-order comment were fixed in LH-05. The
    BrowserTable/Browser line counts in the layout census (1302/1231) match
    the tree. The "Nine LibKa0s seams" figure was already reworded by an
    earlier item; the remaining "Ten core/*Setup.lua" was made count-free.

    Deviations: the items text's ARCHITECTURE.md line cites predate LH-15's
    module-map spill; edits were made where the text now lives.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit b31ed88025849e63da122482d2d3e23ec6c279b6
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 22:03:19 2026 +0530

    LH-15: spill the hub's module map; fix out-of-scope list; auction exits

    docs/ARCHITECTURE.md:
    - ## Module map (95 lines, past documentation-§3's ~60-line spill
      threshold) is now a summary paragraph plus exactly one link to
      docs/module-map.md (LH-A-03). Event subscriptions and Documented
      deviations stay, per the verified assessment.
    - ## Documentation map's out-of-scope sentence now uses
      documentation-§3's own list as WS-05 words it: docs/audits/,
      docs/reviews/, docs/automated-tests/<run>/, docs/perf-analysis/<run>/,
      docs/revendor/<date>-v<tag>/, docs/superpowers/ (no
      docs/investigations/ here). It notes the three earliest revendor
      bundles that predate the -v<tag> suffix, and that the stores' READMEs
      and RESULTS.md stay registered (LH-A-09).
    - ## Known limitations gains the auction-exit entry: the shared
      escrow.exits ts restarts the EXIT_TTL clock on every new exit, and one
      sale mail books every pending exit of the item as OUT AH_SOLD, so
      expired auctions' returns land as plain IN MAIL. Net counts are right;
      the fix needs a per-auction schema and a migration (LH-R-06).
    - Hub re-measured: 499 -> 432 lines.

    docs/module-map.md: gains ## File roles at a glance (the per-file table
    moved from the hub, unchanged apart from the Diagnostics row's self-link
    becoming an in-page anchor). The load-bearing paragraph under TOC load
    order becomes the hub's bullet list, merged with what was there, and
    now also records core/PerfSetup.lua's position (below Lifecycle and
    Env, above every `local Perf = NS.Perf` upvalue), which LH-05's TOC
    annotations mark LOAD-BEARING. The intro's stale "33 source files" now
    reads 52, the TOC's non-libs entry count.

    docs/data-flow.md: the Exit paragraph cross-references the new known
    limitation (the optional part of LH-R-06's verdict).

    Deviations: the item says the overwrite is in commitExits; it is in
    addExits, which commitExits calls, and the entry names both.

    Findings: LH-A-03, LH-A-09, LH-R-06.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit adf062adb8ae693b995887b70183757327bea30c
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 21:57:47 2026 +0530

    LH-14: automated-test record 20261007-215451, sighted, 0 CCN>15

    The full battery (tests/_kit/run-automated-tests.sh, no --release, no
    version bump) on the clean tree at 15759e0: lint 0/0 over 118 files,
    tests 1521 passed / 1 skipped / 1522, perf pass, complexity pass with
    0 warnings, max CCN 15, 0 blind files over the sighted shadow. The
    previous bundle (20260927-030334, 8e60c1f) predates kit revision 35,
    so this is the record's first sighted complexity reading.

    RESULTS.md is the runner's; the only authored cells are the watch
    list's Dispositions. The five files new in the 1000-1500 band
    (core/Database.lua, settings/Schema.lua, tests/test_browser.lua,
    tests/test_browsertable.lua, tests/test_database.lua) were ruled on,
    and the carried cells whose figures had moved (BrowserTable.lua,
    Panel.lua, test_schema.lua, test_slash.lua) were refreshed to cite
    this run's complexity.txt. modules/Analytics.lua left the band (#32).
    ANALYSIS.md follows AUTOMATED_TESTS.md and names two new actions:
    peel tests/test_browser.lua (41 under the cap), and make
    tests/perf.lua honor --out so perf.json and scenario counts exist
    (the manifest reads 0 scenarios; perf.txt shows five checks passing).

    Findings: LH-A-11 (fresh sighted bundle, band dispositions, runner-
    written RESULTS.md), LH-R-01 (zero warnings recorded).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 15759e072b93896d0f9ecee6c275a6df2f4be221
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 21:54:47 2026 +0530

    LH-14 (1/2): split the last five CCN>15 Browser functions; pin them first

    The last slice of LH-R-01: the five functions the sighted complexity
    run still warned on (all at CCN 16) now sit at 15 or below, so the
    sighted suite reports 0 warnings, max CCN 15, across the whole addon.

    Characterization cases came first and passed against the unchanged
    code, pinning each function's outputs over its branches:
    - tests/test_widgets.lua: the history and holders Character option
      lists, whole (value, label with icon markup, tint), over holder vs
      char rows, the Warband, a known class, an unclassed row, a duplicate,
      and holder entries with a class, without one and with no meta.
    - tests/test_browsertable.lua: the sample's ten holder-move rows whole;
      GroupRecords under a nil mode, an unknown mode and the column-less
      typesub mode (asc, desc, collapsed); SetTestMode's no-op, its [Table]
      trace lines (refused, on, off with a reason) and its table Refresh
      fallback with no OnDatasetChanged.

    The splits remove decisions without changing behavior, with named
    local helpers and no in-function dispatch tables:
    - BrowserWidgets historyCharItems / holderCharItems share classIcon,
      classColor and charItem (one option); rowHolderClass is the
      HolderClassFile seam.
    - BrowserTable holderMoves -> moveOtherEnd, moveInto, pairHolderMove.
    - BrowserTable:SetTestMode -> refuseTestMode, showTestDataset.
    - BrowserTable:GroupRecords -> appendRows, partition, sortGroups.

    Ripple: docs/test-cases.md regenerated (1521), README Tests badge
    moved 1515 -> 1521, docs/browser.md cites for the moved
    BrowserTableGroup.lua functions and the Character icon fold, and the
    docs/ARCHITECTURE.md over-cap census paragraph's line counts.

    Findings: LH-R-01 (last slice), LH-A-11 (complexity half).

    Deviations: the item names test_browser for the char-option pins; they
    went in tests/test_widgets.lua, which already pins the Character
    options, because test_browser.lua at 1459 lines would cross the 1500
    cap. The item's line cites (Browser.lua:393/:420, BrowserTable.lua:701)
    predate LH-08/LH-18; the functions were found where those peels left
    them. Older stale BrowserTable.lua line cites in docs/browser.md that
    this change did not move were left alone.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit e39deb25ff4ebf8db0dfb154ff5ecdc7c2abd432
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 21:43:48 2026 +0530

    LH-13: split currencyLine, Holdings:Search and TestData hot spots

    Slice 5 of LH-R-01: bring the last four of this slice's functions to
    CCN 15 or below with no behaviour change.

    - modules/Collector.lua currencyLine (16 -> under 15): the listed-id,
      twin remap and blacklist guards move to listedCurrency, the direct
      vs. context attribution to currencySource, and the record table to
      currencyRecord. All three are file-local functions (upvalues), so the
      CHAT_MSG_CURRENCY hot path builds no closure per line.
    - modules/Holdings.lua Holdings:Search (20): heldThings collects the
      thing keys and links, thingPasses the text and set filters.
    - modules/TestData.lua walk (17): dayMoves draws the gain and then the
      loss (stream order kept), bookDay writes the cell.
    - modules/TestData.lua TD.DefaultTimelineThing (16): itemDays,
      everlightKey and mostDays.

    Characterization tests first, green on the pre-refactor code:
    - test_collector: every currency-line guard's [Drop] reason in order,
      the ledger-off keep, the refund direct source and the [Currency] line.
    - test_holdings: Search over text, quality, type, subtype, holder,
      empty sets, zero-total exclusion and name order.
    - test_testdata: a checksum of both seeded sample stores on a frozen
      UTC clock (the build reads the wall clock and the local zone, so the
      pin holds on any machine and day), and the default-thing picker's
      Everlight, most-days and tie branches.

    docs/test-cases.md regenerated; README Tests badge 1511 -> 1515.

    Deviations: tests/perf.lua has no currency-line scenario, so the
    "not slower" check rests on the full perf run staying green (it does)
    and on the helpers being upvalues; no new perf scenario was added.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 16e8205ddc1bf9a9440165a7cbda760d4646ba8e
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 21:29:21 2026 +0530

    LH-12: walk StandDown/StandUp as step lists; split Compat currency rungs

    Slice 4 of LH-R-01 (complexity). No function in core/LifecycleSetup.lua or
    core/Compat.lua is above CCN 15 now.

    - core/LifecycleSetup.lua: NS.StandDown (CCN 18) and NS.StandUp (CCN 24)
      each walk a file-scope ordered list of steps (STAND_DOWN_STEPS,
      STAND_UP_STEPS) in one loop. Each step keeps its own nil-guard in a named
      helper: method(key, member), call(key), cancelDeferralsStep,
      registerEnterWorldStep, standUpLogStep. The steps read NS when they run,
      because the modules publish into NS after this file loads. The order is
      unchanged.
    - core/Compat.lua: Compat.ListedCurrencyID (CCN 16) is now listedOrHeld
      plus sameNameTwin. Compat.ListCurrencies was already under 15 (about 8),
      but it is split into the per-rung helpers the item names anyway:
      expandCollapsedHeaders and listedCurrencyRows.
    - Characterization tests: test_disabled.lua checks the exact order of
      StandDown's and StandUp's effects with every surface swapped for a
      recorder, that each surface is reached exactly once, that the [State]
      lines are gated on logging, and that every step is nil-guarded.
      test_compat.lua adds two cases: a twin that is both listed and held, or
      is only held, and an ambiguous twin among the held currencies. It also
      checks ListCurrencies when the list API or ExpandCurrencyList is missing.
    - docs/test-cases.md regenerated (1511). README Tests badge 1505 -> 1511.

    Deviation (one behaviour change at an edge): the old StandDown walked the
    eight module Disables with ipairs over { NS.Collector, ... }. A nil module
    ended that ipairs early, so with NS.Collector unbuilt no later module was
    disabled. The item asks for each step to keep its own nil-guard, so now
    every present module is disabled whatever is missing before it. In normal
    play every module is built, so nothing changes there. The nil-guard
    characterization case was red against the old code for exactly this reason.

    Findings: none directly (item traces to LH-R-01 via LH-14).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 2a38e4be8140504a416a887d2b10fe5923a6ed56
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 21:23:53 2026 +0530

    LH-11: bring Reconciler and Escrow hot spots to CCN 15 or below

    Slice 3 of LH-R-01: six functions in modules/Reconciler.lua and
    modules/Escrow.lua above CCN 15 are reduced by removing decisions, with
    characterization cases written first and green against the old code.

    Reconciler:
    - onEvent (18): the elseif ladder becomes a file-scope EVENT_HANDLERS
      table (built once at load, not per event), with dirtyAndFlush(part)
      for the events that only mark a part and light the fuse.
    - planHolder (19): baselineColumns and addPurseNet helpers.
    - R:WriteRows (16): writeMoves, writePairs and writeNet helpers; the
      row order (moves, pairs, extra, net) is unchanged.

    Escrow:
    - planMailMoney (16): the guard ladder becomes mailMoneyGain and
      mailMoneyMasked, in the same order.
    - planExits (18): planReturns, liveSaleName and exitSold helpers.
    - commitExits (17): addExits and resolveExits helpers.

    R.SCAN_STEPS / PLAN_STEPS / COMMIT_STEPS and Escrow's load-time appends
    are untouched. No behaviour change.

    Characterization: test_reconciler pins every capture event's dirty
    part, fuse and handler (both sides of the mailbox and owned-auction
    readable gates). test_escrow adds seven cases: mail money with the
    mailbox closed, a gold loss beside waiting mail money, two auctions of
    one item exiting as one exit with a partial return, one sale mail
    booking every pending exit of the item as AH_SOLD and a second exit
    restarting the shared TTL clock (both pinned as current behaviour, the
    LH-R-06 known limitation), a genesis pass resolving no exit, and a sale
    mail for another item. docs/test-cases.md regenerated; README Tests
    badge 1497 -> 1505.

    Findings: LH-R-01 (via LH-14 trace).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit d1725543e6add7149f075df6f1ab7b934a3d902f
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 21:18:51 2026 +0530

    LH-10: address review — reattach PairHolders and RecomputeFlows doc comments

    The CCN refactor in 5d24847 left helper functions between two public
    functions and their contract comments. Ledger.PairHolders's comment sat
    above byTostring, and Ledger.RecomputeFlows's comment ran into
    clearTouchedCells's own comment, forming one block with two conflicting
    "Answers" clauses. Move each comment to sit directly above the function
    it describes. Comment-only; no behaviour change.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 5d24847aee609eaef611de171a7788a533923201
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 21:15:18 2026 +0530

    LH-10: bring Ledger and AnalyticsLedger hot spots to CCN 15 or below

    Slice 2 of LH-R-01 (traced on LH-14). No behaviour change; characterization
    cases were added first and passed against the old code:
    - test_ledger: PairHolders withdrawal direction, exact cancel, one-sided keys,
      tostring key order; PickReason scope precedence (guild bank > merchant >
      trainer > taxi > auction > mailbox) and gold-out scopes only for gold out.
    - test_rollup: RecomputeFlows skips pruned days, ts-less rows, unwanted things
      and untouched (day, thing) pairs; creates a touched-but-absent cell; n==0.
    - test_analytics: BackToBackRows nil maps, zero peak, label colors, tie-break.

    Refactor (lizard, before -> after):
    - core/Ledger.lua Ledger.PairHolders (17 per audit) -> 6: file-scope
      byTostring comparator and a named shrink(n, q) helper.
    - scopeReason 16 -> 7: file-scope MERCHANT_REASON[isOut][isItem] table and
      the GOLD_OUT_SCOPES ordered list walked by goldOutReason.
    - Ledger.RecomputeFlows 19 -> 3: phases split into clearTouched /
      clearTouchedCells (clear) and refoldRow (re-sum). Migration path, not hot.
    - modules/AnalyticsLedger.lua AL.BackToBackRows (18 per audit) -> 11:
      unionKeys, frac and a file-scope byTotalThenLabel comparator.

    tests/analytics_golden.txt is byte-identical. docs/test-cases.md regenerated
    and the README Tests badge moved to 1497/1497.

    Deviation: lizard silently skipped PairHolders and BackToBackRows (it drops a
    function when `#x ... end` share one line), which is why they were absent
    from the local lizard report though the audit cited them. Those one-liners
    are now split so lizard measures both functions.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 6a0e502dd9395e4ed293788ad025a745ebedb622
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 21:08:07 2026 +0530

    LH-09: bring core/Database.lua's four CCN>15 functions to 12 or below

    Slice 1 of LH-R-01: convertHolderMoves (24), compileFilter (18),
    accumulateLedger (20) and Database:Stats (23) are now 12, 11, 7 and 12.
    No behaviour change.

    Characterization first, run green against the unrefactored code:
    - test_database: the v12->v13 step over a v12 fixture with holder moves,
      pinning the exact pairIds (<ts>:m<queue index>, first-come pairing, an
      unpartnered half's own index, a ts-less row's "nil:m4"), the kept
      pairId, the intra-holder MOVE and the rebuilt rollup cells.
    - test_database: QueryList's clause type gates (wrong-type clauses are
      unfiltered, exact vs set quality, exempt list, bound NONE, text, window).
    - test_stats: one pass over every per-row branch of Stats and
      accumulateLedger (legacy dir/kind defaults, currency value 0, no ts,
      gold in/out, holder-only row, OUT with no holder, MOVE, holder-move IN).

    Refactor, by named helpers only (performance-§11), no in-function dispatch
    tables and no per-call allocation:
    - convertHolderMoves: queueForPairing, markTouched and assignPairIds.
    - compileFilter: clauseOfType(v, t), one rule for the five type-gated
      clauses. Its unmatched clause is now nil instead of false inside the
      private query plan, which every reader tests only for truthiness. The
      any* `or` chains stay inline, as the existing comment requires.
    - accumulateLedger: tallySide does one side's reason/value/holder/kind
      maps; the gain and loss arms each pick their own maps.
    - Stats: rowFacts reads one record's inlined legacy defaults (one local
      call per record replaces the inline expressions), and accumulateLoot
      holds the gains-only legacy block. The single pass stays in Stats.

    An ad hoc 20,000-row bench (scratch dir, not committed) showed Stats and
    QueryList unchanged within run-to-run noise; tests/perf.lua passes.

    Ripples: docs/test-cases.md regenerated (Total 1490 -> 1493), README
    Tests badge moved to 1493/1493. Database.lua is 1258 lines.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 8caf2eeb7675bd04f4f47fe1ba34315262652749
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 21:02:18 2026 +0530

    LH-18: address review — repoint qualityOptions comment to BrowserWidgets.lua

    The BrowserFilterBar.lua header comment still pointed at modules/Browser.lua
    for qualityOptions, which 6d3cd42 moved to modules/BrowserWidgets.lua.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 6d3cd42ff17d7b1ca92a327d1429acf6325e2a9b
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 20:59:13 2026 +0530

    LH-18: peel Browser's dropdown-option kit into BrowserWidgets.lua

    modules/Browser.lua sat at 1416 lines, past its own "Re-check at 1400,
    peel the widget kit then" watch-list trigger (second half of review
    2026-10-07 F-002, finding LH-R-02). The filter bar's dropdown-option kit
    moves VERBATIM to a new modules/BrowserWidgets.lua: qualityColor,
    BOUND_LABEL / BOUND_ORDER (B._boundLabel / B._boundOrder), dataset,
    withAll, historyCharItems, holderCharItems and the seven option builders
    (source, char, type, subtype, zone, quality, bound) with their B._withAll
    and B._options publishes. Browser.lua is now 1231 lines, BrowserWidgets.lua
    209.

    The new file extends NS.Browser (idempotent publish) and reads no browser
    state, so it loads directly ABOVE modules\Browser.lua, which binds
    B._dataset (one new private seam, the repo's `_` convention) and the
    B._options builders as file-scope locals at load, so its call sites
    (UpdateFooter, RefreshFilterOptions, OnSettingsChanged) are unchanged. The
    TOC line carries a LOAD-BEARING POSITION annotation. Public members are
    unchanged, no new globals, .luacheckrc unchanged. Every removed line is
    present unchanged in the new file; the only lines added to Browser.lua are
    the binding block and one comment cite ("see charOptions below" now names
    BrowserWidgets.lua).

    Characterization: test_browser gains a case asserting the TOC loads
    BrowserWidgets.lua directly before Browser.lua and every moved member is on
    NS.Browser (red before the move: the previous TOC file was
    LedgerFormat.lua). Goldens unchanged. docs/module-map.md (tree, load-bearing
    list, new entry 34 with the rest renumbered), docs/ARCHITECTURE.md (load
    order, module table, the layout-§1 census sentence), docs/browser.md's
    class-icon cite and the live RESULTS.md watch-list row are updated;
    docs/test-cases.md regenerated and the README badge moved to 1490/1490.

    Deviations from the item text: the item names a widget kit of
    "frame/button/dropdown/filter-bar construction helpers", but none of that
    is left in Browser.lua: the dropdown factory and popup became
    LibKa0s-Widgets-1.0 (core/WidgetsSetup.lua), the filter bar's construction
    is already modules/BrowserFilterBar.lua, and ApplySkin / MakeCloseButton
    are three-line forwarders to the library that are the window shell's own
    seam. What moved is the remaining kit, the code that turns the dataset into
    dropdown options. The file is listed BEFORE Browser.lua (the item allows
    either side). historyCharItems' pre-existing CCN 16 moves unchanged, so
    LH-14's cite for it is now modules/BrowserWidgets.lua.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 6874e6d36446e94a2a15890d32fae08636c40870
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 20:51:26 2026 +0530

    LH-08: peel BrowserTable's display-list layer into BrowserTableGroup.lua

    modules/BrowserTable.lua sat at 1476 lines, 24 under the layout-§1 cap and
    past its own "Re-check at 1300" watch-list trigger (review 2026-10-07 F-002,
    finding LH-R-02). Its filter -> sort -> group layer moves VERBATIM to a new
    modules/BrowserTableGroup.lua: NUMERIC_SORT, the groupBy / collapsed /
    groupAsc state, GROUP_OF, groupOf, GROUP_PREFIX, SortRecords, SetSort,
    SetGroupBy, ToggleCollapse, GroupRecords, CurrentRecords, BuildDisplayList,
    SetFilter and OrderedFilteredRecords. BrowserTable.lua is now 1272 lines,
    BrowserTableGroup.lua 227.

    The new file extends NS.BrowserTable (idempotent publish) and binds two
    private seams BrowserTable.lua now publishes, BrowserTable._columnByKey and
    BrowserTable._groupColumn, at file load (the repo's existing `_` seam
    convention, as BrowserTable._qtySamples and B._applyFilter). GROUP_COLUMN
    stays in BrowserTable.lua because UpdateHeaderArrows reads it too. So the
    TOC lists it directly after modules\BrowserTable.lua under a LOAD-BEARING
    POSITION annotation. Public members are unchanged; luacheck globals and
    read_globals are unchanged (one per-file 212/self entry, as its parent has).
    Every removed line is present unchanged in the new file; the only added
    lines in BrowserTable.lua are the seam publish and the split GROUP_COLUMN /
    GROUP_PREFIX comment.

    Characterization: test_browsertable gains a case asserting the TOC loads
    BrowserTableGroup.lua directly after BrowserTable.lua and every moved member
    is still on NS.BrowserTable (red before the move: the next TOC file was
    Export.lua). Goldens unchanged. docs/module-map.md (tree, load-bearing list,
    new entry 37 with the rest renumbered), docs/ARCHITECTURE.md (load order,
    module table, the stale layout-§1 census sentence), docs/browser.md cites
    for the moved functions, and the live RESULTS.md watch-list row are updated;
    docs/test-cases.md regenerated and the README badge moved to 1489/1489.

    Deviations from the item text: holderMoves did NOT move. It is not part of
    grouping; it is the final pass of the test-mode generator (called only by
    BuildTestData, reads TEST_CLASSES), so moving it would take two more private
    seams and mix an unrelated concern into the group file. To get under the
    1300 trigger without it, the sort half and the pipeline (SortRecords,
    SetSort, CurrentRecords, BuildDisplayList, SetFilter,
    OrderedFilteredRecords) moved with the grouping, i.e. the whole display-list
    layer. GroupRecords' pre-existing CCN 16 (and holderMoves' and
    SetTestMode's) move or stay unchanged; the CCN fixes are LH-09..LH-14.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 66e71459295a338e784ddb48a25ba0363d632e79
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 20:42:12 2026 +0530

    LH-07: route five pre-formatted chat lines through NS.Format

    Five chat lines built their text before handing it to the shared printer
    (events-frames-taint-§8 SHOULD NOT): `/lh debug events` (settings/Schema.lua),
    both `/lh holdings` lines (settings/Slash.lua) and the Browser's SaveView and
    ResetView announcements (modules/Browser.lua). Each now passes the format and
    its arguments to NS.Format, so formatting (and secret-safe stringification)
    happens once inside the printer. Output is byte-identical.

    Tests: the `/lh debug events` lines were already pinned exactly; the
    `/lh holdings` case is tightened from substring finds to exact, prefixed
    equality; a new Browser case pins the SaveView/ResetView lines exactly and
    that a silent reset prints nothing. All written and green before the
    conversion, and green after. docs/test-cases.md regenerated; README Tests
    badge moved to 1488.

    Finding: LH-A-12.

    Deviation from the item text: the spec says NS.Print(fmt, ...), but NS.Print
    space-joins its arguments rather than formatting them, which would change the
    output. The verified remediation names NS.Format (the printer's format form,
    already used elsewhere in these files), so that is what is used.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 7e6ae10b6661e48ce7ee6852b53887dcb0ab9f6d
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 20:36:35 2026 +0530

    LH-06: one location parser in TimelineModel; pin the resize double render

    LH-R-08: TimelineModel's local sideOf split a "<holder>/<container>" end at
    the FIRST "/", while NS.Ledger.LocationHolder (and Database's ledger pass)
    split at the LAST. They agreed only because no holder key carries a "/".
    TM.RowDelta now reads the holder through NS.Ledger.LocationHolder (Ledger
    loads earlier in the TOC; a call-time read) and the local parser is gone.
    Reconciler's unrelated local sideOf (which picks a CONTAINER name for a pair
    end) is renamed containerFor, with a comment, so the name no longer clashes.
    New case in tests/test_timeline.lua: a MOVE row whose container part holds a
    "/" is split the same way Ledger.LocationHolder does (red before the swap).

    LK-R-04: no library seam. A headless case in tests/test_timeline.lua counts
    chart Render calls for one pane resize -- the pane's OnSizeChanged
    (TL:Layout's explicit chart:Render) plus the anchored chart's own
    OnSizeChanged -- and pins 2. The mock does not cascade a size change through
    anchors, so the case fires both scripts as the client does. docs/performance.md
    gains an "Accepted costs" section recording it as bounded (pooled regions, one
    extra LTTB pass and repaint, resize only).

    docs/test-cases.md regenerated; README Tests badge 1485 -> 1487.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 43d4b324841a647eec6f3dc31e3996e6fbba7fd1
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 20:28:35 2026 +0530

    LH-05: annotate load-bearing TOC positions; publish NS.Analytics idempotently

    modules/AnalyticsCharts.lua now opens with `NS.Analytics = NS.Analytics or {}`
    like every other Analytics* file (LH-A-02); a new test_analytics case loads it
    on a bare namespace (red before: index of nil local 'Analytics').

    LootHistory.toc, re-read against toc-file-§5 for every # Modules / # Settings
    position (LH-A-01, LH-A-15, LH-A-16, LH-A-17, LH-A-18):
    - Escrow: below Reconciler (appends to SCAN/PLAN/COMMIT_STEPS at load).
    - AnalyticsCharts: below AnalyticsFormat (binds Analytics.K at load).
    - Timeline: below TimelineModel (TM.TOTAL) and Browser (RegisterTab).
    - settings\Panel.lua: below Schema (MASTER_GROUP/MasterAfterGroup).
    - "# Modules (Attribution before Collector)" loses the false parenthesis and
      gains one CONVENTIONAL line for every unannotated modules\ position.
    - the Slash.lua note cites LibKa0s-Slash lib:New's checkDescriptor refusal by
      symbol instead of libs\LibKa0s\Slash.lua:487 (documentation-§6).
    settings/Panel.lua's header no longer says OptionsSetup loads immediately
    before it (Schema.lua and Slash.lua load between) (LH-A-06 items 6 and 7).
    docs/ARCHITECTURE.md and docs/module-map.md: load-order bullets list the new
    positions, the "Seven" count becomes the grep that derives it, and the false
    "(Attribution and Filters before Collector)" goes. docs/test-cases.md
    regenerated; README Tests badge 1485/1485.

    Deviations from the item text:
    - Re-reading every modules\ file found three more load-bearing positions the
      audit missed, so "every other modules\ position is CONVENTIONAL" would have
      been false: Analytics.lua (binds Analytics.K/_fmt/_* helpers from
      AnalyticsFormat at load), BrowserFilterBar.lua (binds B._applyFilter etc.
      from Browser at load) and HoldingsTab.lua (NS.Browser:RegisterTab at load).
      They are annotated too, so grep -c LOAD-BEARING rises by 7 (9 -> 16), not 4.
    - AnalyticsCharts' note names AnalyticsFormat (which sets K), not "one of
      AnalyticsFormat/Analytics/AnalyticsLedger": after the idempotent publish the
      table always exists, and K is the real load-time dependency. The new test
      therefore pins the publish (table exists before the first read, a sibling's
      table is kept) rather than a full load on a bare namespace.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 22974e5c27db147c540c597a9ac04774914827ae
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 20:20:06 2026 +0530

    LH-04: add a Perf case to the stub-surface parity suite

    tests/test_surface_parity.lua gains a Perf case beside Core/Widgets/Slash/
    DebugLog/Options/Bus/Compat/Schema/Item/Pool/Lifecycle/Env/Media. It compares
    the nine members core/PerfSetup.lua's library-absent stub carries (on,
    suspended, BUCKET_ORDER, Note, Open, Close, Suspend, Resume, OnCommand) on the
    live lib:New instance and on the degraded arm from tests/degraded_env.lua
    (two-table form: an instance has no major to name), and asserts each is
    present on both arms.

    The '-- members from: grep' comment gives the derivation
    (grep -rhoE 'Perf[.:][A-Za-z_]+' core modules settings | sort -u); the case
    runs that scan over the TOC's core/modules/settings files (minus PerfSetup
    itself) and fails if the addon reads a Perf member the list does not name,
    so a new read forgotten in the stub goes red here. The case passed on first
    run: the stub already carries every member, so core/PerfSetup.lua is
    unchanged.

    Ripple: docs/test-cases.md regenerated (1484 total) and the README Tests
    badge moved to 1484/1484.

    Finding: LH-A-04 (audit LH-68, testing-§8).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit a7739ebac3511e428c9551f756726c59f504bfbd
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 20:15:15 2026 +0530

    LH-03: run the combat-exit LoginScan/Flush outside the ledgerEvent bracket

    R:OnEvent now dispatches PLAYER_REGEN_ENABLED to an unbracketed
    onRegenEnabled before the Perf bracket opens, so the ledgerEvent bucket
    holds only dirty bits and debounces, as core/PerfSetup.lua's bucket
    declaration and docs/performance.md say. A /lh perf capture across a
    combat exit no longer charges a whole login scan or flush to ledgerEvent.
    No new measurement is added for the flush. This also takes one branch
    out of onEvent (lizard CCN 21 -> 18; the rest is LH-11's).

    tests/test_perf.lua gains "PLAYER_REGEN_ENABLED records no ledgerEvent
    sample while BAG_UPDATE does" (red first: regen was noted under
    ledgerEvent), which also asserts the deferred flush still runs.
    docs/test-cases.md regenerated, README Tests badge 1482 -> 1483, and the
    docs/combat-path-sweep.md PLAYER_REGEN_ENABLED row says it sits outside
    the bucket.

    Finding: LH-R-05 (review F-005).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit abccc51544d7406b06bdefd1e643690a47c0c144
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 20:10:10 2026 +0530

    LH-02: keep a stand-down-canceled Coalesce window from wedging it

    Util.Coalesce set a `pending` boolean before NS.After and cleared it only
    inside the deferred body. NS.StandDown cancels every deferral
    (NS.CancelDeferrals), so a window that was in flight at the stand-down never
    ran its body, and the flag stayed set for the rest of the session. The
    settings panel's RECORD_ADDED coalescer is built once and outlives the
    stand-down, so `/lh disable` or a perf suspend within 0.2 s of a loot line
    froze the record-count readout. The Browser, Analytics and Timeline
    coalescers had the same exposure.

    The coalescer now holds the NS.After handle. A canceled handle counts as no
    window in flight, so the next trigger after the stand-up arms a fresh one.
    The existing guarantees still hold: the handle is cleared before the body so
    a raising fn cannot wedge it, the trigger runs straight through when
    C_Timer is absent, and at most one window is in flight. settings/Panel.lua
    is unchanged.

    tests/test_util.lua gains "Coalesce: a window canceled by the stand-down
    does not wedge the trigger". It failed red first with "runs after
    stand-down + new trigger: 0". docs/test-cases.md is regenerated and the
    README Tests badge moves to 1482/1482.

    Finding: LH-R-04 (review F-004).

    Deviation: the test cancels the window with NS.CancelDeferrals, the step of
    NS.StandDown that does the canceling, instead of a full stand-down and
    stand-up. Toggling settings.enabled in test_util left the Attribution
    peripherals enabled for the suites that run after it, and five Attribution
    cases failed on that leaked state.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 79131e38a9a83a125de8999ad8d713fcfe110955
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 20:01:49 2026 +0530

    LH-01: rebuild loot, currency and roll-won patterns when their globals change

    core/Util.lua compiled the self-loot, self-currency and roll-won patterns
    once per session and never re-checked them. PrettyChat rewrites those
    chat globals mid-session (settings writes, profile changes, /pc
    disable|enable, combat boundaries under its visibility rules; its docs
    call this handoff H-1), so every self-loot and currency record was
    silently lost until /reload.

    Each pattern set now keeps the exact source strings it was compiled from
    (positional, beside the patterns). ParseSelfLoot, ParseSelfCurrency and
    ParseRollWon compare the live globals against them on every parse with
    rawequal over a reader function's multiple returns (no table or string
    built on the hit path; tests/perf.lua's loot-line scenario still reads
    0.0 B/iter) and rebuild on any difference, including a global that
    appeared or disappeared. A roll-won `false` cached while
    LOOT_ROLL_YOU_WON was absent no longer survives the global appearing.
    The duplicated match loop is shared as matchPatterns. Comments, and the
    data-flow.md and module-map.md descriptions, now say "once per distinct
    set of globals" and name the reason. No PrettyChat change, no bus
    message, no GitHub issue (OWNER_SCOPE 5).

    tests/test_util.lua gains four cases, each seen red before the fix;
    docs/test-cases.md regenerated and the README Tests badge moved to
    1481/1481.

    Finding: PC-R-01.

    Deviations: the spec's test names say "honoured"; the repo's prose gate
    (localization-§5, US English) rejects that spelling, so the names read
    "honored". The "unchanged global set does not rebuild" case also counts
    exactly one rebuild per change first, so it is red against the old code
    (a pure no-rebuild count passed before the fix).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 2f79755bbd2a97b2643f898263f734b35ce5bf0b
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 19:55:34 2026 +0530

    RV-LH: address review — 01_DELTA.md line 1 in the canonical form

    Line 1 of docs/revendor/2026-10-07-v1.71.0/01_DELTA.md carried a "# "
    heading marker. wow-revendor-libka0s requires line 1 to be exactly
    "Delta: LibKa0s <base> -> <new>" because the standards audit's re-vendor
    check and the Step 0 pre-flight read both tags off it. The bundle is new
    in RV-LH and not yet frozen, so it is corrected in place.

    Docs only; no code or test change.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit e74eb2668d9fb152d7477839729a6669100e115e
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 19:51:06 2026 +0530

    RV-LH: re-vendor LibKa0s v1.71.0 and regenerate the test inventory

    Replace libs/LibKa0s/ and tests/_kit/ whole from the local v1.71.0 tag
    (cb274a4, via git archive) and roll the CLAUDE.md provenance line and the
    docs/debug.md vendored-set stamp to v1.71.0. Minors: Env 2, Slash key 20.2,
    WidgetsLineChart 3, WidgetsAutocomplete 2, OptionsIdList 4; kit revision 38
    (adds secrets.lua). Both payloads diff clean against the tag.

    Kit 38's --list Totals leave declared skips out of Total and print a
    Skipped row, so regenerating docs/test-cases.md resolves LH-A-13 (Total
    was one above the badge). Total is 1477, Skipped 1.

    Re-vendor reds fixed here (consumer-owes, test-only): tests/test_libka0s.lua
    pinned KIT_VERSION 37 and WidgetsAutocomplete 1 / WidgetsLineChart 2 in the
    v1.69.0 and v1.70.0 cases. They relax to >= as the file does for every
    earlier release, and a new v1.71.0 case pins the new minors and kit 38.
    That case moves the README badge 1476/1476 -> 1477/1477. No addon code
    changed. modules/Timeline.lua's ClearHover before repaint stays, as
    v1.71.0's "What a consumer owes" allows.

    Frozen bundle docs/revendor/2026-10-07-v1.71.0/ (01_DELTA, 02_CANDIDATES,
    05_SUMMARY). Every candidate (Kit.secret, ChartMath.ClipSegment, dropping
    the ClearHover call) is not adopted in this run, per owner scope 5.

    Deviations from the item text: the spec said no code changes; the test pin
    edit and the new pin case (and so the badge move to 1477) were needed to
    keep the suite green. Lizard's 23 pre-existing CCN breaches in untouched
    files are owned by LH-09..LH-14.

    Findings: LH-A-13.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit aaee6e1342d3284e9e1df6918e5b7f3372e9e10b
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 16:51:56 2026 +0530

    RA-00: record 2026-10-07 standards audit and review bundles

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01RoCGDEVoaSdzqSHHsASPMi

commit 3f70dfdce2f3188fa9725838c2d459f748093572
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 15:12:17 2026 +0530

    docs: README Tests badge at 1476

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 3f70dfdce2f3188fa9725838c2d459f748093572
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 15:12:17 2026 +0530

    docs: README Tests badge at 1476

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit be1b97e2da492a98e97366d2d07c926cf1b33b49
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 15:09:08 2026 +0530

    docs: LED-9 stray text confirmed as world nameplates through the window

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit e12e5ab85f2486453a3206fbebc08440bc5ab9c3
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 15:07:49 2026 +0530

    fix(timeline): legend tooltip refreshes under a resting cursor after a click or repaint

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 59b9a8fead867a3a320f695d4aa16c3ad199c0a9
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 13:11:15 2026 +0530

    fix: Phase 11 task 2 (restore Reset/Clear meanings per tab) final-review fixes

    docs/browser.md said Reset on the Timeline leaves both the charted thing and
    Total only until the next load. Total only is read straight from the saved
    slot, so Reset turns it off at once; only the charted thing (TL.thing) lasts
    the session. Reworded, and pinned by a new tests/test_views.lua case.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 59b9a8fead867a3a320f695d4aa16c3ad199c0a9
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 13:11:15 2026 +0530

    fix: Phase 11 task 2 (restore Reset/Clear meanings per tab) final-review fixes

    docs/browser.md said Reset on the Timeline leaves both the charted thing and
    Total only until the next load. Total only is read straight from the saved
    slot, so Reset turns it off at once; only the charted thing (TL.thing) lasts
    the session. Reworded, and pinned by a new tests/test_views.lua case.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 66e1c8c0b87188b8d37dbf323ae8d6efae5b6999
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 13:06:03 2026 +0530

    fix(browser): Reset deletes the tab's saved view, Clear returns to it (original meanings, per tab)

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 9fdecda0b7c78dfa1020a0619b3d74ebfb01a988
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 13:04:26 2026 +0530

    docs(plan): P11 task 2 (restore Reset/Clear meanings per tab)

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 0c11b824de8de4f365bafd9babf5c57b235c70d2
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 13:02:13 2026 +0530

    fix: Phase 11 (per-tab filter views; Holdings Save/Reset/Clear) final-review fixes

    Docs still described a single shared filter and the retired savedView;
    update browser.md, module-map.md, ARCHITECTURE.md, slash-dispatch.md and
    the HIST-27 smoke to per-tab state, CurrentFilter(tab) and savedViews.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 804c55a84cded5b0d3500ebd3a3005f24c57a915
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 12:56:20 2026 +0530

    fix(task 1): README Insights bullet and INS-1 describe per-tab filters

    Both still described the superseded issue-#13 shared-slice design; each
    tab now keeps its own filters.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit f212f58567eb879f198bf0f55f7d715f9ea6584c
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 12:51:41 2026 +0530

    test(views): compare a re-applied Date range without its clock-resolved bound

    The tab-switch round-trip case compared the whole filter, including the
    Date range's `from`, which is re-resolved against time() on every apply
    and can move on by a second between the two reads.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit d85556bf88253a93ef18788ed189efac805f1eb6
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 12:47:24 2026 +0530

    feat(browser): per-tab filter views; Save/Reset/Clear act on the active tab (v14)

    Each browser tab (History, Insights, Timeline, Holdings) now keeps its own
    live filter state on the shared bar (group, sort, date, search, multi-select
    filters, Character scope, tab fields) and its own saved view in
    profile.savedViews[tab]. Save stores the active tab's state, Reset restores
    its saved view (stock when none), Clear applies its stock view and keeps the
    saved one. Holdings' group and sort join its view, which is why Save, Reset
    and Clear did nothing there before. Schema step v14 copies a stored
    savedView into every tab's slot and removes it.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit eafa26ca3019937217da81da743acad4748ba490
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 12:26:46 2026 +0530

    docs(plan): timeline ledger P11 (per-tab views)

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 062007db2b797cc6a3d1abe380caed67ae4610d2
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 12:06:14 2026 +0530

    fix: Phase 10 (legend tooltip and spacing; perf capture record) final-review fixes

    Drop the false parity claim on TM.FormatCount: History's Qty column
    (LedgerFormat.QtyText) prints plain tostring(q) with no separators.
    Comment-only; behavior unchanged.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit d4c0ce573e16147e242fb8517d9e947e355132e3
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 12:02:23 2026 +0530

    docs(perf): record the 2026-10-07 in-game capture (no measurable combat cost)

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 0bfb80c5f2bd18ac6b73e58569570d6cf55f037a
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 11:58:25 2026 +0530

    feat(timeline): legend tooltip shows holder color and current holding; even legend spacing

    Hovering a legend entry titles the tooltip in the line's color (class color, the Warband's blue,
    the Total in gold), then "Holding" with what that holder holds of the charted thing now (active
    Holdings store; gold as coins, counts with thousands commas, 0 when none) and the gray click hint.
    The Total sums the charted holders, as its line does, and reads "Holding (all shown characters)"
    when the filter or the line cap leaves out a holder that holds some.

    Legend entries are now as wide as their labels and one even 16 px gap apart (Warband included);
    the Total keeps its 120 px slot, and a legend wider than the pane wraps to another row with the
    plot giving up the height. Spec 8.1, browser.md and smoke TL-17 updated.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 4d1b699a1f302db89834f6cded96511d8e2359e6
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 11:50:02 2026 +0530

    docs(plan): timeline ledger P10 (legend tooltip and spacing; record perf capture)

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 51ae30ec9e058dc435fc6571b59251cb1802dcd0
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 11:46:41 2026 +0530

    fix: Phase 9 final-review fixes

    README Tests badge brought in line with the docs/test-cases.md Totals
    (pass/pass convention), as docs/testing.md requires.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit a0b87c3d2b1a74cc0b90f0aed23e8b1bd72dff3c
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 11:13:42 2026 +0530

    fix(B6): TL-8 Holdings Group list includes Type & SubType

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 19f272a34234776071ad13baeb7cb8fc0554f2d5
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 11:11:43 2026 +0530

    docs(smoke): HIST-6 covers Group by Type & SubType

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 5873517dd91a347341bc1d1f8c53541ef21aa83e
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 11:07:30 2026 +0530

    feat(history): test-mode rows show a sample tooltip on hover

    The test-mode sample's item names are made up, so its rows carry no item
    link and the History hover drew nothing. A link-less row in test mode now
    gets a plain tooltip (Compat.ShowTintedTooltip): the name in its quality
    color, "Type · SubType", the INFERRED note, a gray "Test-mode sample" and
    the menu hint. Linked rows and live rows are unchanged. TM-1 extended.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 8dab2dcae4b4cf2b846595b8977626fc1c5a61ed
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 11:01:17 2026 +0530

    feat(group): Group by Type & SubType on History and Holdings

    A `typesub` group mode keyed on itemType\001itemSubType, header
    "Type: <Type> · <SubType>" ("Type: <Type>" with no subtype, no trailing
    separator; currencies read "Currency · <category>"), ordered by type then
    subtype. Shared label/order helper NS.LedgerFormat.TypeSub; History offers
    "Group: Type & SubType" after Type, Holdings adds it to its own modes, and a
    saved view stores it like any other groupBy.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit a8c495cd45e3bb0a4307f59da969c64d94c45273
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 10:54:19 2026 +0530

    feat(timeline): smoother lines (6 px per point, 2 px strokes)

    Create the chart with pxPerPoint = 6 and raise the holder line width to 2 (Total stays 2.5);
    fewer, longer segments, values untouched. Tests pin the option, the widths and the thinned count;
    smoke TL-16 added.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit ea7fceed542b162a006b8582869f78e86a01fc8d
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 10:48:50 2026 +0530

    feat(search): autocomplete under the Search box on every tab (LibKa0s Autocomplete)

    - core/WidgetsSetup.lua: NS.MakeAutocomplete seam over LibKa0s-Widgets-1.0's Autocomplete
      (v1.70.0); nil without the library, leaving a plain filter box.
    - BrowserFilterBar: attach the list to the shared Search box after its own scripts (the library
      hooks them); History/Insights provider B.SuggestNames (distinct item and currency names under
      the other filters, active dataset, quality-colored, no gold, prefix matches first), B.PickName
      and B:SetSearchText (applies the filter exactly once with or without the client's
      OnTextChanged).
    - Browser: tab specs gain optional suggest(text)/pick(item); B:Suggest/B:PickSuggestion route to
      the active tab (nothing when Search is grayed); a tab switch and Disable close the list.
    - Holdings: HT.Suggest (Holdings:Search names under the tab's filters, Gold included).
    - Timeline: the local picker list (makeSuggestRow/RenderSuggestions) is gone; TL.Suggest offers
      things with Gold first and TL:Pick charts the thing and keeps its name in Search.
    - tests/test_autocomplete.lua (new suite): seam, placement under the box, per-tab providers and
      picks, routing, old list gone. test_timelinetab and test_browser adjusted.
    - Docs: browser.md Search autocomplete section, smoke AC-1 (all four tabs) and TL-4, testing.md,
      module-map, ARCHITECTURE, test-cases.md regenerated.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 4d4a1ec7457ec10034bbbb4fedff4fc21358e1e3
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 10:34:52 2026 +0530

    chore: re-vendor LibKa0s v1.70.0 (Autocomplete, LineChart pxPerPoint)

    Both payloads copied whole from tag v1.70.0 via git archive; diff -r empty.
    Adds libs/LibKa0s/WidgetsAutocomplete.lua (minor 1); WidgetsLineChart minor 2
    (Widgets key 12.1.4.2.1). Kit stays at revision 37. CLAUDE.md provenance and
    the docs/debug.md stamp roll in this commit. Bundle: docs/revendor/2026-10-07-v1.70.0/.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 42af72206495aafc5f7b0b654c13c392fbf8add3
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 09:59:29 2026 +0530

    docs(plan): timeline ledger P9 (autocomplete via LibKa0s v1.70.0, smoother lines, type+subtype grouping, test-mode tooltips; BankLedger)

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 67a40cafef4af8ed4d61f71bd00a6481810f4c4e
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 01:23:49 2026 +0530

    fix: Phase 8 (timeline toggles, strip tooltips, test-mode default item, label case) final-review fixes

    - TM-1 smoke: qualify the Everlight Crystal default (a saved pick the sample holds is kept).
    - Timeline: clear a parked strip bar's flow through ReleaseAll's per-item hook instead of walking
      the pool's private free list; the ledger-off path now clears it too.
    - test_timelinetab: rewrap the header comment to the file's comment width.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit ca946d9c506672a1d4e04fac0a1cff881ae62a79
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 01:19:23 2026 +0530

    fix(labels): Title Case for holder-move reasons

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 436fd2ae55b6171be72b264af6d4bbe2916c551d
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 01:17:00 2026 +0530

    feat(testmode): Timeline opens on a sample item in test mode

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 9c43700d56268a005018da0effbf07f6ad104edd
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 01:12:42 2026 +0530

    feat(timeline): tooltips on the daily gain/loss strip

    Each day's strip column (its pooled bar frame) is a hover region: "<day> · Total"
    with Gained / Lost / Net, signed and colored, gold as coin strings (TM.FlowLines,
    Compat.ShowLinesTooltip). A repaint redraws or drops it; the chart's hover ending
    now hides only a tooltip the chart owns. Smoke TL-15.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 2b89d9bc7cdb69023729ba6bf203f01c4e01d8cf
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 01:04:24 2026 +0530

    fix(task 1): keep the in/out strip drawn with every line hidden

    With every line hidden the chart is cleared and has no plot rect, so the
    strip released its bars and drew nothing, against browser.md, TL-14 and
    spec 8.1 ("the strip never changes"). The strip now takes the same x
    mapping from the chart's published paddings (NS.LineChartChrome) and the
    width Layout last rendered at; the chart still draws no axes.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 5414358dd77ab6c88a776a338f80d1ce9c63f2b1
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 00:57:04 2026 +0530

    feat(timeline): Total-only toggle and click-to-toggle legend

    Each legend entry is now a button that hides or shows its line (hidden
    entries dim in place); a header "Total only" toggle hides every holder
    and restores the previous set when turned off. Only visible lines are
    drawn, hovered and used for the y range; the in/out strip stays the
    Total's. All lines hidden shows an empty-state message and no axes.
    "Total only" persists as savedView.timelineTotalOnly; the per-holder
    hidden set is session-only.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit bebd63e04c0706864accc92ce28dd9900644728a
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 00:48:12 2026 +0530

    docs(plan): timeline ledger P8 (timeline toggles, strip tooltips, test-mode default item, label case)

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 660154d972e8441e09fdca13bef30ab166ebfce2
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 00:45:21 2026 +0530

    fix: Phase 7 (hidden currencies; holder moves become loss + gain) final-review fixes

    - Stats: the IN half of a holder move (Ledger.HOLDER_MOVE_REASON) stays out
      of the gains-only legacy loot breakdowns; it is written by the sender and
      has no OUT to offset it there.
    - Collector: with trackLedger off, a currency ListedCurrencyID cannot place
      keeps the link's id instead of being dropped (no baseline/diff to fall
      back on); the twin remap still applies first.
    - Reconciler: an own-alt mail's OUT carries no pairId (its IN is written in
      another pass); docs say so.
    - Docs: Compat surface rows for ListedCurrencyID / CurrencyListChanged and a
      corrected CurrencyCategory row; midnight-quirks cite; smoke index TR row.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 07e948de6097fc9b1cf8de35c787177adc0d5a26
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 00:31:09 2026 +0530

    feat(history): holder column, warband filter, insights reasons for holder moves

    Timeline ledger Phase 7, Task 3. History's Character column and filter
    read the row's holder (the Warband half of a move reads "Warband" and is
    selectable); Insights colors the five holder-move reasons and keys its
    gains-vs-losses by-character chart on the holder; test mode's History
    sample writes holder moves as OUT + IN pairs (one pairId) that the sample
    rollup tallies per holder. Spec amended (D10), data-flow, schema, browser
    and smoke docs (TR-1..3) updated.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 3449101c09153745d570fbb75d87a0d4f4e131ed
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 00:18:29 2026 +0530

    feat(db): v13 converts inter-holder transfer pairs to loss + gain

    Every stored MOVE whose from and to name different holders becomes an OUT
    on the from-holder's row and an IN on the other, under the action's reason
    (Ledger.HolderMoveReason): a Warband end gives WARBAND_DEPOSIT /
    WARBAND_WITHDRAW; between characters a mail end gives ALT_MAIL, a currency
    CURRENCY_TRANSFER, and anything else ALT_TRADE. A move inside one holder stays
    a MOVE. Converted halves without a pairId get a shared "<ts>:m<n>" (or their
    own when the partner is gone), and every touched (day, holder, thing) has its
    rollup in/out rebuilt from the rows (Ledger.RecomputeFlows); closes and days
    the rollup no longer holds are left alone. Idempotent.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 744e7a6b41226165b627eaefb1dd3efa9abb006e
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 00:10:43 2026 +0530

    fix(task 1): mail gold sent before Phase 7 stays a MOVE when taken

    Track the alt-sent part of escrow.mailMoney in escrow.mailMoneyAlt (credited
    when an alt sends gold). Taking mail money books that part as IN ALT_MAIL and
    the remainder, gold whose sender-side pair v13 converts to OUT + IN, as a
    single-holder MOVE, so the alt's gain is not counted twice.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit c64717cbea39592b9b77150413dcb1bc8196d466
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Wed Oct 7 00:06:03 2026 +0530

    feat(ledger): moves between holders are a loss and a gain with action reasons

    A move between two different holders now writes an OUT on the sender and an
    IN on the receiver instead of a MOVE pair, both under the action's reason and
    one shared pairId. Five SourceType members are appended: WARBAND_DEPOSIT,
    WARBAND_WITHDRAW, ALT_MAIL, ALT_TRADE and CURRENCY_TRANSFER. A move inside
    one holder (bags to bank, a post) is still a single MOVE / TRANSFER row.

    - Warband pairs take WARBAND_DEPOSIT / WARBAND_WITHDRAW by direction.
    - Account currency transfers to an own alt are CURRENCY_TRANSFER; the fee
      beyond what arrived stays OUT TRANSFER.
    - Mail to an own alt is an OUT ALT_MAIL on the sender at send time. The alt's
      IN ALT_MAIL is written when it takes the mail. The new escrow.mailAlt tells
      an alt's mail apart from an auction's return, which stays a MOVE.
    - A trade with an own alt stamps ALT_TRADE on both the loss and gain sides.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 09e6a291280247bb6038d9eaa6bbabbce5642dde
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 23:55:15 2026 +0530

    fix(currency): hidden tracking currencies never record; remap same-name twins

    A chat currency link can name a hidden tracking currency the token list
    never shows ("Nebulous Voidcore": hidden 3513 beside listed 3418), which
    wrote an unclaimed duplicate row plus an OTHER diff row for the real one.
    Compat.ListedCurrencyID keeps a listed or held id, remaps a hidden id to
    its one same-name twin, and otherwise drops the line (reason=unlisted, no
    claim). The CurrencyCategory miss memo now clears when the list changes
    size or on a nil-id CURRENCY_DISPLAY_UPDATE.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit b5d9ced3435e3775593e49e713c9015c2832a496
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 23:46:41 2026 +0530

    docs(plan): timeline ledger P7 (hidden currencies; holder moves become loss + gain)

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 24ccb2c99a71ef66c9b2ac699fd00d9aaa50b6b8
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 23:44:19 2026 +0530

    fix: Phase 6 (test-mode data, holdings group-by, scaling filter bar) final-review fixes

    - HoldingsTab.RowActions: "Forget this character" is disabled while test
      mode's sample holdings are live, so a sample holder sharing a real
      character's key can never delete that character's real data; new test.
    - Browser.lua: correct the filter-bar relayout hook rationale (the library
      already hooks OnSizeChanged; onResize is deliberately unused).
    - BrowserFilterBar.lua: makeBarButton comment describes the scaled
      Clear/Save/Reset geometry instead of a fixed 36px cluster.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 76f1036cc11cc3531b66be0b8af562e7527c1e13
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 23:37:45 2026 +0530

    feat(browser): filter bar fills the window and scales proportionally

    Row 2 (eight dropdowns + Export) now spans the bar exactly: each control's
    measured base width is scaled by one ratio r = available / sum(base),
    floored at 1, with Export taking the rounding remainder, so the right
    margin always equals the left. Row 1 sits on row 2's grid (Group over
    Date, Direction over Bound, Save/Reset/Clear over Export, search between).
    B:LayoutFilterBar re-runs on the window's OnSizeChanged (positions and
    widths only, closes an open menu). B:ExportWidth is retired.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 5c5f768e8d777f04a9f8a0e9edf1015c78c02c6f
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 23:28:10 2026 +0530

    feat(holdings): group-by (quality, type, subtype, character)

    The shared Group dropdown is live on the Holdings tab over its own modes
    (None, Quality, Type, SubType, Character). Holdings keeps a per-tab group
    value (HoldingsTab.groupBy): B:SetGroup routes a pick to the active tab and
    B:SyncGroupControl repaints the dropdown's options and value per tab, so
    History's group is never moved; unsupported modes read as None.

    Headers match History's (chevron, "<Prefix>: <Value> (N)", collapsible,
    collapse remembered for the session). Under Character a thing is listed
    per holder with that holder's count and container split. Sort holds
    within groups; banding counts things down the whole list.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 9b7700cac22d605f54538f98b0e9efbc08f0a772
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 23:18:17 2026 +0530

    feat(testmode): sample holdings and timeline data in test mode

    /lh test now also publishes session-only NS.State.testHoldings and
    NS.State.testDaily (modules/TestData.lua), built deterministically from
    the History sample's universe: four sample characters and the Warband,
    the thirty sample items, three currencies and gold, over 120 days walked
    back from today's holdings with the sample rows' flows folded in.

    Read paths resolve through Holdings:ActiveStore / Holdings:View and
    Rollup:ActiveStore (Rollup:Keys caches the sample's keys apart), as
    Database:ActiveHistory does for rows; every write stays on the live
    stores. Toggling off clears both and the OnDatasetChanged repaint puts
    Holdings and Timeline back on the live data. Smoke row TM-1.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 43c6f5ba09bbe01d33262502b53a0a395a3bbe7e
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 23:08:16 2026 +0530

    docs(plan): timeline ledger P6 (test-mode data, holdings group-by, scaling filter bar)

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 5cf5cf9ceffc7312291b0a7345ddad98262833e2
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 19:10:49 2026 +0530

    fix: Phase 5 tasks 2-3 (Qty width, Gold tooltip, stray chart text) final-review fixes

    Narrow the LED-9 claim to what the headless trace shows: creation-time
    parenting of the Timeline tab and the Insights chart layout is ruled out;
    re-parenting (SetParent/SetScrollChild), the Insights Attach/scroll/card
    chain, GameTooltip and other shared frames are not traced. Same limits in
    docs/testing.md and the tests/region_trace.lua header.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit ad5bae5fd10917ab3a6bf4a2b3384509b324bcf8
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 19:06:18 2026 +0530

    fix(task 3): mark the LED-9 stray-text bug open pending /fstack evidence

    The headless trace ruled out the pane-parenting hypothesis, so no
    production fix was made. Say plainly in LED-9 that the bug is still open,
    no fix has shipped, and the fix waits on the in-game /fstack frame path.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit fa40c44e2cfb46c4a9375b1e31fea49922e6d70d
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 19:02:58 2026 +0530

    test(timeline): LED-9 trace shows chart labels belong to their panes

    The stray faint green "Cou..." text over History and Holdings was suspected
    to be a Timeline (or Insights) region parented outside its pane. A new
    headless tracer (tests/region_trace.lua) records the owner of every frame,
    FontString, Texture and Line a traced build makes and walks them the way
    the client's IsVisible does. The Timeline case builds the tab fresh on a
    traced pane, draws the chart, strip, legend and suggestion list, then
    shows History and Holdings: nothing it made reads visible. The Insights
    case does the same over a full layout with the gains-vs-losses section.

    Both pass on the code as built, so the parenting hypothesis is ruled out
    and no production change is made; a deliberate UIParent-parented legend
    fails the Timeline case. Smoke LED-9 now says so and carries the in-game
    check (Timeline or Insights visit, then History/Holdings, /fstack on any
    stray text).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit a13819b5d539e6b0df03d6561e42d9ed4d0c9336
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 18:50:41 2026 +0530

    feat(history): wider Qty for gold amounts; BankLedger-style Gold tooltip

    The Qty column is measured at the row font against the widest signed gold
    string the cell can show (the gold cap, either sign, through the column's own
    valueFn); 34px stays the floor, so a headless font keeps it. Browser measures
    before it takes the window floor. Gold rows hover BankLedger's tooltip via a
    new presence-gated Compat.ShowAmountTooltip; row leave goes through
    Compat.HideTooltip. Smoke LED-12.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 1f80730d2deea72ab73ee7208336892e0ff4adab
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 18:39:59 2026 +0530

    feat(history): Direction column with glyph and colored label (BankLedger style)

    The History Direction column is now a labeled, 86px left-aligned column: a
    mono-face glyph FontString (row.dirGlyph) followed by the Gain/Loss/Transfer
    label in the row font, both colored from LedgerFormat.Color. The new
    BrowserTable:PaintCell sets glyph text, color and shown-state on every bind
    (pooled rows); other columns and group headers hide the glyph. Window floor
    is column-derived and moves 1246 -> 1314. Smoke LED-10 formatting fixed and
    LED-11 added.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 8fa25c2cb4a16eb8565894071f272623b405a0ae
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 18:36:52 2026 +0530

    docs(plan): P5 tasks 2-3 (Qty width, Gold tooltip, stray chart text)

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit b87f6dacd81f2d8aa06197844fe7f9c806c48d8c
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 18:35:45 2026 +0530

    docs(plan): timeline ledger P5 Direction column

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit a56688c8cd9f08f21316c8173e40c332419398e6
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 18:31:48 2026 +0530

    fix: Phase 4 (polish from first in-game review) final-review fixes

    - Reconciler driftPass restores the forceReason it found instead of clearing
      it, so a combat login deferred to the regen edge with a banker open keeps
      its bags/money/currency drift UNTRACKED (new test pins it).
    - core/Database.lua and docs/schema.md: the v11->v12 step only drops an
      explicit false that reached the raw profile outside AceDB; the default
      flip itself is defaults/Profile.lua's.
    - docs/smoke-tests.md: HIST-35 (one-line filter bar, equal Direction/Bound
      widths, measured minimum width, Export and cluster >= 120 px) and LED-10
      (bank and warband-tab drift from outside the addon, with the ~0.35 s
      debounce caveat).

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit d9e4e810d7eadd999c03c2445afcc38d5f3103bd
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 18:24:22 2026 +0530

    fix(task 4): the bank drift pass leaves the currency accumulators alone

    The drift pass sets the currency delta aside, but the currency commit step
    still ran in it and wiped pendingCur, curGain, curLoss and pendingTransfer.
    The normal pass that followed then saw currencyDelta dirty with nothing to
    fold: the change was never applied or written (it came back UNTRACKED at the
    next login), and a pending account transfer lost its MOVE pair and the alt's
    credit. The commit step now returns before clearing when the pass is a drift
    pass. New test: a currency spend and an account transfer pending when the
    banker opens are still written with their mapped reasons.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 4acec4a3993c7b4943c336075d747a11932f8988
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 18:20:26 2026 +0530

    feat(ledger): bank and warband-tab drift on a visit's first read is UNTRACKED

    The bank and warband tabs are only readable at a banker, so changes made there
    while the addon was not watching (disabled, or another PC) used to land on the
    next visit as held, paired gain/loss rows with a guessed reason. Opening a
    Banker/AccountBanker now makes the visit's first flush a drift pass over bank,
    tabs and warbandMoney alone: UNTRACKED, no hold, no pairing, no claims. Other
    dirty parts keep normal classification; later flushes of the visit are normal.
    Documents the cross-PC limitation in data-flow.md and ARCHITECTURE.md.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit f98de580d982ac1a59734f9e26ac1885deabf01f
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 18:14:41 2026 +0530

    feat(settings): Show transfers on by default, migrated profiles included (v12)

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 23a381aad91c7cfa5e0a2e0a2088af308bb9d2a9
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 18:11:00 2026 +0530

    fix(task 2): add smoke LED-9 for the Holdings header row and the Cou… overlap

    The leaking green "Cou…" FontString could not be named from the code, so
    the requirement is recorded as an open in-game check with an /fstack step
    that names the frame. LED-9 also covers the P4 columns, column hiding,
    per-thing banding, hover tooltips and header sorting.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 1ddc20dd9a4ae9acfbfa317e7a081c915e1255c4
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 18:05:02 2026 +0530

    feat(holdings): metadata columns, per-thing banding, tooltips, sortable header

    The Holdings tab gains iLvl, Quality, Type, SubType and AH Price columns
    (History's widths; optional columns drop right to left on a narrow pane,
    Name/Total/Value always stay), every header cell sorts with History's
    arrow and toggle rule, rows band per thing with expanded holder lines on
    the parent's stripe, and hovering a thing shows its item, currency or
    gold tooltip. New presence-gated Compat shims: GearItemLevel and the
    Show*Tooltip/HideTooltip family. The header is now its own frame holding
    exactly one cell per column.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 65243fd22f6a4c656cd4dc3eb29b57db14da66c6
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 17:50:43 2026 +0530

    fix(browser): one-line filter controls, equal Direction/Bound widths, larger minimum window

    Each filter dropdown is now as wide as the widest static label it can show
    ("Direction: 3 selected", "Quality: Uncommon+", every bound state and source,
    the "N selected" summaries), measured with its own label FontString at build
    time, never narrower than its shipped width; labels are pinned to one
    non-wrapping line. Direction and Bound share the larger width and Group stays
    paired with Date. The toolbar floor (B:ToolbarSpan) follows the measured
    widths; EnsureFrame re-takes B:MinWidth() after the bar is built so the resize
    grip and RestoreWindow clamp to it, widening an older, smaller saved size.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 3b59e3c395fec628d207fa2843d144f7dde2ace5
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 17:44:17 2026 +0530

    refactor(browser): move the filter bar to modules/BrowserFilterBar.lua

    modules/Browser.lua sat at 1497 of the 1500-line layout cap. B:BuildFilterBar,
    the static option sets it seeds (Group, Date, Direction) and the flat-skin bar
    button move verbatim to modules/BrowserFilterBar.lua, which loads directly
    after Browser.lua and binds the window's helpers through B._ fields
    (B._applyFilter and B._currentKey newly published). No behavior change.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 853e1afb983271030f67279b5bccc85023ae9487
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 17:39:36 2026 +0530

    docs(plan): timeline ledger P4 polish from first in-game review

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit f69b7788489fac9b3cc412dcc8ccfa2f49e26f49
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 15:06:37 2026 +0530

    fix: Phase 3 final-review fixes

    - TimelineModel: TotalSeries keeps an intraday step vertical. Where any holder series steps at x
      (two points at one x), the Total emits the left-limit sum (new TM.ValueBefore) before the
      post-step sum, so it overlays the holder lines on Today / 7d instead of cutting a diagonal.
    - Browser: the Character dropdown switches its option source between holders (Holdings,
      Timeline) and history rows (History, Insights). On a source switch, RefreshFilterOptions now
      drops picks the new list lacks through B:PruneCharSet -> SetCharSet (the logged-in character
      is always kept), so a Warband pick carried to History no longer filters every row out.
    - Timeline: TL:Refresh calls chart:ClearHover() before SetData. The chart re-fires onHover only
      on an index change, so a coalesced repaint under a resting cursor kept the old model's tooltip
      and crosshair; the armed OnUpdate now re-hovers against the new data on the next frame.
    - Tests: a duplicate-x TotalSeries case, a Holdings->History warband case, a repaint-drops-hover
      case; each red without its fix. docs/test-cases.md regenerated; browser.md and the
      ARCHITECTURE largest-file line (Browser.lua 1497) updated.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 7462f5f2fd154164dde6ab2c5ee6144ed4b750d6
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 14:48:30 2026 +0530

    docs: timeline ledger phase 3 - Timeline tab, daily rollup, filter graying, smokes TL-1..13

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 816ee2d3baa72e456bd8f9fe3ec48c9358a07604
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 14:31:53 2026 +0530

    feat(timeline): Show in Timeline from History and Holdings rows; Forget this character

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 44dcf5590836aa7ff652f5b4fcb6009e0f247eaa
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 14:25:28 2026 +0530

    feat(timeline): Timeline tab - LibKa0s line chart, thing picker, in/out strip, legend, hover; timelineMaxLines

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 14c39bb322756a6525816877cb46ab130e490f00
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 14:17:10 2026 +0530

    feat(browser): per-tab filter graying, 90d/1y ranges, holders Character list, remembered view field

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 1e73e498a86e62efc187d516b9186098f62411f8
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 14:11:33 2026 +0530

    feat(timeline): pure Timeline model - carry-forward, ranking, cap, intraday, flows, hover

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 92119a62f6340ee338b6ecab291c2a9e73594459
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 14:06:42 2026 +0530

    feat(rollup): rollupRetentionDays (account-wide, default Always), login prune and one-time seed

    Rollup:SeedOnce writes today's close for every held thing once per account
    (db.global.rollupSeeded), never over a close already written today;
    Rollup:Prune applies db.global.rollupRetentionDays (0 = Always) through
    Ledger.PruneDaily. Both run from the 5 s login deferral while the rollup hook
    is up. New schema row settings.rollupRetentionDays (General > History,
    global-stored, RESET_EXEMPT). History now holds three rows, so the by-name
    two-controls exemption is dropped; row-count docs move to twenty-one and
    debug.md gains the [Rollup] coverage row.

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

commit 98aee5bbd3fa77f7f9c712c35acdc74946118d49
Author: Tushar Saxena <tushar.saxena@gmail.com>
Date:   Tue Oct 6 14:00:20 2026 +0530

    feat(rollup): daily rollup writer - closes from Holdings, in/out from the Database write hook

    Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01L4XiFWzQrd9ee19aBpkVmt

This mod has no additional files