CLAUDE WATERMARK REMOVER · PRACTICAL TEST
Why does text[-1] miss a final character that text.at(-1) returns?
Our AB reference returns B from at(-1), undefined from bracket access with -1, and an empty string from charAt(-1). After a trailing U+200B is removed, at(-1) returns B instead of the marker. Empty input needs a separate check.
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 |
|---|---|---|---|
| Trailing marker direct string / keep / invisible true | "AB"U+0041 U+0042 U+200B | "AB"Removed 1 invisible character | {"atMinusOne":"","bracketMinusOne":null,"atMinusThree":"A","charAtMinusOne":"","length":3}{"atMinusOne":"B","bracketMinusOne":null,"atMinusThree":null,"charAtMinusOne":"","length":2} |
| Plain reference direct string / keep / invisible true | "AB"U+0041 U+0042 | "AB"No selected invisible characters found | {"atMinusOne":"B","bracketMinusOne":null,"atMinusThree":null,"charAtMinusOne":"","length":2}{"atMinusOne":"B","bracketMinusOne":null,"atMinusThree":null,"charAtMinusOne":"","length":2} |
| Single unit direct string / keep / invisible true | "A"U+0041 | "A"No selected invisible characters found | {"atMinusOne":"A","bracketMinusOne":null,"atMinusThree":null,"charAtMinusOne":"","length":1}{"atMinusOne":"A","bracketMinusOne":null,"atMinusThree":null,"charAtMinusOne":"","length":1} |
| Empty source direct string / keep / invisible true | "" | ""No selected invisible characters found | {"atMinusOne":null,"bracketMinusOne":null,"atMinusThree":null,"charAtMinusOne":"","length":0}{"atMinusOne":null,"bracketMinusOne":null,"atMinusThree":null,"charAtMinusOne":"","length":0} |
Three ways of writing minus one produce different results
The trailing-marker fixture initially contains A, B and U+200B. Calling at with minus one retrieves the marker; bracket access using minus one yields undefined, and charAt with minus one returns an empty string. After the saved cleaner deletes the marker, at returns B while the other two observations remain unchanged. The plain AB control repeats the latter set of results without a cleanup event. Our record converts undefined observations to JSON null deliberately so those properties remain visible in the downloaded evidence. That null is a logging sentinel, not the actual return value of bracket access or at. The reproducer shows the conversion and keeps the empty charAt string distinct.
The longer negative offset can stop being in range
The same observer also checks at with minus three. In the marked three-unit fixture it retrieves A before cleanup; in the cleaned two-unit value it is outside the source and therefore becomes the null sentinel in the record. The single-unit A control returns A from at minus one but has no minus-three result. The empty control has neither at result, while charAt still supplies an empty string. These rows test positional validity separately from finding the final visible letter. We use no supplementary character or combining sequence here; at accesses UTF-16 units and this experiment does not claim grapheme-safe character selection. Earlier emoji and slicing pages cover that separate boundary.
Treat a missing lookup as a result to handle
When checking a final delimiter or suffix after cleanup, choose the access operation deliberately and handle an empty source before interpreting the returned value. Avoid treating bracket minus one as a portable synonym for the last unit in a JavaScript string. If an earlier length check established that minus three was valid, reevaluate it against the final string after deletions. Keep the raw return category visible in diagnostic records rather than allowing JSON serialization to silently omit undefined-valued properties. The four controls demonstrate only the named string operations in the recorded runtime. They do not validate an entire suffix, infer the intended final character, inspect a file extension, or prove removal of a model-level watermark.
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.at 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.