| name | bug-bundle |
| description | Inspect, extract, install, and validate YAAT v4 bug bundles. Use when a *.yaat-bug-report-bundle.zip or *-recording.zip path appears in conversation, when triaging a YAAT controller bug report or recording-driven complaint, when correlating in-game behavior with recorded snapshots / actions / logs, or when fetching GitHub issue attachments into tests/Yaat.Sim.Tests/TestData/. Start with `info` for an overview, then `history --callsign X` for per-aircraft chronology. |
Bug Bundle Tool
Python CLI that makes v4 bug bundles (*.yaat-bug-report-bundle.zip,
*-recording.zip) easy to triage, install into TestData, and validate.
Requires brotli (pip install brotli).
Usage
When the user attaches a bug bundle, asks about the contents of a recording,
or wants an issue's recording placed into tests/Yaat.Sim.Tests/TestData/,
reach for this tool instead of writing throwaway C# or manual unzip scripts.
Common Queries
Triage summary (duration, ARTCC, aircraft at t=0):
python tools/bug_bundle.py info <bundle.zip> 2>&1 | tee .tmp/bb-info.log
Dump snapshot nearest to a bug time:
python tools/bug_bundle.py snapshot <bundle.zip> --at 182 --out .tmp/bb-snap-182.json
Filter snapshot to one aircraft:
python tools/bug_bundle.py snapshot <bundle.zip> --at 182 --callsign UAL238 --out .tmp/bb-ual238-182.json
Timeline of recorded user actions:
python tools/bug_bundle.py actions <bundle.zip> 2>&1 | tee .tmp/bb-actions.log
Per-callsign chronological story (commands + phase / route / target / approach changes):
python tools/bug_bundle.py history <bundle.zip> --callsign N42416 --out .tmp/bb-hist-N42416.log
This is usually the first thing to run when triaging a single-aircraft complaint — it shows everything that was issued to and happened to one aircraft in one sweep, so you don't have to walk multiple snapshot --at calls.
Just the phase-transition timeline:
python tools/bug_bundle.py phases <bundle.zip> --callsign N9225L --out .tmp/bb-phases-N9225L.log
Just the commands issued to one aircraft:
python tools/bug_bundle.py commands <bundle.zip> --callsign N42416 --out .tmp/bb-cmds-N42416.log
Time-series of aircraft state, with selectable columns (--fields):
python tools/bug_bundle.py track <bundle.zip> --callsigns BXR1960 --start 3050 --end 3130
python tools/bug_bundle.py track <bundle.zip> --callsigns BXR1960 --fields nav
python tools/bug_bundle.py track <bundle.zip> --callsigns N42416 --fields phase,hdg,sid,nextfix,offnose
--fields shapes only the text table; --json always emits every field. Reach for the nav preset on "turned the wrong way / didn't follow the SID/STAR" bugs: offnose is the bearing to the next nav fix minus true heading (negative = fix is left of the nose), turn is the commanded turn direction (L/R), and an empty nextfix means no route waypoint is loaded. Field keys: phase, alt, vs, ias, hdg, mhdg, trk, bank, thdg, ahdg, turn, tgt_spd, aspd, aalt, talt, following, lat, lon, nextfix, offnose, sid, star, deprwy (mhdg/ahdg are magnetic; hdg/trk/thdg are true).
One-line summary of every aircraft in the scenario (callsign / type / dep-dest / start / presets):
python tools/bug_bundle.py scenario <bundle.zip> --show summary 2>&1 | tee .tmp/bb-scen-summary.log
Preset commands for one or more aircraft:
python tools/bug_bundle.py scenario <bundle.zip> --aircraft N346G --show presets
python tools/bug_bundle.py scenario <bundle.zip> --aircraft N346G N172SP --show presets
Starting conditions (parking spot / fix / coordinates) for one or more aircraft:
python tools/bug_bundle.py scenario <bundle.zip> --aircraft N346G --show spawns
Full scenario block for one aircraft (everything: type, FP, presets, autotrack, etc.):
python tools/bug_bundle.py scenario <bundle.zip> --aircraft N346G
Extract logs to .tmp/:
python tools/bug_bundle.py logs <bundle.zip>
Trim a bundle to a shorter time window (in place):
python tools/bug_bundle.py trim <bundle.zip> --max-seconds 90
python tools/bug_bundle.py trim <bundle.zip> --max-snapshots 60 --out .tmp/trimmed.zip
Drops snapshots past --max-seconds N (keeps snapshots whose ElapsedSeconds <= N) or keeps only the first --max-snapshots N in index order. Actions, scenario, weather, ARTCC config, layouts, and logs are preserved unchanged; the manifest's Snapshots index is rewritten to match. With --out writes a new file; without --out overwrites the input bundle. Use it to:
- Shrink a TestData fixture to just the snapshots needed to reproduce a bug, so the test starts replaying from the relevant time window faster.
- Cut a large recording (50+ MB) into a focused fixture before committing it to
tests/Yaat.Sim.Tests/TestData/.
- Isolate "pre-bug" state when the recording captures minutes of unrelated taxi/cruise time before the moment of interest. Pair with
history --callsign X to pick a cutoff just past the symptom.
- Pre-trim before
install --issue N to keep TestData lean. Always verify the trimmed bundle with validate afterwards.
Install into TestData (local path):
python tools/bug_bundle.py install <local.zip> --issue 134 --desc oak-runway-exit
Install with a custom (non-issue-numbered) name:
python tools/bug_bundle.py install <local.zip> --desc sa-armed-for-downwind
Omitting --issue produces {desc}-recording[.yaat-bug-report-bundle].zip —
useful when the bundle isn't yet tied to a GitHub issue.
Install from a GitHub issue (uses gh):
python tools/bug_bundle.py install --issue 134 --desc oak-runway-exit
The GitHub-fetch path still requires --issue.
Format integrity check:
python tools/bug_bundle.py validate <bundle.zip>
Subcommands Reference
| Command | Purpose |
|---|
info | Manifest summary + aircraft callsigns at t=0 (--json) |
snapshot | Snapshot nearest to --at <seconds>, optional --callsign X |
track | Time-series per callsign across snapshots. Columns via --fields (keys or presets default/nav/vert/pos/proc/full; --json emits all). Also --callsigns A B, --pair A B, --start/--end |
actions | Recorded user actions timeline (--json) |
history | Per-callsign chronological events: commands + phase / route / target / approach / track / runway changes (--callsign X, --start/--end, --include-global, --json) |
phases | Per-callsign phase-transition timeline only (--callsign X, --start/--end, --json) |
commands | Actions filtered to one recipient callsign (--callsign X, --start/--end, --json) |
scenario | Pretty-print scenario.json.br. Optional --aircraft CS [CS ...] filter and --show {full,presets,spawns,summary} (default full). |
weather | Print weather.json if present |
layouts | List airport IDs, --airport X to dump one, --all --out-dir D for all |
logs | Extract yaat-client.log/yaat-server.log to .tmp/ |
trim | Shrink a bundle by dropping late snapshots (--max-seconds N or --max-snapshots N, optional --out); preserves actions/scenario/weather/logs and rewrites the manifest's snapshot index |
install | Copy into TestData as [issue{N}-]{desc}-recording[.yaat-bug-report-bundle].zip (--issue optional for local installs) |
validate | Manifest + Brotli decompression integrity check |
Tips
info is the first thing to run; it tells you duration, aircraft involved, ARTCC, and whether logs are included.
- For single-aircraft triage,
history --callsign X is the second thing to run. It collapses 5+ targeted snapshot --at calls into one chronological view.
snapshot --at T uses the same nearest-at-or-before-T rule as the C# RecordingArchive.ReadSnapshotAt — so --at 60 returns the snapshot whose ElapsedSeconds is the largest value ≤ 60.
history event tags: CMD (action), PHASES (chain installed/rebuilt), PHASE+ (current phase advanced), PHASE- (chain cleared), ROUTE (NavigationRoute changed), TGT (assigned alt/spd/hdg changed), APPR (Approach state), TRACK (ownership), RWY (DestinationRunway), SPAWN/DESPAWN. Output is ASCII-only (no unicode arrows) so it survives Windows cp1252 stdout.
install validates the archive post-copy; a post-install warning usually means the bundle is truncated.
- Output goes to stdout by default (pipeable). Use
--out <path> to write a file; logs always writes files and prints paths.
scenario, weather, artcc-config, and layouts always pretty-print the JSON they emit (indent=2). Falls back to raw text if the payload isn't valid JSON.