CLAUDE WATERMARK REMOVER · PRACTICAL TEST
Why does a cleaned -0 lose its sign after a JSON round trip?
Number of our cleaned -0 preserves negative zero, but JSON.stringify emits 0 and parsing returns positive zero. Object.is and reciprocal labels reveal the distinction that String(number) hides. Cleanup does not select a numeric serialization policy.
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 minus zero direct string / keep / invisible true | "-0"U+002D U+200B U+0030 | "-0"Removed 1 invisible character | {"numberLabel":"NaN","finite":false,"negativeZero":false,"reciprocalLabel":"NaN","json":"null","roundTripNegativeZero":false,"exactRoundTrip":false}{"numberLabel":"0","finite":true,"negativeZero":true,"reciprocalLabel":"-Infinity","json":"0","roundTripNegativeZero":false,"exactRoundTrip":false} |
| Minus zero direct string / keep / invisible true | "-0"U+002D U+0030 | "-0"No selected invisible characters found | {"numberLabel":"0","finite":true,"negativeZero":true,"reciprocalLabel":"-Infinity","json":"0","roundTripNegativeZero":false,"exactRoundTrip":false}{"numberLabel":"0","finite":true,"negativeZero":true,"reciprocalLabel":"-Infinity","json":"0","roundTripNegativeZero":false,"exactRoundTrip":false} |
| Plus zero direct string / keep / invisible true | "0"U+0030 | "0"No selected invisible characters found | {"numberLabel":"0","finite":true,"negativeZero":false,"reciprocalLabel":"Infinity","json":"0","roundTripNegativeZero":false,"exactRoundTrip":true}{"numberLabel":"0","finite":true,"negativeZero":false,"reciprocalLabel":"Infinity","json":"0","roundTripNegativeZero":false,"exactRoundTrip":true} |
| Negative decimal zero direct string / keep / invisible true | "-0.0"U+002D U+0030 U+002E U+0030 | "-0.0"No selected invisible characters found | {"numberLabel":"0","finite":true,"negativeZero":true,"reciprocalLabel":"-Infinity","json":"0","roundTripNegativeZero":false,"exactRoundTrip":false}{"numberLabel":"0","finite":true,"negativeZero":true,"reciprocalLabel":"-Infinity","json":"0","roundTripNegativeZero":false,"exactRoundTrip":false} |
The numeric sign survives conversion but disappears in export
The interrupted minus-zero input converts to NaN before cleanup. Removing its U+200B yields the spelling -0, which Number converts to negative zero. String of that numeric value reads 0, so we additionally record Object.is with negative zero and the reciprocal label. Those fields report true and -Infinity. JSON serialization emits the numeric literal 0, and parsing it produces a value whose negative-zero test is false. The ordinary -0 and -0.0 controls give that same loss without any cleanup. Positive zero remains positive and passes the exact Object.is round-trip comparison. This places the sign loss in numeric export rather than in the cleaner or an assumed visible minus-sign substitution.
Finite zero needs a different diagnostic from invalid numbers
Our existing nonfinite JSON guide studies values such as NaN and Infinity that serialize as null. Here the main after-cleanup value is finite, but its identity still changes under Object.is during the round trip. The pre-cleanup NaN field remains in the record as a conversion-failure control, with null JSON; it is not the explanation for the later finite zero result. The observer uses numeric JSON values, not quoted strings containing -0. A quoted original spelling would be a different representation. We do not test every arithmetic path that creates negative zero, binary serialization or application-specific treatment of signed zero. All reciprocal results are labels retained for diagnosis rather than raw nonfinite values that JSON might silently alter in the evidence file.
Decide whether the sign has application meaning before export
If the distinction matters for your destination, preserve an appropriate explicit representation and test its actual serialization contract. If the application intentionally treats both zeros alike, document that choice instead of assuming a JSON round trip retains every finite-number detail. Inspect the source spelling, converted value and exported value separately when debugging pasted numeric text. The positive-zero control prevents interpreting every zero round trip as information loss. Our fixture makes no claim about business significance, statistical watermarks or numerical precision beyond these exact zero cases. Keep the original text when reversibility is needed, and rerun the chosen destination check after cleanup. The cleaner’s success status reports selected character edits; it does not certify that a later numeric export preserves the equality relation your code intends to use.
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 JSON parsing and serialization 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.