Skip to content

docs(changelog): file shipped fixes under 0.1.0, log this round under Unreleased - #3

Merged
cverorg merged 3 commits into
mainfrom
fix/health-check-gaps
Sep 28, 2026
Merged

cverorg merged 3 commits into
mainfrom
fix/health-check-gaps

Conversation

@cverorg

@cverorg cverorg commented Sep 28, 2026

Copy link
Copy Markdown
Member

The published liquidframe@0.1.0 tarball was built from b4f3f80 (npm gitHead;
dist.shasum matches a local npm pack of that commit), so the wheel clamp,
clock alignment, a11y and test-suite entries shipped in 0.1.0 rather than
being unreleased.

---- PR description ----

PR title: Fix script-loading docs, gate releases on CHANGELOG, and make CI steps honest

Fixes the gaps from the 2026-09-28 health check. Priority: things that break users, then things that make CI look greener than it is. A few hygiene items are also done. Branch base: main @ 8de4d40.

What's fixed

# Issue Fix
D-1 README (L109, L138) and the liquidframe.js header say the file works as a plain <script>. It's an ES module, so Chromium throws Unexpected token 'export' and window.liquidframe is undefined. The docs now say <script type="module" src="liquidframe.js"></script>. That form auto-runs enhance() and exposes window.liquidframe. No code change.
C-1 npm liquidframe@0.1.0 was built from b4f3f80, but CHANGELOG listed its fixes as [Unreleased], and the readiness gate couldn't notice. The shipped entries now sit under ## [0.1.0] - 2026-08-04. The gate has a release mode (a v* tag run or --release) that fails while [Unreleased] still has entries. prepublishOnly runs the gate with --release, so a manual npm publish is gated too.
C-2 The tag/version check never ran, because CI didn't trigger on tags. ci.yml now also runs on push: tags: ["v*"].
C-3 The test named "one clock" had no clock assertion. startClock and the typeof window auto-run branch never ran in any test. Added tests for: the first render, the roll-over at the minute boundary (fake timers), one clock per element across repeated enhance() calls, and auto-run (readyState loading → waits for DOMContentLoaded; interactive → runs immediately).
C-4 The Build step is a silent no-op that shows up green. ci.yml and scripts/test.sh now print that the build was skipped when there's no build script.
H-1 npm test needs Node ≥ 21 (the node --test glob), but package.json declared no engines. "engines": { "node": ">=21" } (lockfile root updated to match).
H-2 No repository / homepage / bugs fields. Added. They show up on npm only after the next publish.
H-4 The pre-push hook needs a manual opt-in that wasn't documented. New README "Contributing" section with git config core.hooksPath hooks.
H-5 scripts/test.sh re-ran npm ci every time, because a zero-dep repo never gets node_modules/. It installs only when dependencies are declared.
H-6 Dead _attrs branch in the test DOM stub. FakeEl.setAttribute() added, so [data-lf-clock] matches. This is what made the C-3 tests possible.

How it was verified

Red first

Before any fix, the new contract/gate tests failed (npm test, Node v22.22.2):

not ok 32 - a release tag run fails while [Unreleased] still has entries
not ok 33 - --release (used by prepublishOnly) fails while [Unreleased] still has entries
not ok 37 - docs never promise a plain (classic) <script> load
not ok 38 - CI runs on v* tag pushes, so the release-tag check is reachable
not ok 39 - npm publish runs the release gate in release mode
not ok 40 - the build step says so when there is nothing to build
not ok 41 - package.json declares the Node version `npm test` needs
not ok 42 - package.json links back to the GitHub repo
not ok 43 - README tells contributors how to enable the pre-push hook
# pass 34
# fail 9

The C-3 / H-6 tests cover code that already works, so I checked them by breaking that code on purpose (reverted after each run):

Mutation Result
clock back to a fixed 30s setInterval not ok minute-boundary test + one-clock test
clock not wrapped in once() not ok one-clock-per-element
auto-run block disabled not ok both auto-run tests
auto-run ignores readyState === 'loading' not ok DOMContentLoaded test
stub's [attr] branch back to return false 5 not ok (attr + clock + auto-run tests)

Green

# tests 43
# pass 43
# fail 0

bash scripts/test.sh:

→ test
→ build: skipped (no build script in package.json)
→ release readiness
Release readiness passed for v0.1.0.
✅ ALL GREEN

