Skip to content

Release prep: BAC v4 docs, metrics refresh + gate, and a BAC test that never ran - #71

Merged
dknauss merged 6 commits into
mainfrom
chore/release-prep-bac-v4
Aug 3, 2026
Merged

Release prep: BAC v4 docs, metrics refresh + gate, and a BAC test that never ran#71
dknauss merged 6 commits into
mainfrom
chore/release-prep-bac-v4

Conversation

@dknauss

@dknauss dknauss commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Release prep for the next version, plus one test defect found along the way.

Documentation the BAC v4 work never got

#68 updated the Block Accessibility Checks integration for BAC 4.0 but left no changelog trace, and readme.txt had no unreleased section at all — so the headline change of this release would have shipped invisible on WordPress.org. Recorded in both, along with the docs/current-metrics.md addition from #67.

BAC 4.0 replaced the registration API, so Borges now needs that plugin at 4.0 or later for its four checks to load. On 3.x the function_exists guard makes the integration a silent no-op — invisible to the user — so the requirement is now stated in the readme description, a new FAQ entry, and README.md.

Metrics refreshed and gated

docs/current-metrics.md was last verified 2026-07-05 at 49f623b; four merges had landed since. Every figure re-derived with the command the doc itself documents.

The footprint turned out smaller than recorded, not larger:

Metric Was Now
bibliography-builder.php 1,881 1,928
All first-party PHP 1,979 2,026
JS source 8,851 8,802
Release vendor/ ~1.0 MB 792 KB
Total installed ~2.1 MB ~1.9 MB
Distributed ZIP ~0.9–1 MB ~461 KB

The ZIP moved enough to be suspicious, so it was checked for completeness before recording — 242 entries, unzip -t clean, all citeproc and CSL payloads present. It is a real reduction, not a short archive.

Nothing caught that drift, so composer verify:metrics (.github/scripts/verify-metrics.sh) now runs in CI. It checks the lines-of-code figures and re-runs the persistence/hook audit that underpins the zero-query runtime claim. It deliberately does not assert the du-based footprint or built-asset byte sizes: du reports allocated blocks and differs between macOS and the Linux runner, and webpack output is only byte-stable for a fixed toolchain. Asserting those would produce failures that say nothing about the repository, so they stay hand-verified and the script says so. Verified in both directions — exit 0 clean, exit 1 on a perturbed figure and on an introduced update_option call.

The BAC test never actually ran

scripts/test-a11y.sh booted Playground with --auto-mount --login and no blueprint, so BAC was never installed. The test that covers the integration detects BAC, skips when absent, and the suite still reported green — in CI too. The integration shipped in #68 with zero end-to-end coverage, which matters because BAC 4.0 silently ignores hooks registered under their pre-4.0 names: every check simply passes.

The assertions were also vacuous. They targeted .ba11y-block-indicator--error / --warning, classes with zero occurrences in v4 (it replaced them with a validation toolbar button). A .not.toBeVisible() on a class that no longer exists cannot fail.

The environment now installs BAC, and assertions read the block-accessibility-checks data store — the interface v4 documents for validation state. Verified non-vacuous: renaming the editor filter back to ba11yc_validate_block makes the test fail. All 5 a11y tests pass, none skipped.

Installing BAC also surfaced a race in the publish helper. BAC registers an error-level post_title_required editor check that holds core's post-saving lock while the title is empty; the helper set the title and saved in the same tick, so the save was rejected. This is not a Borges defect — a plain paragraph post with no bibliography block fails identically, and publishing through the UI works fine. The helper now waits for the lock to lift and verifies the post actually reached publish, instead of returning an auto-draft permalink that 404s later in the test.

Security hardening

PMID records now resolve through wp_safe_remote_get() rather than wp_remote_get(). The request follows up to three redirects, and only the safe variant runs each hop through wp_http_validate_url, which blocks targets on the site's own network. The exposure was narrow — the PMID is validated ^\d{1,8}$ before use and the endpoint host is a fixed constant, so the redirect chain was the only part of the request an upstream change could point somewhere unintended — but the safe variant is the correct default for an outbound call the plugin doesn't fully control.

Done test-first. The PHPUnit bootstrap now records which HTTP helper a call reached for, so the assertion is on the function rather than only the URL. Confirmed the assertion fails against the old call site before the change.

The skip mechanism, not just the skip

The commit above fixes why the BAC test never ran. This fixes how that went unnoticed: the test called test.skip() whenever BAC was absent, and a skip is indistinguishable from a pass on a green run.

It now skips gracefully for local runs without the plugin, but throws when CI is set, naming the blueprint and the script flag to check. Verified by booting Playground with no blueprint and CI=1 — the run goes red with an actionable message instead of quietly reporting success over no coverage.

Risk

Low. Documentation, a metrics refresh, a new CI check, and test-only changes. No plugin runtime code is touched.

Verification

Jest 660 passed, PHPUnit 174 tests / 394 assertions, PHPCS clean, Psalm clean, ESLint clean, a11y suite 5/5 with none skipped, verify-metrics green.

Deliberately not included: no version bump. That is a separate call when you are ready to tag.

