1 Commits

Author SHA1 Message Date
a6fc0431d7 feat(screens): retake the two frames a signed-in character changes
The org lead signed a character into the shard by hand — the step automation
could not reach — so shard-status and app-shard were retaken. The shard page
now reads 1 player online in Britain, and the app's card agrees.

Two things worth noticing in the retake. Presence reaches the public page as
counts and regions rather than names, which is the visibility framework working
unprompted. And the guild board's online column did not move: it refreshes only
when a guild's signature changes, which is the stale-roster defect wearing a
different hat.

A sixth defect, visible in the shipped phone capture: the app interpolates a
count into a fixed plural and says "1 players online". Raised, not fixed —
it wants a plurals resource in the app.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-25 10:08:41 -05:00
5 changed files with 29 additions and 17 deletions

32
PLAN.md
View File

@@ -1076,7 +1076,7 @@ hashed off each object's serial, so a re-run reproduces the same world and a scr
be retaken later and still match.
**What the rig found.** A screenshot rig is an integration test with a human in the loop, and
this one turned up five things nothing else had:
this one turned up six things nothing else had:
- **A fresh `module-uo` install pinned wire protocol 3 while the sidecar speaks 4**, so a new
deployment 409s on every shard read until an admin edits the number by hand. The protocol-4
@@ -1096,6 +1096,9 @@ this one turned up five things nothing else had:
the site connects is therefore invisible — the page said none while the shard had two.
- **The Android news list prints raw ISO timestamps.** Found while choosing the phone
captures; the news screen was dropped from that set rather than shipping a picture of it.
- **The app says "1 players online".** `shard_online_count` and `ShardEventText.kt` both
interpolate a count into a fixed plural. Found in the retake after a character was signed in,
and it is in the shipped phone capture — a `plurals` resource is the fix, in the app.
The first is fixed. The rest are raised as product observations, with the rig working around
them: the guilds are built *after* the rename, and the IDOC staging is two passes with a wait
@@ -1114,15 +1117,24 @@ The shard screen is the one worth having. It shows the two houses entering IDOC
activity feed — the same event that reached `/uo/houses` in the browser, on the same rig, in
the same minute.
**One thing that did not happen: a character logged in.** The org lead asked for it, so the
scaffolding sets a known password on a seeded account and a client was driven as far as its
login screen. ClassicUO stores its password crypted and mangles a plaintext one from
`settings.json`, so auto-login fails; synthetic clicks reach the client but synthetic text
does not; and the remaining route — taking the foreground and typing — was tried once, missed
the client, and typed into the browser window the person at this machine was using. It was
not tried again. **Players online therefore reads 0, and the page is honest about a quiet
realm.** The client is left at its login screen: one manual sign-in and
`npm run screens:capture shard-status app-shard` retakes the two frames that would change.
**The character that had to be logged in by hand.** The org lead asked for a player in the
world, and the scaffolding does its half — it sets a known password on a seeded account,
because `BridgeSeeder` gives every account a random GUID nobody kept. Driving the client is
where automation stopped. ClassicUO stores its password crypted, so a plaintext one in
`settings.json` decrypts to garbage and auto-login fails; posted mouse clicks reach the client
but posted text does not; and the remaining route — taking the foreground and typing — was
tried once, failed to take focus, and typed into the browser window the person at this machine
was using. It was not tried again.
The org lead signed in instead, and the two frames that depended on it were retaken: the shard
page now reads **1 player online, in Britain**, and the app's shard card agrees. Both came from
the same `npm run screens:capture shard-status app-shard`, which is the whole point of D45 —
the thing that changed was the world, not the recipe.
Two things that pass is worth noticing here. Presence reaches the public page as **counts and
regions, not names**, which is the visibility framework doing its job unprompted. And the
**guild board's "online" column did not move**: it is refreshed only when a guild's signature
changes, which is the same defect as the stale roster above wearing a different hat.
**A layout decision worth recording.** The `/features/` figures are one-up at the column's
full width, not a two-column grid. Two-up was built first and is the obvious layout for a set

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -22,9 +22,9 @@ import Screenshot from '../Screenshot.astro';
<p class="eyebrow">What it looks like</p>
<h2>The other end of that diagram</h2>
<p class="prose looks__lede">
A demo deployment with a real shard behind it. The gold supply, the uptime and the online
count are read from the game server over the bridge — none of it is typed in, and the page
is honest about a quiet realm.
A demo deployment with a real shard behind it. The gold supply, the state of the link and
the player online in Britain are all read from the game server over the bridge. None of it
is typed in, and none of it is a mock-up.
</p>
<Screenshot id="shard-status" />

View File

@@ -71,9 +71,9 @@ export const screens = [
id: 'shard-status',
route: '/uo/shard',
admin: false,
alt: 'The shard page of a Runic Gateway site, showing the shard online, its gold supply, the state of the shard link and how many players are online.',
alt: 'The shard page of a Runic Gateway site, showing the shard online, its gold supply, the state of the shard link, and one player online in Britain.',
caption:
'The shard console. Every number on it came over the bridge from a running game server — nothing here is stored by hand.',
'The shard console. Every number on it came over the bridge from a running game server — including the player who was standing in Britain when this was taken.',
family: 'web',
},
{
@@ -187,9 +187,9 @@ export const screens = [
id: 'app-shard',
route: '/shard',
admin: false,
alt: "The app's shard screen, showing the shard online with its gold supply, links to champion spawns, guilds, governors and falling houses, and a live activity feed.",
alt: "The app's shard screen, showing the shard online with one player and its gold supply, links to champion spawns, guilds, governors and falling houses, and a live activity feed.",
caption:
'The same bridge feeds the phone. The activity list is live — those two houses entered their final decay stage while this was open.',
'The same bridge feeds the phone: the same player online, and an activity list that is live — those houses entered their final decay stage while it was open.',
family: 'phone',
},
{