Zerowidth CleanerAll measured guides

CLAUDE WATERMARK REMOVER · PRACTICAL TEST

Why does search find a token before the regex lastIndex?

String.search with our global regex starts its search from zero and restores lastIndex to 3. exec starting at 3 finds nothing. Cleanup shifts the token position but does not turn search into a cursor-based scan.

Tested October 20, 2026 · v24.19.0 · 4 measured runs

Open the Claude text cleaner · Full measured data

Code-point comparison for Marker before token

Measured inputs and outputs

These are locally constructed test strings, not evidence that Claude inserts these characters. We executed the saved homepage script snapshot with a minimal DOM harness and compared exact strings. The invisible-checkbox state and dash mode appear in each row. The observations below test this page's specific question. Destination observations run independently on the exact input and cleaned strings in the recorded Node runtime. We make no detector-score or statistical-watermark removal claim.

Before and after observations; full code points and strings are in the JSON download.
Fixture and modeInput string and code pointsOutput and cleaner statusObserved before / after
Marker before token
direct string / keep / invisible true
"A​B"
U+0041 U+200B U+0042
"AB"
Removed 1 invisible character
{"found":2,"lastIndexAfter":3,"execFromThree":null}
{"found":1,"lastIndexAfter":3,"execFromThree":null}
Plain token
direct string / keep / invisible true
"AB"
U+0041 U+0042
"AB"
No selected invisible characters found
{"found":1,"lastIndexAfter":3,"execFromThree":null}
{"found":1,"lastIndexAfter":3,"execFromThree":null}
Token at zero
direct string / keep / invisible true
"B"
U+0042
"B"
No selected invisible characters found
{"found":0,"lastIndexAfter":3,"execFromThree":null}
{"found":0,"lastIndexAfter":3,"execFromThree":null}
Missing token
direct string / keep / invisible true
"AX"
U+0041 U+0058
"AX"
No selected invisible characters found
{"found":-1,"lastIndexAfter":3,"execFromThree":null}
{"found":-1,"lastIndexAfter":3,"execFromThree":null}

The saved cursor does not constrain this search

We create /B/g, set lastIndex to three, and pass it to String.search. The marked A plus U+200B plus B returns two; the cleaned AB returns one. Both observations leave lastIndex at three. That property is recorded after the call rather than inferred from the match position. The plain reference returns one without a cleanup change. These paired measurements demonstrate why a stored cursor is not an instruction to begin String.search at that point. The expression is an ordinary built-in RegExp; we do not install a custom search method or intercept its properties.

A separate exec call gives the missing comparison

For each string we create another global expression and also set its cursor to three. Its exec call returns no match in every fixture. That includes B at position zero, where search returns zero. The AX control gives search minus one and still restores the saved property. These controls separate absence of a token from presence before the cursor. We use different expression objects so an exec failure cannot change the state later attributed to search. The reproducible observer makes that allocation visible, allowing a reviewer to check the operation sequence directly.

Use the API matching the scan contract

If a parser must resume from an existing position, select an operation whose cursor behavior matches that requirement and check its no-match behavior. For a simple first-location query, search is useful precisely because it does not mean resume this global scan. After editing the subject, recompute positions against the new value. In our first row the token moves left by one unit, while the restored numeric cursor stays three. A saved lastIndex can therefore outlive the text it described. Pair a scan state with a text version instead of assuming cleanup updates either state automatically.

Scope and negative evidence

Our earlier regex-state guide tests repeated test calls; this page isolates a different operation that restores its prior cursor. It is not a claim about every regex-like object, custom Symbol.search method, proxy or destination editor. We measure the built-in behavior in the recorded Node runtime and retain both result and post-call state. The cleaner only removes its selected actual code point from the string. It does not execute a regex scan for the downstream application, preserve annotations, or certify that all content has been processed. A negative exec result here is not a watermark finding.

Reproduce this test

Save reproduce.cjs and tested-app.js in the same folder. Run the command below with Node.js. The harness prints its runtime, script SHA-256 and every measured row. Compare those rows with the original record. Using a newer script or runtime creates a new experiment; retain the version information with your rerun.

node reproduce.cjs

Reference and next check

ECMAScript RegExp search provides the relevant primary definition. The table and fixture analysis are original measurements. For broader inspection, use our Unicode inspector. Read the scope distinction before interpreting cleanup as a watermark result.