🤖 Generated with Claude Code

@codecov

codecov Bot commented Aug 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.01%. Comparing base (8945eeb) to head (0011288).

Additional details and impacted files
@@           Coverage Diff           @@
##             main      #71   +/-   ##
=======================================
  Coverage   81.01%   81.01%           
=======================================
  Files          43       43           
  Lines        3113     3113           
  Branches      522      522           
=======================================
  Hits         2522     2522           
  Misses        185      185           
  Partials      406      406           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

dknauss and others added 6 commits August 3, 2026 07:35
PR #68 updated the Block Accessibility Checks integration for BAC 4.0 but
left no changelog trace, and readme.txt had no unreleased section at all.
Record both, along with the docs/current-metrics.md addition from #67.

BAC 4.0 replaced the registration API, so Borges now needs that plugin at
4.0+ for its four checks to load. On 3.x the function_exists guard makes
the integration a silent no-op, which is invisible to the user, so state
the requirement in the readme description, a new FAQ entry, and README.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The doc was last verified 2026-07-05 at 49f623b; #66, #67, #68 and #70
have landed since. Re-derive every figure with the command the doc itself
documents.

Lines of code moved with the BAC v4 integration: main plugin file
1,881 -> 1,928, all first-party PHP 1,979 -> 2,026, JS source
8,851 -> 8,802.

The installed footprint is smaller than recorded rather than larger:
release vendor/ 792 KB (was documented ~1.0 MB), total ~1.9 MB (was
~2.1 MB), and the distributed ZIP ~461 KB (was ~0.9-1 MB). The ZIP was
checked for completeness -- 242 entries, unzip -t clean, all citeproc and
CSL payloads present -- so this is a real reduction, not a short archive.
Record the exact byte count alongside the rounded figure so the next
check is unambiguous.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The metrics doc is hand-verified and had gone stale across three merges
with nothing to catch it. Add verify-metrics.sh, wired into the Quality
job and exposed as composer verify:metrics, so drift fails CI instead.

The gate checks the three lines-of-code figures and re-runs the
persistence/hook audit that underpins the zero-query runtime claim. It
deliberately does not assert the du-based footprint figures or built
asset byte sizes: du reports allocated blocks and differs between macOS
and the Linux runner, and webpack output is only byte-stable for a fixed
toolchain. Asserting those would produce failures that say nothing about
the repository, so they stay hand-verified and the script says so.

Placed before the build steps so it cannot false-fail on a checkout with
no build artifacts. Verified in both directions: exit 0 on a clean tree,
exit 1 on a perturbed figure and on an introduced update_option call.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The accessibility Playground booted with no blueprint, so Block
Accessibility Checks was never installed, so the test that covers the BAC
integration skipped itself on every run -- including CI, which still
reported green. The integration shipped in #68 had no end-to-end coverage
at all, which matters because BAC 4.0 silently ignores hooks registered
under their pre-4.0 names: every check just passes.

Install BAC in the a11y environment and assert against the
block-accessibility-checks data store rather than BAC's markup. The old
assertions targeted .ba11y-block-indicator--error/--warning, classes v4
removed in favour of a validation toolbar button, so the negative
assertions could not have failed. Verified in both directions: renaming
the editor filter back to ba11yc_validate_block makes the test fail.

Installing BAC also exposed a race in the publish helper. BAC registers
an error-level post_title_required editor check that holds core's
post-saving lock while the title is empty; the helper set the title and
saved in the same tick and the save was rejected. This is not a Borges
defect -- a plain paragraph post with no bibliography block fails the
same way, and publishing through the UI works. Wait for the lock to lift,
and verify the post reached publish instead of returning an auto-draft
permalink that 404s later in the test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The PMID resolver follows up to three redirects. wp_remote_get follows
them anywhere, including a host on the site's own network; only
wp_safe_remote_get runs each hop through wp_http_validate_url.

The exposure was narrow -- the PMID is validated against ^\\d{1,8}$
before use and the endpoint host is a fixed constant, so the redirect
chain was the one part of the request an upstream change could have
pointed somewhere unintended -- but the safe variant is the correct
default for an outbound call the plugin does not fully control.

The test bootstrap now records which HTTP helper a call reached for, so
the assertion is on the function rather than only the URL, and fails if
the call site regresses.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The previous commit fixed why the BAC integration test never ran. This
fixes how that went unnoticed: the test skipped itself whenever Block
Accessibility Checks was absent, and a skip is indistinguishable from a
pass on a green run.

Keep the graceful skip for local runs without the plugin, but throw when
CI is set, naming the blueprint and the script flag to check. If
blueprint provisioning ever breaks again, the run goes red instead of
quietly reporting success over no coverage.

Verified by booting Playground with no blueprint and CI=1: the test fails
with the intended message rather than skipping.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@dknauss
dknauss force-pushed the chore/release-prep-bac-v4 branch from 0d20c13 to 0011288 Compare August 3, 2026 14:58
@dknauss
dknauss merged commit 1140ad7 into main Aug 3, 2026
16 checks passed
@dknauss
dknauss deleted the chore/release-prep-bac-v4 branch August 3, 2026 19:42
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.

1 participant