Before this change, the same script printed → install deps / up to date, audited 1 package on every run, and → build with no output.

D-1 in real Chromium (Playwright 1.56, headless)

Test page: <span data-lf-clock>9:41</span> plus the script tag.

<script src="/liquidframe.js">                -> pageerrors: ["Unexpected token 'export'"], window.liquidframe: undefined, clock: "9:41"
<script type="module" src="/liquidframe.js">  -> pageerrors: [], window.liquidframe: [enhance, setChromeMode, setTitanium], clock: "09:41"

C-1: where 0.1.0 came from, and what the gate says now

$ npm view liquidframe gitHead dist.shasum
gitHead: b4f3f806d148e4f44c88cae82d39bb05b26ae097
dist.shasum: 13816dfd11a658b26b7a90e4ec8c2fb480289775   # == `npm pack` of b4f3f80
$ npm publish --dry-run --registry=http://127.0.0.1:9
> node scripts/check-release-readiness.mjs --release
Release readiness FAILED (1):
  ✗ CHANGELOG.md still has entries under [Unreleased]; move them into the "## [0.1.0]" section (or bump the version) before releasing.

Plain node scripts/check-release-readiness.mjs (branch/PR runs) still passes. [Unreleased] entries are normal between releases.

H-1 on Node 20.20.2

npm ci   -> npm warn EBADENGINE ... required: { node: '>=21' }, current: { node: 'v20.20.2' }
npm test -> Could not find '/…/test/**/*.test.mjs'

engines only turns this into an up-front warning at install time. npm test on Node 20 still fails the same way.

Not verified here

  • GitHub Actions. I couldn't reach the GitHub API or Actions, so the new tags: ["v*"] trigger, the ::notice:: output and the multi-line Build step haven't been seen running on a real runner. The shell was only run locally through scripts/test.sh.
  • macOS. Nothing here is macOS-specific, and nothing was run on macOS.
  • npm page. The repository / homepage / bugs links will only show on npmjs.com after the next publish.
  • Live demo. index.html is unchanged. Its external resources (fonts, the cver.net logo, esm.sh) are blocked in this container.

Not done, and why

  • H-3 (README tagline "iPhone 16 Pro & 17 Pro"). Not changed. It was a deliberate recent edit by the maintainer, and I can't tell whether it's wrong or just ahead of the CSS. Please decide whether to revert it or add 17 Pro geometry.
  • The published 0.1.0 still has the wrong plain-<script> claim in its README. Fixing it needs a new release (e.g. 0.1.1). I didn't bump the version or publish. With this PR, npm publish requires moving [Unreleased] into a new version section first.
  • No v0.1.0 git tag. It would belong on b4f3f80. I didn't create it because it's a release action.
  • A classic-script (IIFE/UMD) build of liquidframe.js. I fixed the docs instead. A second artifact would be a new feature and would need a build step.
  • scripts/check-release-readiness.mjs, ci.yml and scripts/test.sh are vendored from a shared template. The changes here will need upstreaming to that template if other repos should get them.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Fo5qXvfknPTYfe3beJ3fZ7

Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01Fo5qXvfknPTYfe3beJ3fZ7

The "one clock" idempotency test never asserted anything about the clock,
and the attribute-selector branch of the DOM stub read an `_attrs` map that
was never set, so `[data-lf-clock]` never matched and startClock() and the
`typeof window` auto-run block were not executed by any test.

- FakeEl gains setAttribute(); the `[attr]` selector branch now works.
- Clock renders on enhance() and rolls over on the minute boundary
  (mock timers; fails against the old fixed 30s interval).
- Repeated enhance() starts exactly one clock per element.
- Loaded in a (fake) browser, the module exposes window.liquidframe and
  auto-runs enhance() on DOMContentLoaded, or immediately if already parsed.
- Rename the wheel idempotency test to what it actually asserts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fo5qXvfknPTYfe3beJ3fZ7
…st CI steps

- README / liquidframe.js header: liquidframe.js is an ES module, so a classic
  <script> fails with "Unexpected token 'export'" and window.liquidframe stays
  undefined. Document <script type="module" src="liquidframe.js"> instead,
  which auto-runs enhance() and exposes window.liquidframe.
