Runtime matrix: test the release package, formatter parity, and write routes; add dev write-API Playground - #105
Merged
Merged
Conversation
… routes; add dev write-API Playground
The matrix mounted the source checkout, which has no vendor/, so
citeproc-php was absent in every cell and the formatter never ran there.
Each cell now packages the release (npm run package:release) and tests
what users install, then additionally:
- formats tests/fixtures/csl-styles/items.json in all nine styles on that
PHP version from the package's own vendor/ and compares with the
reviewed goldens byte for byte (scripts/runtime-matrix/format-styles.php);
- enables the opt-in write routes with a test-only mu-plugin and, over
real HTTP with an application password, runs a dry run, gets 428
without If-Match and 412 with a stale ETag, commits a write, checks
the new entry in the text route and on the front end, and checks the
rewritten block's markup equals save()'s (check-blocks.php). Real HTTP
also proves Authorization/ETag/If-Match survive Apache and nginx.
playground/blueprint-write-api.json (development only, unlinked) boots
the main build with the routes enabled and a borgesWrite helper in the
editor console (playground/dev/): each call dry-runs first; { commit:
true } writes with the dry run's ETag and reloads the editor.
Verified locally against the packaged release in Playground: 180/180
style lines match; the smoke script's own HTTP write sequence passes;
check-blocks reports the rewritten block valid; the console helper's
dry runs, 409 message, and committed write work, and the editor reopens
with every block valid.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KbVuMPN7YTcV27vwsG3LZ2
dknauss
marked this pull request as ready for review
September 26, 2026 19:59
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #105 +/- ##
=======================================
Coverage 87.20% 87.20%
=======================================
Files 54 54
Lines 5847 5847
Branches 597 597
=======================================
Hits 5099 5099
Misses 267 267
Partials 481 481 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
The web server keeps running the opcache-cached wp-config.php without WP_ENVIRONMENT_TYPE for a couple of seconds after wp config set, so application passwords are ignored and the write requests arrive logged out (403). Poll an authenticated /wp/v2/users/me until it returns 200, and fail fast when no application password was created. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KbVuMPN7YTcV27vwsG3LZ2
dknauss
pushed a commit
that referenced
this pull request
Sep 26, 2026
Full GPL CSL styles and locales (#103), Phase 05 M0-M3 (stable IDs, review routes and abilities, opt-in citation and block write routes: #104, #106), the save-markup language fix, reference-manager .bib fixes, the Playground demo page (#102), and the runtime matrix on the release package with formatter-parity and write-route checks (#105). Version bumped in the plugin header, block.json, readme.txt Stable tag, the POT header, and the package manifests. CHANGELOG [Unreleased] is dated as 1.7.0; readme.txt gains a user-facing changelog entry, an Upgrade Notice, and an FAQ note on the opt-in write routes. README highlights and STATE/ROADMAP move to the 1.7.0 baseline. Tested up to stays 7.1: WordPress latest is 7.1.2, which CI's runtime matrix exercises, including formatter parity across all nine styles. package-release.sh now also prunes .git directories from vendor/. When Composer falls back from dist to a git clone (as it did in this sandbox), the ZIP otherwise carried 4 MB of git metadata. Release checklist gates run locally: lint:js, lint:css, lint:i18n, npm audit (0), composer audit (none), Jest 873 passed / 2 skipped, PHPUnit 318 OK (the 4 vendor deprecations already on main), build, package:release (552,718-byte ZIP). citeproc-php v2.7.1 is current. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KbVuMPN7YTcV27vwsG3LZ2
dknauss
added a commit
that referenced
this pull request
Sep 26, 2026
* chore(release): 1.7.0 Full GPL CSL styles and locales (#103), Phase 05 M0-M3 (stable IDs, review routes and abilities, opt-in citation and block write routes: #104, #106), the save-markup language fix, reference-manager .bib fixes, the Playground demo page (#102), and the runtime matrix on the release package with formatter-parity and write-route checks (#105). Version bumped in the plugin header, block.json, readme.txt Stable tag, the POT header, and the package manifests. CHANGELOG [Unreleased] is dated as 1.7.0; readme.txt gains a user-facing changelog entry, an Upgrade Notice, and an FAQ note on the opt-in write routes. README highlights and STATE/ROADMAP move to the 1.7.0 baseline. Tested up to stays 7.1: WordPress latest is 7.1.2, which CI's runtime matrix exercises, including formatter parity across all nine styles. package-release.sh now also prunes .git directories from vendor/. When Composer falls back from dist to a git clone (as it did in this sandbox), the ZIP otherwise carried 4 MB of git metadata. Release checklist gates run locally: lint:js, lint:css, lint:i18n, npm audit (0), composer audit (none), Jest 873 passed / 2 skipped, PHPUnit 318 OK (the 4 vendor deprecations already on main), build, package:release (552,718-byte ZIP). citeproc-php v2.7.1 is current. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KbVuMPN7YTcV27vwsG3LZ2 * Parse each CSL style once per format request CiteProc::render() calls init() every time, which builds a new Context, reads and parses the locale file, and rebuilds the style's object tree: about 3 ms, against well under 1 ms to render an entry. With one render per entry (the fix that stopped an "et al." entry from dropping the next entry's "and"), 50 entries took about 90 ms, against about 8 ms in 1.6.0 with its short stand-in styles. Bibliography_Builder_Reusable_CiteProc parses once, records every property of every object in the parsed style tree, and before each later render restores them, resets the Context's per-render lists, and zeroes Layout's static cited-item counter. Each entry renders against the state a fresh parse would give it: 50 entries now take about 25 ms. The nine style goldens still match byte for byte. A new test formats the corpus in reverse order, putting the "et al." and APA 21+ entries ahead of the short author lists, and requires every entry to match its golden line; with the restore disabled, both the goldens and the new test fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KbVuMPN7YTcV27vwsG3LZ2 * Drop the #[\Override] attribute from the reusable formatter PHP 7.4 reads an attribute on its own line as a comment (php -l on 7.4 passes, and so does the PHP 7.4 runtime smoke), but Copilot flagged it as a 7.4 parse error, and compatibility scanners can do the same. It does nothing at runtime, so drop it, and turn off Psalm's MissingOverrideAttribute, which cannot apply to a plugin that supports PHP 7.4. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KbVuMPN7YTcV27vwsG3LZ2 --------- Co-authored-by: Claude <noreply@anthropic.com>
dknauss
pushed a commit
that referenced
this pull request
Sep 26, 2026
Since #106, all three nginx cells of the full matrix fail at the settings PATCH with nginx's own "405 Not Allowed": the smoke test sent REST requests to /?rest_route=, and for a directory request nginx's index module only hands GET, HEAD, and POST to index.php, so PATCH, PUT, and DELETE fall through to the static handler. #105's write steps used only GET and POST, so they passed. Sites are not affected: WordPress builds plain-permalink REST URLs as index.php?rest_route=, and pretty permalinks reach index.php through try_files. Send every smoke REST request to index.php?rest_route= (REST_URL), and add nginx-php83-wplatest to the pull-request matrix, which had only Apache cells and so could not catch this before merge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KbVuMPN7YTcV27vwsG3LZ2
4 of 10 tasks
dknauss
added a commit
that referenced
this pull request
Sep 27, 2026
Since #106, all three nginx cells of the full matrix fail at the settings PATCH with nginx's own "405 Not Allowed": the smoke test sent REST requests to /?rest_route=, and for a directory request nginx's index module only hands GET, HEAD, and POST to index.php, so PATCH, PUT, and DELETE fall through to the static handler. #105's write steps used only GET and POST, so they passed. Sites are not affected: WordPress builds plain-permalink REST URLs as index.php?rest_route=, and pretty permalinks reach index.php through try_files. Send every smoke REST request to index.php?rest_route= (REST_URL), and add nginx-php83-wplatest to the pull-request matrix, which had only Apache cells and so could not catch this before merge. Claude-Session: https://claude.ai/code/session_01KbVuMPN7YTcV27vwsG3LZ2 Co-authored-by: Claude <noreply@anthropic.com>
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
What changed?
1. The runtime matrix tests what users install.
vendor/, so citeproc-php was missing in every cell and the formatter never ran on PHP 7.4–8.4.npm run package:releaseand mounts the package (WP_BIBLIO_PLUGIN_DIR), with its production-onlyvendor/.2. New smoke steps in every cell (
scripts/runtime-matrix/smoke.sh):Formatter parity (
format-styles.php, run withwp eval-file). It formatstests/fixtures/csl-styles/items.jsonin all nine styles on that cell's PHP version and compares the output byte for byte with the reviewed goldens. Until now, PHPUnit pinned the styles on PHP 8.3 only.Write routes over real HTTP. A test-only mu-plugin enables the routes and an application password authenticates, with
WP_ENVIRONMENT_TYPE=local. The step:428withoutIf-Matchand412with a stale ETag;check-blocks.phpthat the rewritten block's markup equalssave()'s.Real HTTP also shows that
Authorization,ETag, andIf-Matchsurvive both Apache and nginx.3. A development-only Playground for the write routes (
playground/blueprint-write-api.json, not linked from any badge).borgesWritehelper in the block editor's browser console (playground/dev/, fetched frommain).{ commit: true }it writes, sending the dry run's ETag, then reloads the editor so a stale editor can't overwrite the write on save.npm run playground:build, andsrc/playground-demo.test.jskeeps it in sync.Once merged, open it with:
https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/dknauss/Borges/main/playground/blueprint-write-api.jsonDocs: README (the matrix section and blueprint maintenance),
CLAUDE.md,docs/rest-write-routes.md(a new "Trying it" section), and the CHANGELOG.Why? To close the gaps named after #104: the formatter and the write routes had no coverage across PHP and WordPress versions, and there was no easy way to try the write routes by hand.
Validation
npm run lint:jspassesnpm run lint:css: no CSS changesnpm run lint:i18n: no source strings changednpm run testpasses (873)composer test:php(310) andverify-metrics.shpassformat-styles.php:styles-ok 180;check-blocks.php:blocks-ok 1;list(), the add and patch dry runs, the clear 409 message on an APA reorder, and a committed add. The editor then reopens with every block valid and nothing unsaved.mariadbpull and the mirror's CDN is blocked. This PR's CI runs the 3-cell PR subset, and the full 10 cells run on merge.Checklist
🤖 Generated with Claude Code
https://claude.ai/code/session_01KbVuMPN7YTcV27vwsG3LZ2
Generated by Claude Code