CLAUDE WATERMARK REMOVER · PRACTICAL TEST
Why does flat shorten my field array while keeping an empty string?
Our four-slot sparse array becomes three elements after flat: its hole disappears, but explicit undefined and empty text remain. Cleanup changes the first field only. Record array keys when missing positions matter.
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 |
|---|---|---|---|
| Marked field direct string / keep / invisible true | "AB"U+0041 U+200B U+0042 | "AB"Removed 1 invisible character | {"beforeLength":4,"beforeKeys":["0","2","3"],"beforeJSON":"[\"AB\",null,null,\"\"]","afterLength":3,"afterKeys":["0","1","2"],"afterJSON":"[\"AB\",null,\"\"]","afterTypes":["string","undefined","string"]}{"beforeLength":4,"beforeKeys":["0","2","3"],"beforeJSON":"[\"AB\",null,null,\"\"]","afterLength":3,"afterKeys":["0","1","2"],"afterJSON":"[\"AB\",null,\"\"]","afterTypes":["string","undefined","string"]} |
| Plain field direct string / keep / invisible true | "AB"U+0041 U+0042 | "AB"No selected invisible characters found | {"beforeLength":4,"beforeKeys":["0","2","3"],"beforeJSON":"[\"AB\",null,null,\"\"]","afterLength":3,"afterKeys":["0","1","2"],"afterJSON":"[\"AB\",null,\"\"]","afterTypes":["string","undefined","string"]}{"beforeLength":4,"beforeKeys":["0","2","3"],"beforeJSON":"[\"AB\",null,null,\"\"]","afterLength":3,"afterKeys":["0","1","2"],"afterJSON":"[\"AB\",null,\"\"]","afterTypes":["string","undefined","string"]} |
| Empty field direct string / keep / invisible true | "" | ""No selected invisible characters found | {"beforeLength":4,"beforeKeys":["0","2","3"],"beforeJSON":"[\"\",null,null,\"\"]","afterLength":3,"afterKeys":["0","1","2"],"afterJSON":"[\"\",null,\"\"]","afterTypes":["string","undefined","string"]}{"beforeLength":4,"beforeKeys":["0","2","3"],"beforeJSON":"[\"\",null,null,\"\"]","afterLength":3,"afterKeys":["0","1","2"],"afterJSON":"[\"\",null,\"\"]","afterTypes":["string","undefined","string"]} |
| Comma field direct string / keep / invisible true | ","U+002C | ","No selected invisible characters found | {"beforeLength":4,"beforeKeys":["0","2","3"],"beforeJSON":"[\",\",null,null,\"\"]","afterLength":3,"afterKeys":["0","1","2"],"afterJSON":"[\",\",null,\"\"]","afterTypes":["string","undefined","string"]}{"beforeLength":4,"beforeKeys":["0","2","3"],"beforeJSON":"[\",\",null,null,\"\"]","afterLength":3,"afterKeys":["0","1","2"],"afterJSON":"[\",\",null,\"\"]","afterTypes":["string","undefined","string"]} |
Identical JSON null spellings conceal two different source positions
The observer creates four positions: supplied text, a hole, explicit undefined and an empty string. Before flattening, length is four and Object.keys lists zero, two and three. JSON serialization displays null at both the hole and undefined positions. After flat, length is three and the keys become zero, one and two. The resulting JSON retains one null. Saving keys and length alongside JSON makes the removed hole observable even though its original export looked the same as the explicit undefined value.
Empty content survives without becoming a hole
In the empty-field control, the first and final strings are both empty, and both remain after flattening. The comma control likewise remains one string element; punctuation does not create an additional field. The afterTypes array records string, undefined and string for every fixture. In the marked case cleanup changes the first value from interrupted AB to AB, but the exact same four-to-three structural reduction occurs before and after. This isolates sparse-position removal from the targeted string edit and prevents a missing slot from being described as a deleted text value.
Preserve position explicitly when exporting field data
If a destination uses array positions as columns, decide how missing slots should be represented before flattening or JSON export. A dense array with an explicit placeholder is different from an absent property. This page does not recommend one placeholder for every schema and does not claim that JSON roundtrips preserve holes. It measures one shallow flat call on an otherwise simple array. No nested array, custom species, inherited numeric property or parser is involved. Earlier filtering coverage measures truthiness-based element removal; here flat removes a hole while keeping a falsy empty string.
Use structural evidence for a structural diagnosis
The original local record retains lengths, keys, serialized data and element types because no one view explains every distinction. The string supplied to the homepage contains no array syntax; the observer constructs the sparse array afterward. Our synthetic controls are neither CSV exports from users nor Claude examples. Successful marker deletion does not certify that later reshaping keeps every destination position. No authorship or statistical watermark claim follows from these array results. Rerun the supplied harness in the destination runtime before relying on a structural conversion.
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 Array.prototype.flat 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.