- check-release-readiness.mjs: in release mode (v* tag run or --release) fail
  while CHANGELOG [Unreleased] still has entries; share the tag detection.
- package.json: prepublishOnly runs the gate with --release, so a manual
  `npm publish` is gated too; add repository/homepage/bugs and engines.node.
- ci.yml: also run on v* tag pushes so the tag/version check is reachable.
- ci.yml / scripts/test.sh: say "no build script" instead of a silent green
  Build step; test.sh only installs when dependencies are declared.
- README: document enabling the tracked pre-push hook.
- Tests: release gate fixtures and repo contract tests for the above.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fo5qXvfknPTYfe3beJ3fZ7
… Unreleased

The published liquidframe@0.1.0 tarball was built from b4f3f80 (npm gitHead;
dist.shasum matches a local `npm pack` of that commit), so the wheel clamp,
clock alignment, a11y and test-suite entries shipped in 0.1.0 rather than
being unreleased.

---- PR description ----

PR title: Fix script-loading docs, gate releases on CHANGELOG, and make CI steps honest

Fixes the gaps from the 2026-09-28 health check. Priority: things that break users, then things that make CI look greener than it is. A few hygiene items are also done. Branch base: `main` @ 8de4d40.

## What's fixed

| # | Issue | Fix |
|---|---|---|
| **D-1** | README (L109, L138) and the `liquidframe.js` header say the file works as a plain `<script>`. It's an ES module, so Chromium throws `Unexpected token 'export'` and `window.liquidframe` is `undefined`. | The docs now say `<script type="module" src="liquidframe.js"></script>`. That form auto-runs `enhance()` and exposes `window.liquidframe`. No code change. |
| **C-1** | npm `liquidframe@0.1.0` was built from b4f3f80, but CHANGELOG listed its fixes as `[Unreleased]`, and the readiness gate couldn't notice. | The shipped entries now sit under `## [0.1.0] - 2026-08-04`. The gate has a **release mode** (a `v*` tag run or `--release`) that fails while `[Unreleased]` still has entries. `prepublishOnly` runs the gate with `--release`, so a manual `npm publish` is gated too. |
| **C-2** | The tag/version check never ran, because CI didn't trigger on tags. | `ci.yml` now also runs on `push: tags: ["v*"]`. |
| **C-3** | The test named "one clock" had no clock assertion. `startClock` and the `typeof window` auto-run branch never ran in any test. | Added tests for: the first render, the roll-over at the minute boundary (fake timers), one clock per element across repeated `enhance()` calls, and auto-run (`readyState` `loading` → waits for DOMContentLoaded; `interactive` → runs immediately). |
| **C-4** | The Build step is a silent no-op that shows up green. | `ci.yml` and `scripts/test.sh` now print that the build was skipped when there's no build script. |
| **H-1** | `npm test` needs Node ≥ 21 (the `node --test` glob), but package.json declared no `engines`. | `"engines": { "node": ">=21" }` (lockfile root updated to match). |
| **H-2** | No `repository` / `homepage` / `bugs` fields. | Added. They show up on npm only after the next publish. |
| **H-4** | The pre-push hook needs a manual opt-in that wasn't documented. | New README "Contributing" section with `git config core.hooksPath hooks`. |
| **H-5** | `scripts/test.sh` re-ran `npm ci` every time, because a zero-dep repo never gets `node_modules/`. | It installs only when dependencies are declared. |
| **H-6** | Dead `_attrs` branch in the test DOM stub. | `FakeEl.setAttribute()` added, so `[data-lf-clock]` matches. This is what made the C-3 tests possible. |

## How it was verified

### Red first
Before any fix, the new contract/gate tests failed (`npm test`, Node v22.22.2):
```
not ok 32 - a release tag run fails while [Unreleased] still has entries
not ok 33 - --release (used by prepublishOnly) fails while [Unreleased] still has entries
not ok 37 - docs never promise a plain (classic) <script> load
not ok 38 - CI runs on v* tag pushes, so the release-tag check is reachable
not ok 39 - npm publish runs the release gate in release mode
not ok 40 - the build step says so when there is nothing to build
not ok 41 - package.json declares the Node version `npm test` needs
not ok 42 - package.json links back to the GitHub repo
not ok 43 - README tells contributors how to enable the pre-push hook
# pass 34
# fail 9
```
The C-3 / H-6 tests cover code that already works, so I checked them by breaking that code on purpose (reverted after each run):

