CLAUDE WATERMARK REMOVER · PRACTICAL TEST
Why does ?? keep an empty cleaned string instead of using my fallback?
Our marker-only input becomes empty text. The nullish operator and destructuring default preserve that empty string; logical OR selects the fallback. Decide whether your fallback means missing data or empty content.
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 only direct string / keep / invisible true | ""U+200B | ""Removed 1 invisible character | {"nullish":"","logicalOr":"","destructured":"","missingDefault":"fallback","length":1}{"nullish":"","logicalOr":"fallback","destructured":"","missingDefault":"fallback","length":0} |
| Plain text direct string / keep / invisible true | "AB"U+0041 U+0042 | "AB"No selected invisible characters found | {"nullish":"AB","logicalOr":"AB","destructured":"AB","missingDefault":"fallback","length":2}{"nullish":"AB","logicalOr":"AB","destructured":"AB","missingDefault":"fallback","length":2} |
| Empty string direct string / keep / invisible true | "" | ""No selected invisible characters found | {"nullish":"","logicalOr":"fallback","destructured":"","missingDefault":"fallback","length":0}{"nullish":"","logicalOr":"fallback","destructured":"","missingDefault":"fallback","length":0} |
| Zero spelling direct string / keep / invisible true | "0"U+0030 | "0"No selected invisible characters found | {"nullish":"0","logicalOr":"0","destructured":"0","missingDefault":"fallback","length":1}{"nullish":"0","logicalOr":"0","destructured":"0","missingDefault":"fallback","length":1} |
The deletion exposes three different default policies
The first fixture contains exactly one U+200B, so its original string length is one. Before cleanup both fallback operators return that string. After deletion the recorded length is zero: nullish coalescing returns empty text, logical OR returns fallback, and destructuring the supplied text property also returns empty text. The separate missing-property control returns fallback at both stages. Those four observations identify the decision boundary without relying on how the invisible input looks in a form. The product supplied a string successfully; the consuming expression decides which kind of absence matters.
Zero spelling is content in these controls
The ordinary AB reference survives every expression unchanged. The explicit empty-string reference reproduces the cleaned first fixture even when the cleaner finds nothing. The zero-spelling reference stays the one-character string 0 under both operators, rather than selecting fallback. We do not supply numeric zero, false or null as the observer input. This matters because a configuration field read as text has different truthiness from a converted numeric value. The missing-default comparison deliberately constructs an object with no text property, making that separate source of a default observable.
Name the state that should activate a replacement
If empty text is a meaningful result, replacing it with a default may discard a deliberate deletion. If a destination requires visible content, preserving empty text may instead require an explicit validation error. Choose the policy before applying a fallback and retain the original input alongside the cleaned value. Destructuring defaults are not an empty-string validator. The narrow function in the download demonstrates only a missing property and a present string; it does not define how your application should handle explicit null, whitespace-only values or non-string records.
The operators do not inspect provenance
The actual homepage callback removes its selected marker before the observer evaluates the fallback expressions. It does not insert fallback text itself. Every string and object in this page is locally authored, with no imported conversation or external form submission. Earlier flag coverage asks what text true and false mean; this page asks when a replacement value is chosen. The two questions need separate contracts. An empty result and a chosen default provide no evidence of Claude authorship, statistical marking or detector behavior. Rerun the exact expressions when changing the destination data type.
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 coalesce expression 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.