Ship the measured Meta Content Seal cohort with auto routing and --vendor override

Full Meta Muse Image support in the invisible-removal path:

- QWEN_ZIMAGE_META_STRENGTH = 0.1: derived by the standard
  worst-boundary-plus-cross-source-spread method over five oracle-bracketed
  generations (data/contentseal/manifest.csv)
- Auto mode: vendor_for_strength routes a file whose only provenance is the
  standalone AI IPTC trainedAlgorithmicMedia tag onto the meta cohort; C2PA
  issuers win first, so Google/OpenAI/Microsoft routing is unchanged. Muse
  WebP outputs place the XMP in a tail chunk, so the scan uses the shared
  chunk-aware metadata.scan_head rather than a plain head read
- Explicit override: --vendor on invisible/all/batch and
  InvisibleOptions.vendor name the cohort on stripped files; naming a cohort
  asserts the watermark is present, so the no-signal gate treats it like
  --force at both the CLI and API seams
- sdxl-zimage has no measured Meta rung: an explicit meta vendor falls to
  the conservative unknown 0.25 rather than inventing one
- identify emits a Content Seal caveat pointing at the removal path
- The legacy visible 'Imagined with AI' mark stays unregistered: a dedicated
  sample hunt (newsroom mockups, community posts, press screenshots, dead
  imagine.meta.com, broken Wayback captures) found no pixel-verifiable
  capture, and the registry rule forbids encoding a corner without one.
  erase --region remains its removal path; outcome recorded in the landscape

Co-Authored-By: Claude Fable 4.5 <noreply@anthropic.com>
This commit is contained in:
Victor Kuznetsov
2026-08-26 22:59:23 -07:00
co-authored by Claude Fable 4.5
parent a1811b6221
commit ab528ec0e8
12 changed files with 260 additions and 33 deletions
+33
View File
@@ -426,6 +426,39 @@ class TestInvisibleCommand:
assert result.exit_code == 0, result.output
mock_engine.remove_watermark.assert_called_once()
def test_invisible_explicit_vendor_implies_force_and_sets_cohort(self, runner, sample_png, tmp_path):
"""--vendor meta names a cohort the file cannot prove (Content Seal carries
no C2PA), so it must both bypass the no-signal skip and arrive at the engine
as the vendor, where it resolves to the measured Meta floor (not the
area-curve value the same size would otherwise get)."""
mock_cls, mock_engine = _mock_invisible_engine()
output = tmp_path / "clean.png"
with (
patch("remove_ai_watermarks.invisible_engine.is_available", return_value=True),
patch("remove_ai_watermarks.cli.InvisibleEngine", mock_cls, create=True),
patch("remove_ai_watermarks.invisible_engine.InvisibleEngine", mock_cls),
):
result = runner.invoke(main, ["invisible", str(sample_png), "-o", str(output), "--vendor", "meta"])
assert result.exit_code == 0, result.output
kwargs = mock_engine.remove_watermark.call_args.kwargs
assert kwargs["vendor"] == "meta"
assert "0.1" in result.output # the resolved Meta floor, printed
assert "0.094" not in result.output # not the sample's area-curve value (200x200 -> ~0.0944)
def test_invisible_vendor_auto_keeps_detection_semantics(self, runner, sample_png, tmp_path):
"""--vendor auto is the default spelled out: detection still runs and a
no-signal file still skips."""
mock_cls, mock_engine = _mock_invisible_engine()
output = tmp_path / "clean.png"
with (
patch("remove_ai_watermarks.invisible_engine.is_available", return_value=True),
patch("remove_ai_watermarks.cli.InvisibleEngine", mock_cls, create=True),
patch("remove_ai_watermarks.invisible_engine.InvisibleEngine", mock_cls),
):
result = runner.invoke(main, ["invisible", str(sample_png), "-o", str(output), "--vendor", "auto"])
assert result.exit_code == 2, result.output
mock_engine.remove_watermark.assert_not_called()
def test_invisible_runs_without_force_when_signal_present(self, runner, tmp_path):
"""An image carrying an AI metadata signal IS a scrub target, so the run
proceeds with no --force needed."""