| Mutation | Result |
|---|---|
| clock back to a fixed 30s `setInterval` | `not ok` minute-boundary test + one-clock test |
| clock not wrapped in `once()` | `not ok` one-clock-per-element |
| auto-run block disabled | `not ok` both auto-run tests |
| auto-run ignores `readyState === 'loading'` | `not ok` DOMContentLoaded test |
| stub's `[attr]` branch back to `return false` | 5 `not ok` (attr + clock + auto-run tests) |

### Green
```
# tests 43
# pass 43
# fail 0
```
`bash scripts/test.sh`:
```
→ test
→ build: skipped (no build script in package.json)
→ release readiness
Release readiness passed for v0.1.0.
✅ ALL GREEN
```
Before this change, the same script printed `→ install deps` / `up to date, audited 1 package` on every run, and `→ build` with no output.

### D-1 in real Chromium (Playwright 1.56, headless)
Test page: `<span data-lf-clock>9:41</span>` plus the script tag.
```
<script src="/liquidframe.js">                -> pageerrors: ["Unexpected token 'export'"], window.liquidframe: undefined, clock: "9:41"
<script type="module" src="/liquidframe.js">  -> pageerrors: [], window.liquidframe: [enhance, setChromeMode, setTitanium], clock: "09:41"
```

### C-1: where 0.1.0 came from, and what the gate says now
```
$ npm view liquidframe gitHead dist.shasum
gitHead: b4f3f80
dist.shasum: 13816dfd11a658b26b7a90e4ec8c2fb480289775   # == `npm pack` of b4f3f80
$ npm publish --dry-run --registry=http://127.0.0.1:9
> node scripts/check-release-readiness.mjs --release
Release readiness FAILED (1):
  ✗ CHANGELOG.md still has entries under [Unreleased]; move them into the "## [0.1.0]" section (or bump the version) before releasing.
```
Plain `node scripts/check-release-readiness.mjs` (branch/PR runs) still passes. `[Unreleased]` entries are normal between releases.

### H-1 on Node 20.20.2
```
npm ci   -> npm warn EBADENGINE ... required: { node: '>=21' }, current: { node: 'v20.20.2' }
npm test -> Could not find '/…/test/**/*.test.mjs'
```
`engines` only turns this into an up-front warning at install time. `npm test` on Node 20 still fails the same way.

## Not verified here
- **GitHub Actions.** I couldn't reach the GitHub API or Actions, so the new `tags: ["v*"]` trigger, the `::notice::` output and the multi-line Build step haven't been seen running on a real runner. The shell was only run locally through `scripts/test.sh`.
- **macOS.** Nothing here is macOS-specific, and nothing was run on macOS.
- **npm page.** The `repository` / `homepage` / `bugs` links will only show on npmjs.com after the next publish.
- **Live demo.** `index.html` is unchanged. Its external resources (fonts, the cver.net logo, esm.sh) are blocked in this container.

## Not done, and why
- **H-3 (README tagline "iPhone 16 Pro & 17 Pro").** Not changed. It was a deliberate recent edit by the maintainer, and I can't tell whether it's wrong or just ahead of the CSS. Please decide whether to revert it or add 17 Pro geometry.
- **The published 0.1.0 still has the wrong plain-`<script>` claim in its README.** Fixing it needs a new release (e.g. 0.1.1). I didn't bump the version or publish. With this PR, `npm publish` requires moving `[Unreleased]` into a new version section first.
- **No `v0.1.0` git tag.** It would belong on b4f3f80. I didn't create it because it's a release action.
- **A classic-script (IIFE/UMD) build of `liquidframe.js`.** I fixed the docs instead. A second artifact would be a new feature and would need a build step.
- **`scripts/check-release-readiness.mjs`, `ci.yml` and `scripts/test.sh` are vendored from a shared template.** The changes here will need upstreaming to that template if other repos should get them.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01Fo5qXvfknPTYfe3beJ3fZ7

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fo5qXvfknPTYfe3beJ3fZ7
@cverorg
cverorg merged commit e0353c1 into main Sep 28, 2026
1 check passed
@cverorg
cverorg deleted the fix/health-check-gaps branch September 28, 2026 16:39
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