blust.ch's two decks adopt deck runtime and deck transport v2 - #46
Merged
Conversation
… what it is go() has always clamped, so prev at slide zero and next at the last slide were already no-ops. Nothing said so: the buttons looked live and did nothing. render() now sets disabled on both, and on first alongside prev, which is equally inert at slide zero, in both decks. The styling arrives with the next design release — .tbtn lives inside the shared transport fence, so a disabled treatment is a package change. role=group and aria-label go on both decks' language control, which measured pixel-identical: they change only what a screen reader announces, from two unlabelled buttons to one named control. mental-model's narration comments also move to essential-complexity's wording. Both quoted an example from a note, and the quoted phrase lives only in guestgraph's content — a comment shared by four decks cannot illustrate itself with one deck's speaker notes. essential-complexity's deck-agnostic phrasing is what the shared runtime carries now.
A release shipped the deck lockup visible on mobile, on two decks, because the lockup and the transport fences both carry a .name rule at identical specificity and one site emitted them in the opposite order. Every gate was green: design:check compares each fence's bytes independently, and the fences check asserts presence. Neither can see a relationship between two fences. fenceOrder takes the order from PAGES — the site's own declaration of what it ships — and asserts the fences appear in it. Demonstrated by swapping two adjacent blocks and watching it name both orders.
Pins @robertblust/design v0.6.0 with a real install (node_modules and the
lockfile both move to v0.6.0, not just the lockfile). Each deck declares
its own TALK payload — four strings extracted verbatim from its current
UI — above a new `deck runtime · v1 · shared` fence, and the nested
`language` fence stays exactly where it already was, untouched. Since the
runtime block was extracted from mental-model's own code, syncing it back
returns the runtime body byte-identical except for the intended
TALK.xx.title/desc substitution — verified line by line.
deck transport v2 arrives with the boundary-state styling
(.tbtn:disabled{opacity:.35}) and brings `.lcd:has(.n.msg)` inside the
fence, so each deck's own unfenced copy of that rule — and the comment
noting a later plan would decide it — is dropped.
Both decks' `fences` and `fenceOrder` arrays in verify/check.mjs now
carry "deck runtime" in the position it actually occupies: between
`deck transport` and `language`, matching where its opening marker sits
relative to the nested language fence.
npm run verify, design:check and og:check all pass; og.sha refreshed for
both decks since their markup moved, even though the rendered cards are
pixel-identical.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
v0.6.0's deck runtime block baked blust.ch's own storage key into the
nested language fence instead of carrying the {{langKey}} template, and
declared no params — so a sync had no fixed point: one pass wrote
rb-lang, the nested pass rewrote it, and design:check never settled.
This site's decks were green only by coincidence, because rb-lang is
also this site's own key.
v0.6.1 fixes it. Re-syncing moves the runtime fence's marker v1 -> v2
and its documentary comment; LANG_KEY resolves through the template to
rb-lang, unchanged in value. A second npm run design writes nothing.
…ion check Finding 6: fences and fenceOrder on the two decks' PAGES entries read as though they disagreed — deck runtime last in one, third in the other. They don't: fences is presence-only and order-blind. One line beside the pair says so, as promised when the fifth fence landed. Finding 7: CLAUDE.md said "Six blocks are generated" when there are ten now, and still described the deck footer as a hand-maintained copy asserted by footerVersion — both retired in the previous plan and replaced by four generated fences (deck transport, deck lockup, deck fit, deck runtime), enforced by design:check instead. Corrected the count, the block list and every footerVersion/deck-footer reference; left the rest of the prose alone. npm run verify, design:check and og:check all still pass.
deck runtime v2 -> v3: boundary controls set aria-disabled and guard their own handlers instead of setting the disabled property, so a control that goes inert under the user's own Enter keypress does not drop focus to <body>. deck transport v2 -> v3 follows with the matching CSS selector, .tbtn[aria-disabled="true"]. Verified in Chromium on the mental-model deck: focus stays on tPrev after it goes inert (aria-disabled=true, disabled property false, opacity 0.35).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
@robertblust/designto the publishedv0.6.0with a realnpm install(bothpackage.jsonandpackage-lock.jsonmove to the real tag and resolved commit — not a lockfile-only bump).TALKpayload (title/desc, de/en) extracted verbatim from its existingUIobject, then wraps its runtime in a newdeck runtime · v1 · sharedfence. The nestedlanguagefence is untouched, exactly where it already sat.talks/mental-model/index.html, syncing it back returns the runtime body byte-for-byte identical except for the intendedtitle:'…'/desc:'…'→title:TALK.xx.title/desc:TALK.xx.descsubstitution — verified line by line against a pre-sync copy of both decks.deck transportmoves to v2, which brings.tbtn:disabled{opacity:.35; cursor:default}(the boundary-state styling) and folds.lcd:has(.n.msg)into the fence. Each deck's own unfenced copy of that rule, and the comment noting a later plan would decide it, is dropped — this is that plan.verify/check.mjs'sfencesandfenceOrderarrays for both decks now include"deck runtime", positioned betweendeck transportandlanguage— matching where its opening marker physically sits relative to the nested language fence.og.sharefreshed for both decks: their markup moved, so the recipe hash changed, even though the rendered cards are pixel-identical to before.Test plan
npm install github:robertblust/design#v0.6.0— real install,node_modulesand lockfile both on v0.6.0npm run design— synceddeck runtimeanddeck transportfences on both decksTALKblock, only the transport's two new:disabledrules and the removed duplicate.lcd:has(.n.msg)(+ its comment, + the now-empty media block) changedvar slides …through thebeforeunloadline) in a before/after diff for both decks — the only difference is the twotitle/desclines now readingTALK.xx.title/TALK.xx.descnpm run verify— all checks pass, including the newfenceOrderpositionnpm run design:check— 7 files / 43 fences matchnpm run og && npm run og:check— every card matches the page it renderstPrev.disabled === true, computed opacity0.35talks/mental-model/index.htmlfromfile://directly (no server): renders correctly, no console/page errors, no failed requests — confirms no external assets and that the deck still stands alone🤖 Generated with Claude Code