Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions .github/workflows/build-loremaster.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ jobs:
- name: Install UI validation tooling
run: python -m pip install --disable-pip-version-check pillow tzdata==2026.3

- name: Verify update manifest builder
run: python tools/build_spinui_update_manifest.py --self-test

- name: Run release quality gate
run: python tools/release_quality_gate.py

Expand All @@ -123,11 +126,23 @@ jobs:
Copy-Item -Force installer/INSTALL-MANUAL.md (Join-Path $uiPackage 'INSTALL.md')
Compress-Archive -Path "$uiPackage/*" -DestinationPath package/SpinUI-UI.zip -CompressionLevel Optimal

$tag = '${{ github.event.release.tag_name || inputs.release_tag }}'.Trim()
$version = $tag -replace '^v', ''
if ($version -notmatch '^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$') {
$version = (Get-Content loremaster-desktop/package.json -Raw | ConvertFrom-Json).version
}
python tools/build_spinui_update_manifest.py `
--archive package/SpinUI-UI.zip `
--version $version `
--output package/SpinUI-Update.json

- name: Upload UI test package
uses: actions/upload-artifact@v6
with:
name: SpinUI-UI
path: package/SpinUI-UI.zip
path: |
package/SpinUI-UI.zip
package/SpinUI-Update.json
if-no-files-found: error

build-loremaster:
Expand Down Expand Up @@ -165,6 +180,9 @@ jobs:
pnpm test:fixtures
pnpm build
pnpm test:gear
pnpm test:items
pnpm test:updates
pnpm test:skin-updates

- name: Run release quality gate
run: python tools/release_quality_gate.py
Expand Down Expand Up @@ -255,7 +273,9 @@ jobs:
run: |
$manualPackage = Join-Path $PWD 'package/SpinUI-Manual'
New-Item -ItemType Directory -Force -Path $manualPackage | Out-Null
Expand-Archive -LiteralPath package/ui-component/SpinUI-UI.zip -DestinationPath $manualPackage -Force
Copy-Item -Force package/ui-component/SpinUI-UI.zip package/SpinUI-UI.zip
Copy-Item -Force package/ui-component/SpinUI-Update.json package/SpinUI-Update.json
Expand-Archive -LiteralPath package/SpinUI-UI.zip -DestinationPath $manualPackage -Force
New-Item -ItemType Directory -Force -Path dist-electron-release | Out-Null
Copy-Item -Force package/loremaster-component/Loremaster.exe dist-electron-release/Loremaster.exe
Copy-Item -Force dist-electron-release/Loremaster.exe $manualPackage
Expand All @@ -278,6 +298,8 @@ jobs:
# exact CI-built file when an antivirus heuristic questions it.
$lines = foreach ($file in @(
'package/SpinUI-Manual.zip',
'package/SpinUI-UI.zip',
'package/SpinUI-Update.json',
'dist-electron-release/Loremaster.exe')) {
$hash = (Get-FileHash -Algorithm SHA256 $file).Hash.ToLower()
"$hash $(Split-Path -Leaf $file)"
Expand All @@ -299,6 +321,8 @@ jobs:
name: SpinUI-Windows-tools
path: |
dist-electron-release/Loremaster.exe
package/SpinUI-UI.zip
package/SpinUI-Update.json
package/SHA256SUMS.txt
if-no-files-found: error

Expand All @@ -312,6 +336,8 @@ jobs:
if (-not $tag) { throw 'release_tag cannot be empty' }
$assets = @(
'package/SpinUI-Manual.zip',
'package/SpinUI-UI.zip',
'package/SpinUI-Update.json',
'package/SHA256SUMS.txt',
'dist-electron-release/Loremaster.exe'
)
Expand All @@ -332,6 +358,8 @@ jobs:
run: >
gh release upload "${{ github.event.release.tag_name }}"
package/SpinUI-Manual.zip
package/SpinUI-UI.zip
package/SpinUI-Update.json
package/SHA256SUMS.txt
dist-electron-release/Loremaster.exe
--clobber
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ Loremaster turns the text log EverQuest already writes into a live **Adventurer'
| Capability | What Loremaster does |
|---|---|
| **Encounter Lab** | Encounter, Session, and Records views with multi-enemy pulls plus actor, ability, healing, target, and a timeline grouped into two-second buckets. |
| **Durable Combat Archive** | Preserves encounter totals, duration, kills, zone, and raid context across restarts, while clearly labeling older summary-only records instead of fabricating actor or timeline detail. |
| **Automatic raid context** | Reads the logged Solo/Group instance suffix and D0–D4 label, then attaches exact zone, tier, mode, timestamp, and kill evidence to the weekly clear. Manual confirmation remains only for genuinely unknown tiers. |
| **Spoils Chronicle** | Stores and searches observed loot across restarts, including stacks, storage, currency, auto-sales, merges, and ranked upgrades; filters by item, source, zone, owner, and raid tier. |
| **Item intelligence** | Shows optional cached EQL Wiki stats, drops, quests, and notes beside the original loot evidence. Network lookup can be disabled without losing the local ledger or cached cards. |
| **Adventure ledger** | XP/hour, time to level, kills, loot, all ten mote grades, coin and plat/hour, factions, skills, zones, and a bounded death recap. |
| **Pets and charms** | Credits summoned pets and conservatively claimed charmed creatures; same-name charm totals are included but clearly labeled as estimates when the text log cannot distinguish actor IDs. |
| **Optional DPS attribution** | Keeps total personal DPS unchanged while optionally exposing separate Self, Charmed pet, and Summoned pet damage/DPS rows for both the current encounter and session. |
Expand All @@ -124,6 +128,7 @@ Loremaster turns the text log EverQuest already writes into a live **Adventurer'
| **Alerts** | Opt-in banners and sound for tells, summons, deaths, charm breaks, big hits, name calls, and fight completion. Compact banners stay beside the Rune Seed with edge-safe Auto, Right, Left, Above, and Below placement choices. |
| **Character continuity** | Follows standard `eqlog_*.txt` activity and supports manual log-folder selection. Packaged builds store selected records and settings under `%LOCALAPPDATA%\SpinsLoremaster`; source runs keep state beside `loremaster.py`. |
| **Two native themes** | Vellum & Ember and Midnight Frost Glass are selectable in Settings so Loremaster can visually belong to either SpinUI skin. |
| **One-click verified updates** | The Settings Update Center shows the installed Loremaster version, verifies new portable builds before a rollback-safe restart, and can check, install, or repair Reloaded and Glass independently without touching EQ logs, character layouts, other skins, or the durable combat and loot journal. |

### Charm intelligence that respects the log

Expand Down Expand Up @@ -382,11 +387,20 @@ Its first **BiS Gear Path** milestone imports the version-1 JSON produced by [EQ
cd loremaster-desktop
pnpm install --frozen-lockfile
pnpm test:fixtures
pnpm test:updates
pnpm test:skin-updates
pnpm build
```

