From 4b910f19bf61d31ab19e3c6931f5785057ba997b Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 17 Aug 2026 16:23:46 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=8D=20fix:=20apply=20the=20code=20revi?= =?UTF-8?q?ew=20=E2=80=94=20two=20visible=20regressions,=20and=20the=20gat?= =?UTF-8?q?es=20behind=20them?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nine review angles, fourteen verified findings, all but the byte-table generator applied. The two that mattered most were regressions of mine: - a:hover repainted button-styled anchors, and in dark theme --accent-text equals --accent-solid — hovering the hero CTA drew its label in its own background colour. Verified invisible before (computed color == computed background) and distinct after: 10.39:1 dark, 6.90:1 light. The buttons and the skip link now re-assert their label colours on hover. - Footer links had lost every non-hover affordance: the text-decoration:none carve-out plus body-coloured links left a 2.37:1 shade difference as the only cue. The carve-out is deleted — .nav-links a and .brand already declare none themselves — and the accent rule is back on the footer. Also on the page: #ref-filter, the one text input, moves to --border-ui (it still had the 1.68:1 border the token's own comment calls decorative); focusable code surfaces get the --accent-on-code ring at -2px offset, inside the .code overflow clip; #output .out-err drops #ff8095, the last surviving colour of the deleted indigo palette; the two rgba(255,106,126) washes become color-mix over --err-line so a grep for the token finds them. The theme machinery loses a whole block: the dark media query is guarded with :not([data-theme="light"]), so an explicit light toggle falls through to the bare :root palette and the 21-token hand-copy in [data-theme="light"] is gone. Verified in all four system/toggle combinations. The page stops contradicting the repo: it claimed cereale/min "cannot tree-shake — nothing left to shake" while src/treeshake.test.ts proves the opposite on every run. Corrected here and in FRAMEWORKS.md, with the measured figures (1,837 vs 1,996 bytes for one decorator). The release facts the page was hand-bumping — both tgz names, "0.4.0 lives in the repository", the sixty-eight — now fill from meta.js/the bundle like the version badge always has. The workflows close three holes: - The docs sync gate was blind to NEW untracked build outputs (git diff does not report them; demonstrated). Both workflows now run check:docs-sync, one shared script that fails on anything porcelain reports — which also ends the copy-paste divergence between them. - pages.yml deploys on CI succeeding on main (workflow_run) instead of on the push itself, so a deploy implies green tests, not just in-sync docs. The deploy job refuses refs other than main, closing the workflow_dispatch any-branch deploy, and the build job drops pages/id-token — npm postinstall scripts no longer run alongside an OIDC grant. - The Junie action is pinned to the commit behind v1.7.4 rather than the tag, which is the immutability the previous comment promised but a mutable ref cannot deliver. Verified: every fix confirmed in a rendered browser in both themes; 72 contrast pairs still pass; no overflow at 20 widths; 268 tests, build, check:types, check:docs, actionlint all green. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01SAcqrz3FcadkYr3xG32CjK --- .github/workflows/ci.yml | 6 ++-- .github/workflows/junie-review.yml | 8 +++-- .github/workflows/pages.yml | 53 +++++++++++++++++------------- FRAMEWORKS.md | 7 ++-- docs/index.html | 53 +++++++++++++++--------------- docs/page.js | 16 +++++++++ package.json | 3 +- scripts/check-docs-sync.mjs | 21 ++++++++++++ 8 files changed, 107 insertions(+), 60 deletions(-) create mode 100644 scripts/check-docs-sync.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 99ad018..0ef2cf9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,7 +47,5 @@ jobs: - name: Landing page loads nothing from the network run: npm run check:docs - name: Landing page bundle is in sync with src/ - run: | - npm run build:docs - git diff --exit-code -- docs/ \ - || (echo "docs/ is stale — run 'npm run build:docs' and commit the result" && exit 1) + # Also fails on NEW untracked files under docs/ — a plain `git diff` does not. + run: npm run check:docs-sync diff --git a/.github/workflows/junie-review.yml b/.github/workflows/junie-review.yml index a7d7cda..22a64e7 100644 --- a/.github/workflows/junie-review.yml +++ b/.github/workflows/junie-review.yml @@ -39,9 +39,11 @@ jobs: steps: - uses: actions/checkout@v4 - name: Review the pull request - # Pinned to the newest release rather than the moving v1 tag, so the version - # running is the version reviewed here. Bump deliberately. - uses: JetBrains/junie-github-action@v1.7.4 + # Pinned to the commit behind release v1.7.4. A tag is a mutable ref the + # publisher can repoint; only the SHA guarantees the version running is the + # version that was reviewed — this workflow handles a repo secret. Bump by + # resolving the new release's commit, not by moving the tag name alone. + uses: JetBrains/junie-github-action@c2ae82fc9fbe0eb81942ceb3d9bd3f89a6b17b95 # v1.7.4 with: junie_api_key: ${{ secrets.JUNIE_API_KEY }} # Built-in structured review prompt, as opposed to a free-form instruction. diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 8802566..d9d2236 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -4,30 +4,28 @@ name: Deploy Pages # directly, so the page is rebuilt from src/ and checked before it goes live instead # of after. # -# REQUIRES A ONE-TIME SETTING. Settings → Pages → Build and deployment → Source must -# be "GitHub Actions", not "Deploy from a branch". Until it is, the deploy job fails -# with "Resource not accessible by integration" — the workflow is correct, the -# repository is still configured to serve the branch. The switch cannot be made from -# here: it needs a token with administration:write, which GITHUB_TOKEN is not. +# Triggered by CI completing on main rather than by the push itself, so a deploy +# implies the full suite passed — type-check, lint, tests, build, entry points, docs. +# A push that breaks a test turns main red and never reaches Pages; the previous +# wiring deployed on any docs push, green CI or not. workflow_dispatch stays as the +# manual escape hatch, and the deploy job refuses any ref that is not main. # -# It is reversible. Setting Source back to a branch restores the old behaviour and -# this workflow simply stops being able to deploy. +# REQUIRES A ONE-TIME SETTING. Settings → Pages → Build and deployment → Source must +# be "GitHub Actions", not "Deploy from a branch". Until it is, the first run fails — +# in the build job at configure-pages if Pages was never enabled, or in the deploy +# job with "Resource not accessible by integration" if Pages still serves a branch. +# Either way the workflow is correct; the repository setting is what needs to move. +# The switch cannot be made from here: it needs administration:write, which +# GITHUB_TOKEN is not. It is reversible — setting Source back to a branch restores +# the old behaviour and this workflow simply stops being able to deploy. on: - push: + workflow_run: + workflows: [ CI ] + types: [ completed ] branches: [ main ] - # docs/ holds both the page and its generated bundle, so a src/ change only - # matters here once it has been rebuilt into docs/ — which is what CI enforces. - paths: - - 'docs/**' - - '.github/workflows/pages.yml' workflow_dispatch: -permissions: - contents: read - pages: write - id-token: write - # Never cancel a deploy in flight: a half-published site is worse than a stale one. # Queue instead, so the last push wins without interrupting the one already going out. concurrency: @@ -38,6 +36,12 @@ jobs: build: name: Build and check runs-on: ubuntu-latest + # workflow_run fires on failure too — deploying is the one thing that must not. + if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' + # This job runs third-party code (npm postinstall scripts, the build toolchain), + # so it gets read-only. The Pages/OIDC grants live on the deploy job alone. + permissions: + contents: read steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -46,12 +50,10 @@ jobs: cache: 'npm' - name: Install dependencies run: npm ci - - name: Rebuild the page bundle from src/ - run: npm run build:docs - name: The committed page is in sync with src/ - run: | - git diff --exit-code -- docs/ \ - || (echo "docs/ is stale — run 'npm run build:docs' and commit the result" && exit 1) + # Rebuilds from src/ and fails on any difference, new untracked files included. + # Same script CI runs, so the two workflows cannot drift apart. + run: npm run check:docs-sync - name: The page loads nothing from the network run: npm run check:docs - uses: actions/configure-pages@v5 @@ -63,6 +65,11 @@ jobs: name: Deploy needs: build runs-on: ubuntu-latest + # workflow_dispatch can be pointed at any branch; production only ever serves main. + if: github.ref == 'refs/heads/main' + permissions: + pages: write + id-token: write environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} diff --git a/FRAMEWORKS.md b/FRAMEWORKS.md index 9525f58..f3e575a 100644 --- a/FRAMEWORKS.md +++ b/FRAMEWORKS.md @@ -331,9 +331,10 @@ await esbuild.build({ `cereale/min` is the whole library flattened into one minified ES module (33.9 KB, 9.6 KB gzipped) for import maps, `