# Agent Working Guide Start with [AGENTS.md](../AGENTS.md) for project rules. Paths and PowerShell commands below are relative to the repository root unless stated otherwise. Read only the sections relevant to the task. ## Architecture and Entry Points LumiTracker tracks Genshin Impact TCG gameplay using screen capture and image recognition. The main WPF application manages decks, match history, overlays, settings, and updates. The OB application receives game events for observer display. The runtime flow is: ```text Game window -> Python capture -> FrameManager -> states/tasks -> JSON events -> C# PythonBackend/ProcessWatcher -> GameWatcher -> WPF view models -> OB client/server ``` `App.xaml.cs` registers the main app's services and view models. `Models/GameWatcher.cs` manages the watcher lifecycle. `LumiTracker.Watcher/Backend.cs` launches bundled Python with `-m watcher.window_watcher`: Python emits structured JSON through stderr, while C# sends commands through a loopback TCP socket. `GameEventHook.cs` dispatches recognized events. Keep event names and payloads compatible across both languages. | Task | Start with | | --- | --- | | UI or navigation | `src/LumiTracker/Views/`, `ViewModels/`, `Controls/`, and `App.xaml.cs` | | Deck import, tracking, history | `src/LumiTracker/Models/DeckUtils.cs`, `DeckData.cs`, `CardList.cs`, and `ViewModels/Pages/DeckViewModel.cs` | | Game detection or backend lifecycle | `src/LumiTracker/Models/GameWatcher.cs`; `src/LumiTracker.Watcher/ProcessWatcher.cs`, `Backend.cs` | | Recognition or capture | `src/LumiTracker.Watcher/watcher/window_watcher.py`, `capture/`, `frame_manager.py`, `states/`, `tasks/`, `feature.py` | | Recognition regions | `src/LumiTracker.Watcher/watcher/regions.py`, `src/LumiTracker.Config/Regions.cs`, `assets/regions.json` | | Events shared across languages | `src/LumiTracker.Watcher/GameEventHook.cs`, `src/LumiTracker.Config/Enums.cs`, `src/LumiTracker.Watcher/watcher/enums.py` | | Configuration or localization | `src/LumiTracker.Config/Configuration.cs`, `Localization.cs`, `Lang*.resx`; `assets/config.json`, `assets/obconfig.json` | | Observer connections | `src/LumiTracker/Services/OBClientService.cs`; `src/LumiTracker.OB/Services/OBServerService.cs`, `Models/OBGameWatcherProxy.cs` | | Card data and generated enums | [Card-update workflow](scripts/README.md); `src/LumiTracker.Watcher/watcher/database.py` | | Updates, launcher, release | [Release pipeline and current boundaries](release.md); `src/LumiTracker/Services/UpdateService.cs`, `src/LumiTracker.Launcher/`, `Directory.Build.props`, `dev_assets/` | ## Fresh-Clone Setup Clone [LumiTracker](https://github.com/LumiOwO/LumiTracker) into a local Windows directory. Prefer a path without spaces because several existing build hooks contain unquoted paths. All commands below run from that checkout's root unless explicitly stated otherwise; no maintainer-local files are assumed. | Goal | Setup needed | | --- | --- | | Edit source and compile | Steps 1 and 5; tracked database/indexes and generated enums can be used as-is | | Run/debug the frontend and existing tracker | Steps 1-3 and 5; private card inputs and the root junction are not needed for this path | | Run Python modules from the repository root | Steps 2 and 4, plus the inputs required by the chosen module | | Rebuild ANN indexes or update/test feature extraction | Contact the author for source data, then follow the relevant setup and card workflow | | Maintain cards or package releases | Relevant runtime setup plus optional tooling below; see the card/release guides | ### 1. Install Build Tools Use 64-bit Windows 10/11, the .NET 8 SDK, and Visual Studio 2022 or its Build Tools with .NET desktop/WPF and Desktop development with C++ components, the MSVC v143 toolset, and a Windows SDK compatible with the target. Projects target `net8.0-windows10.0.17763.0`. The .NET runtime alone is insufficient for compilation. The main app references the native `LumiTracker.Launcher.vcxproj`, so use Visual Studio MSBuild rather than assuming `dotnet build` alone can build the solution. NuGet dependencies are declared in the project files and restored during step 5. In Visual Studio Developer PowerShell, change to the repository root and check: ```powershell dotnet --list-sdks Get-Command msbuild ``` Expect an 8.x SDK and an MSBuild executable from VS 2022. The IDE window need not be open. If MSBuild is missing from an ordinary shell, use Developer PowerShell or the installed VS 2022 executable directly. ### 2. Initialize the Bundled Python Runtime The clone includes `python/python.exe`, the Python 3.9 standard library, and the two local wheels referenced by [requirements.txt](../requirements.txt). Installed packages under `python/Lib` are absent. This requirements file covers the backend runtime, not all development/maintenance tools; its wheels require Windows x64/Python 3.9. From the repository root, use the existing setup script: ```powershell & '.\dev_assets\[1] setup.bat' ``` It first removes `python/Scripts`, `python/Lib` and `python/images`, then bootstraps pip and installs the runtime requirements with `--no-deps`. It is suitable for initialization, but rerunning it resets an existing bundled environment, including extra packages. It pauses for input before exiting. Read its output and verify imports afterward: ```powershell .\python\python.exe --version .\python\python.exe -E -B -c "import cv2, numpy, annoy, windows_capture, win32api, overrides" .\python\python.exe -E -B -m pip check ``` Expect Python 3.9 and successful imports. Investigate dependency errors rather than assuming a completed batch file proves the environment is complete. Initial installation normally requires internet access. The checked-in `python/pip.ini` selects the Tsinghua PyPI mirror; if downloads fail, inspect pip's active configuration and that mirror's reachability. The bootstrap also clears Python environment variables in its local batch environment. ### 3. Obtain Runtime Images The `cards/` source dataset is not public for now; it may be made public in the future. For frontend development/testing, download the latest full release package from [GitHub Releases](https://github.com/LumiOwO/LumiTracker/releases), extract it, and copy its runtime images into the corresponding repository directory: ```text Extracted release: LumiTrackerApp-/assets/images/ Repository: assets/images/ ``` Preserve the contents and layout, including `avatars/`, `snapshots/`, `costs/` and `empty.png`. For agent work, place downloaded/extracted temporary files under `agent/temp/`. The destination `assets/images/` is an ignored runtime directory, not a new tracked source directory. Check the copied layout: ```powershell Get-ChildItem .\assets\images Test-Path .\assets\images\empty.png ``` Use the corresponding release source tag when a matching code/resource baseline is needed. Newer development code may refer to cards absent from an older package. The clone already includes `assets/database/` and generated enums; frontend testing does not require regenerating them or copying release configuration over source configuration. For rebuilding ANN indexes or updating/testing feature-extraction algorithms, contact the author through the [project repository](https://github.com/LumiOwO/LumiTracker) for the necessary source data. Runtime images from a release are not a replacement for the complete `cards/` inputs. Access to the maintainer's dataset checkout is separate from cloning this public repository. ### 4. Create the Root Junction Only If Needed Root `watcher/` is an ignored local helper and is absent from a fresh clone. The bundled interpreter's `python39._pth` includes the repository/output root, so the documented root-level `-m watcher...` commands need this link to the tracked source. Compilation and normal app startup use separate output-directory junctions created by build hooks. From the repository root, inspect any existing path first. If none exists, create the helper: ```powershell Get-Item -LiteralPath .\watcher -Force -ErrorAction SilentlyContinue | Format-List FullName,LinkType,Target if (-not (Get-Item -LiteralPath .\watcher -Force -ErrorAction SilentlyContinue)) { New-Item -ItemType Junction -Path .\watcher -Target (Resolve-Path .\src\LumiTracker.Watcher\watcher).Path } .\python\python.exe -E -B -c "import watcher; print(watcher.__file__)" ``` Expect the imported package to resolve through the junction to `src/LumiTracker.Watcher/watcher/`. Do not replace an existing directory or broken link blindly. The junction does not install packages or supply card data. Python configuration reads `assets/config.json` relative to the working directory. Launching `window_watcher` directly also requires live initialization parameters; use the app for normal capture testing. ### 5. Restore, Build and Run From the repository root in Developer PowerShell: ```powershell msbuild .\LumiTracker.sln /restore /m /p:Configuration=Debug /p:Platform=x64 ``` This restores NuGet packages and builds all projects. Use `Release` when release behavior matters. Building the solution supplies `SolutionDir`, which shared properties and custom hooks require. `Directory.Build.props` determines the output at `bin/x64/Debug/LumiTrackerApp-/`; a nonempty `BetaNumber` adds a beta suffix. Check the versioned output for `LumiTrackerApp.exe`, `LumiTrackerOB.exe`, and the `assets`, `python` and `watcher` junctions. The launcher hook also creates the parent `LumiTracker.ini` and launcher files. These are generated during the build, not inputs to copy from the maintainer's machine. Changing files through output junctions changes their targets. After steps 2-3, run `LumiTrackerApp.exe` or `LumiTrackerOB.exe` from that output directory. Alternatively, open `LumiTracker.sln` in Visual Studio and select the desired startup project with Debug/x64. Live recognition requires a supported game/client window. User configuration, deck builds and logs are created under the Windows Documents special folder's `LumiTracker` directory; see `Configuration.cs`. The error log is `log/error.log`. ### Without Internet Building/publishing offline requires installed tools, restored packages valid for the selected configuration, and the runtime/assets needed for that operation. With a valid restore, omit `/restore` from the build command. Local card generation and packaging can also use local inputs; API fetching, missing dependency downloads and upload require network access. See [release verification limits](release.md#internet-and-verification-limits): this guide has not been validated by a complete clean-machine installation/build/publish run. ## Optional Maintenance and Test Tools [requirements.txt](../requirements.txt) covers the bundled backend, not the whole development environment. Install only the extra tools needed for the task. A standard Python 3 installation providing the `python` command can create a separate tooling environment; do not assume the embedded interpreter includes `venv`. From the repository root, create and activate a tooling environment under the allowed temporary directory: ```powershell python -m venv .\agent\temp\tools .\agent\temp\tools\Scripts\Activate.ps1 python -c "import sys; print(sys.executable)" ``` Expect the executable under `agent/temp/tools/`. If shell policy prevents activation, invoke that environment's `Scripts/python.exe` explicitly wherever tooling examples use `python`. Commands using `./python/python.exe` still target the bundled runtime regardless of activation. | Task | Additional dependencies / verification imports | | --- | --- | | Card fetch/update | `tqdm`, `Pillow`; import `tqdm` and `PIL.Image` | | Release packaging | `py7zr`, `sortedcontainers`, `tqdm`; full installer creation also needs Inno Setup | | Private spreadsheet generation | `pandas`, `xlwings`, an XLSX engine such as `openpyxl`; the fallback repair path needs installed Excel | | Interactive recognition scripts | Runtime dependencies plus `matplotlib` in the interpreter running the harness, and suitable local captures/source data | Run only the relevant install/import pair in the tooling environment: ```powershell # Card maintenance python -m pip install tqdm Pillow python -B -c "import tqdm; from PIL import Image" # Packaging python -m pip install py7zr sortedcontainers tqdm python -B -c "import py7zr, sortedcontainers, tqdm" # Spreadsheet generation, after obtaining the source dataset python -m pip install pandas xlwings openpyxl python -B -c "import pandas, xlwings, openpyxl" ``` These tools have no repository-wide version lock; the commands describe required packages, not a tested compatibility matrix. Preserve the pinned backend requirements when adding plotting dependencies to a recognition environment. Existing image scripts also need compatibility review and local fixtures. See [card maintenance](scripts/README.md) and [packaging](release.md#packaging-contract) for inputs and operations; check the configured Inno Setup path on your machine before packaging. ## Source and Generated Files | Input or owner | Output / editing rule | | --- | --- | | `src/LumiTracker.Watcher/watcher/` | Canonical Python source; root/output `watcher/` paths are junctions | | `cards/` | Not public for now; it may be made public in the future. The maintainer's dataset is a separate nested Git repository, ignored by the parent and not a registered submodule. Review its changes independently when available | | `cards/generate.py` and its spreadsheet | Rewrites `cards/generated/*.csv`; this is the spreadsheet workflow, distinct from the agent CSV-update workflow | | `agent/scripts/update_cards_db.py` | Updates card CSVs and copies art into `cards/`; does not rebuild runtime recognition data | | `watcher.database` | Reads card CSVs/images; writes `assets/database/db.json`, `.ann` indexes, `Enums.gen.cs`, `_enums_gen.py`, and `assets/config.json`; `image` also exports runtime images | | `src/LumiTracker.Config/Lang.resx` | Base localization resources; Visual Studio's `PublicResXFileCodeGenerator` produces `Lang.Designer.cs` | | `Lang.zh-HANS.resx`, `Lang.ja-JP.resx` | Translated resources; maintain corresponding keys when changing UI text | | `Directory.Build.props`, publish profile, `dev_assets/` | Version/build/package configuration; `bin/` and `publish/` contain generated output | ### Private and Local Dependencies | Location | Classification and availability | | --- | --- | | `cards/` | Source dataset and tooling, not public for now and possibly public in the future; contact the author for the required inputs. A public clone does not include it | | `assets/images/` | Ignored generated runtime images; included in release distributions | | Installed packages under `python/` | Local runtime dependencies; the bundled interpreter is tracked, while installed package directories are generally ignored and included in distributions | | `bin/`, `publish/` | Generated build and release output | | `agent/temp/` | Ignored temporary agent work | Ignored does not mean private. Keep private repository addresses, credentials, and access instructions in private documentation; public guidance records roles and prerequisites only. Parent Git status does not track the private card changes or ignored generated images. Keep temporary scripts, captures, and logs for agent work under `agent/temp/`. Some legacy debug paths still reference root `temp/`; inspect and redirect those paths for new agent work rather than copying that convention. ## Validation by Change Type ### Culture-Safe Numeric Parsing Use `CultureInfo.InvariantCulture` for numeric strings in XAML, version identifiers, and update metadata. Use an explicit `CultureInfo.CurrentCulture` for localized user input. Do not change thread cultures or enable invariant globalization to fix internal parsing; UI language selection and regional formatting remain separate. The C# projects share a build-only `Microsoft.CodeAnalysis.BannedApiAnalyzers` dependency through `Directory.Build.props`. `src/BannedSymbols.txt` lists numeric `Parse`/`TryParse` overloads without a culture provider; `src/.editorconfig` makes their use a build error (`RS0030`). Choose a provider-taking overload rather than suppressing the diagnostic. Provider-taking APIs must also receive an explicit, non-null provider, including APIs with optional provider arguments. Enum, GUID, and JSON parsers are outside this rule. When upgrading the target framework, review new numeric overloads against the list. For parsing changes, exercise at least English, French, Russian, and German cultures, including mismatched UI and numeric cultures. For layout converters, check invalid parameters, finite results, initial zero dimensions, and the affected main/observer controls after resizing. ### Checks by Area There is no tracked C# test project or CI workflow. `watcher/test/` contains interactive image-debugging scripts, not a general automated test suite. Choose checks that exercise the changed behavior and report any missing prerequisites. | Change | Useful validation | | --- | --- | | Documentation | Check linked paths, commands against their implementation, and `git diff --check` | | C#/XAML | Build Debug/x64; open the affected page/dialog and exercise the changed interaction | | Localization | Check resource keys across the three `.resx` files; regenerate the designer if needed, build, and inspect the affected UI languages | | Python recognition | Parse changed Python files, then exercise representative captures or a live game; inspect emitted events and tracking UI | | C#/Python event contract | Build and run the producer/consumer path; verify event name, fields, and resulting UI state, including OB if affected | | Card data | Follow the script guide; inspect both repositories, mappings, generated enums, and recognition/import behavior | | Launcher or packaging | Build the relevant configuration; validate staged launch/update behavior when release work is in scope | For a Python syntax-only check that does not import application modules or create bytecode, replace the path below with the changed file: ```powershell .\python\python.exe -E -B -c "import ast, pathlib; p = pathlib.Path('src/LumiTracker.Watcher/watcher/frame_manager.py'); ast.parse(p.read_text(encoding='utf-8-sig'), filename=str(p))" ``` The existing image scripts require local captures and `matplotlib`, which is not in runtime `requirements.txt`. Several also use old constructor calls or hardcoded paths; inspect compatibility before using one. Syntax checks alone do not verify recognition accuracy. Card-pipeline edge cases are described in [the testing spec](openspec/specs/testing/spec.md). Its version-specific examples and `.bak` fixtures are historical: adapt them to isolated data under `agent/temp/`, not the live card database. Publishing invokes additional copy/reset hooks and publishes OB. Packaging uses system Python plus `py7zr`, `sortedcontainers`, and `tqdm`; inspect `dev_assets/package.py` for its local Inno Setup compiler path. These operations are separate from a normal build and are not routine smoke tests. ## Keeping Guidance Small Keep mandatory rules in `AGENTS.md`, navigation/build guidance here, card commands in `scripts/README.md`, and release state in `release.md`. Update the relevant section when an entry point or command changes instead of adding a parallel guide. Consult existing specs under `agent/openspec/specs/` for the relevant behavior; create or manage OpenSpec artifacts only under `agent/openspec/`.