Skip to content

Commit 034a790

Browse files
authored
Merge pull request #38 from peans99/release/0.8.32
0.8.32 - a report to send with a bug, and a Discord to send it to
2 parents 5e42fde + 6342f1c commit 034a790

14 files changed

Lines changed: 1225 additions & 13 deletions

File tree

.github/workflows/release.yml

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,12 @@ jobs:
128128
$section = [regex]::Match($readme, $pattern)
129129
130130
if ($section.Success) {
131-
$changed = "### What changed`n" + $section.Groups[1].Value.Trim() + "`n`n"
131+
$summary = $section.Groups[1].Value.Trim()
132+
$changed = "### What changed`n" + $summary + "`n`n"
133+
Set-Content -Path release-summary.md -Value $summary -Encoding utf8
132134
} else {
133135
Write-Host "::warning::No '### $version' section in README.md; releasing without a changelog."
136+
$summary = ''
134137
$changed = ''
135138
}
136139
@@ -176,3 +179,64 @@ jobs:
176179
'QuantumWake.exe' '${{ steps.archive.outputs.asset }}' `
177180
--title 'Quantum Wake ${{ steps.version.outputs.version }}' `
178181
--notes $notes
182+
183+
# Told to the support Discord after the release exists, not before: an
184+
# announcement pointing at a release that failed to publish is worse than
185+
# silence. Failing here must not fail the release either - the build is
186+
# already out by this point, and a webhook is not a release step.
187+
- name: Announce on Discord
188+
if: success()
189+
continue-on-error: true
190+
shell: pwsh
191+
env:
192+
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
193+
run: |
194+
if (-not $env:DISCORD_WEBHOOK) {
195+
Write-Host "No DISCORD_WEBHOOK secret set; skipping the announcement."
196+
exit 0
197+
}
198+
199+
$version = '${{ steps.version.outputs.version }}'
200+
$tag = '${{ steps.version.outputs.tag }}'
201+
$url = "https://github.com/${{ github.repository }}/releases/tag/$tag"
202+
203+
# Discord refuses an embed description over 4096 characters, and a
204+
# long release would take the whole announcement down with it. Cut on
205+
# a line boundary so the last bullet is whole rather than clipped
206+
# mid-word, and say that there is more rather than implying there is not.
207+
# Written by the Release step from the README section it published,
208+
# so the announcement and the release page cannot disagree.
209+
$summary = if (Test-Path release-summary.md) {
210+
(Get-Content release-summary.md -Raw).Trim()
211+
} else {
212+
"See the release page for what changed."
213+
}
214+
215+
if ($summary.Length -gt 3500) {
216+
$cut = $summary.Substring(0, 3500)
217+
$lastBreak = $cut.LastIndexOf("`n")
218+
if ($lastBreak -gt 0) { $cut = $cut.Substring(0, $lastBreak) }
219+
$summary = $cut + "`n`n[Read the rest on the release page]($url)"
220+
}
221+
222+
$payload = @{
223+
username = "Quantum Wake"
224+
embeds = @(@{
225+
title = "Quantum Wake $version is out"
226+
url = $url
227+
description = $summary
228+
color = 4771799
229+
footer = @{ text = "Download QuantumWake.exe from the release page" }
230+
})
231+
} | ConvertTo-Json -Depth 6 -Compress
232+
233+
# The webhook is a secret and stays one: never echoed, never written
234+
# to a file, and the response body is not printed either.
235+
try {
236+
Invoke-RestMethod -Uri $env:DISCORD_WEBHOOK -Method Post `
237+
-ContentType 'application/json; charset=utf-8' `
238+
-Body ([System.Text.Encoding]::UTF8.GetBytes($payload)) | Out-Null
239+
Write-Host "Announced $version to Discord."
240+
} catch {
241+
Write-Host "::warning::Discord announcement failed: $($_.Exception.Message)"
242+
}

Directory.Build.props

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
<Copyright>Copyright © nekron</Copyright>
1111
<Description>A pilot's logbook for Star Citizen: second-screen dashboard, in-game overlay, and flight-log analysis for Star Citizen, driven by Game.log.</Description>
1212

13-
<Version>0.8.29</Version>
14-
<AssemblyVersion>0.8.29.0</AssemblyVersion>
15-
<FileVersion>0.8.29.0</FileVersion>
13+
<Version>0.8.32</Version>
14+
<AssemblyVersion>0.8.32.0</AssemblyVersion>
15+
<FileVersion>0.8.32.0</FileVersion>
1616

