fix(transformer): preload modules so babel-standalone can't break import(); add e2e + unified CI#36
Conversation
Adding .gitkeep for PR creation (default mode). This file will be removed when the task is complete. Issue: #35
…ort()
Babel-standalone (which compiles the `text/babel` mode files in the
browser) rewrites every dynamic `import('./x.js')` into a CommonJS
`require('./x.js')` call. `require` is undefined in the browser, so the
transformer mode failed at boot with:
Failed to load transformer: require is not defined
Fix: import `text-to-qp-transformer.js` and `text-transformer-test.js`
eagerly in app.html (real `<script type="module">`) and expose them on
`window.HumanLanguageApp`. The mode file now reads those names off the
shared window object — same pattern every other mode already uses for
the Wikidata client.
Verified end-to-end: navigating to #mode=transformer no longer shows the
banner; "Paris is the capital of France" produces a Q/P sequence.
Adds the test infrastructure that's been missing: every mode now has an
end-to-end smoke test, plus regression tests that guard the headline
issue-35 fix (the "Failed to load transformer: require is not defined"
banner stays gone, Transform runs to completion against Wikidata, Clear
empties the textarea).
* tests/e2e/app.spec.mjs – 9 Playwright tests over all six modes
* tests/e2e/playwright.config.mjs – Chromium-only, retries:1 on CI
* tests/unit/routing.test.mjs – 8 tests for parseHash/serializeHash
* tests/unit/ipa.test.mjs – 7 tests for toIpa / toIpaForEntity
with fetch stubbed via mock.fn
* scripts/serve-static.mjs – zero-dep static server (Node core only)
* scripts/run-e2e-local.mjs – boots server, reuses existing one if
already listening, runs Playwright
* scripts/run-unit-tests.mjs – orchestrates fast (gating) suites and
legacy live-Wikidata (informational)
suites with a 5-min per-suite timeout
* scripts/check-mjs-syntax.mjs – `node --check` on every .js / .mjs
* package.json – npm scripts wired up, @playwright/test
pinned as devDependency
* .gitignore – ignore Playwright artifacts
* docs/screenshots – before/after screenshots of the
transformer banner regression
All gating suites pass locally:
• 8 routing tests, 7 ipa tests (node --test)
• 29 files clean under check-mjs-syntax
• 9 Playwright e2e tests across alphabet / dictionary / ontology /
entities / properties / transformer
Subsumes the previous three workflows (test.yml, pages.yml, links.yml)
into one orchestrated pipeline that matches the structure of
link-foundation/js-ai-driven-development-pipeline-template/release.yml
trimmed for a static SPA (no npm publish, no changeset, no Docker).
Job graph
─────────
syntax-check ── unit-tests ── e2e-local ─┐
├──► pages-build ── pages-deploy ── e2e-deployed
link-check ──┘
Key changes vs the legacy workflows:
* `syntax-check` calls `scripts/check-mjs-syntax.mjs` (pure Node) instead
of the previous one-off `node --check app/routing.js && node --check
app/ipa.js`, so every .js/.mjs in the repo is now syntax-checked.
* `unit-tests` runs `scripts/run-unit-tests.mjs`, gating on the
routing/ipa unit suites and treating the legacy live-Wikidata
integration scripts as informational (preserves the previous
`continue-on-error` behaviour without burying it in step config).
* `e2e-local` is new: it boots `scripts/serve-static.mjs` and runs the
Playwright suite from `tests/e2e/` against `http://localhost:8000` on
every PR and main push, gating the Pages deploy.
* `pages-build` / `pages-deploy` keep the original Jekyll workflow but
now also depend on the new tests passing.
* `e2e-deployed` is new: same Playwright suite, re-run against the
freshly deployed Pages URL (reads `pages-deploy.outputs.page_url`),
so a deploy that breaks the SPA fails the workflow.
* `link-check` keeps the existing lychee + Web-Archive fallback logic
verbatim, just inlined as a single job.
* Concurrency: cancel-in-progress on main, queue on PR branches —
matches the template's policy and avoids cancelling checks on
PR force-pushes.
Compile the artifacts requested in the issue brief into docs/case-studies/issue-35/: * README.md — top-level summary and index * requirements.md — each requirement from #35 mapped to status in PR #36 * timeline.md — reconstructed timeline T0..T+5h with commit hashes * root-cause.md — proof that babel-standalone's env preset rewrites dynamic import() to a CommonJS require() call * solution-plans.md — chosen approach + rejected alternatives per requirement * ci-template-comparison.md — alignment with link-foundation/js-ai-driven-development-pipeline-template * external-research.md — upstream behaviour, related repos, downstream guidance
Working session summaryDone. PR #36 is now ready for review: #36 What shipped:
CI status on PR: 4/4 PR-gated checks pass (Syntax, Lychee, Unit, E2E-local). The 3 pages-* jobs correctly skip on PR and will run on merge to Deferred to follow-up (documented in This summary was automatically extracted from the AI working session output. |
🤖 Solution Draft LogThis log file contains the complete execution trace of the AI solution draft process. 💰 Cost: $10.560705📊 Context and tokens usage:Claude Opus 4.7: (3 sub-sessions)
Total: (5.0K new + 244.2K cache writes + 14.1M cache reads) input tokens, 78.2K output tokens, $10.544292 cost Claude Haiku 4.5:
Total: 14.0K input tokens, 475 output tokens, $0.016413 cost 🤖 Models used:
📎 Log file uploaded as Gist (5521KB)Now working session is ended, feel free to review and add any feedback on the solution draft. |
✅ Ready to mergeThis pull request is now ready to be merged:
Monitored by hive-mind with --auto-restart-until-mergeable flag |
This reverts commit 9a10f10.
|
Read again all requirements, and fully meet them #35 For example I clearly see, no JavaScript code was moved to ./js/src, we should have fewer files in the root of the repository. All CI/CD related code can be in ./js/scripts. We need to ensure all changes are correct, consistent, validated, tested, documented, logged and fully meet each and all discussed requirements in widest possible sense (check issue description and all comments in issue and in pull request, make sure each and every requirement listed before actually checking if they were addressed). Ensure all CI/CD checks pass. Please plan and execute everything in a single pull request, you have unlimited time and context, as context auto-compacts and you can continue indefinitely, until it is each and every requirement fully addressed, and everything is totally done. |
|
🤖 AI Work Session Started Starting automated work session at 2026-05-11T10:18:15.843Z The PR has been converted to draft mode while work is in progress. This comment marks the beginning of an AI work session. Please wait for the session to finish, and provide your feedback. |
Issue #35 asked for "all JavaScript should live in ./js/". The previous PR scope deferred this to a follow-up; reviewer feedback on PR #36 asked for it to be folded back in. This commit completes the migration: * js/src/ — application source consumed by the deployed HTML pages (app/, transformation/{text-to-qp-transformer,text-transformer-test}.js, and the nine top-level browser modules). * js/scripts/ — Node-only CI scripts and integration runners (former scripts/*.mjs plus the eight repo-root *-test.mjs files). * js/tests/ — node:test unit suites (unit/) and Playwright e2e specs (e2e/), preserving the template's tests/ convention one level down. Deployed pages stay at their public URLs (app.html, entities.html, properties.html, transformation/{index,test-ngram}.html, demo HTMLs) and have their <script src> + import paths rewritten to point at js/src/... The CI workflow, package.json scripts, both READMEs, the case study, and _config.yml's exclude list are updated to match. All gating tests still pass locally: * node js/scripts/check-mjs-syntax.mjs — 29 files clean * node js/scripts/run-unit-tests.mjs — 15/15 gating tests pass * node js/scripts/run-e2e-local.mjs — 9/9 Playwright tests pass
Working session summaryPR #36 is now out of draft, mergeable, and CI green. Summary of what landed in commit Migration completed (issue #35 requirement 4.1):
Verified locally: 29 files clean syntax · 15/15 gating unit tests pass · 9/9 Playwright tests pass (8.1s) CI confirmed green: run 25664970655 — all 4 PR-gated jobs ( PR: #36 This summary was automatically extracted from the AI working session output. |
🤖 Solution Draft LogThis log file contains the complete execution trace of the AI solution draft process. 💰 Cost: $8.142308📊 Context and tokens usage:Claude Opus 4.7: (2 sub-sessions)
Total: (5.2K new + 241.7K cache writes + 10.0M cache reads) input tokens, 64.0K output tokens, $8.142309 cost 🤖 Models used:
📎 Log file uploaded as Gist (4087KB)Now working session is ended, feel free to review and add any feedback on the solution draft. |
✅ Ready to mergeThis pull request is now ready to be merged:
Monitored by hive-mind with --auto-restart-until-mergeable flag |
Summary
Fixes #35.
The Transformer mode on the deployed SPA shipped broken — opening
app.html#mode=transformerrendered "Failed to load transformer:require is not defined" because
@babel/standalone'senvpresetrewrites dynamic
import()to a CommonJSrequire()call, and there isno
requirein the browser. There were also no e2e tests for any ofthe six SPA modes, so the regression had silently shipped. JavaScript
files were also scattered across the repo root rather than living under
a single
./js/tree.This PR ships every requirement from #35 in one go:
app.htmlnow preloads the transformermodules in a real
<script type="module">and stashes them onwindow.HumanLanguageApp.js/src/app/modes/transformer.jsxreadsthem off
windowinstead of doing a dynamicimport()that Babelrewrites.
js/tests/e2e/app.spec.mjs) — 9 testscovering all six modes plus three transformer-specific regression
assertions (banner-text negative check, button-enabled check,
transformation-runs check).
node:testunit suites (js/tests/unit/routing.test.mjs,js/tests/unit/ipa.test.mjs) — 15 tests, zero new runtime deps, theIPA suite stubs
globalThis.fetchwithnode:test'smock.fn..github/workflows/js.yml) — single workflowreplacing
test.yml+pages.yml+links.yml. Job graph:syntax-check → unit-tests → e2e-local + link-check → pages-build → pages-deploy → e2e-deployed.Deploy is gated on tests for the first time;
e2e-deployedre-runsPlaywright against the live Pages URL.
./js/(issue Transformer does not work, that needs to be fixed, and e2e tests for all other sections #35 requirement 4.1) —js/src/houses application source (app/,transformation/,plus the nine top-level browser modules formerly at the repo root).
js/scripts/houses every Node-only CI script and integrationrunner (former
scripts/*.mjsplus the eight repo-root*-test.mjsfiles).
js/tests/houses thenode:testunit suites and Playwright e2especs.
./js/src/...;_config.yml'sexcludelist keepsjs/scripts,js/tests, and the Node-only modules injs/src/out of thedeployed Pages artifact.
docs/case-studies/issue-35/— 7 markdown filescovering requirements, timeline, root-cause, solution plans,
CI-template comparison, and external research.
Root cause
Full proof and call chain in
docs/case-studies/issue-35/root-cause.md.Before / after
Test plan
node js/scripts/check-mjs-syntax.mjs— 29 files cleannode js/scripts/run-unit-tests.mjs— 8 routing + 7 ipa tests pass (gating); 7 informational suites also runnode js/scripts/run-e2e-local.mjs— 9 Playwright tests pass (Chromium, ~8s)app.html#mode=transformer, click Load example, click Transform — Q/P sequence rendersjs.ymlgreen on this PR after the move (run 25664970655 — all 4 PR-gated jobs ✓)e2e-deployedgreen after merge tomain(post-deploy verification)Fixes #35