CLAUDE WATERMARK REMOVER · PRACTICAL TEST
Why can /a/g find a later letter while /a/y fails at the same cursor?
With lastIndex set to 1, the global regex skips our U+200B gap and matches at 2; the sticky regex fails. Cleaning closes that gap, letting both match at 1. An ordinary space still causes sticky failure.
Open the Claude text cleaner · Full measured data
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.
| Fixture and mode | Input string and code points | Output and cleaner status | Observed before / after |
|---|---|---|---|
| Marker at cursor direct string / keep / invisible true | "aa"U+0061 U+200B U+0061 | "aa"Removed 1 invisible character | {"startCursor":1,"global":{"index":2,"end":3},"sticky":null,"stickyFinalCursor":0}{"startCursor":1,"global":{"index":1,"end":2},"sticky":{"index":1,"end":2},"stickyFinalCursor":2} |
| No gap direct string / keep / invisible true | "aa"U+0061 U+0061 | "aa"No selected invisible characters found | {"startCursor":1,"global":{"index":1,"end":2},"sticky":{"index":1,"end":2},"stickyFinalCursor":2}{"startCursor":1,"global":{"index":1,"end":2},"sticky":{"index":1,"end":2},"stickyFinalCursor":2} |
| Ordinary space gap direct string / keep / invisible true | "a a"U+0061 U+0020 U+0061 | "a a"No selected invisible characters found | {"startCursor":1,"global":{"index":2,"end":3},"sticky":null,"stickyFinalCursor":0}{"startCursor":1,"global":{"index":2,"end":3},"sticky":null,"stickyFinalCursor":0} |
| Retained joiner gap direct string / keep / invisible true | "aa"U+0061 U+200D U+0061 | "aa"No selected invisible characters found | {"startCursor":1,"global":{"index":2,"end":3},"sticky":null,"stickyFinalCursor":0}{"startCursor":1,"global":{"index":2,"end":3},"sticky":null,"stickyFinalCursor":0} |
The same start cursor imposes different matching contracts
For each string we create two fresh expressions, one global and one sticky, and set each lastIndex to one. In the selected-marker fixture the global expression finds the second a at index two and ends at three. The sticky expression returns no match and resets its cursor to zero. After deletion the text is aa, and both operations match at one and end at two. The ordinary aa reference already has that result. The ordinary-space and retained-joiner controls keep their gap: global search finds the later a while sticky search still fails. Match indices and final cursors are saved together so the null result does not conceal its state transition.
This experiment tests anchoring at a chosen cursor
Our previous lastIndex guide performs repeated test calls and observes the evolving state of a global expression. Here each expression runs only once at an explicitly chosen cursor; the difference is whether the operation can search forward past a gap. The cleaner has no parser cursor and does not decide whether skipping text is permissible. The control with a normal space matters because the behavior is not unique to invisible characters. We do not implement a tokenizer, test sticky-plus-global flags or remap arbitrary saved positions after an edit. All measured positions refer to these exact runtime strings, and the observer starts fresh for every before and after stage.
Choose the search contract before changing text
For a lexical scanner that must consume the next token exactly at its cursor, a sticky failure can be useful evidence of an unexpected gap. For a forward search, finding a later match may be intended. Keep the actual flags and start position in a bug report, then inspect the characters at that position before removing anything. A selected deletion changes the string version, so recompute any cursor policy for the edited text instead of assuming stored offsets remain valid. The four controls establish a concrete contract difference and unchanged failures. They do not decide which gap is meaningful, supply a general tokenizer or certify that every marker should be discarded. Verify the destination parser after an intentional cleanup.
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.cjsReference and next check
ECMAScript string operations 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.