"New: a live CSS editor for your profile." The banner beside it already
names the platform, and so does the changelog entry; the line under the
version does not need to. "Live" earns its place there instead — the
preview is the thing that makes the editor worth opening.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NX2SsmUqQftWTZAY4BDuFa
Version heading bumped in both layouts, and the tagline under it now
points at the CSS editor instead of ECHO — the banner beside it is
advertising the editor, so the two now say the same thing.
Changelog entry is written for the people who hit this: they saw the
dingus error every time and had no way to know it was not their fault.
It says what happened in their terms and tells them to try again.
README's version log gets the matching line.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NX2SsmUqQftWTZAY4BDuFa
The first pass read the name from the last user turn and the token from
the last assistant turn. Both are wrong once a conversation continues.
Only sucker's *first* reply carries a conversation token — later ones say
"Character updated" or "unchanged" with no token in them — so reading the
last assistant turn lost the link three turns in and would have created a
duplicate card on every message. tokenCandidates() now searches the whole
conversation, still preferring whatever the user just typed, since pasting
a token is deliberate.
The name is the first user turn after the greeting, not the last one. That
is what the old code read at messages[3], and unlike the last turn it stays
put as messages are appended.
Tests cover a three-turn conversation for both.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NX2SsmUqQftWTZAY4BDuFa
Some users' JanitorAI sends a "." user turn between the card and the
greeting; others' does not. Sucker read fixed indices, so on the shorter
shape every slot was off by one: first_mes was set to the name line, and
the name slot did not exist at all. That TypeError was caught by the
handler and reported as the "you dingus, read the directions" message,
which blamed the user for a shape they never chose.
src/lib/messages.ts now resolves the slots by role instead — the card is
the system turn, the greeting is the first assistant turn, the user's
latest input is the last user turn, and sucker's own previous reply is the
last assistant turn. All four hold in both shapes and in a continued
conversation, so the conversation token is found in either as well.
Extraction now throws a description of what is missing rather than a
TypeError, and tests/messages.test.ts pins both shapes. The tests need no
framework: `npm test` runs node's built-in runner.
Existing cards are unaffected: the update path already discards the
extracted name and keeps the original.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NX2SsmUqQftWTZAY4BDuFa
- Bump Avalon member count to 885
- Add looping, muted video banner linking to the new Janitor profile CSS editor
- Desktop: show the Avalon and CSS banners side by side
- Mobile: show them in a carousel (random start, 8s auto-advance, arrows/dots)
- Paint video frames to a canvas so browsers like Opera GX don't overlay
pop-out controls on the banner
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>