From e85307f1c071a582c21c14151d73546dad234cd0 Mon Sep 17 00:00:00 2001 From: Victor Kuznetsov Date: Tue, 8 Sep 2026 09:29:12 -0700 Subject: [PATCH] Scrub private infrastructure detail and move the GPU harnesses out The Content Seal manifest named the production GPU worker in its provenance column and in two row keys, several docstrings described their sources as user uploads from the private corpus, and that corpus was called by the storage product holding it. Each is now what a public reader can check: a pipeline and strength, material that is not publication-cleared, and a private corpus. The corpus test follows the renamed rows. Deployment and tier detail goes the same way, since which backend each hosting tier can afford is a product decision, not a library fact. Twelve harnesses that need a cloud GPU account leave scripts/. The research pages that cite their findings name them as harnesses kept outside this repository and stop implying a reader can rerun them; the tracked inputs and recorded verdicts remain the durable record, and the offline analysis step stays here with its test. A development invariant states the rule so the next harness is not added back. Co-Authored-By: Claude Opus 5 --- .claude/rules/development.md | 12 + .gitignore | 4 +- data/README.md | 2 +- data/contentseal/README.md | 2 +- data/contentseal/manifest.csv | 46 ++-- data/evaluations/engine-selection/README.md | 4 +- data/fixtures/README.md | 2 +- docs/chroma1-engine-research.md | 42 +-- docs/development.md | 2 +- docs/module-internals.md | 14 +- docs/synthid-detector-removal-plan.md | 48 ++-- docs/synthid-oracle-ladders.md | 2 +- docs/synthid-robust-identity-research.md | 2 +- docs/synthid.md | 8 +- scripts/README.md | 2 - scripts/analyze_engine_selection_study.py | 3 +- scripts/chroma_google_high_rungs.py | 114 -------- scripts/chroma_meta_high_rungs.py | 109 -------- scripts/chroma_microsoft_ladder.py | 142 ---------- scripts/chroma_muse_expansion.py | 160 ------------ scripts/chroma_openai_expansion.py | 99 ------- scripts/chroma_preship_validation.py | 152 ----------- scripts/chroma_scrub_prototype.py | 188 -------------- scripts/chroma_seed_probes.py | 101 -------- scripts/chroma_text_restoration_study.py | 232 ----------------- scripts/engine_cohort_calibration.py | 272 -------------------- scripts/engine_quality_price_probe.py | 249 ------------------ scripts/engine_selection_study.py | 221 ---------------- scripts/invisible_quality_audit.py | 2 +- scripts/resource_ceilings.py | 2 +- src/remove_ai_watermarks/text_draft.py | 4 +- src/remove_ai_watermarks/video_visible.py | 4 +- tests/test_contentseal_corpus.py | 2 +- tests/test_invisible_engine.py | 2 +- 34 files changed, 114 insertions(+), 2136 deletions(-) delete mode 100755 scripts/chroma_google_high_rungs.py delete mode 100755 scripts/chroma_meta_high_rungs.py delete mode 100755 scripts/chroma_microsoft_ladder.py delete mode 100644 scripts/chroma_muse_expansion.py delete mode 100644 scripts/chroma_openai_expansion.py delete mode 100755 scripts/chroma_preship_validation.py delete mode 100755 scripts/chroma_scrub_prototype.py delete mode 100644 scripts/chroma_seed_probes.py delete mode 100644 scripts/chroma_text_restoration_study.py delete mode 100755 scripts/engine_cohort_calibration.py delete mode 100755 scripts/engine_quality_price_probe.py delete mode 100644 scripts/engine_selection_study.py diff --git a/.claude/rules/development.md b/.claude/rules/development.md index 4510a99..7fa8b4b 100644 --- a/.claude/rules/development.md +++ b/.claude/rules/development.md @@ -39,6 +39,18 @@ Boundary modules for cv2, Torch, and Diffusers may carry narrow per-file relaxat From a worktree, `uv run` imports the package from the MAIN checkout -- that is where the editable install points. A script measuring a worktree's edit must insert that worktree's `src` at `sys.path[0]` and assert `module.__file__` resolves inside it, or it silently compares unmodified code against itself. +## Research harnesses stay out of this repository + +A research script that needs a cloud GPU account to run is not kept here, and +`scripts/` carries no `import modal`. Twelve such harnesses were moved out on +2026-09-07; the pages that cite their findings +([chroma1](../../docs/chroma1-engine-research.md), +[module internals](../../docs/module-internals.md)) name them as harnesses kept +outside this repository, and the tracked inputs under `data/evaluations/` plus +the recorded verdicts are the durable record. Keep a new one outside too, and +leave only its offline analysis step here, the way +`scripts/analyze_engine_selection_study.py` stayed with its test. + ## Visible-mark example gallery Every registered mark carries a committed example: `data/fixtures/visible//example.png` diff --git a/.gitignore b/.gitignore index e28c284..6155015 100644 --- a/.gitignore +++ b/.gitignore @@ -30,8 +30,8 @@ _refs/ yolov8n.pt .coverage -# Local prototype and evaluation outputs (scripts/chroma_scrub_prototype.py and -# friends); the durable record of an oracle verdict lives under data/evaluations/ +# Local prototype and evaluation outputs (research harnesses and probes); the +# durable record of an oracle verdict lives under data/evaluations/ out/ # Claude Code local settings diff --git a/data/README.md b/data/README.md index 00e80a4..f4ad9e3 100644 --- a/data/README.md +++ b/data/README.md @@ -33,7 +33,7 @@ duplicating it and record unsupported gaps and source-specific licensing. ## Storage rules -Large local-only research data (the 211 GB Spaces corpus and the frozen +Large local-only research data (the 211 GB private research corpus and the frozen checkpoints, research corpora, and campaign reports) lives under gitignored paths documented in `data/research/README.md` (ignored via `.git/info/exclude`, never committed). Worktree `.local-eval/` directories are scratch copies; the diff --git a/data/contentseal/README.md b/data/contentseal/README.md index 3797fb5..584500f 100644 --- a/data/contentseal/README.md +++ b/data/contentseal/README.md @@ -96,6 +96,6 @@ uv run python scripts/contentseal_transforms.py /tmp/contentseal-derived The Meta API generations and remote GPU outputs are not reproducible from this repository alone. Their prompts, exact output hashes, model/profile settings, and oracle results are recorded in `manifest.csv`, but the generation API is -stochastic and the private worker environment is not tracked. `MUSE_API_KEY` and +stochastic and the GPU environment that produced them is not tracked. `MUSE_API_KEY` and the anonymous detector session are deliberately absent. A new calibration must therefore create new manifest rows rather than claiming to recreate these bytes. diff --git a/data/contentseal/manifest.csv b/data/contentseal/manifest.csv index 3c66a7e..cc687ad 100644 --- a/data/contentseal/manifest.csv +++ b/data/contentseal/manifest.csv @@ -19,26 +19,26 @@ blog_teen_cat,,meta-blog-cdn,https://lookaside.fbsbx.com/elementpath/media/?medi blog_hero_1,,meta-blog-cdn,https://lookaside.fbsbx.com/elementpath/media/?media_id=2140990336800598&version=1783727678,,,1344x1792,7655639acb9f826cdb864d869530153efc1e1467ff414b5a63e80aa7b39b2fb7,no,detected,Muse Image 1 - Meta,,,2026-08-26T19:00Z,seal survived CDN transcode without any metadata control_synth_gradient,,synthetic-local,,PIL gradient with rectangle JPEG q90; never touched any AI pipeline,,1024x768,25f29c0b993ed1a8e41060ed50de778d875a6d94847ced180aafc5a6ad429f82,no,not_detected,,,,2026-08-26T19:01Z,negative control: No AI signatures from Meta were found fox_nometa,,derived:gen_fox_forest,,metadata --remove only (no pixel change),,1600x1600,685d3a5c5d74e653ec7615fc7a347a0584c277fc7fb59594d388ac619ffe3985,no_stripped,detected,Muse Image 1 - Meta,AXZpZGVvc2VhbHY0X2NhX3NjbLlNjYhvPAxD,2026-08-26T19:07Z,2026-08-26T22:19Z,metadata stripping does NOT remove Content Seal; seal lives in pixels; same generation ID as original -fox_modal_invisible,,derived:gen_fox_forest,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=default-adaptive(approx 0.1305 at 1600x1600),,1600x1600,6daa3e9b5dde5cb443d8071c5294262742f001c02b694243764a50345769d8b8,no_stripped,not_detected,,,,2026-08-26T22:21Z,current default pipeline clears Content Seal -text_modal_invisible,,derived:gen_text_poster,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=default-adaptive(approx 0.1305 at 1600x1600),,1600x1600,8530a82fb856b0a00651076ac1ad8a7544b5d8873cac9bd5780704fbe10f53f8,no_stripped,not_detected,,,,2026-08-26T22:22Z,current default pipeline clears Content Seal -fox_str0.06000,,derived:gen_fox_forest,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.06,,1600x1600,7b5e5ae75ca20f2a3cdfcfa7666104752d9557b08ac236db6f1548434940a1f3,no_stripped,not_detected,,,,2026-08-26T22:28Z,strength calibration ladder -fox_str0.04500,,derived:gen_fox_forest,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.045,,1600x1600,26da15694b3096e2f1717154db213e814cdd27f2fc40e5f924db2324213cf960,no_stripped,not_detected,,,,2026-08-27T02:28Z,strength calibration ladder; re-confirmed clean at 0.045 -fox_str0.03750,,derived:gen_fox_forest,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.0375,,1600x1600,b7eb0616d10042933edf22cfc30aff4df915384828289b409f6cfa4cdf2807d4,no_stripped,not_detected,,,,2026-08-26T22:30Z,fresh-page protocol; fox first-clean boundary is in (0.03 0.0375] -fox_str0.03000,,derived:gen_fox_forest,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.03,,1600x1600,cff80d18d9d00000f47e0f97c419a37c13a13831795768aee8727aa9516d1401,no_stripped,detected,Muse Image 1 - Meta,,,2026-08-26T22:31Z,fresh-page protocol; seal survives 0.03 -fox_str0.02000,,derived:gen_fox_forest,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.02,,1600x1600,b19183ec60b63a5b73d3e1c723e7943584912857d51a4b5f85259c5c77da0e53,no_stripped,detected,Muse Image 1 - Meta,,,2026-08-26T22:28Z,settled-read protocol; monotonic below the 0.03 boundary -text_str0.03750,,derived:gen_text_poster,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.0375,,1600x1600,bacfd4eca7b13616502f74497cbe4f02ef6893918870f13f9e76fdb93b43107f,no_stripped,not_detected,,,,2026-08-26T22:33Z,fresh-page protocol -text_str0.03000,,derived:gen_text_poster,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.03,,1600x1600,d5c6cffbf471ef8bb74ee8c0d22cc17d9da2c446b83e46c4be67e6ea4cdd09de,no_stripped,not_detected,,,,2026-08-26T22:33Z,fresh-page protocol; text first-clean boundary is at or below 0.03 - cross-source spread vs fox confirmed -lh_str0.03750,,derived:gen_lighthouse_watercolor,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.0375,,1600x1600,f5169debc5fd2792399c0ea3fa88cb1d05f523d95004bec240c73db0e9aaee51,no_stripped,detected,Muse Image 1 - Meta,,,2026-08-27T02:28Z,seal survives 0.0375 where fox is already clean -lh_str0.03000,,derived:gen_lighthouse_watercolor,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.03,,1600x1600,110d2112d91dd53df5ccd1839e0e2b41c44aa1832adb0090032660e071fb1fd4,no_stripped,detected,Muse Image 1 - Meta,,,2026-08-27T02:28Z,fresh-page protocol; lighthouse holds its seal below the fox boundary: cross-source spread is wide -text_str0.02500,,derived:gen_text_poster,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.025,,1600x1600,f46a6c53b4f3d39fccb1d62cca82ced2e163e4424d13c98e6468a8e083c0fa54,no_stripped,not_detected,,,,2026-08-27T02:28Z,mid rung inside the clean zone -text_str0.02000,,derived:gen_text_poster,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.02,,1600x1600,a19cbe22313e0f19768c98567ea89f2d9dc30827691fc7ec2971c52f3e7c6cc6,no_stripped,not_detected,,,,2026-08-27T02:28Z,text clean at 0.02: boundary <= 0.02 - the easiest source measured -text_str0.01500,,derived:gen_text_poster,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.015,,1600x1600,aa3816c75e38f3ab5afc378d349caafad56f2bb6da859a5ee68fdea57ad00d73,no_stripped,not_detected,,,,2026-08-27T02:41Z,text clean at 0.015: boundary <= 0.015 - the easiest source measured -lh_str0.02500,,derived:gen_lighthouse_watercolor,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.025,,1600x1600,989c4a7a804bc8420ec4d86b9445bc3a37382c1834782a7f8842f781d69b05e2,no_stripped,,,,,,below the measured detected boundary (0.03) for this source; not individually checked -lh_str0.02000,,derived:gen_lighthouse_watercolor,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.02,,1600x1600,6a4a4ec94292a145e7d73e6900b8ec6d0eede17137f2b91fba7757ec0bdba5ec,no_stripped,,,,,,below the measured detected boundary (0.03) for this source; not individually checked -nc_str0.03750,,derived:gen_night_city,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.0375,,1920x1280,46f322335f801ee54427eb39275216465f9a7cfa3d918c698e4d90a2439a0815,no_stripped,not_detected,,,,2026-08-27T02:28Z,boundary (0.03; 0.0375] -nc_str0.03000,,derived:gen_night_city,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.03,,1920x1280,3f42632319248ad1a91ef2457c7e0b13ed17e1d2569decbbaab67c2072e9a305,no_stripped,detected,Muse Image 1 - Meta,,,2026-08-27T02:28Z,night_city holds seal at 0.03 -mug_str0.03750,,derived:gen_studio_mug,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.0375,,1600x1600,3b6109ae7e86b8ea74ce33315e3f2a7eda1cadb724d429f0951f13c3ead34b0f,no_stripped,not_detected,,,,2026-08-27T02:28Z,upper rung for the mug bracket -mug_str0.03000,,derived:gen_studio_mug,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.03,,1600x1600,1c24c984677e1528da83003ac40594f6e5ef1fa9351f1368b6d31a0101308583,no_stripped,not_detected,,,,2026-08-27T02:28Z,mug clean at 0.03: boundary <= 0.03 -lh_str0.05250,,derived:gen_lighthouse_watercolor,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.0525,,1600x1600,8912ba1ff4a26790f69224c49dd649e46835e277c375276ac9604f5339775b2a,no_stripped,detected,Muse Image 1 - Meta,,,2026-08-27T02:41Z,bisection: lighthouse first-clean boundary bracketed to (0.0525; 0.06] -lh_str0.04500,,derived:gen_lighthouse_watercolor,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.045,,1600x1600,cfdcf7bbb27c740846a1de4edffee3b25a624c2a8e1aba2362feaa25b682e3ae,no_stripped,detected,Muse Image 1 - Meta,,,2026-08-27T02:28Z,seal survives 0.045: lighthouse is the worst source measured -lh_str0.06000,,derived:gen_lighthouse_watercolor,,modal raiw-worker qwen-zimage mode=invisible seed=0 strength=0.06,,1600x1600,4e214be00a89dc9f1f32ec39483c5e9668a1ec7f38b15e5794942479c839fcca,no_stripped,not_detected,,,,2026-08-27T02:28Z,lighthouse first-clean boundary bracketed to (0.045 0.06] +fox_default_invisible,,derived:gen_fox_forest,,qwen-zimage mode=invisible seed=0 strength=default-adaptive(approx 0.1305 at 1600x1600),,1600x1600,6daa3e9b5dde5cb443d8071c5294262742f001c02b694243764a50345769d8b8,no_stripped,not_detected,,,,2026-08-26T22:21Z,current default pipeline clears Content Seal +text_default_invisible,,derived:gen_text_poster,,qwen-zimage mode=invisible seed=0 strength=default-adaptive(approx 0.1305 at 1600x1600),,1600x1600,8530a82fb856b0a00651076ac1ad8a7544b5d8873cac9bd5780704fbe10f53f8,no_stripped,not_detected,,,,2026-08-26T22:22Z,current default pipeline clears Content Seal +fox_str0.06000,,derived:gen_fox_forest,,qwen-zimage mode=invisible seed=0 strength=0.06,,1600x1600,7b5e5ae75ca20f2a3cdfcfa7666104752d9557b08ac236db6f1548434940a1f3,no_stripped,not_detected,,,,2026-08-26T22:28Z,strength calibration ladder +fox_str0.04500,,derived:gen_fox_forest,,qwen-zimage mode=invisible seed=0 strength=0.045,,1600x1600,26da15694b3096e2f1717154db213e814cdd27f2fc40e5f924db2324213cf960,no_stripped,not_detected,,,,2026-08-27T02:28Z,strength calibration ladder; re-confirmed clean at 0.045 +fox_str0.03750,,derived:gen_fox_forest,,qwen-zimage mode=invisible seed=0 strength=0.0375,,1600x1600,b7eb0616d10042933edf22cfc30aff4df915384828289b409f6cfa4cdf2807d4,no_stripped,not_detected,,,,2026-08-26T22:30Z,fresh-page protocol; fox first-clean boundary is in (0.03 0.0375] +fox_str0.03000,,derived:gen_fox_forest,,qwen-zimage mode=invisible seed=0 strength=0.03,,1600x1600,cff80d18d9d00000f47e0f97c419a37c13a13831795768aee8727aa9516d1401,no_stripped,detected,Muse Image 1 - Meta,,,2026-08-26T22:31Z,fresh-page protocol; seal survives 0.03 +fox_str0.02000,,derived:gen_fox_forest,,qwen-zimage mode=invisible seed=0 strength=0.02,,1600x1600,b19183ec60b63a5b73d3e1c723e7943584912857d51a4b5f85259c5c77da0e53,no_stripped,detected,Muse Image 1 - Meta,,,2026-08-26T22:28Z,settled-read protocol; monotonic below the 0.03 boundary +text_str0.03750,,derived:gen_text_poster,,qwen-zimage mode=invisible seed=0 strength=0.0375,,1600x1600,bacfd4eca7b13616502f74497cbe4f02ef6893918870f13f9e76fdb93b43107f,no_stripped,not_detected,,,,2026-08-26T22:33Z,fresh-page protocol +text_str0.03000,,derived:gen_text_poster,,qwen-zimage mode=invisible seed=0 strength=0.03,,1600x1600,d5c6cffbf471ef8bb74ee8c0d22cc17d9da2c446b83e46c4be67e6ea4cdd09de,no_stripped,not_detected,,,,2026-08-26T22:33Z,fresh-page protocol; text first-clean boundary is at or below 0.03 - cross-source spread vs fox confirmed +lh_str0.03750,,derived:gen_lighthouse_watercolor,,qwen-zimage mode=invisible seed=0 strength=0.0375,,1600x1600,f5169debc5fd2792399c0ea3fa88cb1d05f523d95004bec240c73db0e9aaee51,no_stripped,detected,Muse Image 1 - Meta,,,2026-08-27T02:28Z,seal survives 0.0375 where fox is already clean +lh_str0.03000,,derived:gen_lighthouse_watercolor,,qwen-zimage mode=invisible seed=0 strength=0.03,,1600x1600,110d2112d91dd53df5ccd1839e0e2b41c44aa1832adb0090032660e071fb1fd4,no_stripped,detected,Muse Image 1 - Meta,,,2026-08-27T02:28Z,fresh-page protocol; lighthouse holds its seal below the fox boundary: cross-source spread is wide +text_str0.02500,,derived:gen_text_poster,,qwen-zimage mode=invisible seed=0 strength=0.025,,1600x1600,f46a6c53b4f3d39fccb1d62cca82ced2e163e4424d13c98e6468a8e083c0fa54,no_stripped,not_detected,,,,2026-08-27T02:28Z,mid rung inside the clean zone +text_str0.02000,,derived:gen_text_poster,,qwen-zimage mode=invisible seed=0 strength=0.02,,1600x1600,a19cbe22313e0f19768c98567ea89f2d9dc30827691fc7ec2971c52f3e7c6cc6,no_stripped,not_detected,,,,2026-08-27T02:28Z,text clean at 0.02: boundary <= 0.02 - the easiest source measured +text_str0.01500,,derived:gen_text_poster,,qwen-zimage mode=invisible seed=0 strength=0.015,,1600x1600,aa3816c75e38f3ab5afc378d349caafad56f2bb6da859a5ee68fdea57ad00d73,no_stripped,not_detected,,,,2026-08-27T02:41Z,text clean at 0.015: boundary <= 0.015 - the easiest source measured +lh_str0.02500,,derived:gen_lighthouse_watercolor,,qwen-zimage mode=invisible seed=0 strength=0.025,,1600x1600,989c4a7a804bc8420ec4d86b9445bc3a37382c1834782a7f8842f781d69b05e2,no_stripped,,,,,,below the measured detected boundary (0.03) for this source; not individually checked +lh_str0.02000,,derived:gen_lighthouse_watercolor,,qwen-zimage mode=invisible seed=0 strength=0.02,,1600x1600,6a4a4ec94292a145e7d73e6900b8ec6d0eede17137f2b91fba7757ec0bdba5ec,no_stripped,,,,,,below the measured detected boundary (0.03) for this source; not individually checked +nc_str0.03750,,derived:gen_night_city,,qwen-zimage mode=invisible seed=0 strength=0.0375,,1920x1280,46f322335f801ee54427eb39275216465f9a7cfa3d918c698e4d90a2439a0815,no_stripped,not_detected,,,,2026-08-27T02:28Z,boundary (0.03; 0.0375] +nc_str0.03000,,derived:gen_night_city,,qwen-zimage mode=invisible seed=0 strength=0.03,,1920x1280,3f42632319248ad1a91ef2457c7e0b13ed17e1d2569decbbaab67c2072e9a305,no_stripped,detected,Muse Image 1 - Meta,,,2026-08-27T02:28Z,night_city holds seal at 0.03 +mug_str0.03750,,derived:gen_studio_mug,,qwen-zimage mode=invisible seed=0 strength=0.0375,,1600x1600,3b6109ae7e86b8ea74ce33315e3f2a7eda1cadb724d429f0951f13c3ead34b0f,no_stripped,not_detected,,,,2026-08-27T02:28Z,upper rung for the mug bracket +mug_str0.03000,,derived:gen_studio_mug,,qwen-zimage mode=invisible seed=0 strength=0.03,,1600x1600,1c24c984677e1528da83003ac40594f6e5ef1fa9351f1368b6d31a0101308583,no_stripped,not_detected,,,,2026-08-27T02:28Z,mug clean at 0.03: boundary <= 0.03 +lh_str0.05250,,derived:gen_lighthouse_watercolor,,qwen-zimage mode=invisible seed=0 strength=0.0525,,1600x1600,8912ba1ff4a26790f69224c49dd649e46835e277c375276ac9604f5339775b2a,no_stripped,detected,Muse Image 1 - Meta,,,2026-08-27T02:41Z,bisection: lighthouse first-clean boundary bracketed to (0.0525; 0.06] +lh_str0.04500,,derived:gen_lighthouse_watercolor,,qwen-zimage mode=invisible seed=0 strength=0.045,,1600x1600,cfdcf7bbb27c740846a1de4edffee3b25a624c2a8e1aba2362feaa25b682e3ae,no_stripped,detected,Muse Image 1 - Meta,,,2026-08-27T02:28Z,seal survives 0.045: lighthouse is the worst source measured +lh_str0.06000,,derived:gen_lighthouse_watercolor,,qwen-zimage mode=invisible seed=0 strength=0.06,,1600x1600,4e214be00a89dc9f1f32ec39483c5e9668a1ec7f38b15e5794942479c839fcca,no_stripped,not_detected,,,,2026-08-27T02:28Z,lighthouse first-clean boundary bracketed to (0.045 0.06] diff --git a/data/evaluations/engine-selection/README.md b/data/evaluations/engine-selection/README.md index 8c7d7c9..909c948 100644 --- a/data/evaluations/engine-selection/README.md +++ b/data/evaluations/engine-selection/README.md @@ -49,8 +49,8 @@ strengths. The tracked oracle/carrier inputs remain in their canonical homes: `data/contentseal/manifest.csv`. There is no tracked, publication-cleared Microsoft InvisMark carrier yet. The -three Paint sources used by the earlier calibration are user uploads and remain -outside git. A Microsoft row may be added only from a newly generated or +three Paint sources used by the earlier calibration are not publication-cleared +and remain outside git. A Microsoft row may be added only from a newly generated or otherwise publication-cleared source, with a pixel-identical metadata-stripped control that remains positive in Microsoft's detector. diff --git a/data/fixtures/README.md b/data/fixtures/README.md index d453f50..6379d39 100644 --- a/data/fixtures/README.md +++ b/data/fixtures/README.md @@ -177,4 +177,4 @@ dimensions. `digitalSignature` key usage and subject `CN=Ideogram, Inc`, then `c2pa.Builder.from_json(...).sign_file(png, out, Signer.from_info( C2paSignerInfo(b"es256", leaf_pem + ca_pem, pkcs8_key, None)))`. -- No user upload and no Ideogram artifact contributes pixels or bytes. +- No third-party image and no Ideogram artifact contributes pixels or bytes. diff --git a/docs/chroma1-engine-research.md b/docs/chroma1-engine-research.md index 78c69bc..7a00364 100644 --- a/docs/chroma1-engine-research.md +++ b/docs/chroma1-engine-research.md @@ -32,15 +32,17 @@ Two Flux-family traps found while wiring the prototype: - dimensions floor to the /16 latent-patch grid, so the result must be resized back to the input size for pixel-exact comparison. -Scripts: `scripts/chroma_scrub_prototype.py` (first sweep), -`scripts/engine_quality_price_probe.py` (head-to-head with the production -qwen-zimage path), `scripts/engine_cohort_calibration.py` (the cohort ladders -below), `scripts/chroma_meta_high_rungs.py` (the Meta rungs above 0.08), -`scripts/chroma_muse_expansion.py` (harvest-2 Meta API fixtures), -`scripts/chroma_openai_expansion.py` (extra OpenAI SynthID carriers), -`scripts/chroma_seed_probes.py` (seed-1/2 at measured first-cleans). -Generated outputs stay outside the repository (`out/`, gitignored); the durable -verdicts are the tables on this page. +Harnesses (Modal GPU scripts kept outside this repository; each mounts this +library's `src/` and reads its tracked corpora): `chroma_scrub_prototype.py` +(first sweep), `engine_quality_price_probe.py` (head-to-head with the +qwen-zimage path), `engine_cohort_calibration.py` (the cohort ladders below), +`chroma_meta_high_rungs.py` (the Meta rungs above 0.08), +`chroma_muse_expansion.py` (harvest-2 Meta API fixtures), +`chroma_openai_expansion.py` (extra OpenAI SynthID carriers), +`chroma_seed_probes.py` (seed-1/2 at measured first-cleans). +These harnesses are internal tooling and are not distributed, so a reader outside +the project cannot rerun them. Generated outputs stay outside the repository +(`out/`, gitignored); the durable verdicts are the tables on this page. ## Measured floors @@ -99,7 +101,7 @@ superseded by the 2026-09-07 holdout below): - **Microsoft: 0.125**, measured 2026-08-30 on the SAME three valid Paint carriers behind the qwen floor (staged under `out/cohort-calibration/microsoft/` with pixel-identical metadata-stripped - controls; they are real raiw-corpus user uploads and are never committed). + controls; they are not publication-cleared and are never committed). Controls re-verified `Microsoft AI detected` on the day of the run. Against qwen-zimage 0.15: Chroma needs LESS strength on InvisMark. @@ -276,7 +278,8 @@ With the `chroma-zimage` profile implemented @synthid oracle. The composited face regions do not re-introduce a detectable signal on top of the floor. -Generation script: `scripts/chroma_preship_validation.py`; outputs under +Generation harness: `chroma_preship_validation.py` (kept outside this +repository); outputs under `out/preship-chroma/` (gitignored). ## Verdict @@ -326,7 +329,7 @@ Goal: test whether `flat_ratio` (fraction of 16x16 blocks with luma std < 8) predicts Chroma1's first-clean Content Seal boundary well enough to ship a Meta arm analogous to Google's face-count split. -**Harvest 1, from a 495-file spaces dump, was not a diverse expansion.** +**Harvest 1, from a 495-file uncommitted corpus scan, was not a diverse expansion.** Seven "unique" files were staged under `out/cohort-calibration/meta/muse-*` (gitignored). After control checks on `meta.ai/identification`: @@ -365,7 +368,7 @@ committed five), chosen to span class and `flat_ratio`: | illustration_watercolor_botanical | illustration | 0.442 | 0.089 | | scene_tokyo_alley | busy scene | 0.258 | 0.175 | -Script: `scripts/chroma_muse_expansion.py`. Outputs under +Harness: `chroma_muse_expansion.py` (kept outside this repository). Outputs under `out/cohort-calibration/meta-api/` (gitignored). Chroma1 ladders (seven rungs, seed 0, four effective steps) ran for all six. Oracle 2026-08-31, anonymous `playwright-isolated` against @@ -440,12 +443,12 @@ generations (medium, 1024) carry C2PA (`detected`) but SynthID "openai" recreations are also SynthID-negative. New ChatGPT-UI downloads are not in the tree beyond the three committed files. -**Spaces harvest (one day of `_full_scan`, 2026-07-24):** 41 files with +**Uncommitted corpus scan (one day, 2026-07-24):** 41 files with OpenAI C2PA, of which 7 checked by the provenance API were SynthID `DETECTED` (one `NOT_DETECTED`). Four diverse DETECTED files were staged -under `out/cohort-calibration/openai-expand/` (gitignored; user uploads, -not committed) and given a Chroma1 ladder (0.04-0.12, seed 0) by -`scripts/chroma_openai_expansion.py`: +under `out/cohort-calibration/openai-expand/` (gitignored; not +publication-cleared) and given a Chroma1 ladder (0.04-0.12, seed 0) by +`chroma_openai_expansion.py` (a harness kept outside this repository): | id | faces | flat_ratio | |---|---|---| @@ -577,8 +580,9 @@ there is no coherent input feature that justifies overriding the cohort choice. Inputs and integrity manifests are under `data/evaluations/engine-selection/`. Raw generated outputs remain gitignored -under `out/engine-selection-study/`; `scripts/engine_selection_study.py` -reproduces the run and `scripts/analyze_engine_selection_study.py` reproduces +under `out/engine-selection-study/`; the `engine_selection_study.py` harness +(kept outside this repository) reproduces the run and +`scripts/analyze_engine_selection_study.py` reproduces the paired statistics. One generation per prompt is a discovery set, not a license to fit thresholds. Any future content override must first predict a rule here and then survive unused generation indices without changing it. diff --git a/docs/development.md b/docs/development.md index afd6806..37fb84c 100644 --- a/docs/development.md +++ b/docs/development.md @@ -22,7 +22,7 @@ The optional TrustMark decoder downloads weights into its installed package dire ### Known security-gate blocks -`maintain.sh` fails while PyPI ships no fixed release for a transitive CVE. Current case (triaged 2026-08-17): `lightning` 2.6.5, pulled only by the optional `trustmark` extra, carries PYSEC-2026-3624 (RCE via `load_from_checkpoint` on an attacker-crafted checkpoint). The vulnerable API is unreachable here, because the TrustMark decoder loads only its own pinned weights downloaded from the TrustMark release, never a user-supplied checkpoint. The upstream fix is merged but unreleased, and ignores are never added, so run and report the remaining core checks (Ruff, Pyright, tests) separately until a fixed `lightning` release lands; bump it with `uv lock --upgrade-package lightning` as soon as one does. +`maintain.sh` fails while PyPI ships no fixed release for a transitive CVE. Current case (triaged 2026-08-17): `lightning` 2.6.5, pulled only by the optional `trustmark` extra, carries PYSEC-2026-3624 (RCE via `load_from_checkpoint` on an attacker-crafted checkpoint). The vulnerable API is unreachable here, because the TrustMark decoder loads only its own pinned weights downloaded from the TrustMark release, never a user-supplied checkpoint. The upstream fix is merged but unreleased, and ignores are never added, so run and report the remaining core checks (Ruff, Pyright, tests) separately until a fixed `lightning` release lands; bump it with `uv lock --upgrade-package lightning` as soon as one does. The gate prints the same advisory twice, as PYSEC-2026-3624 and as its alias GHSA-qqmf-gpg7-g8gw (CVE-2026-58659); the `2022.6.15` fix version on the second row belongs to the retired calver line and is not an upgrade from 2.6.5, so neither row is actionable. ## CI diff --git a/docs/module-internals.md b/docs/module-internals.md index 69a6d7e..80c1ae4 100644 --- a/docs/module-internals.md +++ b/docs/module-internals.md @@ -502,7 +502,7 @@ over the certificate issuer: an application can sign through an upstream model provider without becoming that provider's product. Only exact product mappings receive this precedence; an unknown claim generator still falls back to issuer attribution. An unmapped issuer org reads as unknown-signer C2PA with no platform; -that is how Ideogram was surfaced (4 corpus uploads signed "Ideogram, Inc", +that is how Ideogram was surfaced (4 private-corpus files signed "Ideogram, Inc", 2026-08-08) before its vendor row was added on 2026-08-27. ### Metadata scanning and stripping @@ -759,7 +759,7 @@ minimum normalized margin across those gates, so its decision threshold is `1.0`. The earlier single-threshold version produced 68 false positives among 11,273 -symmetrically downscaled Spaces controls. A top-candidate plus period-bin version +symmetrically downscaled private-corpus controls. A top-candidate plus period-bin version removed those but still produced 6 false positives among 1,000 source-independent Open Images controls. The high-band gate removed them and then accepted none of 499 previously untouched Open Images reserve controls. The resulting rule @@ -841,7 +841,7 @@ A separate half-scale patch-consensus branch initially looked promising. Its 64-pixel, 90th-percentile patch statistic retained 33 of 49 validation positives and zero of 166 controls, then 27 of 52 locked-test positives and zero of 140 controls. The frozen broad challenge rejected it: 61 of 10,906 symmetrically -half-scaled Spaces controls and 22 of 1,000 independent Open Images controls +half-scaled private-corpus controls and 22 of 1,000 independent Open Images controls crossed the unchanged threshold. A post-challenge Green negative-phase spread gate removed those errors but retained only 2 of 234 later Google rows and zero of 689 later controls. Half-scale support therefore remains explicitly absent. @@ -1416,7 +1416,7 @@ variant is not covered. `_keep_pill` never removes a metadata-bare pill, and the question "can a bare arm (score + footprint-flatness) be opened" was measured to a closed NO over the local -spaces corpus: 68 OCR-confirmed bare pills (an independent pixel-level label: the +private corpus: 68 OCR-confirmed bare pills (an independent pixel-level label: the band sweep read a flush-left `AI生成`) score p50 0.181 / max 0.317, while 799 clean no-signal negatives reach 0.353 and 18 of them already pass the shipped 0.22 raw gate. The true-pill and clean distributions overlap completely -- there is no @@ -1726,7 +1726,8 @@ an unconditional quality claim: Qwen CER stayed 0.074, while Chroma moved from stage is therefore implemented and fidelity-positive on both OpenAI sources, but not assumed to improve every OCR reading. This is a fidelity check, not a provider oracle certification; exact output hashes and per-box metrics are produced by -`scripts/chroma_text_restoration_study.py` under the gitignored +the `chroma_text_restoration_study.py` harness (kept outside this repository) +under the gitignored `out/text-restoration-engine-study/` directory. A matched stage-isolation check on the 18-face Gemini portrait grid confirms the @@ -1824,7 +1825,8 @@ two-sided sign-test p-values were 3.8e-6 for the OpenAI SSIM and PSNR directions and 7.6e-5 for the Meta LPIPS and edge-F1 directions. The tracked discovery inputs and manifests are in [`data/evaluations/engine-selection/`](../data/evaluations/engine-selection/), -the run is reproduced by `scripts/engine_selection_study.py`, and paired analysis +the run is reproduced by the `engine_selection_study.py` harness (kept outside +this repository), and paired analysis by `scripts/analyze_engine_selection_study.py`. These content files were locally re-encoded and are not watermark oracles; they validate fidelity at already oracle-calibrated floors, not removal by themselves. No content-stratum override diff --git a/docs/synthid-detector-removal-plan.md b/docs/synthid-detector-removal-plan.md index 46ba1be..5c049d8 100644 --- a/docs/synthid-detector-removal-plan.md +++ b/docs/synthid-detector-removal-plan.md @@ -1353,7 +1353,7 @@ norm on content-correlated periodic structure and was rejected in favor of the narrow carrier direction. The geometry challenge then selected three `first_only` carrier positives from -each of the 20 most frequent native Spaces geometries. The edit repeats the +each of the 20 most frequent native private-corpus geometries. The edit repeats the same 16x16 carrier past the image boundaries and crops the repetition to the decoded dimensions, so it does not require dimensions divisible by 16. A zero score target cleared 60 of 60 aligned candidates and 5 of 60 matched shifted @@ -1373,7 +1373,7 @@ shifted controls cleared 7, 1, 1, 5, and 17. The increased shifted-control rate is the measured price of adding transform margin. The frozen -0.25 recipe was finally run once on one deterministic first-carrier -positive from every represented native Spaces geometry. All 647 images at 647 +positive from every represented native private-corpus geometry. All 647 images at 647 distinct decoded sizes reached the target, with no maximum-amplitude failure. Median fidelity was 57.67 dB PSNR and 0.99867 SSIM; the worst case was 51.78 dB and 0.99400. Of 323 source images whose carrier survived JPEG-95, 323 aligned @@ -1400,7 +1400,7 @@ refuses overwrite and locally negative input, and records source/output hashes, the selected scalar amplitude, local scores, fidelity metrics, and runtime in a sidecar JSON report. Unit tests cover non-divisible geometry, target attainment, an unreachable target, and the negative-input guard. A real CLI smoke test on a -Spaces source reproduced its reported score exactly through the runtime detector +private-corpus source reproduced its reported score exactly through the runtime detector after saving. It remains a research script rather than a routed package command. ### 2026-08-10: confirmatory oracle-batch readiness @@ -1612,7 +1612,7 @@ carrier epochs, and provider attribution remain outside the claim. The fast native fold remains the default and the `identify` path. That period-8 conclusion was overturned by a later symmetric negative test. -Every one of the 11,506 known non-Google Spaces controls was downscaled by 0.5, +Every one of the 11,506 known non-Google private-corpus controls was downscaled by 0.5, matching the positive transformation; 11,273 outputs remained in the registered geometry range. The direct analytic 8-by-8 template was dominated by shared resize structure: 80.8% of its energy projected onto a 2-by-2 lattice and 94.0% @@ -1629,7 +1629,7 @@ rule: 68 of 11,273 supported controls crossed `0.2460603834083705`. Fixed thresholds for nine recovered-period bins eliminated those errors while retaining 238 of 355 transformed positives, but one of 4,900 COCO controls then crossed through the third spectral candidate. Requiring the canonical winner to -match the strongest spectral candidate removed that case and all 68 Spaces +match the strongest spectral candidate removed that case and all 68 private-corpus errors, with 239 of 355 positives retained. This version was not shipped: a fresh, content-deduplicated 1,000-image Open Images validation corpus produced six false positives. @@ -1646,7 +1646,7 @@ high-band score was `0.004682175209264222`. The retained positives by scale were 0/65 at 0.5, 8/15 at 0.65, 53/55 at 0.8, 33/40 at 0.9, 13/15 at 1.0, 30/40 at 1.1, 38/55 at 1.2, 40/55 at 1.333, and 14/15 at 1.5. A physically transformed template recovered strong correlations -for some period-8 positives, but 975 top-candidate Spaces controls fully +for some period-8 positives, but 975 top-candidate private-corpus controls fully overlapped every tested amplitude, spectral-band, and joint feature. No zero-control operating point retained a period-8 positive. The calibrated runtime therefore uses the top-candidate, period-bin, and high-band gates and @@ -1658,7 +1658,7 @@ threshold frozen above all 341 top-1 development controls recovered 11 of the 126 current false negatives and accepted none of a separate 499-image Open Images reserve; the reserve maximum was 0.100583 against the 0.118168 threshold. The decisive symmetric challenge rejected it: 19 of all 11,506 -Spaces controls after 0.5x resizing crossed the frozen threshold, with a +private-corpus controls after 0.5x resizing crossed the frozen threshold, with a maximum of 0.179989. The errors spanned OpenAI, Firefly, Microsoft, hosted jobs, and other generators. Raising the threshold post hoc above that maximum would recover only seven false negatives, none at scale 0.65 or 0.8. The joint @@ -1717,7 +1717,7 @@ median of 0.27. A development-selected rescue therefore multiplied normalized amplitude by the stronger ring and required ring balance at or below 0.5. A threshold above 341 development controls recovered 11 of 65 top-1 false negatives and accepted none of the 499-image Open Images reserve. The full -symmetric challenge again rejected it: 13 of 11,506 resized Spaces controls +symmetric challenge again rejected it: 13 of 11,506 resized private-corpus controls passed, with a maximum score of 0.694818 against the 0.308683 threshold. Strong single-ring lattices occurred in Firefly, OpenAI, hosted jobs, China-labeled generators, Canva, and other controls. Radial imbalance is therefore another @@ -1732,7 +1732,7 @@ of 0.88 through 0.95, while the additional states were less stable. A threshold above 2,500 development natural-image controls accepted none of a separate 2,500-image reserve and selected 225 of 770 metadata-labeled Google images that the shared-template threshold missed. The broader challenge decisively rejected -the feature: 828 of 11,506 metadata-labeled non-Google Spaces controls crossed +the feature: 828 of 11,506 metadata-labeled non-Google private-corpus controls crossed the frozen threshold. Errors occurred across OpenAI, Microsoft, Firefly, China-labeled generators, hosted jobs, Stable Diffusion, and other sources. A post-hoc intersection above every control that also passed the registered @@ -1744,7 +1744,7 @@ runtime. A related spatial-payload pilot stopped averaging all 16-by-16 blocks and measured carrier and codebook responses block by block. The positive carrier response was spatially coherent: median adjacent-block correlation was 0.61 on -both axes, compared with 0.20 and 0.24 in a heterogeneous Spaces sample and +both axes, compared with 0.20 and 0.24 in a heterogeneous private-corpus sample and 0.04 and 0.06 among codebook false positives. The development-selected rescue was instead the standard deviation of the best codebook response across blocks. It retained 11 of 60 reserve positives and none of 180 reserve controls, @@ -1957,7 +1957,7 @@ challenged related experts. It requires a new content-deduplicated AI-control corpus before it can be treated as validation or runtime logic. The next source-independent model-cohort challenge sharply bounded that -hypothesis. With no exact-byte overlap against the Spaces inventory, the +hypothesis. With no exact-byte overlap against the private-corpus inventory, the original group-separated conjunction accepted 2 of 589 public Gemini 3.1 Flash Image Preview images, none of 520 Nano Banana Pro Preview, and none of 280 DALL-E 3 images. The two Gemini hits were visually distinct diverse images at @@ -1968,7 +1968,7 @@ base rule therefore has weak transfer to a current Gemini cohort but still collides with 2 of 11,506 arbitrary-size controls; the strict rule removes both the controls and the current-Gemini transfer only through a post-test threshold. Neither is a validated universal Google-model or cross-provider SynthID -detector. The 16 Spaces all-size hits and two public Gemini base hits are useful +detector. The 16 private-corpus all-size hits and two public Gemini base hits are useful hard positives for epoch analysis, not justification for implementation. The near-duplicate audit also provided a small mechanistic diagnostic. In all @@ -2470,7 +2470,7 @@ retained as versioned calibration infrastructure, while the independently frozen production thresholds remain the valid two-expert decisions. A wider calibration reused the already saved component reports for 11,273 -supported, symmetrically resized Spaces controls. The stored high-band value +supported, symmetrically resized private-corpus controls. The stored high-band value made the current registered decision score exactly reconstructible throughout the relevant upper tail; rows screened below the historical 0.1182 amplitude ratio cannot affect this tail. At alpha 0.001, the two-expert cascade accepted @@ -2495,7 +2495,7 @@ the fixed detector available as a separately scoped diagnostic does not make their union safe. The fixed-only geometry does not provide a fallback. Among 89 saved non-Google -Spaces controls from 10 to 18 megapixels, where registered mode is unsupported +private-corpus controls from 10 to 18 megapixels, where registered mode is unsupported but fixed mode is supported, 10 crossed the fixed threshold. The errors span multiple generator families. A geometry router therefore cannot extend recall by selecting fixed whenever registered is unavailable. @@ -2514,7 +2514,7 @@ separate OpenAI family still require additional validated experts. Directly enlarging registered mode's pixel ceiling also failed. The unchanged registered components were computed on every saved 10-to-18-megapixel example: -37 Google candidates and 89 non-Google Spaces controls. The frozen threshold +37 Google candidates and 89 non-Google private-corpus controls. The frozen threshold accepted one positive and zero controls. Amplitude passed for 28 positives and the selected spatial and spectral periods agreed for 21, but only three cleared the high-band gate. Large full-frame spectra therefore lose almost all recall; @@ -2687,7 +2687,7 @@ validation only. The selected period-16 power candidate used a separately fitted template for each view. It accepted 8 of 140 validation positives and 8 of 158 locked-test positives, with no native-geometry control accepted in either split. On the complete wide challenge it accepted none of 2,227 -validation and 2,162 test Spaces controls, one of all 261 action-derived +validation and 2,162 test private-corpus controls, one of all 261 action-derived same-provider controls, and none of the 118 exact-version `gpt-image 2.0` controls. Five of its eight test hits overlapped the signed period-8 candidate; three were additional. @@ -2705,7 +2705,7 @@ measured view directions correlated 0.992 for native versus JPEG and 0.900 for native versus resize. It retained 7 of 158 native-geometry locked-test positives and none of 135 controls. That apparent invariance failed on the wide geometry challenge: the same thresholds accepted 11 of 2,227 validation -and 14 of 2,162 test Spaces controls, plus seven of 261 same-provider controls +and 14 of 2,162 test private-corpus controls, plus seven of 261 same-provider controls and two of 118 exact-version controls. It is a general renderer or resampling spectrum and is rejected. @@ -2750,7 +2750,7 @@ absolute residual of the third cube-root LMS component at period 4. It retained 33 of 140 validation and 43 of 158 locked-test positives, but also accepted 2 of 135 locked-test controls. The frozen wide challenge confirmed a renderer confound: it accepted 48 of 1,854 validation and 52 of 1,839 test OpenAI images, -against 7 of 2,227 validation and 5 of 2,162 test Spaces controls. It also +against 7 of 2,227 validation and 5 of 2,162 test private-corpus controls. It also accepted 10 of 261 action-derived same-provider controls, including 5 of 118 that explicitly name `gpt-image 2.0`. Requiring spatial agreement did not repair specificity; the validation-selected median over four quadrants kept @@ -3180,9 +3180,9 @@ validation controls at the frozen 0.552176 threshold, then 27 of 52 locked-test positives and zero of 140 controls. This looked like a useful low-resolution expert but did not survive scale-matched specificity testing. -The frozen challenge symmetrically resized every remaining Spaces control and a +The frozen challenge symmetrically resized every remaining private-corpus control and a separate 1,000-image Open Images reserve to 0.5x. The expert accepted 61 of -10,906 Spaces controls and 22 of 1,000 Open Images controls. All 83 errors were +10,906 private-corpus controls and 22 of 1,000 Open Images controls. All 83 errors were rescored with the prespecified feature inventory. A negative-Green patch-spread gate could remove them post hoc, but retained only 12 of 106 base-positive development hits. On the later August 7-10 cohort the original patch expert @@ -3203,7 +3203,7 @@ Near-ceiling windows, color spaces, and JPEG-paired phase directions did not provide a missing large-image expert. Three aligned windows of approximately 10 megapixels retained 1 of 37 candidates and zero of 89 controls. A native fixed-score plus Green mid-band rule retained 15 of 19 candidates in four exact -recurring geometries and accepted one of 11,417 resized Spaces controls, but +recurring geometries and accepted one of 11,417 resized private-corpus controls, but collapsed to 0 of 19 after JPEG 90. A codebook fitted to the minimum native/JPEG period-16 correlation selected RGB Green mid-band on the pre-July split. It retained 23 of 26 candidates and zero of 40 controls there, then 10 of 11 and 7 @@ -3242,7 +3242,7 @@ is the minimum normalized gate margin and crosses at `1.0`. The rule retained all 37 inferred candidates, including all seven official pixel positives. It accepted none of 17,417 exposed COCO, Open Images, and -Spaces controls after the portrait alias gate. Because those controls informed +private-corpus controls after the portrait alias gate. Because those controls informed the final gate, they do not certify the operating point. The constants were then challenged through the actual runtime on a frozen, decoded-pixel-deduped local holdout: 2,000 COCO val2017 images excluded from the earlier 3,000-image @@ -6059,7 +6059,7 @@ parents at nine scales from 0.5 through 0.9, but accepted 605/2,997 and 587/2,996 controls in two Open Images cohorts. The crossings concentrated at periods 8 and 12.8 and tracked JPEG sampling. A 3,964-image COCO challenge added one period-10 crossing below one megapixel, while 3,772 heterogeneous -non-Google/non-OpenAI Spaces controls added 28 crossings, again only at periods +non-Google/non-OpenAI private-corpus controls added 28 crossings, again only at periods 8 and 12.8. The unrestricted branch is a codec/resize-lattice detector and is rejected. @@ -6105,7 +6105,7 @@ non-block phases. All seven lossless 0.5x positives had both Red-Green and Blue-Yellow ratios no greater than the frozen `1.05` ceiling. The ceiling rejected 600/600 development period-8 codec crossings, then 582/582 crossings in the nonoverlapping Open Images holdout, 601/601 in the feature-unseen frozen -reserve, and 7/7 in the heterogeneous Spaces challenge. An additional 350 +reserve, and 7/7 in the heterogeneous private-corpus challenge. An additional 350 controls transformed through the identical lossless 0.5x resize produced zero base crossings before the veto. diff --git a/docs/synthid-oracle-ladders.md b/docs/synthid-oracle-ladders.md index e8cc17e..27e624d 100644 --- a/docs/synthid-oracle-ladders.md +++ b/docs/synthid-oracle-ladders.md @@ -26,7 +26,7 @@ | L1 repair, L1 geometry, camera vs edit pair, E3 | [detector](synthid-detector-research.md) | | CLIP-L photo vs AI, provider CLIP, union | [AI classifiers](ai-generated-image-classifiers.md), [source classifiers](synthid-classifiers.md) | | 124-d three-class and binary AI | [source classifiers](synthid-classifiers.md) | -| `pipeline_lattice` re-check, Spaces census | [source classifiers](synthid-classifiers.md) | +| `pipeline_lattice` re-check, private-corpus census | [source classifiers](synthid-classifiers.md) | | Attack / kill / flip / add / surround ladders | [removal](synthid-removal-research.md) | | 16-32 titration, E2 scramble, Bayer and geometry | [removal](synthid-removal-research.md) | | S4 provider split, M2 Imagen `addWatermark`, reverse-SynthID, Bypass | [detector](synthid-detector-research.md) | diff --git a/docs/synthid-robust-identity-research.md b/docs/synthid-robust-identity-research.md index 36965ff..a0f88e5 100644 --- a/docs/synthid-robust-identity-research.md +++ b/docs/synthid-robust-identity-research.md @@ -228,7 +228,7 @@ from the test set + this doc). - New deps: `diffusers` already in the diffusion extra; PhotoMaker ships as a `.bin` loaded via `pipeline.load_photomaker_adapter(...)`. The OpenCLIP encoder is the same one diffusers already pulls. No new heavy pip dep. -- Weight download: PhotoMaker-V1 weights are ~3 GB. Add to the Modal HF volume +- Weight download: PhotoMaker-V1 weights are ~3 GB. Add to the model cache alongside SDXL. - VRAM: SDXL + canny ControlNet + PhotoMaker-V1 fits comfortably in A100-40GB. - Latency: a few extra seconds on cold start (load PhotoMaker), negligible per diff --git a/docs/synthid.md b/docs/synthid.md index bec7e7e..4564b80 100644 --- a/docs/synthid.md +++ b/docs/synthid.md @@ -397,7 +397,7 @@ shifted control cleared one. The same native-period edit works without resizing when dimensions are not multiples of 16: repeat the carrier past both image boundaries and crop it to the decoded geometry. A deterministic development challenge selected three -first-carrier-positive Spaces images from each of the 20 most frequent native +first-carrier-positive private-corpus images from each of the 20 most frequent native geometries, for 60 images total. Searching to a zero fixed-tile target cleared 60 of 60, compared with 5 of 60 norm-matched one-pixel-shifted controls. Median fidelity was 60.37 dB PSNR and 0.99919 SSIM; the minima were 53.56 dB and @@ -406,7 +406,7 @@ local clearances at median 57.70 dB PSNR and 0.99863 SSIM, with minima of 52.38 dB and 0.99443. The frozen -0.25 rule was then evaluated once on one deterministic first-carrier -positive from every native geometry represented by that Spaces subset: 647 +positive from every native geometry represented by that private-corpus subset: 647 images at 647 distinct decoded sizes. It reached the local target on all 647, with no maximum-amplitude failure. Median fidelity was 57.67 dB PSNR and 0.99867 SSIM; the worst case was 51.78 dB and 0.99400. Among the 323 images @@ -899,8 +899,8 @@ The default was **vendor-adaptive** (`watermark_profiles.resolve_strength` + `vendor_for_strength`): the tool read the C2PA issuer on the original input and picked `OPENAI_STRENGTH` 0.10 / `GEMINI_STRENGTH` 0.15 / `UNKNOWN_STRENGTH` 0.15 **(LOWERED 2026-06-14 from the 2026-06-04 cert floors 0.20/0.30/0.30)**. **The SAME ladder applied -to both pipelines** (`sdxl` and `controlnet`). The 2026-06-14 re-test on the deployed -Modal controlnet worker (v0.10.0) cleared SynthID on the oracle at OpenAI 0.10 (2 +to both pipelines** (`sdxl` and `controlnet`). The 2026-06-14 re-test on a deployed +GPU worker running the controlnet profile (v0.10.0) cleared SynthID on the oracle at OpenAI 0.10 (2 photoreal) and Google 0.15 (2 NATIVE 2816x1536, contradicting the "native >= 0.30" guess on line above), and a pixel sweep showed 0.20/0.30 over-regenerated for no efficacy gain. **This re-opens a genuine tension with the 2026-06-04 pass, which found photoreal STILL diff --git a/scripts/README.md b/scripts/README.md index 1340550..0c8cc72 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -56,10 +56,8 @@ explicitly names a tracked canonical result. | Script | Purpose | | --- | --- | -| `chroma_text_restoration_study.py` | Compare verified-text restoration for Qwen and Chroma on H100 without running both engines in production. | | `cjk_tail_probe.py` | Test a generic template for otherwise uncovered CJK labels. | | `controlnet_sweep.py` | Sweep the historical ControlNet removal prototype. | -| `engine_selection_study.py` | Run one global engine at a time over the tracked prompt-matched content matrix. | | `analyze_engine_selection_study.py` | Reduce engine-study output to paired deltas and exact sign tests. | | `infer_text_lines.py` | Draft stable source-text lines without modifying pixels. | | `qwen_scrub_prototype.py` | Probe low-strength Qwen regeneration on a GPU. | diff --git a/scripts/analyze_engine_selection_study.py b/scripts/analyze_engine_selection_study.py index 2c1abcd..3d1b55a 100644 --- a/scripts/analyze_engine_selection_study.py +++ b/scripts/analyze_engine_selection_study.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 """Summarize paired fidelity results from the engine-selection study. -Run from the repository root after ``engine_selection_study.py``: +Run from the repository root after the ``engine_selection_study.py`` harness has +written ``out/engine-selection-study/summary.json``: uv run scripts/analyze_engine_selection_study.py diff --git a/scripts/chroma_google_high_rungs.py b/scripts/chroma_google_high_rungs.py deleted file mode 100755 index 4f97849..0000000 --- a/scripts/chroma_google_high_rungs.py +++ /dev/null @@ -1,114 +0,0 @@ -# /// script -# requires-python = ">=3.11" -# dependencies = ["modal>=1.5"] -# /// -"""Extra high Chroma1 rungs (0.25-0.40) for the Google cohort fixtures. - -The 0.08-0.20 ladder came back detected end-to-end on the first fixture, so -this appends the high rungs for every Google fixture without touching the -already-oracled lower outputs. -""" - -from __future__ import annotations - -import json -import math -from pathlib import Path - -import modal - -_ROOT = Path(__file__).resolve().parent.parent - -app = modal.App("chroma-google-high-rungs") - -image = ( - modal.Image.debian_slim(python_version="3.12") - .pip_install( - "torch", - "diffusers>=0.38,<1", - "transformers>=4.53", - "accelerate", - "sentencepiece", - "protobuf", - "pillow", - "numpy", - ) - .env({"HF_HOME": "/cache"}) -) - -cache = modal.Volume.from_name("chroma-hf-cache", create_if_missing=True) - -CHROMA_MODEL_ID = "lodestones/Chroma1-HD" -RUNGS = (0.25, 0.30, 0.35, 0.40) -EFFECTIVE_STEPS = 4 -_PROMPT = "high quality, sharp, detailed, faithful to the original" -_NEGATIVE = "blurry, lowres, distorted text, garbled text, artifacts" - -FIXTURES = ( - "Gemini_Generated_Image_633uuy633uuy633u.png", - "Gemini_Generated_Image_akdbeiakdbeiakdb.png", - "Gemini_Generated_Image_y48j3cy48j3cy48j.png", - "Gemini_Generated_Image_3mc4t93mc4t93mc4.png", -) -MAX_SIDE = 1536 - - -@app.function(image=image, gpu="H100", volumes={"/cache": cache}, timeout=2400) -def run(payload: dict[str, bytes]) -> dict: - import io - import time - - import torch - from diffusers import ChromaImg2ImgPipeline - from PIL import Image - - chroma = ChromaImg2ImgPipeline.from_pretrained(CHROMA_MODEL_ID, torch_dtype=torch.bfloat16).to("cuda") - out: dict = {} - for name, data in payload.items(): - source = Image.open(io.BytesIO(data)).convert("RGB") - if MAX_SIDE and max(source.size) > MAX_SIDE: - scale = MAX_SIDE / max(source.size) - source = source.resize( - (round(source.width * scale), round(source.height * scale)), - Image.Resampling.LANCZOS, - ) - width = max(16, (source.width // 16) * 16) - height = max(16, (source.height // 16) * 16) - for strength in RUNGS: - started = time.perf_counter() - generator = torch.Generator(device="cpu").manual_seed(0) - image = chroma( - prompt=_PROMPT, - negative_prompt=_NEGATIVE, - image=source, - width=width, - height=height, - strength=strength, - num_inference_steps=max(1, math.ceil(EFFECTIVE_STEPS / strength)), - guidance_scale=5.0, - generator=generator, - ).images[0] - if image.size != source.size: - image = image.resize(source.size, Image.Resampling.LANCZOS) - buffer = io.BytesIO() - image.save(buffer, format="PNG") - out[f"{Path(name).stem}/chroma_s{strength:.2f}"] = { - "png": buffer.getvalue(), - "seconds": round(time.perf_counter() - started, 2), - } - print(f"{name} s={strength} done", flush=True) - cache.commit() - return out - - -@app.local_entrypoint() -def main(out: str = "out/cohort-calibration/google") -> None: - payload = {name: (_ROOT / "data" / "synthid" / "originals" / name).read_bytes() for name in FIXTURES} - results = run.remote(payload) - timing = {} - for key, item in results.items(): - destination = Path(out) / f"{key}.png" - destination.parent.mkdir(parents=True, exist_ok=True) - destination.write_bytes(item["png"]) - timing[key] = item["seconds"] - print(json.dumps(timing, indent=2)) diff --git a/scripts/chroma_meta_high_rungs.py b/scripts/chroma_meta_high_rungs.py deleted file mode 100755 index 39a7bf7..0000000 --- a/scripts/chroma_meta_high_rungs.py +++ /dev/null @@ -1,109 +0,0 @@ -# /// script -# requires-python = ">=3.11" -# dependencies = ["modal>=1.5"] -# /// -"""Extra high Chroma1 rungs for the Meta Content Seal cohort. - -The first calibration ladder topped out at 0.08 and the worst fixture -(gen_lighthouse_watercolor) was still detected there, so this appends 0.10, -0.12 and 0.15 for every Meta fixture without touching the already-oracled -lower rungs. -""" - -from __future__ import annotations - -import json -import math -from pathlib import Path - -import modal - -app = modal.App("chroma-meta-high-rungs") - -_ROOT = Path(__file__).resolve().parent.parent - -image = ( - modal.Image.debian_slim(python_version="3.12") - .pip_install( - "torch", - "diffusers>=0.38,<1", - "transformers>=4.53", - "accelerate", - "sentencepiece", - "protobuf", - "pillow", - "numpy", - ) - .env({"HF_HOME": "/cache"}) -) - -cache = modal.Volume.from_name("chroma-hf-cache", create_if_missing=True) - -CHROMA_MODEL_ID = "lodestones/Chroma1-HD" -RUNGS = (0.17,) -EFFECTIVE_STEPS = 4 -_PROMPT = "high quality, sharp, detailed, faithful to the original" -_NEGATIVE = "blurry, lowres, distorted text, garbled text, artifacts" - -META_FIXTURES = ( - "gen_fox_forest.webp", - "gen_text_poster.webp", - "gen_lighthouse_watercolor.webp", - "gen_night_city.webp", - "gen_studio_mug.webp", -) - - -@app.function(image=image, gpu="H100", volumes={"/cache": cache}, timeout=1800) -def run(payload: dict[str, bytes]) -> dict: - import io - import time - - import torch - from diffusers import ChromaImg2ImgPipeline - from PIL import Image - - chroma = ChromaImg2ImgPipeline.from_pretrained(CHROMA_MODEL_ID, torch_dtype=torch.bfloat16).to("cuda") - out: dict = {} - for name, data in payload.items(): - source = Image.open(io.BytesIO(data)).convert("RGB") - width = max(16, (source.width // 16) * 16) - height = max(16, (source.height // 16) * 16) - for strength in RUNGS: - started = time.perf_counter() - generator = torch.Generator(device="cpu").manual_seed(0) - image = chroma( - prompt=_PROMPT, - negative_prompt=_NEGATIVE, - image=source, - width=width, - height=height, - strength=strength, - num_inference_steps=max(1, math.ceil(EFFECTIVE_STEPS / strength)), - guidance_scale=5.0, - generator=generator, - ).images[0] - if image.size != source.size: - image = image.resize(source.size, Image.Resampling.LANCZOS) - buffer = io.BytesIO() - image.save(buffer, format="PNG") - out[f"{Path(name).stem}/chroma_s{strength:.3f}"] = { - "png": buffer.getvalue(), - "seconds": round(time.perf_counter() - started, 2), - } - print(f"{name} s={strength} done", flush=True) - cache.commit() - return out - - -@app.local_entrypoint() -def main(out: str = "out/cohort-calibration/meta") -> None: - payload = {name: (_ROOT / "data" / "contentseal" / "originals" / name).read_bytes() for name in META_FIXTURES} - results = run.remote(payload) - timing = {} - for key, item in results.items(): - destination = Path(out) / f"{key}.png" - destination.parent.mkdir(parents=True, exist_ok=True) - destination.write_bytes(item["png"]) - timing[key] = item["seconds"] - print(json.dumps(timing, indent=2)) diff --git a/scripts/chroma_microsoft_ladder.py b/scripts/chroma_microsoft_ladder.py deleted file mode 100755 index e895cce..0000000 --- a/scripts/chroma_microsoft_ladder.py +++ /dev/null @@ -1,142 +0,0 @@ -# /// script -# requires-python = ">=3.11" -# dependencies = ["modal>=1.5"] -# /// -"""Chroma1 ladder for the Microsoft InvisMark cohort (three valid Paint sources) -plus the matching qwen-zimage production runs at the shipped 0.15 floor. - -The sources are the same three Paint carriers behind the qwen cohort floor -(staged under out/cohort-calibration/microsoft/