Zerowidth CleanerAll measured guides

CLAUDE WATERMARK REMOVER · PRACTICAL TEST

Why does cleaned 12 plus 1 become 121 instead of 13?

The cleaner returns a string. In our fixture string plus one, concat and template interpolation produce 121; explicit Number conversion followed by addition produces 13. Decide whether the destination value is a label or a quantity.

Tested October 26, 2026 · v24.22.1 · 4 measured runs

Open the Claude text cleaner · Full measured data

Code-point comparison for Marked digits

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
Marked digits
direct string / keep / invisible true
"1​2"
U+0031 U+200B U+0032
"12"
Removed 1 invisible character
{"stringPlus":"1​21","numericPlus":"NaN","concat":"1​21","number":"NaN","template":"1​21"}
{"stringPlus":"121","numericPlus":"13","concat":"121","number":"12","template":"121"}
Plain digits
direct string / keep / invisible true
"12"
U+0031 U+0032
"12"
No selected invisible characters found
{"stringPlus":"121","numericPlus":"13","concat":"121","number":"12","template":"121"}
{"stringPlus":"121","numericPlus":"13","concat":"121","number":"12","template":"121"}
Empty value
direct string / keep / invisible true
""
""
No selected invisible characters found
{"stringPlus":"1","numericPlus":"1","concat":"1","number":"0","template":"1"}
{"stringPlus":"1","numericPlus":"1","concat":"1","number":"0","template":"1"}
Leading zero
direct string / keep / invisible true
"012"
U+0030 U+0031 U+0032
"012"
No selected invisible characters found
{"stringPlus":"0121","numericPlus":"13","concat":"0121","number":"12","template":"0121"}
{"stringPlus":"0121","numericPlus":"13","concat":"0121","number":"12","template":"0121"}

Successful character deletion does not change the return type

The marked digit source contains 1, U+200B and 2. After the actual callback removes the marker, the observer receives the string 12. Adding numeric one to that string produces 121, just like concat with the string 1 and the template suffix comparison. The explicit Number branch produces numeric thirteen, recorded as a string in the diagnostic JSON. Before cleanup that numeric branch reports NaN. This separates the repair of a numeric spelling from the later choice of an addition or concatenation operation.

Leading zeros expose the semantic choice

The leading-zero control remains 0121 under the three string-producing constructions, whereas Number conversion followed by addition produces thirteen. The empty-string control gives a visible 1 under both paths, but its Number diagnostic is zero. Equal-looking outputs on empty input therefore do not establish that the same operation ran or the same type was returned. The plain 12 control reproduces the cleaned first fixture with no invisible character. We retain the conversion diagnostic alongside the results rather than inferring types from how a small output looks.

Convert only when the field represents a quantity

An identifier, version component or fixed-width label may need its original digit spelling and leading zeros. A quantity requires a conversion and a validity policy before arithmetic. The matrix deliberately does not recommend automatic Number conversion for every digit-looking field. It tests only four short strings and adding one; large integer precision, numeric separators, locale punctuation and overflow need separate checks. The diagnostic converts numeric results to strings so NaN remains explicit in JSON, rather than silently becoming null during export. The reproducer retains the actual expressions for inspection.

A suffix operation is not performed by the homepage

The cleaner returns the edited source and does not append any digit. All suffixes in this experiment are authored observer operations. Earlier conversion coverage asks which strings become numbers; this new question explains why a valid digit string can still concatenate under the addition operator. No real identifier or measurement is modified, and no form is submitted. The fixtures are not Claude outputs or detector samples. Retain source spelling and intended type together when reviewing arithmetic after cleanup; a removal count alone cannot certify the destination calculation.

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 addition operator 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.