chore(skills): add bug-report processing skill

Skill for triaging in-game bug reports from the Godot client's
user://bug-reports/ directory. Reads snapshot, render, inputs,
and description files; presents summaries; offers investigate,
create ticket, or dismiss actions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-21 13:43:36 +01:00
co-authored by Claude Opus 4.6
parent 136d21ac8b
commit e1e9f3479a
+231
View File
@@ -0,0 +1,231 @@
---
name: bug-report
description: >
Process in-game bug reports captured by the Godot client's bug reporter.
Use when the user says "bug reports", "check bug reports", "process bugs",
or invokes /bug-report. Scans the user:// bug-reports directory, summarizes
each report, and offers investigation, ticket creation, or dismissal.
user-invocable: true
allowed-tools: Bash, Read, Grep, Glob, Write
---
# Bug Report Skill
Process in-game bug reports exported by the Godot client to the user data
directory. Each report is a directory containing a snapshot of game state at the
moment the tester filed the report.
```
BUG_REPORT_DIR: /var/home/jeroenschweitzer/.local/share/godot/app_userdata/The Settled Reach/bug-reports/
```
## Report structure
Each report lives in a directory named `gauntlet-t{tick}-{timestamp}/` and
contains these files:
| File | Purpose |
|------|---------|
| `description.txt` | Tester notes + metadata (tick, room, stance, facing, position) |
| `render.txt` | Simplified text render of the game snapshot |
| `snapshot.json` | Full JSON snapshot (entities, dialogue state, etc.) |
| `inputs.jsonl` | Last 60 ticks of player input (replay format) |
| `snapshots.jsonl` | Last 60 ticks of observer snapshots |
| `seed.txt` | RNG seed for deterministic replay |
## Invocation
- `/bug-report` — scan and process all unprocessed reports
- `/bug-report <directory-name>` — process a specific report by directory name
## Workflow
### 1. Scan for unprocessed reports
List all report directories in the bug reports directory:
```bash
ls -1d "/var/home/jeroenschweitzer/.local/share/godot/app_userdata/The Settled Reach/bug-reports/"*/
```
If no directories are found, report "No bug reports found." and stop.
If the user provided a specific directory name as argument, filter to only that
directory. If it does not exist, report the error and list available reports.
### 2. Read and summarize each report
For each report directory, read the following files using the Read tool:
1. **`description.txt`** — extract:
- Tester description / notes (free text at top)
- Tick number
- Room name
- Player stance, facing, position
2. **`render.txt`** — extract:
- A brief description of what the text render shows (room layout, visible
entities, player position marker)
3. **`snapshot.json`** — extract:
- Total entity count
- Whether dialogue is active (look for `dialogue` or `conversation` keys
with non-null/non-empty values)
- Whether monologue is active (look for `monologue` keys with non-null/
non-empty values)
- NPC names and positions if present
- Any error or anomaly fields
4. **`seed.txt`** — note the seed value for reference
Do NOT read `inputs.jsonl` or `snapshots.jsonl` during the summary phase.
These are large files reserved for the investigation step.
### 3. Present the summary list
Present a numbered list of all reports with their summaries. Format:
```
## Bug Reports Found: N
### 1. gauntlet-t{tick}-{timestamp}
- **Tick:** {tick} | **Room:** {room} | **Position:** ({x}, {y})
- **Stance:** {stance} | **Facing:** {facing}
- **Entities:** {count} | **Dialogue active:** yes/no | **Monologue active:** yes/no
- **Seed:** {seed}
- **Description:** {tester notes, first 2-3 lines}
- **Render overview:** {brief description of what render.txt shows}
- **Observations:** {any anomalies spotted in the snapshot}
### 2. gauntlet-t{tick}-{timestamp}
...
```
### 4. Offer actions per report
After presenting the summary list, ask the user which action to take for each
report. The three actions are:
#### Investigate
Dig deeper into the report for root cause analysis:
1. Read `snapshot.json` in full — analyze entity states, component values,
relationships between entities, any inconsistencies
2. Read `inputs.jsonl` — reconstruct what the player was doing in the 60 ticks
leading up to the report. Look for:
- Rapid input changes (stuck keys, input spam)
- Movement into walls or invalid positions
- Interaction attempts that may have failed
- Timing patterns (actions on same tick as state changes)
3. Read `snapshots.jsonl` — compare entity states across recent ticks to find
when the bug manifested:
- Entity position jumps
- State machine transitions that look wrong
- Component values going out of expected range
- Entities appearing or disappearing unexpectedly
4. Cross-reference with `render.txt` to confirm visual manifestation
5. Read `seed.txt` and note it — the seed plus `inputs.jsonl` should allow
deterministic replay of the scenario
Present findings as a root cause analysis:
```
## Investigation: gauntlet-t{tick}-{timestamp}
### Timeline
- t{tick-N}: {what happened}
- t{tick-M}: {state change}
- t{tick}: {bug manifests}
### Root cause
{Analysis of what went wrong and why}
### Affected systems
- {system 1}: {how it's involved}
- {system 2}: {how it's involved}
### Reproduction
Seed: {seed}
Replay inputs.jsonl from tick {start} to reproduce.
### Suggested fix
{If identifiable from the snapshot data}
```
After investigation, return to the action prompt for this report (the user
may want to create a ticket or dismiss after investigating).
#### Create ticket
Create a bug ticket in the project database. Determine the team from the
nature of the bug:
- **server** — simulation bugs (entity state, movement, AI, ECS systems,
perception, knowledge graph)
- **client** — rendering bugs (display glitches, UI issues, input handling,
audio, visual artifacts)
- **server,client** — integration bugs (protocol mismatch, desync, bridge
issues)
Construct the ticket title and description from the report summary and any
investigation findings. Use the ticket CLI:
```bash
db/connectors/ticket create bug "{title}" --team {team} --description "{description}"
```
The description should include:
- Bug summary (from tester notes)
- Tick, room, position
- Key observations from snapshot analysis
- Seed for reproduction
- Report directory name for reference
After creating the ticket, report the ticket ID to the user.
#### Dismiss
Mark the report as not actionable. Remove the report directory:
```bash
rm -rf "/var/home/jeroenschweitzer/.local/share/godot/app_userdata/The Settled Reach/bug-reports/{report-dir}/"
```
**Always confirm with the user before deleting.** State clearly which directory
will be removed and wait for confirmation.
### 5. Batch processing
When processing multiple reports, work through them one at a time in the
numbered order presented. For each report, complete the chosen action before
moving to the next.
If the user wants to batch-dismiss multiple reports, confirm the full list
of directories that will be deleted before proceeding.
### 6. Final summary
After all reports have been processed, present a summary:
```
## Bug Report Processing Complete
- **Investigated:** {count}
- **Tickets created:** {count} ({ticket IDs})
- **Dismissed:** {count}
- **Remaining unprocessed:** {count}
```
## Tips
- Large `snapshot.json` files may need to be read with offset/limit parameters.
Start with the first 200 lines to get the structure, then target specific
sections.
- `inputs.jsonl` and `snapshots.jsonl` are newline-delimited JSON. Each line
is one tick. Read the last 10-20 lines first to focus on the moments before
the report was filed.
- The `render.txt` is a text-art representation of the game view. Entity
positions in the render should match positions in the snapshot. Mismatches
are themselves a bug signal (rendering vs simulation desync).
- The seed in `seed.txt` combined with `inputs.jsonl` enables deterministic
replay on the server. Note this in any ticket you create.
- If the bug-reports directory does not exist, the tester has not yet run any
gauntlet sessions or has not filed any reports. This is not an error.