mirror of
https://github.com/wiltodelta/remove-ai-watermarks.git
synced 2026-08-23 14:02:34 +02:00
fix(cli): stop silent passthrough when visible finds no known mark
When `visible --mark auto` (or an explicit `--mark` with detection on) found no registered mark, it exited 0 without writing output -- which a wrapping service reads as success and re-serves the unchanged input. ~74% of real uploads carry no registered visible mark, so this was the dominant "it didn't work" / NPS score-0 failure mode. Now it runs a cheap metadata-only identify, prints actionable guidance (route to `all` for an invisible/metadata mark, or `erase` for an arbitrary logo), writes no output file, and exits EXIT_NO_VISIBLE_MARK (2) -- distinct from success (0) and a hard error (1) so the caller can surface the message. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
b08405bece
commit
30b56f0ea3
@@ -125,6 +125,32 @@ class TestVisibleCommand:
|
||||
assert "visible AI watermark" in result.output
|
||||
assert "--mark" in result.output
|
||||
|
||||
def test_visible_auto_no_mark_exits_two_with_eraser_hint(self, runner, sample_png, tmp_path):
|
||||
# No known visible mark and no AI provenance signal: the command must not
|
||||
# re-serve the input as a finished result. It exits EXIT_NO_VISIBLE_MARK
|
||||
# (2) -- distinct from success (0) and a hard error (1) -- writes no
|
||||
# output file, and points the user at the region eraser.
|
||||
output = tmp_path / "clean.png"
|
||||
result = runner.invoke(main, ["visible", str(sample_png), "-o", str(output)])
|
||||
assert result.exit_code == 2, result.output
|
||||
assert not output.exists()
|
||||
assert "erase" in result.output
|
||||
|
||||
def test_visible_auto_no_mark_routes_to_all_when_metadata(self, runner, tmp_path):
|
||||
# An image whose only signal is an invisible/metadata watermark (here SD
|
||||
# generation parameters) has no visible mark to remove; the command must
|
||||
# exit 2 and upsell the full 'all' pipeline rather than the eraser.
|
||||
img = Image.fromarray(np.random.default_rng(0).integers(0, 255, (200, 200, 3), dtype=np.uint8))
|
||||
pnginfo = PngInfo()
|
||||
pnginfo.add_text("parameters", "Steps: 20, Sampler: Euler, a test landscape")
|
||||
src = tmp_path / "ai.png"
|
||||
img.save(src, pnginfo=pnginfo)
|
||||
output = tmp_path / "clean.png"
|
||||
result = runner.invoke(main, ["visible", str(src), "-o", str(output)])
|
||||
assert result.exit_code == 2, result.output
|
||||
assert not output.exists()
|
||||
assert "all" in result.output
|
||||
|
||||
def test_visible_basic(self, runner, sample_png, tmp_path):
|
||||
output = tmp_path / "clean.png"
|
||||
result = runner.invoke(
|
||||
|
||||
Reference in New Issue
Block a user