Every UI release builds and publishes the portable Electron `Loremaster.exe` with its hidden parser engine. No installer or parallel legacy executable is produced. See the [live milestone and validation gates](docs/LOREMASTER_MILESTONE_2.md).

Loremaster's **Settings → SpinUI Update Center** can check the official release,
download and verify the portable app, then replace and relaunch it with automatic
rollback if the new renderer or parser does not become healthy. Reloaded and
Glass are verified from the same release and updated as exact, isolated skin
trees only after EverQuest closes. Updates preserve Loremaster preferences and
history, EQ logs, character UI INIs, and every unrelated skin.

## Customizing and developing

<details>
Expand Down
19 changes: 16 additions & 3 deletions docs/LOREMASTER_MILESTONE_2.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@ versioned UTF-8 JSONL and is the portable desktop shipped with UI releases.
- Proven charm-break events crossing the process boundary into a short danger
banner; unrelated fades still remain silent.
- A conservative D0–D4 raid-reset ledger for Master Yael, Phinigel Autropos,
Lord Nagafen, Lady Vox, Innoruuk, and Cazic-Thule. Only local-player or
proven-pet kills count. Difficulty is explicit because the EQ log does not
reliably announce the selected tier.
Lord Nagafen, Lady Vox, Innoruuk, and Cazic-Thule. Evidenced self, pet, and
group participation can count. Difficulty and Solo/Group mode come from the
logged instance-entry line, with an explicit fallback only for unknown tiers.
- A Settings Update Center that displays the running version, checks the
official release, verifies portable and skin downloads, and can update
Loremaster, Reloaded, and Glass independently. App relaunch has automatic
rollback; skin replacement is isolated and blocked while EverQuest runs.
- A single portable Windows test build containing the React application and
its hidden parser engine. No installer target is produced.

