docs(ui): document overlay setup and verification
Describe the compact panel, module boundaries, build and installation steps, read-only limits, and manual acceptance checks. Record user-confirmed in-game readability.
This commit is contained in:
parent
82f2c98e7e
commit
108fd8bf80
1 changed files with 198 additions and 0 deletions
198
ui/JevOverlay/README.md
Normal file
198
ui/JevOverlay/README.md
Normal file
|
|
@ -0,0 +1,198 @@
|
||||||
|
# Jev decision overlay
|
||||||
|
|
||||||
|
A separate, read-only C# mod for Slay the Spire 2. It displays the bot's existing
|
||||||
|
`decisions.jsonl` file inside the game. It does not depend on STS2MCP at runtime.
|
||||||
|
The bot still uses STS2MCP to observe and control the game.
|
||||||
|
|
||||||
|
## UI plan
|
||||||
|
|
||||||
|
The first version uses the compact panel selected during planning:
|
||||||
|
|
||||||
|
```text
|
||||||
|
┌ Jev decisions · read only ───────── [−] ┐
|
||||||
|
│ Read-only log · no new rows for 2s │
|
||||||
|
│ #42 · JEV · combat │
|
||||||
|
│ Session: … │
|
||||||
|
│ Proposed: play_card │
|
||||||
|
│ Parameters: {"card_index": 0} │
|
||||||
|
│ Proposal only; execution not recorded. │
|
||||||
|
│ Reason: … │
|
||||||
|
│ Recorded confidence: 0.81 · 720 ms │
|
||||||
|
│ [Show questions and answers] │
|
||||||
|
├ Recent decisions · select to inspect ──┤
|
||||||
|
│ #42 JEV play_card │
|
||||||
|
│ #41 CODE use_potion │
|
||||||
|
│ #40 FALLBACK end_turn │
|
||||||
|
│ [Follow latest] │
|
||||||
|
└────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
- The panel starts at the top right. F8 or the header button collapses it.
|
||||||
|
- Selecting a history row stops automatic selection of new decisions.
|
||||||
|
- `Follow latest` resumes automatic selection.
|
||||||
|
- The details button shows recorded Jev questions, answers, model, and latency.
|
||||||
|
- Text areas and history scroll independently. Evidence uses plain text, not markup.
|
||||||
|
- Source names remain visible. Blue identifies Jev; amber identifies fallback.
|
||||||
|
- Only the panel receives mouse input. There is no full-screen input blocker.
|
||||||
|
- The panel uses Godot's default font and controls. It needs no asset pack.
|
||||||
|
|
||||||
|
This is a desktop mouse-and-keyboard first version. Dragging, position persistence,
|
||||||
|
controller navigation, filtering, and a remappable shortcut are not included.
|
||||||
|
The panel does not pause the game or bot. Collapse it if it covers a game control.
|
||||||
|
|
||||||
|
## Module boundaries
|
||||||
|
|
||||||
|
```text
|
||||||
|
ui/JevOverlay/
|
||||||
|
Mod.cs mod startup, frame callback, background polling
|
||||||
|
Core/
|
||||||
|
OverlayConfig.cs explicit absolute log path
|
||||||
|
LogTail.cs bounded, incremental JSONL reader
|
||||||
|
DecisionHistory.cs session/step joins and display text
|
||||||
|
UI/
|
||||||
|
OverlayView.cs Godot controls and selection state
|
||||||
|
Tests/
|
||||||
|
Program.cs temporary-file integration checks
|
||||||
|
JevOverlay.csproj game-facing assembly
|
||||||
|
JevOverlay.json game mod manifest
|
||||||
|
```
|
||||||
|
|
||||||
|
`Core/` has no Godot or game dependency. `UI/` has no file access or game API calls.
|
||||||
|
`Mod.cs` connects them. All controls are built-in Godot nodes, so the mod needs no
|
||||||
|
Godot editor project, custom node source generator, Harmony patch, or `.pck` file.
|
||||||
|
|
||||||
|
The game mod belongs under `ui/`, not a web `frontend/` directory. Python policy,
|
||||||
|
the runner, and vendored code remain unchanged.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
Use a .NET 9 SDK. No NuGet packages are needed; `NuGet.Config` clears package feeds.
|
||||||
|
The game assembly paths are explicit. Builds do not install or start anything.
|
||||||
|
|
||||||
|
If `dotnet` is not on your PATH, a temporary Nix shell is sufficient:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nix shell nixpkgs#dotnet-sdk_9
|
||||||
|
```
|
||||||
|
|
||||||
|
A project flake and direnv configuration are not required for this version.
|
||||||
|
|
||||||
|
Run these commands from the repository root. On macOS arm64:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
GAME_DATA="$HOME/Library/Application Support/Steam/steamapps/common/Slay the Spire 2/SlayTheSpire2.app/Contents/Resources/data_sts2_macos_arm64"
|
||||||
|
dotnet build ui/JevOverlay/JevOverlay.csproj -c Release \
|
||||||
|
-p:STS2GameDataDir="$GAME_DATA"
|
||||||
|
```
|
||||||
|
|
||||||
|
On other platforms, set `STS2GameDataDir` to the installed game's directory
|
||||||
|
containing `sts2.dll` and `GodotSharp.dll`. Use assemblies from the target game build.
|
||||||
|
|
||||||
|
Output: `ui/JevOverlay/bin/Release/net9.0/`.
|
||||||
|
Do not distribute game assemblies with the mod.
|
||||||
|
|
||||||
|
## Offline checks
|
||||||
|
|
||||||
|
The integration checks need .NET 9, but no game installation or connection:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
dotnet run --project ui/JevOverlay/Tests/JevOverlay.Tests.csproj -c Release
|
||||||
|
```
|
||||||
|
|
||||||
|
The checks pass temporary files through the actual reader, history, and text formatter.
|
||||||
|
They cover partial writes, UTF-8, malformed rows, session joins, action errors,
|
||||||
|
rotation, truncation, bounded history, large logs, missing files, and recovery.
|
||||||
|
They do not test Godot rendering or game input behavior.
|
||||||
|
|
||||||
|
## Manual installation
|
||||||
|
|
||||||
|
Do this only when you intend to load the mod. Close the game first.
|
||||||
|
|
||||||
|
1. Build against the installed game assemblies.
|
||||||
|
2. Copy `JevOverlay.dll` and `JevOverlay.json` from the output directory into the game's `mods/` directory.
|
||||||
|
3. Copy `JevOverlay.config.example.json` there as `JevOverlay.conf`.
|
||||||
|
4. Set `log_path` to the absolute path of the bot's decision log.
|
||||||
|
5. Restart the game and enable mods if prompted.
|
||||||
|
|
||||||
|
On macOS, the mod directory is:
|
||||||
|
|
||||||
|
```text
|
||||||
|
SlayTheSpire2.app/Contents/MacOS/mods/
|
||||||
|
```
|
||||||
|
|
||||||
|
Example configuration in `JevOverlay.conf` (JSON content, not a mod manifest):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"log_path": "/absolute/path/to/sts2-bot/capture/decisions.jsonl"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not use `~` or environment variables in this value. For Windows JSON paths,
|
||||||
|
use forward slashes or escape backslashes. Custom `run.py --capture-dir` locations
|
||||||
|
need a matching `log_path`.
|
||||||
|
|
||||||
|
The reader waits if the file does not exist. Missing or invalid configuration
|
||||||
|
appears in the panel. Configuration changes require a full game restart.
|
||||||
|
The mod never creates or changes the configured log file.
|
||||||
|
|
||||||
|
To remove the mod, close the game and remove these three installed files.
|
||||||
|
No saves, capture files, or existing mod files need to change.
|
||||||
|
|
||||||
|
## Log meaning and limits
|
||||||
|
|
||||||
|
The viewer consumes the current `run.py` trace format:
|
||||||
|
|
||||||
|
| Event | Display behavior |
|
||||||
|
| --- | --- |
|
||||||
|
| `decide` | Add a proposed action, identified by session and step |
|
||||||
|
| `action_rejected` | Mark that action request as rejected |
|
||||||
|
| `action_error` | Show the request error; completion remains unknown |
|
||||||
|
| `session_end` | Show the session's stop reason, not action completion |
|
||||||
|
| Model/policy failures, `no_decision` | Show a reader notice |
|
||||||
|
| Other events | Ignore without treating them as malformed |
|
||||||
|
|
||||||
|
The log does not record successful action results or a per-decision dry-run flag.
|
||||||
|
The viewer cannot distinguish an unconfirmed live proposal from a dry-run proposal.
|
||||||
|
It never marks a proposal as executed because the next decision arrived.
|
||||||
|
A transport error does not prove that the game failed to execute a request.
|
||||||
|
|
||||||
|
The policy reason is recorded text, not private model reasoning. A `jev` response
|
||||||
|
can accompany a fallback; the `source` field identifies the actual policy path.
|
||||||
|
Recorded answer gates can differ from policy-specific final gates. Confidence is
|
||||||
|
not proof of correctness. No Jev response means only that none was recorded.
|
||||||
|
|
||||||
|
The status reports file activity, not bot or game liveness. Existing history can
|
||||||
|
be displayed when no bot is running. Sessions remain distinct, including when
|
||||||
|
multiple runners append to the file. The latest appended decision is selected
|
||||||
|
when `Follow latest` is enabled; there is no session filter in this version.
|
||||||
|
|
||||||
|
The reader polls every 500 ms on one background worker. It reads at most 256 KiB
|
||||||
|
per poll and starts within the last 256 KiB of an existing log. It keeps at most
|
||||||
|
100 decisions and at most 128 KiB per incomplete line. Oversized or malformed
|
||||||
|
lines are skipped. Display text is limited to 16,000 characters per text area.
|
||||||
|
A displayed decision can leave history while it is selected.
|
||||||
|
|
||||||
|
Truncation and replacement are detected by file length, a prefix, and a checkpoint
|
||||||
|
near the last read offset. A replacement with identical sampled bytes and no
|
||||||
|
length decrease cannot always be distinguished from an append. This viewer is
|
||||||
|
not a durable audit reader. Concurrent writers must still produce complete JSONL
|
||||||
|
rows; the viewer cannot repair interleaved writes.
|
||||||
|
|
||||||
|
## In-game acceptance check — requires explicit approval
|
||||||
|
|
||||||
|
No live game action or model call is needed to validate the panel itself. Point
|
||||||
|
`log_path` at a disposable JSONL file and use synthetic records:
|
||||||
|
|
||||||
|
1. Start the game with the mod installed and check the initial panel.
|
||||||
|
2. Append a `decide` record with a session, step, and action.
|
||||||
|
3. Confirm the panel updates and does not mark the proposal as executed.
|
||||||
|
4. Expand the evidence area and select an older decision.
|
||||||
|
5. Append another record and confirm the older selection remains selected.
|
||||||
|
6. Test F8, collapse, scrolling, resizing, and clicks outside the panel.
|
||||||
|
7. Switch game scenes and confirm there is exactly one panel.
|
||||||
|
8. Remove or truncate the disposable file and confirm reader recovery.
|
||||||
|
|
||||||
|
The user confirmed that the installed panel appears and is readable in-game.
|
||||||
|
Input routing, scene persistence, and the remaining acceptance steps are not yet
|
||||||
|
verified. Building against game assemblies is not a substitute for these checks.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue