Skip to content

Kick K6: public deck page, !deck ends with the code, E2E pulidos (1.1.0, relay 0.3.0) - #6

Merged
facusantillo merged 3 commits into
mainfrom
kick-k6
Oct 18, 2026
Merged

facusantillo merged 3 commits into
mainfrom
kick-k6

Conversation

@facusantillo

Copy link
Copy Markdown
Owner

What this is

Stage K6 of docs/PRD-kick.md: the public deck page at live.dustplanner.app/d/<slug>, plus the !deck text change you asked for and the four pulidos from this afternoon's E2E. Still build 1.1.0 (unreleased); relay 0.3.0.

!deck

{deck_name}{deck_link} · {deckstring} in both languages: the code goes last, no trailing phrase. With the page on: Control Priest · lista: https://live.dustplanner.app/d/tsukuru-tv · AAECAa0G….

The page (relay 0.3.0)

  • GET /d/<slug>: HTML in Spanish or English (Accept-Language, ?lang= forces), styled like the site, noindex, no cookies. Slug in Kick's spelling or the username's. 404 page when unknown or off.
  • GET /api/d/<slug>/deck: JSON, 15 s cache, CORS *.
  • The browser decodes the deckstring (client/deckstring.ts, same rules as DeckstringCodec, checked against the same 23 python-hearthstone vectors + 5 invalid cases) and asks HearthstoneJSON for names and costs in the viewer's language; sideboards hang under their owner; Copy code; "updated X min ago". The relay still holds only name, code, class, format, time.
  • Script bundled by scripts/build-client.mjs (esbuild, already there via wrangler) into src/generated/deck-page.js.txt, committed; CI rebuilds and fails on a diff.
  • deck.publish is stored only while the DO's config says public_page: true (a publish racing a config that turns it off cannot resurrect the deck).

Host

  • KickDeckPublisher: deck.publish when the active deck changes, when the connection comes up, and after a prefs save (config first, then republish). Nothing is sent while the page is off.
  • The connector sends the config before publishing Connected, so the relay applies public_page before any deck arrives.
  • Panel: the Public deck page row shows the real link once connected (live over SSE).

Pulidos from the E2E

  • Panel cache: assets served as /panel/*.js?v=<version> with Cache-Control: no-cache → no more Ctrl+F5 after an update.
  • Kick's reason on a refused send: send_dropped: Kick refused the message (404: bot user not found) instead of a bare 404.
  • Docs for the app setup: webhooks on and the app's bot user created, with the symptom of each, in VERIFICACION K1 and the relay README.
  • PRD §11 records the K5 human test: answers appear as @DustPlanner with the bot badge (the app's bot, named after the app), as replies.

Tests

198 .NET (host flow extended: active deck from the inbox → nothing while off → deck.publish after switching on → /api/chat/deck with the link) and 67 vitest (+33: page routes, decoder vectors, refusal reason).

After merging

  1. Tag worker-v0.3.0 → /health says "version":"0.3.0".
  2. I rebuild DustPlanner-v1.1.0.zip from main for VERIFICACION K7: tick the page, open your link from the phone, change deck, !deck with the link, untick → 404.

Generated by Claude Code

"copialo y pegalo en Hearthstone" told people what they already knew and
sat after the code they wanted to select. The default templates are now
"{deck_name}{deck_link} · {deckstring}" in both languages, so the public
page link (K6) goes before the code and the code is always last.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RaFitGHCUzwkHrFTjz8qJb
Opt-in per channel. The relay serves name, deckstring, class, format and
time; the viewer's browser decodes the code (client/deckstring.ts, same
rules as the C# codec, checked against the python-hearthstone vectors)
and asks HearthstoneJSON for names and costs. Styled like the site,
Spanish or English from Accept-Language (?lang= forces), noindex, no
cookies. deck.publish is stored only while the page is on, so a publish
racing a config that turns it off cannot bring the deck back.

The browser script is bundled by scripts/build-client.mjs into
src/generated/deck-page.js.txt (committed; CI rebuilds and fails on a
diff). The vector generator now writes the fixtures for both consumers.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RaFitGHCUzwkHrFTjz8qJb
…3.0)

Host: KickDeckPublisher sends deck.publish when the active deck changes,
when the connection comes up and after a prefs save, only while the
page is on. The connector now sends the config before publishing
Connected, so the relay applies public_page before any deck arrives.
!deck carries the page's address before the code while connected and
the page is on (ChatContextFactory gets the URL from the connector).

Panel: the Public deck page row shows the real link once connected and
keeps it current over SSE; assets go out as /panel/*.js?v=<version>
with Cache-Control: no-cache, so an updated service never shows a stale
panel (what the K6 check ran into).

Relay: a refused chat.send carries Kick's reason ("404: bot user not
found" would have saved a search); test for it.

Docs: PRD §11 records the K5 human test (answers appear as @DustPlanner
with the bot badge; the app needs webhooks on and its bot user created)
and the K6 decisions; VERIFICACION K1 gains the bot-user step, K6 is
ticked, K7 (public page) added; kick.md, relay README, PROGRESO.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RaFitGHCUzwkHrFTjz8qJb
@facusantillo
facusantillo merged commit 5407a8e into main Oct 18, 2026
3 checks passed
@facusantillo
facusantillo deleted the kick-k6 branch October 18, 2026 16:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants