mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-11 18:14:03 +01:00
The solver only ran behind ./run.sh, had one media query in the whole
stylesheet, and kept the inventory in a 46vh scroll box that showed maybe a
third of the 43 dice. Setting it up on the PC did nothing for the phone.
Deployment
dice.kuhy.duckdns.org, behind the existing gitea-caddy edge. DuckDNS already
wildcards *.kuhy.duckdns.org (checked against 1.1.1.1 and 8.8.8.8), so no
dashboard step. deploy_build.sh builds to dist.staging and rsyncs into dist/
with --delete-after --delay-updates; plain --delete removes stale assets
before writing the new ones, which 404s a client mid-load. A post-commit hook
starts a MemorySwapMax=0 systemd user unit, so a rebuild can neither slow a
commit nor thrash zram.
Three traps found by driving the live URL in a browser rather than curling it:
a site address of "127.0.0.1:8089" reads as a HOSTNAME, so Caddy enabled
auto-HTTPS and started an HTTP->HTTPS redirect listener that bound *:80 next
to the edge -- SO_REUSEPORT would then split inbound HTTP and intermittently
break ACME for every domain here. The same address also made a Host matcher,
so the edge's forwarded Host matched nothing and served an empty 200 while the
local health check passed. And watching dist/'s own inode could never detect a
detached bind mount: rsync into an existing directory never changes it. Each
now has a guard that asserts positively rather than failing open.
Dice list
All 43 on screen at every width, no inner scrollbar. Column count and size
tier are chosen together from a container query on the panel -- not the
viewport, which mispredicts by 2x at the point the columns split. Two
invariants govern it: the list fits above the fold, and the name column stays
wide enough to tell Painter's die B, G and R apart. The left column holds the
grid alone, so it is sized to fill the height it owns: one --die-row value
drives the type, buttons and bar strip, giving a 52px row and 44px buttons on
a 1296px-tall screen and 20px rows on a phone.
Three safe-design rules are broken inside .die-list deliberately: sub-16px
body text, square icon buttons, sub-8px intra-cell gaps. 43 items with a name,
a chart and a counter in one viewport is arithmetically incompatible with 16px.
Import / export
A file, the clipboard, or a link carrying the inventory in the URL fragment.
One validator behind all four entry points including localStorage; it keeps
what it can and reports what it dropped, so a die added in a later game patch
costs you that entry, not the inventory. A link never silently overwrites what
is saved here -- it offers Keep or Discard, and only a link that actually
carries dice is applied at all, because one encoding a count of zero parsed
cleanly, blanked the screen, disabled Clear and left Keep writing the emptiness
over the visitor's own loadout.
session_autopsy
parse.py (551) and report.py (504) were over the repo's 500-line limit, so
test_file_length has been failing on main since 5ffd035. Extracted TurnTracker
and the two candidate-cell helpers. Report output is byte-identical on real
data apart from its timestamp, checked against HEAD in a worktree.
Verified: 288 TS tests and 911 Python tests, 100% coverage both, lint and
pre-commit clean, 8 viewports measured on the live HTTPS site, solver confirmed
through the real module worker.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
26 lines
3.8 KiB
JSON
26 lines
3.8 KiB
JSON
{
|
|
"title": "Serve the KCD2 dice solver at dice.kuhy.duckdns.org, fit all 43 dice on any screen, and move inventories between devices",
|
|
"objective": "The solver only ran behind ./run.sh, had a single media query in the whole stylesheet, and kept its 43-dice inventory in a 46vh scroll box. Make it reachable at a URL without a terminal, usable on a phone, able to show every die at once at any viewport, and able to carry an inventory between devices so the list is filled in once rather than per browser. Succeeds when the live HTTPS URL renders all 43 dice above the fold on the measured phone viewport and on a 2560px desktop, the solver returns a recommendation through the real module worker, and an inventory set up on one device can be reproduced on another via a file, the clipboard, or a link.",
|
|
"acceptance_criteria": [
|
|
"https://dice.kuhy.duckdns.org/ returns 200 over HTTP/2 with a valid Let's Encrypt certificate, and the four pre-existing sites on the shared gitea-caddy edge still return 200",
|
|
"The serving container listens on 127.0.0.1:8089 only — never :80/:443 (which would contend with the edge via SO_REUSEPORT and break ACME) and never a wildcard address (which host networking would expose to the LAN); setup asserts this positively and refuses to finish otherwise",
|
|
"All 43 dice render with no inner scrollbar and the list ends above the fold at 375x667, 423x845 (the measured device), 768x1024, 1366x768, 1000x800, 1920x1080, 2560x1296 and 2560x1440",
|
|
"Painter's die B, G and R stay distinguishable — never truncated to a common prefix — at every one of those viewports",
|
|
"The dice grid fills the height it owns rather than banding at the top: row height, type and buttons scale together, reaching 44px touch targets on a tall desktop",
|
|
"An inventory round-trips through all three transports (JSON file, clipboard, URL fragment) and through localStorage, all via one validator that keeps valid entries and reports what it discarded",
|
|
"A shared link never silently overwrites a saved inventory: it offers Keep or Discard, is only applied when it actually carries dice or badges, and its fragment is cleared so a reload cannot resurrect it",
|
|
"Committing to main with changes under kcd2_dice_solver/ republishes the site, without slowing the commit or risking an OOM, and the publish detects a detached bind mount and re-attaches it",
|
|
"100% statement/branch/function/line coverage on the TypeScript suite and the Python suite, zero lint suppressions added, pre-commit clean",
|
|
"python_pkg/tests/test_file_length.py passes — parse.py and report.py brought under the 500-line limit with byte-identical report output on real data"
|
|
],
|
|
"out_of_scope": [
|
|
"The solver mathematics, the dice/badge data, and the scoring model — untouched",
|
|
"run.sh, which remains the development entry point",
|
|
"The repo colour palette: the app's existing :root tokens are reused and its divergence from the frozen unified-design-system tokens is left as a separate decision",
|
|
"Reaching 44px touch targets at phone width — arithmetically incompatible with 43 dice on one screen, and explicitly traded away",
|
|
"Rebuilding from the committed tree rather than the working tree; the working-tree hazard is documented instead",
|
|
"The LAN-exposed *:8088 listener on the older personal-website container, noted during review but a separate change"
|
|
],
|
|
"verifier": "bash ~/.claude/scripts/finish.sh gate (pre-commit + full suites); pnpm run lint && pnpm exec vitest run --coverage (288 tests, 100%); python3 -m pytest python_pkg (911 tests, 100%); headless Chrome via CDP measuring 8 viewports and driving the solver on the live HTTPS URL; curl + openssl s_client for status and certificate; setup_kcd2_dice_solver.sh status; worktree diff of session_autopsy report output against HEAD"
|
|
}
|