Expand All @@ -36,6 +40,11 @@ before the same binary is copied into the manual ZIP and attached to the UI
release. The legacy Python GUI remains source/reference code and is not
published as a competing executable.

The release also publishes `SpinUI-UI.zip`, `SpinUI-Update.json`, and
`SHA256SUMS.txt`. The manifest inventories every file in Reloaded and Glass so
Loremaster can reject partial, stale, modified, or unexpectedly expanded update
payloads before touching an installed skin.

## Weekly tracker boundary

The ledger answers “which D0–D4 raid lockouts were completed this reset?” It
Expand All @@ -52,3 +61,7 @@ manually correctable. Plane of Sky is intentionally outside this weekly ledger.
- The packaged engine passes a real subprocess JSONL handshake.
- The unpacked Electron production application launches its bundled engine and
exits cleanly through the smoke-only shutdown hook.
- Dedicated updater suites cover digest disagreement, download bounds,
traversal/path rejection, portable relaunch rollback, exact skin-tree
verification, EQ-running protection, and preservation of unrelated skins and
character layout INIs.
46 changes: 40 additions & 6 deletions loremaster-desktop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,54 @@ MP3, OGG or M4A file selected through the native file picker. Custom audio is
validated and size-limited by Electron's main process; the sandboxed renderer
never receives general filesystem access.

Weekly D0–D4 progress comes from explicit raid difficulty plus combat-log boss
evidence, with a confirmation prompt when the difficulty is not known and a
manual correction grid. Loremaster deliberately does not scrape EverQuest's
Weekly D0–D4 progress now comes directly from the logged instance-entry line
and the later boss-kill evidence. Loremaster records the exact Solo/Group mode,
difficulty label, zone, timestamp, and evidence with the clear. A confirmation
prompt and manual grid remain as conservative fallbacks when the log truly does
not identify a tier. Loremaster deliberately does not scrape EverQuest's
Instance Information window or reserve a global lockout-screen hotkey.

## Adventure memory and Spoils Chronicle

Completed encounters and observed loot survive restarts in a local SQLite
journal using WAL mode, bounded live snapshots, and paged searches. The combat
Archive clearly distinguishes a durable summary from a current fight: totals,
duration, kills, zone, and raid context persist, while actor or timeline detail
is never invented for older summaries.

The **Spoils Chronicle** recognizes ordinary corpse loot, stacks, auto-sales,
Dragon Hoard/depot and currency storage, inventory placement, item merges, and
automatic ranked-item upgrades. Search and filter the complete local history by
item, source, zone, owner, and D0–D4 context. Selecting an item can show cached
EQL Wiki stats, drops, quests, and notes alongside the original log evidence;
network lookup is optional and can be disabled while cached cards remain usable.
All network parsing runs in Electron's main process, never in the renderer.

Combat actors retain stable, accessible colors across the Seed, HUD, and
Archive. Ability evidence is categorized as melee, spell, DoT, proc, pet,
damage shield, or healing, with unknown evidence kept explicitly unknown.

The Gear Path surface imports EQ Legends Tools' version-1 character-sheet JSON
and EverQuest's `/outputfile inventory` TXT locally. It identifies goal items
already equipped or held in bags/bank and groups missing pieces by source zone.
Item/source metadata is refreshed on explicit user action and cached locally.
Credit: [EQ Legends Tools](https://eqlegendstools.com/) by **FlammHammer**.

Because releases remain portable (no installer), Settings includes a safe
GitHub release check and opens the official release page when an update exists;
the app never silently replaces its running executable.
Because releases remain portable (no installer), Settings includes a complete
SpinUI Update Center. It checks the official release at most once per day,
shows the running Loremaster version, and downloads a newer portable build only
after the user chooses Update. The executable is authenticated against both
GitHub's asset digest and `SHA256SUMS.txt`, staged beside app data, then replaced
by a rollback-capable helper; the new build must report a healthy renderer and
parser start or the previous executable is restored.

The same surface verifies `spinui_reloaded` and `spinui_glass` against the
release's exact file manifest. A skin install is blocked while `eqgame.exe` is
running, staged and verified before replacement, and limited to the selected
`uifiles` child with a rollback copy. Character layout INIs, EQ logs, other
skins, Loremaster settings, and the combat/loot journal are never update
targets. Automatic checks are enabled by default; downloads and installs always
remain explicit.

See [milestone 2](../docs/LOREMASTER_MILESTONE_2.md) for the live scope and
release validation gates.
Loading
Loading