Skip to content

refactor: give the client a textUtils mirror so escapeRegExp stops being re-inlined (#5790) - #5986

Merged
atomantic merged 1 commit into
mainfrom
claim/issue-5790
Sep 3, 2026
Merged

refactor: give the client a textUtils mirror so escapeRegExp stops being re-inlined (#5790)#5986
atomantic merged 1 commit into
mainfrom
claim/issue-5790

Conversation

@atomantic

Copy link
Copy Markdown
Owner

Summary

The browser cannot import server/lib/textUtils.js, so the client had no home for the RegExp escape — and every new caller pasted the character class again. Six private copies had accumulated across client/src/lib/, client/src/components/, client/src/pages/ and a hook test.

That gap also forced the documented hole in the server-side guard: server/lib/scenePrompt.js is held in sync with its client mirror, so it could not migrate to escapeRegExp while the client had no equivalent call to mirror. It was the guard's single exemption.

  • New client/src/lib/textUtils.js — the declared client mirror of server/lib/textUtils.js. Partial on purpose: only escapeRegExp crosses, since countWords already mirrors through client/src/utils/formatters.js and nothing on this side calls trimTo/kebabCase. Registered in client/src/lib/index.js and the README.md catalog, and pinned against the server copy by a compareDeclaration parity test in server/lib/textUtils.test.js (which is what mirrorCoverage.test.js requires of a declared mirror).
  • Every client copy migrated to it: lib/loraTriggers.js, lib/editorialChecks.js, lib/manuscriptAnchors.js, lib/scenePrompt.js, components/CmdKSearch.jsx, pages/LoraDatasetDetail.jsx (2 sites), hooks/mountedRefConventions.test.js.
  • server/lib/scenePrompt.js migrated too, in the same change so the two mirrored declarations stay in sync — which retires the HOLDOUT exemption from the guard entirely.
  • The guard now scans client/src/ as well, via a new collectClientSources/readClientSource pair beside collectServerSources in server/lib/testHelper.js. Two deliberate differences from the server walk, documented at the helper: it counts .jsx (two copies lived in components, so a .js-only walk would report a clean tree) and it does NOT skip *.test.js (one copy lived in a client test; the server walk skips tests only because the guard file itself lives there and spells the idiom).

Test plan

  • cd client && npm test — 824 files / 10093 tests pass.
  • cd server && npm test — 1888 files / 38071 tests pass, including the scenePrompt mirror-parity suite and mirrorCoverage.
  • Fault-injection probe: re-inlining the escape in client/src/lib/uuid.js fails the new client-side guard with expected [ 'lib/uuid.js' ] to deeply equal []; reverted. The server-side half was already proven by the existing suite.
  • grep confirms the escape character class now appears in exactly two source files repo-wide: server/lib/textUtils.js and client/src/lib/textUtils.js.

Closes #5790

https://claude.ai/code/session_01Uz59AsJawa1Djqm2T9Fb8t

…ing re-inlined (#5790)

The browser cannot import `server/lib/textUtils.js`, so the client had no home
for the RegExp escape and every new caller pasted the character class again —
six private copies across `lib/`, `components/`, `pages/` and a hook test. That
gap also forced a documented hole in the server-side guard: `server/lib/
scenePrompt.js` is held in sync with its client mirror, so it could not migrate
to `escapeRegExp` while the client had no such call to mirror.

Adds `client/src/lib/textUtils.js` as the declared client mirror (the
`escapeRegExp` half only — `countWords` already mirrors via `utils/formatters.js`
and nothing on this side calls `trimTo`/`kebabCase`), registers it in the barrel
and catalog, and pins it against the server copy with a parity test. Every
client copy now imports it, including both sides of `scenePrompt.js`, which
retires the guard's single exemption.

The guard itself now scans `client/src/` too, via a new `collectClientSources`
beside `collectServerSources`. That walk counts `.jsx` (two of the copies lived
in components) and does NOT skip tests (one lived in a client test), so a
re-inlined copy fails the suite on either side of the mirror.

Claude-Session: https://claude.ai/code/session_01Uz59AsJawa1Djqm2T9Fb8t
@atomantic
atomantic merged commit 17be257 into main Sep 3, 2026
7 checks passed
@atomantic
atomantic deleted the claim/issue-5790 branch September 3, 2026 04:48
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.

Give the client a textUtils mirror so escapeRegExp stops being re-inlined there

1 participant