Commit Graph
3 Commits
Author SHA1 Message Date
Claude 057162e45b 🔖 fix: sync package-lock, and stamp the version fallbacks from the build
Junie's review on #16 caught the lock, and it was worse than reported:
package-lock.json said 0.3.0, so it had already missed the 0.4.0 release. It
does not ship (npm excludes it from tarballs, and `files` lists only dist, src,
FRAMEWORKS.md and CHANGELOG.md) and `npm ci` never complained because it only
diffs dependencies, not the project's own version — which is exactly why it
drifted two releases without anyone noticing. Regenerated with
`npm install --package-lock-only`.

The other half was the two version strings in docs/index.html: the brand badge
and the "It is still 0.x" line. Both are no-JavaScript fallbacks — page.js
overwrites them from meta.js — so they are right in a browser and stale in a
text reader or a scraper. Bumping them by hand is what failed on 0.4.0 and
again here, and it is the "release facts hand-bumped beside their generator"
finding from the code review.

So build-docs.mjs now stamps them, next to the meta.js it already writes. The
docs-sync gate turns a forgotten bump into a CI failure instead of a review
comment. Both regexes are asserted: renaming the markup fails the build with
the pattern that stopped matching, rather than silently stamping nothing —
verified by renaming the id and watching it exit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SAcqrz3FcadkYr3xG32CjK
2026-08-20 16:34:49 +00:00
Claude e626a1003a 🔧 fix: generate .nojekyll instead of hand-editing generated files
The previous commit appended the .nojekyll rationale to
docs/vendor/README.md — a file whose own first line reads "Generated by
npm run build:docs. Do not edit by hand." CI's "Landing page bundle is in
sync with src/" step regenerated it, the text vanished, git diff was
non-empty and all three Node jobs failed.

The guard did its job; I was the one who put a hand-written paragraph in a
generated file. The note now lives in the generator, and build:docs writes
docs/.nojekyll itself so it is part of the generated set rather than a
loose file that a docs/ rewrite could drop.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SAcqrz3FcadkYr3xG32CjK
2026-08-05 15:14:20 +00:00
Claude c828f5cfe9 🌾 feat: rebuild the landing page, and stop it from rotting again
The old page had been quietly broken for some time. It loaded
@babel/standalone from an **unpinned** CDN URL, which rolled over to Babel
8 and dropped the `proposal-class-properties` plugin the page asked for, so
Babel.transform threw before it ever reached the decorators — and the
decorator config it passed was `{ legacy: true }`, which 0.2.0 had already
made wrong. Nothing on the page said so. The copy was still selling the
0.1.0 pitch ("Spring-like"), listed about half the decorators, showed
`npm install cereale` for a package the registry returns 404 for, and
claimed "Zero overhead" against a README that publishes the real
microsecond costs.

The rebuild is one self-contained page: hand-written CSS, no Tailwind CDN,
no CodeMirror, and a vendored compiler pinned by package.json. It loads
nothing from the network. The playground runs the real bundled library
across six examples, all verified in a headless browser. The reference
covers all 68 decorators and the full API, counted from the bundle at
runtime so it cannot drift.

The hero's compiler error is not typed into the HTML. scripts/build-docs.mjs
compiles the snippets with the real tsc and writes the verbatim diagnostics
into docs/diagnostics.js, failing the build if a snippet the page calls a
compile error ever compiles — and two snippets that must compile guard
against the harness passing vacuously.

Three guards keep it honest, all wired into CI:
- check:docs fails on any remote subresource
- build:docs + git diff fails if docs/ is stale against src/
- check:types compiles a consumer against dist/ with no DOM lib, no
  @types/node and no skipLibCheck

That last one found a real packaging defect: `fromRequest` was declared as
taking the global `Request`, so cereale's own published .d.ts raised
"Cannot find name 'Request'" in any project whose lib and types did not
happen to supply it — inside a dependency, in code they may never call, and
unfixable from the outside. It now takes a structural JsonBody, which a
Request still satisfies. The library's own type tests had been hiding it by
enabling both DOM and skipLibCheck.

An adversarial review of the finished page caught four more: the lede
claimed *every* rule is type-checked (@IsDefined and @IsNotIn deliberately
are not), the guarantee section was wrong about the mechanism (a legacy
decorator does get design:type under emitDecoratorMetadata — the real claim
is about its type signature), one sample called a Movie method on a Media[]
and did not compile, and "nested objects come back as real classes" omitted
that you have to declare them. WCAG contrast was measured rather than
eyeballed: seven real failures fixed in the two themes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SAcqrz3FcadkYr3xG32CjK
2026-08-05 10:03:16 +00:00