1717
<RepositoryUrl>https://github.com/peans99/QuantumWake</RepositoryUrl>
1818
<PackageProjectUrl>https://github.com/peans99/QuantumWake</PackageProjectUrl>

README.md

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
![.NET 10](https://img.shields.io/badge/.NET-10-512BD4)
99
![Windows 10/11](https://img.shields.io/badge/Windows-10%20%2F%2011-0078D6)
1010
![Licence Apache 2.0](https://img.shields.io/badge/licence-Apache--2.0-blue)
11-
![827 tests](https://img.shields.io/badge/tests-827%20passing-4fd48a)
11+
![827 tests](https://img.shields.io/badge/tests-854%20passing-4fd48a)
1212
![Network](https://img.shields.io/badge/network-opt--in%20only-46617a)
1313

1414
Star Citizen writes everything you do to `Game.log` and then rotates it away.
@@ -108,9 +108,9 @@ back to the community.
108108

109109
*The 18 slots this install has observed, arranged around the pilot: worn
110110
armour on the frame, stowed weapons and supplies in the field kit. Every card
111-
carries when the log last saw it — four days for most of this kit, nine for the
112-
barrel — because this is what the log watched being equipped, not a live
113-
inventory read out of the game.*
111+
carries when the log last saw it — today for most of this kit, ten days for
112+
the barrel attachment nobody has touched since — because this is what the log
113+
watched being equipped, not a live inventory read out of the game.*
114114

115115
Names are real names — New Babbage, not `Stanton4_NewBabbage`; a Genoa power
116116
plant, not `POWR_JUST_S02_Genoa_SCItem` — read from your own `Data.p4k` at
@@ -184,6 +184,28 @@ The trade-off of doing it safely: an always-on-top window is **not** composited
184184
over exclusive fullscreen, so Star Citizen must run in **Borderless Windowed**
185185
for the overlay to be visible. The dashboard has no such limitation.
186186

187+
## Reporting a problem
188+
189+
If a page is empty here and full for somebody else, **Settings &rarr; Report a
190+
problem** saves a small file that says why: what the parser could not read, the
191+
counts behind each page, your game builds, and which optional data is on. It is
192+
about a kilobyte. Read it, then attach it to an issue.
193+
194+
**Your logs stay on your machine.** A gameplay log here is 8 MB and 29,000
195+
lines, most paste services refuse it, and it names the pilots you flew with as
196+
well as you. The report carries none of it: it is built from a list of things
197+
the app chose to include rather than from a log with the private parts taken
198+
out, so there is no pattern to miss - no handle, no character or account id, no
199+
folder names, no UEX keys.
200+
201+
The exception is the example lines, which are off unless you ask for them. A
202+
line is only in that list because the game changed its format, and a new format
203+
can write your name in a shape nothing knows to look for yet - so the page says
204+
so, and asks separately.
205+
206+
[docs/bug-reports.md](docs/bug-reports.md) has the whole of it, including what a
207+
maintainer reads first.
208+
187209
## Requirements
188210

189211
**To run the release:** Windows 10 or 11. Nothing else — the executable is
@@ -271,7 +293,7 @@ Linux-hosted server mode later.
271293
Only the overlay is Windows-bound, leaving a Linux-hosted server mode open.
272294

273295
```powershell
274-
dotnet test Quantumwake.slnx # 827 tests
296+
dotnet test Quantumwake.slnx # 854 tests
275297
```
276298

277299
Parser fixtures are real log lines, not synthesised ones — which is how three
@@ -302,6 +324,7 @@ rather than eyeballed.
302324
- [docs/credits.md](docs/credits.md) — every external resource used, and what came from where
303325
- [docs/naming.md](docs/naming.md) — why the project is called Quantum Wake
304326
- [docs/releasing.md](docs/releasing.md) — how a release is cut, and what enforces the version bump
327+
- [docs/bug-reports.md](docs/bug-reports.md) — what the problem report holds, and what it deliberately does not
305328
- [docs/landscape.md](docs/landscape.md) — who else is doing this, and what is still ours
306329

307330
## Licence
@@ -361,6 +384,34 @@ affiliated with or endorsed by Cloud Imperium Games.
361384
Newest first. Each version's section is what the GitHub release says too — the
362385
release workflow lifts it from here, so it is written once.
363386

387+
### 0.8.32
388+
389+
- **Settings can save a report to send with a bug.** If a page is empty for
390+
you and full for somebody else, this is what says why: what the parser could
391+
not read, the counts behind each page, your game builds, and which optional
392+
data is on. It is about a kilobyte, and nothing is sent anywhere — it saves a
393+
file you read first and attach yourself.
394+
- **Your logs stay on your machine.** A gameplay log is megabytes, most paste
395+
services refuse it, and it names the pilots you flew with as well as you. The
396+
report carries none of it: it is built from a list of things the app chose to
397+
include rather than a log with the private parts taken out, so there is no
398+
pattern to miss — no handle, no character or account id, no folder names, no
399+
UEX keys.
400+
- **Example lines are a separate yes.** The fastest way to fix a parser is to
401+
see the line that beat it, but a line is only in there because the game
402+
changed its format — and a new format can write your name in a way nothing
403+
knows to look for yet. So they are off unless you ask, and the page says
404+
plainly what it cannot promise about them.
405+
- **There is a Discord**, linked from the About page:
406+
[discord.gg/AV3cDzRs39](https://discord.gg/AV3cDzRs39). Questions, bug
407+
reports, and a place to say a page looks wrong — which is worth more than it
408+
sounds, since most of what this app reads was found by somebody noticing a
409+
number that could not be right.
410+
- Nothing you can see: new releases are announced there automatically,
411+
[docs/bug-reports.md](docs/bug-reports.md) writes down why a log is the wrong
412+
thing to send and what a maintainer reads first, and the Loadout screenshot
413+
is retaken against a current install.
414+
364415
### 0.8.29
365416

366417
- **The first run no longer assumes the newest patch wiped your account.**

docs/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Compiled 2026-08-20 against a real install: **SC 4.9.188.23497**, handle `nekron
2323
| [landscape.md](landscape.md) | Who else builds on Game.log, what overlaps, and what is still ours. |
2424
| [org-network.md](org-network.md) | Plan, unbuilt: pooling blueprints, stashes and prices across an org. |
2525
| [releasing.md](releasing.md) | Bump, tag, and what the pipeline does with it. |
26+
| [bug-reports.md](bug-reports.md) | What the report Settings saves holds, what it deliberately leaves out, and the one thing it cannot promise. |
2627

2728
The seven per-tool write-ups that used to sit in `docs/tools/` have been
2829
removed. Everything worth keeping from them was already lifted into the docs

docs/bug-reports.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Reporting a problem
2+
3+
How "it works for you and not for me" gets answered without anybody sending
4+
their `Game.log` anywhere.
5+
6+
Settings → **Report a problem** saves a small JSON file. This is what is in it,
7+
what is deliberately not, and the one thing it cannot promise.
8+
9+
## Why not just send the log
10+
11+
Three reasons, in order of how quickly they bite.
12+
13+
**Size.** A quiet session here is 0.2 MB. A real one is **8.1 MB and 29,269
14+
lines**. The whole corpus on this machine is **158 files, 435 MB**. Pastebin
15+
refuses a paste over 512 KB on a free account, so almost every gameplay log is
16+
too big before privacy is even discussed. GitHub accepts a 25 MB attachment,
17+
which fits one log and not a set.
18+
19+
**Other people.** A log names the pilots you flew with. Party notifications and
20+
ship comms channels are the only lines in a 4.x log that name another player —
21+
they are the entire basis of the Crew page — so publishing your log publishes
22+
their handles too. That is not yours to give away.
23+
24+
**Yours.** The header carries your handle, character GEID, account id and
25+
session GUIDs, and `Executable:` names a user folder on many installs.
26+
27+
## What the report holds instead
28+
29+
The parser already records what it could not read: a count per unrecognised tag
30+
and one example line each (`LogEventParser.RecordUnmatched`). That is the whole
31+
diagnosis for an empty page, and it is **kilobytes** — a real report from this
32+
install is about 1 KB.
33+
34+
| Field | Why it is in there |
35+
|---|---|
36+
| `producer` | App version and build, so the answer is about the right code |
37+
| `install` | Whether an install was found, its channel, whether `Game.log` is present, how many backups — **never the path** |
38+
| `library` | Sessions stored and counted, first and last dates, and every game build seen with a count |
39+
| `parser` | How many lines went unread this run, and under which tags |
40+
| `views` | The counts behind each page — ships, places, contracts, purchases, trades, fleet, loadout, stash |
41+
| `data` | Whether the community dataset and UEX are on, and which dump the dataset came from |
42+
| `wipe` | The line, its scope, and how many sessions sit before it |
43+
44+
`views` and `wipe` are there because most "this page is empty" reports are not
45+
parser bugs at all. A Crew page with nothing on it and a `wipe.hidden` of 108 is
46+
a wipe line drawn too late, not a defect.
47+
48+
## Allow-list, not deny-list
49+
50+
Every field above is one the code chose to put in. The report is **built up**
51+
from facts the app can name, rather than **built down** from a log with the
52+
private parts stripped out.
53+
54+
That direction is the whole safety argument. A deny-list leaks the pattern
55+
nobody thought of, and the only thing worse than no report is one that promises
56+
to be clean and is not. It is the same reasoning as `LanGuard`, which whitelists
57+
read methods rather than listing forbidden endpoints.
58+
59+
Consequences worth stating:
60+
61+
- **The install path is absent.** It reads `C:\Users\<name>\...` on plenty of
62+
machines, and it has never been the answer to a parser question.
63+
- **UEX keys are absent.** Whether keys are *stored* is a boolean, because "UEX
64+
is on but has no keys" explains a page of blanks.
65+
- **No handle, character or account id appears anywhere.**
66+
67+
A test reads the whole document back and fails if any field is so much as
68+
*named* for one of those, so a field added later that carries one arrives as a
69+
red test rather than a quiet leak.
70+
71+
## The one thing it cannot promise
72+
73+
Example lines are **off unless you ask**, and this is why.
74+
75+
A sample exists only because a known tag stopped parsing — which means the
76+
game changed that line's format. A changed format is free to write your name in
77+
a shape nothing here has ever seen. Scrubbing replaces the identifiers this
78+
install has already read, and the shapes the game has always used
79+
(`Handle[...]`, `nickname="..."`, `- name X -`, GEIDs, account ids, session
80+
GUIDs). It cannot replace a shape that has just been invented.
81+
82+
That is not a hypothetical. A synthetic 4.11-shaped log whose login line was
83+
reshaped to `Pilot{TestPilot42}` came through the scrubber **still naming its
84+
pilot**:
85+
86+
```
87+
2 Legacy login response [CIG-net] User Login OK - Pilot{TestPilot42} - Time[177332566]
88+
2 AccountLoginCharacterStatus_Character Character: createdAt 1784476187540 - geid <id> - accountId <id> - name <pilot> - status CURRENT
89+
2 Context Establisher Done establisher="Game" nonsense session=<session>
90+
```
91+
92+
Two of the three were scrubbed because their shapes were known. The one that
93+
was not is the one whose format had changed — and a format change is the only
94+
reason any of them is in the list.
95+
96+
There is a second, quieter failure in the same case: when the line that broke is
97+
the *login* line, the handle never reaches the session store, so there is no
98+
value to search for either. Shape-based scrubbing is what covers that, and it
99+
covers only shapes it knows.
100+
101+
So the report always carries the **counts**, which are safe by construction and
102+
enough to see that something broke and where. The **lines** are a separate yes,
103+
and the Settings page says plainly what it cannot promise about them.
104+
105+
## Sending one
106+
107+
Nothing is uploaded. The file is built in the page and handed to the browser,
108+
so it lands in your downloads and goes no further until you send it. Read it
109+
first — it is a kilobyte of JSON and that is the point of it being small.
110+
111+
Attach it to a GitHub issue with what you expected to see and what you saw.
112+
113+
## Reading one, as a maintainer
114+
115+
In roughly this order:
116+
117+
1. **`parser.unread`.** Anything above zero with a tag list is a format change:
118+
the game moved a line the app depends on. Ask for the example lines if they
119+
are not attached.
120+
2. **`library.builds`.** Which patch they are on, and whether the sessions are
121+
spread across several. A build nobody else has reported is a strong lead.
122+
3. **`wipe.hidden`.** A large number here explains an empty page with no bug
123+
attached.
124+
4. **`views`.** Zero on one page with sessions in the library narrows it to that
125+
page's resolver rather than the parser.
126+
5. **`data.communityDump`.** Missing names for new ships or items usually means
127+
the dump predates their patch, which the dataset now reports itself.
128+
129+
`install.backups` at zero with `install.found` true means the app is reading a
130+
live `Game.log` and nothing else — a fresh install, or a channel with its
131+
backups cleared. That install cannot show history yet, and no amount of parser
132+
work will change it.

docs/images/loadout.png

-2.76 KB
Loading

0 commit comments

Comments
 (0)