From 2260f9025e4a13cab4e19284037ed411800f3581 Mon Sep 17 00:00:00 2001 From: felirami Date: Sat, 15 Aug 2026 18:14:49 -0400 Subject: [PATCH 1/3] Route DINO preprocess through the shared Pillow-exact resize Extension, Node harness, and probe-training extractor now compute identical DINO inputs. The extractor's local preprocess duplicate is replaced with an import of the shipped function, which also fixes its unguarded grayscale channel reads. Probe retrain on these features follows; the shipped dino-probe.json is unchanged until then. --- eval/extract-features.mjs | 34 ++++-------------- src/clip-preprocess.js | 17 ++++----- src/dino.js | 73 ++++++++++++++++++++++++--------------- tests/dino.test.mjs | 39 +++++++++++---------- 4 files changed, 80 insertions(+), 83 deletions(-) diff --git a/eval/extract-features.mjs b/eval/extract-features.mjs index c277679..a380643 100644 --- a/eval/extract-features.mjs +++ b/eval/extract-features.mjs @@ -107,34 +107,12 @@ async function degradeBytes(buffer, rand) { return { buffer: outBuf, aug: parts.join('+') }; } -function toCHWDino(data, channels, size) { - const plane = size * size; - const out = new Float32Array(3 * plane); - for (let i = 0; i < plane; i++) { - const base = i * channels; - out[i] = (data[base] / 255 - DINO_MEAN[0]) / DINO_STD[0]; - out[i + plane] = (data[base + 1] / 255 - DINO_MEAN[1]) / DINO_STD[1]; - out[i + 2 * plane] = (data[base + 2] / 255 - DINO_MEAN[2]) / DINO_STD[2]; - } - return out; -} - -export async function dinoPreprocess(rawImage) { - const { width, height } = rawImage; - let rw, rh; - if (width < height) { - rw = DINO_SHORTEST; - rh = Math.round((height * DINO_SHORTEST) / width); - } else { - rh = DINO_SHORTEST; - rw = Math.round((width * DINO_SHORTEST) / height); - } - const resized = await rawImage.resize(rw, rh); - const sx = Math.floor((rw - DINO_CROP) / 2); - const sy = Math.floor((rh - DINO_CROP) / 2); - const cropped = await resized.crop([sx, sy, sx + DINO_CROP - 1, sy + DINO_CROP - 1]); - return toCHWDino(cropped.data, cropped.channels, DINO_CROP); -} +// Preprocess comes from the shipped module so probe training, the Node +// harness, and the extension all compute identical DINO inputs (Pillow- +// exact resize, guarded grayscale handling). A local duplicate here once +// drifted from production; do not reintroduce one. +import { dinoPreprocessRawImage as dinoPreprocess } from '../src/dino.js'; +export { dinoPreprocess }; /** CLS + mean(patch tokens) from last_hidden_state [1, T, H]. */ export function poolFeatures(hidden, tokens, hiddenSize) { diff --git a/src/clip-preprocess.js b/src/clip-preprocess.js index 8e820f0..df2c85f 100644 --- a/src/clip-preprocess.js +++ b/src/clip-preprocess.js @@ -145,25 +145,26 @@ export function imageDataToCHW(imageData) { } /** - * Copy a CROP_SIZE window out of a packed row-major pixel buffer. + * Copy a square window out of a packed row-major pixel buffer. * @param {Uint8Array|Uint8ClampedArray} data width * height * channels * @param {number} width * @param {number} height * @param {number} channels * @param {number} sx * @param {number} sy - * @returns {Uint8ClampedArray} CROP_SIZE * CROP_SIZE * channels + * @param {number} [cropSize] window side, defaults to the CF crop + * @returns {Uint8ClampedArray} cropSize * cropSize * channels */ -export function cropPackedPixels(data, width, height, channels, sx, sy) { - if (sx < 0 || sy < 0 || sx + CROP_SIZE > width || sy + CROP_SIZE > height) { +export function cropPackedPixels(data, width, height, channels, sx, sy, cropSize = CROP_SIZE) { + if (sx < 0 || sy < 0 || sx + cropSize > width || sy + cropSize > height) { throw new Error( - `Crop ${CROP_SIZE} at ${sx},${sy} does not fit inside ${width}x${height}` + `Crop ${cropSize} at ${sx},${sy} does not fit inside ${width}x${height}` ); } - const rowLength = CROP_SIZE * channels; - const out = new Uint8ClampedArray(CROP_SIZE * rowLength); - for (let y = 0; y < CROP_SIZE; y++) { + const rowLength = cropSize * channels; + const out = new Uint8ClampedArray(cropSize * rowLength); + for (let y = 0; y < cropSize; y++) { const start = ((sy + y) * width + sx) * channels; out.set(data.subarray(start, start + rowLength), y * rowLength); } diff --git a/src/dino.js b/src/dino.js index aa67ea8..15dc550 100644 --- a/src/dino.js +++ b/src/dino.js @@ -10,6 +10,9 @@ * shortest edge 256, center crop 224, ImageNet mean/std. */ +import { pillowResize } from './pixel-resize.js'; +import { cropPackedPixels, needsCanvasFallback } from './clip-preprocess.js'; + export const DINO_MODEL_ID = 'Xenova/dinov2-small'; export const DINO_ONNX_PATH = 'onnx/model.onnx'; export const DINO_SHORTEST_EDGE = 256; @@ -61,9 +64,10 @@ export function dinoPackedRgbToCHW(data, channels) { } /** - * Node eval path using transformers.js RawImage helpers. Keeping this beside - * the browser preprocessor makes the extension and reproducible harness share - * the same resize, center-crop, channel, and normalization policy. + * Node eval path. Shares the Pillow-exact resize with the browser path so + * the extension, the harness, and probe training all compute identical + * DINO inputs. The probe head shipped with this revision is trained on + * features extracted through this exact path. * @param {import('@huggingface/transformers').RawImage} rawImage * @returns {Promise} */ @@ -72,45 +76,58 @@ export async function dinoPreprocessRawImage(rawImage) { rawImage.width, rawImage.height ); - const resized = await rawImage.resize(resizedW, resizedH); + const resized = pillowResize( + rawImage.data, + rawImage.width, + rawImage.height, + rawImage.channels, + resizedW, + resizedH + ); const sx = Math.floor((resizedW - DINO_CROP_SIZE) / 2); const sy = Math.floor((resizedH - DINO_CROP_SIZE) / 2); - const cropped = await resized.crop([ + const crop = cropPackedPixels( + resized, + resizedW, + resizedH, + rawImage.channels, sx, sy, - sx + DINO_CROP_SIZE - 1, - sy + DINO_CROP_SIZE - 1, - ]); - - if (cropped.width !== DINO_CROP_SIZE || cropped.height !== DINO_CROP_SIZE) { - throw new Error( - `DINO crop produced ${cropped.width}x${cropped.height}, expected ${DINO_CROP_SIZE}` - ); - } - - return dinoPackedRgbToCHW(cropped.data, cropped.channels); + DINO_CROP_SIZE + ); + return dinoPackedRgbToCHW(crop, rawImage.channels); } /** - * Browser path: center 224 crop from an ImageBitmap. + * Browser path: center 224 crop from an ImageBitmap through the same + * Pillow-exact resize as the Node path. Oversized bitmaps fall back to + * the legacy canvas resize (same guard as the CF path). * @param {ImageBitmap} bitmap * @returns {Float32Array} */ export function dinoPreprocessBitmap(bitmap) { const { width: rw, height: rh } = dinoResizeDimensions(bitmap.width, bitmap.height); - const resizeCanvas = new OffscreenCanvas(rw, rh); - const resizeCtx = resizeCanvas.getContext('2d', { willReadFrequently: true }); - resizeCtx.imageSmoothingEnabled = true; - resizeCtx.imageSmoothingQuality = 'high'; - resizeCtx.drawImage(bitmap, 0, 0, rw, rh); - const sx = Math.floor((rw - DINO_CROP_SIZE) / 2); const sy = Math.floor((rh - DINO_CROP_SIZE) / 2); - const crop = new OffscreenCanvas(DINO_CROP_SIZE, DINO_CROP_SIZE); - const cropCtx = crop.getContext('2d', { willReadFrequently: true }); - cropCtx.drawImage(resizeCanvas, sx, sy, DINO_CROP_SIZE, DINO_CROP_SIZE, 0, 0, DINO_CROP_SIZE, DINO_CROP_SIZE); - const imageData = cropCtx.getImageData(0, 0, DINO_CROP_SIZE, DINO_CROP_SIZE); - return dinoPackedRgbToCHW(imageData.data, 4); + + if (needsCanvasFallback(bitmap.width, bitmap.height)) { + const resizeCanvas = new OffscreenCanvas(rw, rh); + const resizeCtx = resizeCanvas.getContext('2d', { willReadFrequently: true }); + resizeCtx.imageSmoothingEnabled = true; + resizeCtx.imageSmoothingQuality = 'high'; + resizeCtx.drawImage(bitmap, 0, 0, rw, rh); + const imageData = resizeCtx.getImageData(0, 0, rw, rh); + const crop = cropPackedPixels(imageData.data, rw, rh, 4, sx, sy, DINO_CROP_SIZE); + return dinoPackedRgbToCHW(crop, 4); + } + + const nativeCanvas = new OffscreenCanvas(bitmap.width, bitmap.height); + const nativeCtx = nativeCanvas.getContext('2d', { willReadFrequently: true }); + nativeCtx.drawImage(bitmap, 0, 0); + const rgba = nativeCtx.getImageData(0, 0, bitmap.width, bitmap.height).data; + const resized = pillowResize(rgba, bitmap.width, bitmap.height, 4, rw, rh); + const crop = cropPackedPixels(resized, rw, rh, 4, sx, sy, DINO_CROP_SIZE); + return dinoPackedRgbToCHW(crop, 4); } /** diff --git a/tests/dino.test.mjs b/tests/dino.test.mjs index 81f4358..29113c9 100644 --- a/tests/dino.test.mjs +++ b/tests/dino.test.mjs @@ -69,33 +69,34 @@ describe('dinoPackedRgbToCHW', () => { }); describe('dinoPreprocessRawImage', () => { - it('uses the shared 256-short-edge center crop', async () => { + it('resizes to the 256 short edge and center-crops 224 via pillowResize', async () => { const plane = DINO_CROP_SIZE * DINO_CROP_SIZE; - let resizeArgs = null; - let cropArgs = null; + // Constant-value pixels survive Pillow bicubic exactly, so a flat + // image proves the resize plus window-crop path end to end. const rawImage = { width: 1024, height: 768, - async resize(width, height) { - resizeArgs = [width, height]; - return { - async crop(box) { - cropArgs = box; - return { - width: DINO_CROP_SIZE, - height: DINO_CROP_SIZE, - channels: 3, - data: new Uint8Array(plane * 3), - }; - }, - }; - }, + channels: 3, + data: new Uint8Array(1024 * 768 * 3).fill(200), }; const chw = await dinoPreprocessRawImage(rawImage); - assert.deepEqual(resizeArgs, [341, 256]); - assert.deepEqual(cropArgs, [58, 16, 281, 239]); assert.equal(chw.length, 3 * plane); + // (200/255 - 0.485) / 0.229 in the R plane, everywhere. + const expectedR = (200 / 255 - 0.485) / 0.229; + assert.ok(Math.abs(chw[0] - expectedR) < 1e-6); + assert.ok(Math.abs(chw[plane - 1] - expectedR) < 1e-6); + }); + + it('handles grayscale sources without NaN poisoning', async () => { + const rawImage = { + width: 512, + height: 512, + channels: 1, + data: new Uint8Array(512 * 512).fill(128), + }; + const chw = await dinoPreprocessRawImage(rawImage); + for (let i = 0; i < 10; i++) assert.ok(Number.isFinite(chw[i])); }); }); From 075e0fc5cadd9fbdabcb15500177d0ebe082cef6 Mon Sep 17 00:00:00 2001 From: felirami Date: Sat, 15 Aug 2026 20:25:48 -0400 Subject: [PATCH 2/3] Make fetch-train resumable, authenticated, and hard-negative aware - Sources already at target count are skipped on rerun, and existing files are never re-downloaded, so a rate-limit abort resumes cheaply - Requests to huggingface.co hosts attach HF_TOKEN or the CLI cached token when present, which raises the datasets-server rate limit - Five hard-negative real sources added (Unsplash stock, Amazon Berkeley product shots, LSUN bedrooms, DeepFashion catalog, Oxford flowers), rows strictly disjoint from the eval stress set, with nested URL columns, a shortest-side gate, and row-index file naming mirroring the exact fetch that built the shipped probe's negatives --- eval/fetch-train.mjs | 109 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 102 insertions(+), 7 deletions(-) diff --git a/eval/fetch-train.mjs b/eval/fetch-train.mjs index 00d8602..f221230 100644 --- a/eval/fetch-train.mjs +++ b/eval/fetch-train.mjs @@ -10,7 +10,7 @@ * Usage: node eval/fetch-train.mjs */ -import { mkdir, writeFile, readdir } from 'node:fs/promises'; +import { access, mkdir, writeFile, readdir } from 'node:fs/promises'; import { join } from 'node:path'; const OUT = process.argv[2]; @@ -37,13 +37,49 @@ const SOURCES = [ { name: 'food', label: 'real', dataset: 'ethz/food101', columns: ['image'], count: 300, offsets: [200, 400, 600] }, { name: 'celeba', label: 'real', dataset: 'nielsr/CelebA-faces', columns: ['image'], count: 300, offsets: [200, 400, 600] }, { name: 'imgnet', label: 'real', dataset: 'frgfm/imagenette', columns: ['image'], count: 300, offsets: [5000, 6000, 7000] }, + // --- Hard-negative reals: professional stock, product catalogs, + // interiors, and high-saturation nature. These teach the probe not to + // fire on polished real photography (github issue 23 failure mode). + // Rows are strictly disjoint from the eval stress set, which uses + // unsplash-lite rows 0-79 and rows 0-391 (stride 10) of the others. + { name: 'unsplash2', label: 'real', dataset: '1aurent/unsplash-lite', urlColumn: 'photo.image_url', urlParam: 'w=1600', nameByRow: true, columns: [], count: 800, offsets: [200, 300, 400, 500, 600, 700, 800, 900] }, + { name: 'abo2', label: 'real', dataset: 'amaye15/amazon_berkeley_objects', columns: ['image'], minSide: 200, nameByRow: true, count: 300, offsets: [500, 600, 700] }, + { name: 'lsunbed2', label: 'real', dataset: 'pcuenq/lsun-bedrooms', columns: ['image'], nameByRow: true, count: 300, offsets: [500, 600, 700] }, + { name: 'deepfashion2', label: 'real', dataset: 'Marqo/deepfashion-inshop', split: 'data', columns: ['image'], nameByRow: true, count: 300, offsets: [500, 600, 700] }, + { name: 'flowers2', label: 'real', dataset: 'nkirschi/oxford-flowers', columns: ['image'], nameByRow: true, count: 300, offsets: [500, 600, 700] }, ]; const FETCH_TIMEOUT = 30000; const CONCURRENCY = 10; +// Optional Hugging Face auth: raises the datasets-server rate limit far +// above the anonymous tier. Reads HF_TOKEN or the huggingface-cli cache; +// the token is only ever attached to huggingface.co hosts. +let HF_TOKEN = process.env.HF_TOKEN || null; +if (!HF_TOKEN) { + try { + const { readFileSync } = await import('node:fs'); + const { homedir } = await import('node:os'); + HF_TOKEN = readFileSync(`${homedir()}/.cache/huggingface/token`, 'utf8').trim() || null; + } catch {} +} + +function hfHeaders(url) { + if (!HF_TOKEN) return undefined; + try { + const host = new URL(url).hostname; + if (host === 'huggingface.co' || host.endsWith('.huggingface.co')) { + return { Authorization: `Bearer ${HF_TOKEN}` }; + } + } catch {} + return undefined; +} + async function fetchJson(url) { - const res = await fetch(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT) }); + const res = await fetch(url, { + signal: AbortSignal.timeout(FETCH_TIMEOUT), + headers: hfHeaders(url), + }); if (!res.ok) throw new Error(`${res.status} ${url}`); return res.json(); } @@ -64,13 +100,30 @@ function extToUse(url, contentType) { return 'jpg'; } -async function downloadImage(url, destBase) { - const res = await fetch(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT) }); +async function downloadImage(url, destBase, minSide) { + for (const ext of ['jpg', 'png', 'webp']) { + try { + await access(`${destBase}.${ext}`); + return true; // already fetched on a prior attempt + } catch {} + } + const res = await fetch(url, { + signal: AbortSignal.timeout(FETCH_TIMEOUT), + headers: hfHeaders(url), + }); if (!res.ok) throw new Error(`download ${res.status}`); const type = res.headers.get('content-type') || ''; const buf = Buffer.from(await res.arrayBuffer()); if (buf.length < 4096) throw new Error('too small'); + if (minSide) { + // Skip (not substitute) images under the gate, mirroring how the + // shipped probe's hard negatives were assembled. + const sharp = (await import('sharp')).default; + const meta = await sharp(buf).metadata(); + if (Math.min(meta.width || 0, meta.height || 0) < minSide) return false; + } await writeFile(`${destBase}.${extToUse(url, type)}`, buf); + return true; } async function pool(items, worker, concurrency) { @@ -97,6 +150,17 @@ async function pullSource(spec) { const dir = join(OUT, spec.label); await mkdir(dir, { recursive: true }); + // Resumable: a rerun after a rate-limit abort skips sources that already + // hit their target count, so retries spend the request budget only on + // what is still missing. + try { + const existing = (await readdir(dir)).filter((f) => f.startsWith(`${spec.name}-`)).length; + if (existing >= spec.count) { + console.log(`[${spec.name}] already complete (${existing}/${spec.count}), skipping`); + return; + } + } catch {} + let resolved; try { resolved = await resolveConfigSplit(spec); @@ -124,18 +188,49 @@ async function pullSource(spec) { let fromThisOffset = 0; for (const row of rowsData.rows || []) { if (jobs.length >= spec.count || fromThisOffset >= perOffset) break; + const rowName = spec.nameByRow + ? `${spec.name}-${row.row_idx ?? offset + fromThisOffset}` + : null; + if (spec.urlColumn) { + // Dotted paths reach into nested row objects, e.g. 'photo.image_url'. + const url = spec.urlColumn + .split('.') + .reduce((v, k) => (v == null ? v : v[k]), row.row); + if (typeof url !== 'string' || !url) continue; + const src = spec.urlParam + ? `${url}${url.includes('?') ? '&' : '?'}${spec.urlParam}` + : url; + jobs.push({ + src, + destBase: join(dir, rowName ?? `${spec.name}-${String(seq++).padStart(5, '0')}`), + }); + fromThisOffset++; + continue; + } for (const col of spec.columns) { if (jobs.length >= spec.count || fromThisOffset >= perOffset) break; const src = row.row?.[col]?.src; if (!src) continue; - jobs.push({ src, destBase: join(dir, `${spec.name}-${String(seq++).padStart(5, '0')}`) }); + jobs.push({ + src, + destBase: join(dir, rowName ?? `${spec.name}-${String(seq++).padStart(5, '0')}`), + }); fromThisOffset++; } } } - const { done, failed } = await pool(jobs, (j) => downloadImage(j.src, j.destBase), CONCURRENCY); - console.log(`[${spec.name}] ${done} downloaded, ${failed} failed (${spec.label})`); + let skipped = 0; + const { done, failed } = await pool( + jobs, + (j) => + downloadImage(j.src, j.destBase, spec.minSide).then((saved) => { + if (!saved) skipped++; + }), + CONCURRENCY + ); + const skipNote = skipped ? `, ${skipped} skipped under ${spec.minSide}px` : ''; + console.log(`[${spec.name}] ${done - skipped} downloaded, ${failed} failed${skipNote} (${spec.label})`); } async function main() { From 5fcaba951e12cf3063a448bb8049368a6deba90b Mon Sep 17 00:00:00 2001 From: felirami Date: Sat, 15 Aug 2026 20:25:48 -0400 Subject: [PATCH 3/3] Retrain probe with hard-negative reals and re-derive fusion bands The probe head is retrained on 11,405 rows: the standard training set plus 1,915 hard-negative reals (professional stock, product catalogs, interiors, high-saturation nature), all features extracted through the shared Pillow-exact resize. On a 240-image full-resolution stress set this removes every DINO-attributable false positive (shipped v1.1.0 measured 7 FPs on identical bytes; this build measures 4, all driven by CommunityForensics alone at >= 0.65 where it is authoritative). With the cleaner probe the rescue bands re-derive wider under the same stress guard. A conservative near-optimum was chosen over the grid maximum (keeps DINO_RESCUE_MIN 0.70 and the CF-hard-zero guard): DINO_CF_FLOOR 0.02, DINO_STRONG_RESCUE_FLOOR 0.10, DINO_STRONG_RESCUE_MIN 0.90, DINO_SUBFLOOR_MIN 0.995, DINO_SUBFLOOR_CF_MIN 0.0005. Bench (893 imgs, raw 0.65, harness-verified): 90.5% BA, 81.2% TPR, 99.8% TNR, vs 87.7 / 75.8 / 99.6 for v1.1.0. Browser-vs-Node DINO parity: max delta 0.000046 on a live-browser sample (was up to 0.22). Full suite: 213 tests green. --- AGENTS.md | 6 +++--- README.md | 15 +++++++-------- models/probe/dino-probe.json | 2 +- src/fuse.js | 16 +++++++++------- tests/dino.test.mjs | 14 +++++++------- tests/fuse.test.mjs | 28 ++++++++++++++-------------- 6 files changed, 41 insertions(+), 40 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 908d051..2e47cf1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -32,7 +32,7 @@ Win POIDH Arbitrum bounty 323 by shipping a privacy-first local MV3 Chrome exten - **Manifest V3.** `onnxruntime-web` in an offscreen document. WebGPU with WASM fallback (probe the adapter; do not latch a WebGPU error). - **Auto-scan ordinary webpages.** Confidence on every badge: AI / OK / uncertain. - **Hybrid is allowed:** neural + C2PA + EXIF/XMP + PNG/JPEG comments + weak URL hints. A URL hint alone must not cross 0.65. -- **Current fusion: CF-primary, three tiers.** CommunityForensics TTA takes the maximum raw sigmoid from inspected views. CF is authoritative at >= 0.65. Sub-floor tier: below CF 0.03, rescue only when CF >= 0.005 (not flatlined) AND DINO >= 0.999; a CF hard zero is never overridden. Strong tier: CF in [0.03, 0.30) needs DINO >= 0.96. Normal tier: CF in [0.30, 0.65) needs DINO >= 0.70. The flat-graphic gate blocks every rescue tier on catalog art and UI-like images. Bands were fit under a hard stress-set constraint (240 stock/catalog/product reals, zero new FPs allowed). **Do not restore raw max(CF, DINO), remove the graphic gate, or loosen these bands without rerunning the bench plus the stress set and live-site checks.** +- **Current fusion: CF-primary, three tiers.** CommunityForensics TTA takes the maximum raw sigmoid from inspected views. CF is authoritative at >= 0.65. Sub-floor tier: below CF 0.02, rescue only when CF >= 0.0005 (not flatlined) AND DINO >= 0.995; a CF hard zero is never overridden. Strong tier: CF in [0.02, 0.10) needs DINO >= 0.90. Normal tier: CF in [0.10, 0.65) needs DINO >= 0.70. The flat-graphic gate blocks every rescue tier on catalog art and UI-like images. Bands were re-derived for the hard-negative probe under a hard stress-set constraint (240 full-resolution stock/catalog/product reals; no DINO-attributable stress FP allowed), choosing a conservative near-optimum over the grid maximum. **Do not restore raw max(CF, DINO), remove the graphic gate, or loosen these bands without rerunning the bench plus the stress set and live-site checks.** - **Overlay:** badge store must be an iterable `Map`, not a `WeakMap`. Reposition on scroll / resize / `visualViewport` / mutations. Never wrap images. - **Load-unpacked users do not auto-update.** GitHub Releases zip + popup banner is the update path. Do not assume CWS. - **Cross-device:** macOS (owner), Windows, Linux. WASM must work when WebGPU has no adapter. @@ -65,7 +65,7 @@ Win POIDH Arbitrum bounty 323 by shipping a privacy-first local MV3 Chrome exten | File | Role | |---|---| -| `src/fuse.js` | `DEFAULT_THRESHOLD` 0.65, `DINO_CF_FLOOR` 0.03, `DINO_STRONG_RESCUE_FLOOR` 0.30, `DINO_STRONG_RESCUE_MIN` 0.96, `DINO_RESCUE_MIN` 0.70, `DINO_SUBFLOOR_CF_MIN` 0.005, `DINO_SUBFLOOR_MIN` 0.999, CF-primary `fuseNeuralScores` | +| `src/fuse.js` | `DEFAULT_THRESHOLD` 0.65, `DINO_CF_FLOOR` 0.02, `DINO_STRONG_RESCUE_FLOOR` 0.10, `DINO_STRONG_RESCUE_MIN` 0.90, `DINO_RESCUE_MIN` 0.70, `DINO_SUBFLOOR_CF_MIN` 0.0005, `DINO_SUBFLOOR_MIN` 0.995, CF-primary `fuseNeuralScores` | | `src/graphic-gate.js` | Shared flat-graphic policy for browser and Node evaluation | | `src/pixel-resize.js` | Pillow-exact bicubic resize shared by the extension and the Node harness for the CF path (byte-exact vs Pillow 12.3.0 goldens) | | `src/offscreen.js` | ORT WebGPU/WASM, DINO 224 then CF TTA | @@ -76,7 +76,7 @@ Win POIDH Arbitrum bounty 323 by shipping a privacy-first local MV3 Chrome exten | `src/c2pa-reader.js` | C2PA reader | - Issue 23 (fixed in PR 24 / v1.0.7): overlay WeakMap drift + DINO max false positives. -- The public 893-image fixture on the Pillow-exact preprocess and three-tier policy: 87.7% BA, 75.8% TPR, 99.6% TNR (harness-verified, not simulated). Stress set (240 stock/catalog/product reals): 2 FPs, identical images to the prior policy. Browser vs Node parity: 16/16 decisions, max per-view CF delta 0.0005. The DINO path still uses canvas/RawImage resize (probe trained against it); retraining the probe on Pillow-preprocessed features is the documented follow-up. Live-smoke checks still remain required before any claim. +- The public 893-image fixture with the hard-negative probe and re-derived bands: 90.5% BA, 81.2% TPR, 99.8% TNR (harness-verified, not simulated). Stress set (240 full-resolution stock/catalog/product reals): 4 FPs, all CF-driven at >= 0.65 where CF is authoritative by design; zero DINO-attributable stress FPs (shipped v1.1.0 measured 7 on identical bytes). The DINO probe is trained on features from the shared Pillow-exact path plus 1,915 hard-negative reals (stock, catalog, product, interiors; rows disjoint from the stress set). Full-resolution professional stock photos can spike CF itself; check exactly that during live smoke. Live-smoke checks still remain required before any claim. --- diff --git a/README.md b/README.md index c9e2688..bceb7f8 100644 --- a/README.md +++ b/README.md @@ -56,8 +56,8 @@ Maintainers cut a release with `git tag v1.0.0 && git push origin v1.0.0`. That Two independent neural heads cover complementary failure modes, plus deterministic metadata: 1. **CommunityForensics head:** ViT-Small official FP32 ONNX (CLIP 384). `p(AI) = sigmoid(logit)`. Near-zero false positives on real photos, but under-scores several modern generators (Flux, GPT-4o-image, photoreal DALL-E 3). -2. **DINOv2 probe head:** frozen DINOv2-small backbone (224 center view) with a transparent logistic head over CLS+mean-pooled features (`models/probe/dino-probe.json`: plain standardize/weights/bias, no lookup tables). Trained on ~9.6k images from public datasets across Flux, SD3.5, SDXL-era, Midjourney, DALL-E 3, GPT-4o-image and diverse real photos, with web-realistic JPEG/resize augmentation. This head carries the modern generators. -3. **Neural fusion:** CF-primary with three rescue tiers. When CommunityForensics is confident AI (`>= 0.65`), its score wins. Between `0.03` and `0.30`, DINO can only rescue if it is near-saturated (`p(AI) >= 0.96`); between `0.30` and `0.65`, DINO can lift at `p(AI) >= 0.70`. Below the `0.03` floor a rescue additionally requires CF to be at least faintly awake (`>= 0.005`) and DINO to be saturated (`>= 0.999`): CF emits hard zeros on real photos it is certain about, while AI images in its blind spots still elicit a faint response, so a flatlined CF is itself evidence of a real photo and is never overridden. On flat graphics and catalog art (low palette / high flat-run pixels), a graphic gate suppresses every DINO rescue tier when CF stays below `0.65`, so icons and UI shots do not mass-label AI 100%. CF-confident AI illustrations (`>= 0.65`) are unchanged. Displayed confidence is this raw fused probability; the AI verdict stays at raw `>= 0.65` with no remapping and no logit bias. The rescue bands were fit on the public bench below under a hard constraint measured on a separate 240-image stock, catalog, and product photo stress set: zero new false positives allowed relative to the previous policy. +2. **DINOv2 probe head:** frozen DINOv2-small backbone (224 center view) with a transparent logistic head over CLS+mean-pooled features (`models/probe/dino-probe.json`: plain standardize/weights/bias, no lookup tables). Trained on ~11.4k images from public datasets across Flux, SD3.5, SDXL-era, Midjourney, DALL-E 3, GPT-4o-image and diverse real photos, including ~1.9k hard-negative reals (stock photography, product catalogs, interiors, high-saturation nature) that teach the head not to fire on professional real photos, with web-realistic JPEG/resize augmentation. Features are extracted through the same Pillow-exact resize the extension ships, so training matches serving exactly. This head carries the modern generators. +3. **Neural fusion:** CF-primary with three rescue tiers. When CommunityForensics is confident AI (`>= 0.65`), its score wins. Between `0.02` and `0.10`, DINO can only rescue if it is highly confident (`p(AI) >= 0.90`); between `0.10` and `0.65`, DINO can lift at `p(AI) >= 0.70`. Below the `0.02` floor a rescue additionally requires CF to be at least faintly awake (`>= 0.0005`) and DINO to be saturated (`>= 0.995`): CF emits hard zeros on real photos it is certain about, while AI images in its blind spots still elicit a faint response, so a flatlined CF is itself evidence of a real photo and is never overridden. On flat graphics and catalog art (low palette / high flat-run pixels), a graphic gate suppresses every DINO rescue tier when CF stays below `0.65`, so icons and UI shots do not mass-label AI 100%. CF-confident AI illustrations (`>= 0.65`) are unchanged. Displayed confidence is this raw fused probability; the AI verdict stays at raw `>= 0.65` with no remapping and no logit bias. The rescue bands were re-derived for the current probe under a hard constraint measured on a separate 240-image full-resolution stock, catalog, and product photo stress set (no DINO-attributable false positives allowed), and a deliberately conservative near-optimum was chosen over the grid maximum. 4. **Adaptive TTA:** the DINO pass and the official 440 center crop always run. Extra CommunityForensics views (440 corners + 512 center) run only when a head is at least mildly suspicious (CF center or DINO in `[0.15, 0.65)`), so confident reals cost two passes total. `Math.max` of sigmoids, early exit at `>= 0.9`. Under heavy queue load (more than 12 pending) CF drops to center-only; the DINO pass still runs. 5. **Metadata:** C2PA, EXIF/XMP/IPTC, generator text in PNG/JPEG, weak URL hints. Strong metadata forces 0.95-0.99; a URL hint alone cannot cross 65%. @@ -77,13 +77,12 @@ Eval harness: `npm run eval -- ./path/to/labeled-folder` after `npm run fetch-mo |---|---:|---:|---:| | CommunityForensics center crop only | 66.4% | 32.8% | 100% | | CommunityForensics adaptive max diagnostic | 73.4% | 47.2% | 99.6% | -| DINOv2 probe only | 93.0% | 89.7% | 96.3% | | Legacy raw max ensemble (not shipped) | 96.1% | 96.1% | 96.1% | | Prior policy, prior Node resize (historical) | 85.0% | 70.4% | 99.6% | -| Prior policy on the Pillow-exact preprocess | 82.9% | 66.3% | 99.6% | -| Production three-tier policy, Pillow-exact preprocess | 87.7% | 75.8% | 99.6% | +| v1.1.0 policy and probe, Pillow-exact preprocess | 87.7% | 75.8% | 99.6% | +| Production: hard-negative probe, re-derived bands | 90.5% | 81.2% | 99.8% | -The legacy raw max result is included to make the tradeoff visible, not as a product claim. It caused unacceptable false positives on live stock and catalog images, so production keeps the CF guard. The historical 85.0% row was measured through a Node resize the extension never ran; the Pillow-exact rows are computed by the same resize the extension ships, byte for byte, and browser versus Node decisions agree 16/16 on a stratified parity sample. The production policy also holds 2 false positives in 240 on a stock, catalog, and product photo stress set, identical images to the prior policy. Public fixtures are directional only and are not a claim about Kenny's private held-out set. +The legacy raw max result is included to make the tradeoff visible, not as a product claim. It caused unacceptable false positives on live stock and catalog images, so production keeps the CF guard. The historical 85.0% row was measured through a Node resize the extension never ran; later rows are computed by the same Pillow-exact resize the extension ships, byte for byte. On a 240-image full-resolution stock, catalog, and product photo stress set the production policy shows 4 false positives, all driven by CommunityForensics alone scoring `>= 0.65` (where it is authoritative by design), and zero attributable to a DINO rescue; the v1.1.0 configuration measured 7 on identical bytes. Public fixtures are directional only and are not a claim about Kenny's private held-out set. ## Limitations @@ -105,9 +104,9 @@ See [PRIVACY.md](PRIVACY.md) and [docs/privacy.html](docs/privacy.html). Images ## Reproducing the probe head ```bash -node eval/fetch-train.mjs /tmp/train # ~9.6k images from public HF datasets +node eval/fetch-train.mjs /tmp/train # ~11.4k images from public HF datasets (incl. hard-negative reals) node eval/extract-features.mjs /tmp/train models/Xenova/dinov2-small/onnx/model.onnx /tmp/feat-train --augment node eval/train-probe.mjs /tmp/feat-train models/probe/dino-probe.json ``` -The head is a linear probe (768 weights + bias + feature mean/std) over frozen DINOv2 features; the JSON is human-auditable. No benchmark images, hashes, or lookup tables are involved. +The head is a linear probe (768 weights + bias + feature mean/std) over frozen DINOv2 features; the JSON is human-auditable. No benchmark images, hashes, or lookup tables are involved. Fetching pulls live public datasets, so counts can drift by a few images between runs; an authenticated Hugging Face token (`HF_TOKEN` or the CLI cache) raises the datasets-server rate limit and is picked up automatically. diff --git a/models/probe/dino-probe.json b/models/probe/dino-probe.json index de56dd4..0475f4c 100644 --- a/models/probe/dino-probe.json +++ b/models/probe/dino-probe.json @@ -1 +1 @@ -{"backbone":"dinov2-small","pooling":"cls+mean","dims":768,"featureMean":[-0.738905,-0.411827,0.270413,-0.473094,0.378236,-0.048525,-0.209464,-0.292543,0.434923,0.372315,-0.144415,0.39701,-0.531787,0.203034,0.730197,0.022278,0.010487,-0.836739,0.159953,-1.00452,0.692091,-0.324785,-0.266485,-0.367564,-0.193056,0.304512,0.111995,-0.538593,1.007014,0.037047,-0.320727,-0.784867,-0.037184,-0.012917,0.552202,0.416338,-0.594595,0.853682,0.279672,0.452163,-0.210598,0.88698,-0.37809,0.102201,-0.345266,-0.720505,-0.712039,0.118456,0.910794,0.298082,0.166965,-0.042104,0.08766,-0.492237,-0.746249,0.274061,0.637606,0.370995,-0.386304,-0.834688,0.745792,0.492766,-0.051457,-0.530743,-0.357024,0.449974,-0.262674,0.131173,0.866854,-0.181417,-0.755383,0.081133,-0.753867,0.101576,0.656691,-0.387593,-0.164871,-0.089536,-0.232643,-0.149508,0.17343,-0.537804,0.087839,-0.045834,-1.160009,-0.177396,-0.456569,-0.22252,-0.399173,0.293812,0.444919,-0.341038,-0.357314,-0.550648,0.79425,-0.323576,0.962954,0.209499,0.174179,-0.525074,-0.269319,0.945198,-0.505049,-0.415334,0.091252,0.257392,-0.206611,-0.352976,0.172338,-0.414392,-0.119295,0.360585,0.415652,0.35705,0.125183,-0.294974,-0.34141,0.448872,-0.521913,-0.088394,0.19289,1.222234,-0.195394,0.434542,0.8288,-0.84679,0.446597,-0.478627,-0.193321,0.442183,0.334537,-0.563713,-0.258073,0.262174,0.133456,1.104287,-0.444177,0.356184,-0.468508,0.236093,-0.926265,0.135389,0.050828,-0.410634,0.192959,-0.514925,0.060553,0.757182,0.238571,0.146093,0.224619,-0.831592,-0.350924,0.111689,-0.446393,-0.944793,0.974925,-0.42169,0.283608,-0.370744,-0.134494,-0.384592,-0.582376,-0.079458,0.482424,-0.320277,-0.103025,-0.242148,-0.499863,0.246419,0.156991,0.220729,0.167757,0.207283,0.468934,-0.284902,-0.085076,-0.32254,0.319602,0.661193,0.704365,0.475449,0.068,-0.32372,0.211143,-0.30412,0.60611,0.046199,0.276315,-0.378912,-0.109733,-0.132597,-0.206951,-0.20309,-0.102523,-0.374058,0.425309,0.530976,-0.626863,-0.274295,0.223593,-1.012587,0.321735,0.067798,0.17944,-0.010223,0.455517,-0.584065,0.343352,0.235446,0.720296,-0.493012,0.524633,-0.115555,-0.185904,-0.271907,-0.361468,-0.1893,-0.080557,-0.121821,0.236954,-0.510587,-0.892244,-0.424535,-0.579737,0.049173,-0.020765,0.440694,-0.564067,0.247372,0.021531,-0.567042,-0.574333,0.45648,-0.073081,0.186555,0.206289,-0.543446,-0.266324,-0.285132,0.331696,0.141599,0.000587,-0.318791,0.310538,-0.076477,0.221562,-0.422953,-0.457196,-0.05275,0.029664,0.433214,0.236718,0.217956,-0.3242,0.266526,0.635686,0.40417,0.402826,-0.103079,0.049018,0.55069,-0.387832,-0.1383,0.300441,-0.573453,-0.397328,-0.510652,-0.128541,-0.208905,0.330616,-0.20161,-0.356535,0.268665,0.688,0.257482,0.106356,1.016814,-0.07298,-0.094128,-0.446231,-0.222177,0.063995,-0.356276,0.388781,0.028232,-0.686454,-0.045578,-0.111982,-0.308916,-0.255083,-0.715231,0.689362,0.548718,0.397671,-0.026819,0.645902,-0.016866,1.006106,0.319438,-0.130572,-0.05081,-0.398499,0.238459,1.033708,0.088092,-0.180763,0.14802,0.075234,0.21159,-0.215715,0.164858,0.476317,-0.593836,-0.328805,0.05208,0.596582,0.062612,-0.834625,-0.177273,0.250836,0.86573,0.158526,-0.134793,-0.248438,0.918305,0.447862,-1.152845,0.45582,-0.937037,-0.019793,-0.316876,0.820406,-0.332802,0.184148,-0.642324,0.374019,0.134388,0.494373,0.3437,0.513305,-0.065481,0.060217,-0.259254,0.237906,0.636076,-0.126686,-0.780147,0.185336,0.606843,0.181579,0.222797,0.313898,-0.330921,-0.715874,-0.034456,-0.13869,0.347949,0.453711,-0.180435,-0.488637,-0.188293,0.506892,-0.426352,-0.189523,0.74656,-0.084786,0.284351,0.294824,0.271253,-0.812947,0.561732,-0.44868,0.513416,0.607847,-0.344844,0.439201,0.288095,-0.386594,0.173299,-0.608728,0.033246,0.571664,0.179872,-0.512247,0.187311,-0.080736,-0.373233,0.456035,0.023294,-0.046632,-0.259016,-0.128097,0.718076,0.5064,0.204417,-0.538667,0.280896,0.332969,0.245952,-0.711661,-0.408006,0.030083,-0.444479,-0.050211,-0.637736,0.002279,0.171655,-0.028649,0.75788,0.024465,-0.260148,0.450876,-0.213581,-0.340206,-0.121918,-0.257921,-0.128166,0.945546,-0.191157,0.119829,0.742177,0.440607,0.184767,0.081867,0.74612,-0.205815,0.305152,0.271437,-0.530826,-1.128038,-0.264115,0.513235,-0.19991,0.187005,0.3347,0.24792,-0.579784,-0.422861,0.20485,-0.006871,0.455653,0.212239,-0.764691,1.067527,-0.045585,-0.334894,-0.099442,-0.573423,1.121409,0.019503,-0.335628,2.476465,0.18318,-0.682112,-0.234493,-0.64318,-0.131091,0.715786,0.366413,-0.450207,-0.073779,-0.027003,-2.102322,0.337529,0.10306,-0.25444,0.029055,-0.220034,-0.233424,-0.420049,-0.319124,-0.6828,0.272066,0.601028,-0.219932,-0.053193,-0.586281,0.592707,-0.120658,0.847286,-0.096447,0.099884,-0.795122,-0.16085,0.877303,0.188071,0.124363,0.182961,0.28153,-0.165854,-0.144628,0.851896,-0.446856,0.402568,-0.223721,0.611491,0.086515,0.412216,-0.559146,-0.469917,0.090681,-0.602717,-0.102733,0.521749,-0.409906,-0.028841,0.617274,0.283401,-0.094222,0.775755,-0.140193,0.068939,0.239387,0.030617,0.177768,-0.101115,-0.161315,-0.037136,-0.617596,-0.753446,0.603207,0.526237,-0.024123,-0.791428,-0.517999,-0.006656,-0.038133,-0.096861,-0.229272,0.024274,0.942612,-0.241483,0.119378,0.409476,-0.043194,-0.053987,0.546398,0.012814,-0.901107,0.687195,-0.159144,-0.309751,-0.387958,0.16105,-0.106996,-1.047495,-0.14133,1.269548,-0.474053,0.231368,-0.343631,-0.252701,0.161773,0.252844,0.565309,0.468628,0.550998,0.206217,-0.145746,0.041665,0.282371,-0.139673,1.25317,0.378081,1.079058,0.134609,-0.099285,0.088182,0.183124,0.658726,-0.307522,-0.093829,0.173985,-0.133553,0.152764,0.231958,-0.534345,0.140029,-0.084175,0.066195,0.278927,-0.5254,-0.14453,-0.145252,-0.52947,0.462889,0.419383,0.234349,0.530881,0.635542,-0.331754,0.230665,0.635731,0.596811,0.175434,-0.279948,0.34365,0.102184,0.163345,-0.215577,-0.446936,0.456536,0.689098,-0.319217,-0.557828,-0.537816,-0.100622,-0.031819,0.212884,0.32929,-0.111519,-0.702567,0.420019,0.234329,-0.290069,-0.249991,-0.393156,-0.810658,0.034252,-0.436196,-0.272887,0.053218,-0.209028,0.324075,-0.326414,-0.262679,-0.640557,0.267367,0.098673,0.1878,-0.374394,-0.474168,-0.179662,-0.204828,0.135618,0.529107,-0.028808,0.067216,-0.012782,0.898184,0.355907,0.217087,0.331596,0.473815,-0.184721,0.509546,0.136808,0.339455,-0.260644,0.156106,-0.460213,-0.215351,-0.637137,0.033508,0.109133,-0.205634,0.2137,0.72825,0.535666,-0.405641,0.907605,-3.014998,-0.01717,-0.532494,-0.219459,0.524582,-0.322984,0.73764,0.401374,-0.691647,-0.428664,-0.191564,-0.1108,-0.176812,-0.120482,0.225883,0.651862,0.162393,-0.167563,0.275379,0.230781,0.052582,0.380169,0.163844,-0.036527,-0.224266,-0.350573,0.756383,0.30107,0.000872,0.099483,-0.54769,0.401381,0.44622,0.312016,0.859539,-0.386545,-0.205186,-0.105593,0.08659,-0.204321,-0.376678,0.008636,0.293873,0.459214,0.34823,1.177419,-0.078389,0.52601,-0.184535,-0.568681,0.720712,-0.459839,0.189647,-0.056513,0.524401,-0.323688,0.050032,-0.387041,0.323948,0.274342,0.373378,0.23581,0.547863,0.158888,0.046011,-0.365633,0.342714,1.135415,-0.200119,-0.102666,0.154399,0.310199,0.145673,0.238682,0.280299,-0.404117,-0.194744,-0.301674,-0.203897,0.080834,0.571034,-0.215784,-0.026154,0.481719,1.003557,-0.246995,0.270321,-0.410499,-0.239814,0.357534,-0.099828,-0.349123,-0.339732,0.419126,0.728745,0.311787,0.559448,0.166206,0.292377,-0.212875,-0.475633,-0.572168,-0.765356,0.522451,0.577148,0.187934],"featureStd":[2.592105,1.450131,2.367914,2.450757,2.430174,1.415987,2.260621,1.964699,2.526612,2.563107,2.378392,2.536566,2.457142,2.404446,2.614927,2.463045,2.48245,2.558441,1.847536,2.27434,2.324177,2.338314,2.486187,1.682119,2.374114,2.34219,2.518924,2.334648,1.566228,2.651068,2.286439,2.333294,2.158509,2.615745,2.319807,2.404845,2.588969,2.457549,2.619891,2.810322,2.498071,2.549607,2.676015,2.342172,2.270668,2.353932,2.394862,2.481787,2.569354,2.292265,2.361441,2.495869,2.514755,2.225827,2.310304,2.646915,2.44828,2.346637,2.632154,2.370387,2.406272,2.480935,2.41512,2.582627,1.859087,2.500706,2.391301,2.490959,2.219511,2.259052,2.640445,2.197661,2.672226,2.38818,2.812832,2.472602,2.388819,2.392087,2.398444,1.509429,2.227933,2.520444,2.355402,2.455357,2.069446,2.404543,2.363876,2.41625,2.343224,2.297192,2.568593,2.408214,2.408497,2.583051,2.629599,2.119339,2.234972,2.479562,2.388885,2.549582,2.554205,2.517504,2.556057,2.697954,2.153762,2.522882,2.590341,2.440297,2.588962,2.548545,2.361184,2.613168,2.448001,2.199002,2.518133,2.419614,2.381398,2.526786,2.545711,2.554765,2.379777,2.019821,2.356777,2.578693,2.593174,1.895847,2.607847,2.535066,2.499139,2.67805,2.002393,2.388674,2.618895,2.37171,2.616682,2.737326,2.472028,2.436377,2.061757,2.608947,2.107927,2.13449,2.147191,2.326284,2.367433,2.61006,2.217595,2.334839,2.195086,2.250801,2.327183,2.248932,2.441035,2.460219,2.542271,2.535592,2.467735,2.474175,2.524151,2.058678,2.529085,2.502261,2.230562,2.308285,2.531284,2.463697,2.347183,2.281444,2.591166,2.334066,2.471698,2.516362,2.376999,2.615407,2.551169,2.396339,2.273837,2.359191,2.399093,2.418793,2.491084,1.780833,2.527854,2.147623,2.313904,2.407043,2.453997,2.561188,1.813885,2.064441,2.349032,2.600961,2.354576,2.287544,2.555957,2.100219,2.426201,2.382326,2.397034,1.946416,2.508329,1.960776,2.567792,2.864302,2.387389,2.451452,2.452592,2.378125,2.853225,2.144132,2.433649,1.995547,2.058279,2.592444,2.546804,2.477043,2.074489,2.611366,2.351314,2.831157,2.223476,2.515063,2.523968,2.365415,2.407015,2.280827,2.395887,1.935223,2.57331,2.361972,2.42029,2.689461,1.958302,2.498208,2.429435,2.504051,2.419564,2.570186,2.43088,2.385283,1.811424,2.429199,2.41497,2.289721,1.983195,1.82214,2.209182,2.35182,2.646702,2.402891,2.419567,2.534392,2.452044,2.035257,2.369367,2.467146,2.194748,2.594769,2.15051,2.463294,2.474815,1.934299,1.782773,1.991174,1.970286,2.510842,2.212059,2.374875,2.64833,2.53063,1.837885,2.422039,2.416127,2.380997,2.546797,1.99397,2.427571,2.265999,0.906246,2.382452,2.247754,2.457458,2.611842,2.574616,2.497911,2.554619,2.142613,2.461802,1.959413,2.40556,2.749036,1.948647,2.57571,2.694052,2.685946,2.436281,2.167147,2.382383,2.755703,2.573183,2.640816,2.25346,2.672518,2.221897,2.770725,2.225844,2.290207,2.401638,2.198833,2.468083,2.463821,2.494356,2.408333,2.585509,2.146079,2.287326,2.679889,2.129627,1.828304,2.362511,2.380858,2.482073,2.282518,1.891543,2.256055,1.921242,2.891545,2.463126,2.447222,2.268682,2.569908,2.353304,2.475626,2.374837,2.555353,2.457539,2.416903,2.492713,1.768111,2.2157,2.44538,2.356548,2.63906,2.532508,2.467168,2.361687,2.541924,2.628662,2.491128,2.379233,2.193263,2.500615,2.616477,2.370996,2.423245,2.4116,2.3629,2.441935,2.657792,2.145695,1.909002,2.428026,2.61926,2.497972,1.991128,2.278184,2.531698,2.730053,2.028492,2.585346,2.123605,2.590183,1.926391,2.655259,2.639991,2.124234,2.344554,2.402377,2.47834,1.470625,2.462079,2.471494,2.63454,1.865209,1.432958,0.87004,1.423253,1.341375,1.315788,0.518888,1.149156,1.044988,1.349565,1.195402,1.244196,1.532066,1.353682,1.330463,1.350596,1.44316,1.400701,1.546068,1.425009,1.21134,1.139672,1.320478,1.365195,1.464466,1.280025,1.54836,1.426176,1.355594,0.738074,1.43471,1.106823,1.301547,1.357951,1.436836,1.133865,1.262096,1.510582,1.220715,1.433768,1.676432,1.459852,1.453833,1.604823,1.526033,1.057826,1.384762,1.408031,1.293899,1.366343,1.213962,1.282062,1.285297,1.377999,1.175986,1.15905,1.581186,1.466845,1.382634,1.590697,1.484257,1.400762,1.302137,1.451335,1.537815,0.850871,1.321617,1.359629,1.366262,2.612379,1.201641,1.592813,1.236958,1.230686,1.501647,1.500223,1.393206,1.341393,1.318176,1.352884,0.874778,1.280354,1.457778,1.364796,1.437778,0.720919,1.251151,1.478911,1.434686,1.255654,1.21717,1.530256,1.326271,1.164824,1.539109,1.53376,1.2281,1.272483,1.474631,1.341456,1.568607,1.414016,1.421989,1.619979,1.608721,1.268637,1.405648,1.522359,1.413457,1.499705,1.554283,1.266873,1.559727,1.342894,1.209958,1.330373,1.352229,1.398928,1.377613,1.467862,1.332637,1.335988,0.984597,1.369341,1.399329,1.382633,0.736881,1.602645,1.370167,1.351844,1.617858,1.156745,1.306735,1.525175,1.26762,1.589335,2.656537,1.366627,1.350945,1.599226,1.328243,0.92834,0.930863,1.015676,1.240919,1.304466,1.480118,1.138472,1.280383,1.193404,1.323706,1.135371,1.053944,1.258404,1.288702,1.569497,1.510685,1.394,1.395484,1.457685,0.967908,1.405114,1.497488,1.340096,1.23576,1.489164,1.593272,1.266461,1.252627,1.527686,1.313625,1.361744,1.180384,1.271203,1.598181,1.524657,1.296159,1.056604,1.277028,1.222613,2.188154,1.483977,1.042907,1.444505,1.103505,1.24257,1.307526,1.420892,1.476883,0.689582,0.911192,1.227962,1.609135,1.306576,1.083228,1.426206,1.033514,1.468805,1.379213,1.183435,0.963287,1.350479,0.869382,1.652832,1.616303,1.26191,1.327123,1.253266,1.328165,3.655344,1.121132,1.36359,1.08169,1.119017,1.491281,1.294281,1.467695,0.903709,1.464507,1.154926,3.438648,1.053239,1.527947,1.443134,1.130671,1.339193,1.290292,1.354561,0.855242,1.395574,1.357615,1.262054,1.641495,1.011631,1.450581,1.364346,1.396929,1.396627,1.458863,1.582202,1.328091,0.695288,1.321764,1.483162,1.106002,1.007282,0.902628,1.067056,1.306788,1.427998,1.471961,1.427045,1.454994,1.231639,1.076712,1.431191,1.641636,1.037508,1.530902,1.139011,1.383898,1.706888,0.978283,1.578705,1.106429,1.363935,1.384356,1.178186,1.338683,1.464426,1.478826,0.818953,1.394732,1.26975,1.378769,1.451409,1.115967,1.265859,1.177112,0.573232,1.307246,1.135887,1.357425,1.487615,1.476995,1.439976,1.387036,2.110904,1.353888,0.901793,1.251009,1.563743,1.070319,1.362902,1.533454,1.537997,1.406997,1.05781,1.398817,1.435778,1.503587,1.68967,1.477864,1.52731,1.218468,1.567672,1.203599,1.289849,1.325557,0.877015,1.31521,1.455638,1.487289,1.421154,1.419386,1.069195,1.117963,1.409829,1.205403,1.457496,1.219225,1.359316,1.447365,1.198625,1.455533,1.275286,1.029454,2.894469,1.246498,1.459497,1.10029,1.48214,1.25877,1.269233,1.317614,1.525711,1.422289,1.361963,1.304743,0.950994,1.031898,1.286693,1.521709,1.571422,1.234867,1.353328,1.202493,1.371557,1.451483,1.293402,1.337881,1.055766,1.394349,1.453861,1.334674,1.357162,1.261398,1.374668,1.348087,1.563086,1.499072,0.754012,1.223227,1.369952,1.607655,0.770564,1.153861,1.336116,1.621008,0.980082,1.548269,1.035453,1.432863,0.849194,1.490781,1.61509,1.154034,1.235767,1.446839,1.452929,0.720548,1.431379,1.4069,1.514581,0.96446],"weights":[-0.031169,0.028923,-0.12732,-0.147882,0.153282,-0.105549,0.019848,-0.041793,0.002593,0.039145,-0.116583,0.00697,-0.013127,-0.048374,0.109489,0.04461,0.003826,-0.205346,-0.032982,-0.177174,-0.09221,-0.015905,-0.139541,0.1671,-0.000265,-0.005133,0.018485,-0.11452,0.184529,0.321251,0.053416,0.173585,0.022657,0.20388,-0.179644,0.171905,-0.063519,-0.112618,-0.096202,0.247652,0.000599,0.131411,-0.200817,0.016473,-0.012124,0.042554,0.097533,0.00007,-0.056195,0.046563,0.031083,-0.090693,-0.186597,0.094833,0.028836,0.021607,0.007034,0.000707,0.075237,-0.18048,0.003751,0.089633,0.067302,-0.185885,-0.156929,0.081551,0.153029,0.151529,-0.104045,-0.058287,-0.050251,0.142574,0.062374,-0.092846,0.00292,-0.035148,-0.001599,-0.067995,0.018414,0.129388,-0.077448,-0.216084,-0.351228,-0.019531,-0.16353,-0.033752,0.103515,0.098102,0.056842,0.003044,0.133269,0.168118,-0.163509,-0.056949,0.117466,-0.056541,0.071908,0.067046,0.012757,-0.032394,-0.05204,0.336283,-0.197845,-0.044495,-0.064096,-0.072945,0.213621,0.053751,0.258014,-0.147419,0.039332,-0.12528,0.100659,0.158669,0.131227,-0.004736,-0.028825,-0.043347,0.05859,0.015704,0.071936,0.680427,0.021728,0.148536,-0.223654,-0.163909,0.1383,-0.172762,-0.065164,-0.18543,0.086447,0.22619,0.090163,0.022008,0.054179,0.293748,0.144756,0.024253,0.24984,0.168043,0.225754,0.113309,0.163089,0.161824,0.103465,-0.107403,-0.090613,0.040531,-0.092383,-0.123906,0.143723,-0.159137,-0.143304,0.08618,0.102968,-0.102197,-0.050514,-0.045778,0.110567,-0.356537,-0.213089,0.03199,-0.164972,-0.23215,-0.144163,0.205359,-0.092384,0.046328,-0.218285,-0.066379,0.129082,-0.181984,0.068037,-0.163472,0.247921,-0.015588,-0.098782,0.005768,0.136556,-0.014107,-0.121016,0.229004,-0.248922,0.094644,0.057981,-0.115975,0.09042,0.102148,-0.1654,0.170159,-0.039749,0.146474,-0.185218,-0.155393,-0.062845,0.025414,0.058153,0.082567,0.003514,-0.384557,-0.226605,-0.144656,-0.047465,-0.012415,-0.040441,0.098639,-0.19415,-0.059595,-0.249627,0.245625,-0.027203,-0.296121,0.185775,-0.07761,-0.254302,-0.055295,-0.159968,-0.226679,-0.05335,0.156808,-0.01859,0.02111,0.032597,-0.077524,-0.036581,-0.214677,-0.154007,0.044052,-0.243314,0.017852,0.044472,0.001995,0.061629,0.129263,-0.036245,-0.040765,0.06899,0.086224,-0.058623,0.070835,-0.126109,0.033618,-0.11173,-0.066447,0.225991,-0.002644,-0.069908,-0.056665,-0.084773,0.114712,0.072701,0.022293,-0.08231,0.083184,-0.043116,0.069803,0.059529,0.13488,-0.213875,-0.034484,-0.152904,-0.062611,0.216934,-0.148786,-0.058936,-0.05905,-0.04205,0.018337,0.253876,-0.290214,0.15853,-0.139767,0.081622,0.084345,-0.103853,-0.178216,-0.136258,0.103739,0.198817,0.074438,0.154494,0.099488,0.074926,-0.111253,-0.001365,0.064122,-0.035425,-0.053398,0.021767,0.135434,0.072939,-0.40558,-0.038857,0.054278,0.16073,0.162335,-0.028157,-0.13874,-0.071278,-0.199362,-0.062759,-0.05684,-0.030747,-0.19959,0.057711,0.054473,-0.234327,-0.076788,0.074785,0.200056,-0.111603,0.248847,0.035926,-0.134548,0.221023,0.176627,0.177953,-0.136463,-0.176524,-0.029639,0.025688,-0.245599,0.006387,-0.194128,0.036617,-0.008445,0.176396,0.04153,0.032238,0.013154,-0.211211,0.072322,-0.063463,-0.073,0.371262,0.171548,-0.153907,0.103319,0.070827,0.057645,-0.083283,-0.028046,0.30587,0.054643,0.296624,0.207807,-0.049798,-0.108169,0.146681,0.045856,-0.06135,0.048679,-0.25386,-0.016968,0.124855,0.025923,0.065017,0.040284,0.028577,0.027477,-0.224043,-0.041671,0.105121,-0.015357,-0.176247,-0.053757,0.110512,-0.052223,0.106365,0.129947,0.147149,0.172639,-0.617405,-0.023446,-0.025333,-0.15533,-0.007965,0.10639,-0.174483,-0.152158,-0.029607,-0.117823,-0.075749,0.174388,-0.020375,0.023596,0.036147,0.146719,0.060369,0.275892,0.077585,0.031607,0.000202,0.034421,-0.149406,0.017887,0.029432,-0.08427,0.21804,-0.218306,0.032381,-0.064921,-0.052588,0.028517,0.111108,-0.252816,0.142264,0.053449,0.118085,-0.059967,-0.063586,-0.109617,0.35522,-0.042793,-0.052014,-0.241133,0.091545,-0.171116,0.029549,-0.156421,-0.09176,-0.04227,0.057402,0.265394,-0.044677,0.058059,0.164481,0.079841,-0.149096,0.166468,0.024842,0.001066,0.282272,0.029807,0.098034,-0.132844,-0.094277,0.143313,0.245423,-0.06489,0.144596,-0.025013,0.009355,-0.269602,-0.041221,0.126659,-0.07871,0.038978,0.000816,-0.098381,-0.102568,0.133395,-0.112235,0.009979,-0.080574,-0.245667,0.191927,0.272874,-0.036635,0.084258,-0.399512,-0.138902,0.004177,0.134414,0.080721,-0.049495,-0.020823,0.401175,0.124122,0.078807,-0.056579,-0.127073,-0.061958,-0.140134,0.111215,0.030778,0.158986,0.160003,0.12688,0.045094,-0.060507,0.079626,-0.086093,0.055022,-0.011483,-0.182321,-0.016998,-0.098123,0.130651,-0.173376,0.162394,0.009876,0.263751,0.002172,-0.043392,-0.206341,-0.249838,0.037421,-0.379298,-0.114348,-0.34909,-0.127169,-0.04753,-0.091116,0.099075,-0.373544,-0.074176,0.113166,-0.053405,-0.086373,0.233635,0.158471,-0.010557,0.013354,-0.119898,0.057881,-0.080481,-0.10127,0.01143,0.160331,-0.33439,-0.00574,-0.307416,-0.123408,0.042558,-0.008891,-0.013014,-0.013542,0.247762,-0.174626,-0.010107,-0.241476,0.127665,-0.116692,0.060458,-0.034226,0.088375,0.055411,-0.189195,-0.085225,0.023051,-0.041179,0.041454,-0.040121,0.1234,0.027679,0.017335,0.097757,0.144275,0.199606,-0.091018,0.06754,0.269927,0.053352,0.23272,0.127603,0.158824,-0.256166,0.470489,0.138155,-0.214024,-0.162492,0.124526,-0.025906,-0.227803,0.051044,-0.086635,0.23146,-0.066198,0.198958,0.122703,-0.175396,0.117882,0.162066,0.098682,-0.108902,0.033524,-0.069447,0.133912,-0.025579,0.242391,-0.132508,-0.097404,0.036962,0.178066,0.009179,-0.026864,0.255824,0.239081,0.214655,0.150201,-0.042573,-0.006011,-0.273968,-0.171325,-0.147066,-0.069304,-0.121984,0.005654,-0.081626,0.189375,0.02069,-0.210313,-0.143978,0.006735,-0.110437,-0.236894,-0.260521,-0.030875,0.047549,0.244704,-0.11755,-0.031892,-0.030964,-0.095127,-0.096465,0.252754,0.084867,-0.086847,-0.118678,-0.167298,0.008286,-0.131997,0.1484,0.086101,0.031075,0.219662,0.119593,0.159369,-0.02102,0.322038,-0.01704,-0.431339,0.054104,-0.009434,0.368174,0.029897,0.259821,0.009234,0.060747,-0.059127,0.015852,-0.044204,0.00829,-0.01533,0.068122,0.198563,-0.039658,0.328221,-0.159189,-0.293106,-0.066082,-0.206421,0.406885,-0.081354,-0.296444,-0.046966,0.075022,0.010498,-0.113417,0.02839,-0.039407,-0.115017,0.17581,0.060946,0.039038,0.02264,-0.321763,0.338251,-0.013901,0.241805,-0.051368,-0.115503,-0.064995,0.096418,-0.114405,0.114172,-0.039413,0.234884,-0.164858,-0.111223,0.04133,-0.065971,-0.125851,-0.003284,-0.134959,-0.019411,-0.058146,0.184165,0.169486,0.041003,-0.156943,-0.063526,0.196255,-0.041262,-0.000419,-0.027192,-0.123971,-0.115063,0.044039,0.087301,-0.042837,0.10221,0.053521,0.090258,-0.092311,-0.09146,0.107299,-0.041393,-0.08018,0.122682,-0.015979,0.073088,-0.18673,0.060571,-0.027591,0.1496,-0.273545,0.082858,-0.096297,-0.105651,0.008838,0.014598,-0.025075,-0.161312,0.012446,0.134646,0.033646,0.02597,0.378273,0.066293,-0.027298,-0.053306,-0.178338,-0.052757,-0.234043,0.186504,0.047541,-0.066418,0.014214,0.195612,0.057648,0.01828,-0.087783,0.104403,-0.067441,-0.071156,-0.144521,0.139925,-0.014928,-0.120075,-0.187185,-0.023173,-0.074025,-0.093403,0.141353,0.34863,0.018457,-0.023347,-0.102042,0.123165,-0.213144,-0.188534,0.17354,-0.120959,0.147642,-0.0176,-0.283622],"bias":0.832581,"trainedOn":"9587 images (see eval/fetch-train.mjs sources)"} \ No newline at end of file +{"backbone":"dinov2-small","pooling":"cls+mean","dims":768,"featureMean":[-0.587975,-0.094064,0.388187,-0.183691,0.389014,-0.03528,-0.034767,-0.26375,0.313221,0.418463,-0.150547,0.241793,-0.441617,0.148957,0.852502,0.057653,-0.201931,-0.814269,0.303307,-0.769804,0.555188,-0.318358,-0.237053,-0.204962,-0.215752,0.205432,0.049399,-0.511024,0.793436,-0.121574,-0.30079,-0.626142,0.028857,0.134217,0.492368,0.534628,-0.53921,0.678229,0.23157,0.371823,-0.192139,0.889275,-0.262973,0.158686,-0.360628,-0.631063,-0.802162,-0.092029,0.962817,0.371611,0.225355,-0.120516,0.342901,-0.285793,-0.694951,0.176231,0.498634,0.417661,-0.397721,-0.789725,0.763898,0.55714,0.111621,-0.539031,-0.324011,0.390558,-0.269609,0.107317,0.870136,-0.075503,-0.5581,0.282389,-0.603112,0.02453,0.482026,-0.532884,-0.317824,0.080954,-0.445118,-0.020532,0.11349,-0.412927,0.080437,-0.192541,-0.991158,-0.222681,-0.430975,-0.1809,-0.423271,0.311884,0.337933,-0.279033,-0.321905,-0.39488,0.776455,-0.458481,0.933325,0.074337,0.048853,-0.465585,-0.465498,0.900798,-0.367444,-0.576422,0.036017,0.325469,-0.341783,-0.374923,0.429428,-0.250852,-0.002197,0.087273,0.471771,0.181571,0.013947,-0.366408,-0.123343,0.30949,-0.417957,-0.28191,0.241463,1.256193,-0.115599,0.425791,0.821136,-0.721735,0.341678,-0.454495,-0.246905,0.50968,0.194299,-0.225802,-0.095598,0.203785,0.072845,1.058425,-0.296343,0.18367,-0.547833,0.075871,-0.663155,0.142279,-0.097237,-0.566986,0.060041,-0.312514,0.122253,0.747029,0.140247,0.266245,0.197988,-0.777732,-0.176156,0.176283,-0.490247,-0.887124,0.891164,-0.520175,0.206008,-0.442203,-0.195839,-0.460117,-0.515188,-0.167662,0.252814,-0.268552,-0.092051,-0.229226,-0.432826,0.457736,0.152554,0.1797,0.184788,0.292237,0.442868,-0.428969,-0.144477,-0.249511,0.31072,0.69643,0.445749,0.34417,0.055399,-0.010668,-0.018404,-0.080901,0.514875,0.276385,0.368935,-0.335876,-0.082503,-0.170969,-0.235624,-0.203766,0.028701,-0.050326,0.70553,0.400489,-0.43496,-0.354247,0.225182,-1.024071,0.352065,-0.253172,0.11066,0.066061,0.511124,-0.363477,0.278419,0.095486,0.665825,-0.502027,0.36272,-0.230787,-0.122765,-0.195727,-0.334865,-0.131487,-0.041678,-0.261052,0.262479,-0.370835,-0.839509,-0.432078,-0.328707,-0.029437,-0.054144,0.3592,-0.629387,0.083973,0.062789,-0.643402,-0.465046,0.379701,0.144936,0.081448,0.029463,-0.469032,-0.33728,-0.141475,0.359924,-0.028534,-0.109033,-0.336319,0.478765,-0.212261,-0.036019,-0.433826,-0.33183,-0.069357,-0.160389,0.314752,0.252278,0.228326,-0.532176,0.003395,0.561955,0.318074,0.204979,-0.393821,0.06273,0.245302,-0.140247,-0.303843,0.0621,-0.447401,-0.33335,-0.38036,-0.014597,-0.13101,0.266009,-0.427313,-0.377637,0.431003,0.589889,0.192261,0.082655,0.932067,-0.078612,-0.241809,-0.38188,-0.315707,0.134304,-0.363783,0.419194,0.134956,-0.599328,-0.18083,0.00489,-0.35889,-0.420401,-0.646764,0.631955,0.546848,-0.008727,0.139225,0.464238,0.095301,0.910026,0.274171,-0.035885,-0.081271,-0.609026,0.290416,1.145015,0.076189,-0.050211,0.173622,-0.10273,0.081563,-0.26311,0.273861,0.640575,-0.529366,-0.064814,-0.126189,0.651274,0.050973,-0.588272,-0.08474,0.296692,0.746444,0.064172,-0.075513,-0.264548,0.343813,0.633145,-0.895489,0.48237,-0.961604,0.079797,-0.177856,0.783591,-0.232921,0.195083,-0.572718,0.128741,0.243497,0.384929,0.417505,0.389078,-0.078273,0.076579,-0.147265,0.055735,0.72316,0.149476,-0.785862,0.059903,0.491495,0.008462,0.26414,0.233666,-0.301515,-0.631521,-0.216402,0.000337,0.201215,0.686283,-0.44991,-0.468667,-0.148807,0.454872,-0.251726,-0.381843,0.740801,0.047709,0.261875,0.328339,0.449155,-0.746784,0.614152,-0.439847,0.393123,0.487923,-0.420936,0.316907,0.406955,-0.23812,0.127694,-0.508902,0.184567,0.367506,0.301398,-0.459783,0.269441,0.003876,-0.246342,0.40167,-0.005977,-0.022747,-0.311014,-0.145334,0.765235,0.359748,0.102194,-0.435697,0.243568,0.38334,0.282357,-0.857057,-0.367895,0.195357,-0.297623,-0.128924,-0.588836,0.091792,0.219812,-0.014878,0.582207,-0.041479,-0.328032,0.262317,-0.283182,-0.415969,-0.137839,-0.255672,-0.024226,0.92589,-0.200145,0.121445,0.609069,0.409984,0.266544,0.067213,0.760914,-0.132166,0.379301,0.274816,-0.498351,-1.182898,-0.437314,0.543169,-0.163434,0.157789,0.379634,0.366162,-0.528209,-0.404568,0.131411,-0.084018,0.458094,0.136039,-0.560245,1.104399,0.015471,-0.274156,-0.139152,-0.532252,1.000395,0.05223,-0.336412,2.858806,0.292073,-0.505123,-0.125639,-0.528936,-0.113324,0.559894,0.253012,-0.406573,-0.036457,-0.186097,-2.012433,0.350996,0.115555,-0.393161,-0.114788,-0.228742,-0.271938,-0.409634,-0.284322,-0.684934,0.248736,0.499936,-0.225719,-0.012959,-0.405655,0.587531,-0.12975,0.73205,-0.133194,0.027896,-0.752818,-0.204851,0.824072,0.260058,-0.041193,0.082104,0.360634,-0.183001,-0.149601,1.02941,-0.34026,0.485442,-0.347906,0.65163,0.081318,0.395741,-0.667851,-0.301977,0.023849,-0.546042,-0.189208,0.499515,-0.56946,-0.005725,0.58731,0.227737,-0.11464,0.836479,-0.11108,0.039808,0.212948,0.003946,0.311947,-0.104226,-0.152645,-0.07588,-0.443603,-0.690995,0.5637,0.362842,-0.008355,-0.619502,-0.519172,0.079569,-0.012055,-0.226433,-0.197385,0.076349,0.887509,-0.199224,0.189152,0.370053,-0.016252,0.04095,0.540584,0.022476,-0.89539,0.703288,-0.234887,-0.266262,-0.379109,0.166099,-0.125871,-0.966179,-0.204287,1.156931,-0.400043,0.190622,-0.316264,-0.287796,0.214263,0.289405,0.62934,0.448696,0.640105,0.229525,-0.227672,0.045887,0.345327,-0.060931,1.210493,0.222469,1.009345,0.076387,0.010478,-0.040406,0.296481,0.604571,-0.181672,-0.036949,0.129302,-0.116943,0.118876,0.215726,-0.496861,0.242137,-0.111106,0.225012,0.267288,-0.517544,-0.066322,-0.152625,-0.574932,0.486472,0.248472,0.160378,0.524943,0.695064,-0.309064,0.115739,0.602706,0.499806,0.116116,-0.229776,0.235418,0.169756,0.140619,-0.158813,-0.327554,0.471144,0.619871,-0.344533,-0.511594,-0.452695,-0.02769,0.069816,0.174441,0.314005,-0.023002,-0.722868,0.346391,0.284689,-0.245952,-0.298563,-0.393169,-0.642809,-0.042394,-0.45433,-0.13287,0.013168,-0.126427,0.267186,-0.331327,-0.280022,-0.576007,0.223661,0.045645,0.059177,-0.389933,-0.365972,-0.277524,-0.264547,-0.027986,0.546796,-0.086678,0.027024,-0.201344,0.85308,0.300601,0.206311,0.209232,0.407434,-0.279145,0.713712,0.100246,0.25919,-0.135071,0.102692,-0.432944,-0.178766,-0.563679,0.072287,-0.06057,-0.200482,0.316457,0.764198,0.453713,-0.376656,0.759194,-2.95688,-0.085011,-0.587951,-0.277082,0.570713,-0.323983,0.734727,0.445457,-0.438078,-0.509942,-0.149286,-0.135624,-0.317897,-0.116691,0.208374,0.593096,-0.130487,-0.035505,0.235881,0.177243,-0.02024,0.316018,0.13533,-0.038237,-0.334865,-0.261194,0.793838,0.31482,0.01806,0.076425,-0.584499,0.332502,0.391397,0.345847,0.951976,-0.378782,-0.07094,-0.092787,0.148784,-0.22873,-0.325966,0.00571,0.33515,0.464256,0.252271,1.121228,0.001736,0.218373,-0.078143,-0.500651,0.722513,-0.437303,0.264046,-0.013276,0.481954,-0.291381,0.182062,-0.336424,0.144196,0.294189,0.390059,0.203474,0.526969,0.196394,-0.006748,-0.371501,0.227491,1.15031,-0.127903,-0.120548,0.109119,0.279924,0.026226,0.280413,0.212739,-0.368002,-0.12312,-0.398959,-0.113201,-0.017459,0.687796,-0.332111,-0.084421,0.448106,0.868388,-0.07666,0.324594,-0.407628,-0.114554,0.329985,-0.074088,-0.279454,-0.342857,0.453994,0.776692,0.206599,0.499095,0.228425,0.299621,-0.115071,-0.349495,-0.568216,-0.696514,0.499988,0.479448,0.241467],"featureStd":[2.563339,1.423751,2.391731,2.456788,2.49136,1.400176,2.292005,2.056408,2.517597,2.521402,2.372317,2.559408,2.45855,2.427769,2.646003,2.431169,2.445219,2.565531,1.868967,2.321755,2.425466,2.340049,2.457585,1.771333,2.345232,2.428889,2.528439,2.373985,1.537687,2.612333,2.253525,2.297394,2.204188,2.561985,2.336477,2.420455,2.580578,2.46789,2.619453,2.796326,2.510579,2.602715,2.72787,2.353813,2.338165,2.356565,2.419166,2.427417,2.570777,2.364378,2.408781,2.458287,2.503559,2.226682,2.301121,2.605879,2.499298,2.316271,2.639385,2.400107,2.391448,2.495875,2.45487,2.638347,1.880394,2.506346,2.431533,2.508441,2.234693,2.330746,2.708151,2.218388,2.655668,2.427462,2.777788,2.465547,2.431291,2.468739,2.37641,1.478274,2.249462,2.473785,2.354831,2.457668,2.094002,2.46003,2.395645,2.392076,2.360279,2.303572,2.532654,2.423549,2.423603,2.638671,2.624535,2.138809,2.282007,2.484847,2.385271,2.566783,2.570779,2.502948,2.505383,2.631558,2.157913,2.546465,2.570621,2.436125,2.627695,2.559257,2.346806,2.628764,2.499247,2.21057,2.495273,2.389233,2.37116,2.536734,2.599883,2.537106,2.417322,2.255326,2.403314,2.570478,2.581508,1.873178,2.554678,2.586836,2.45965,2.797326,2.026586,2.436644,2.622622,2.402128,2.652706,2.795144,2.452358,2.44751,2.116027,2.573459,2.12307,2.109779,2.204842,2.367895,2.393208,2.535227,2.232362,2.345313,2.201099,2.283726,2.384232,2.233622,2.401564,2.523832,2.522131,2.548948,2.527035,2.461946,2.529115,2.117318,2.524763,2.483101,2.219972,2.302431,2.501387,2.487032,2.413064,2.277877,2.568198,2.394802,2.454288,2.473629,2.355906,2.596616,2.559672,2.453075,2.332952,2.402885,2.379027,2.406555,2.546166,1.821679,2.506817,2.187776,2.404567,2.475402,2.459834,2.533744,1.788142,2.165477,2.344194,2.567156,2.336603,2.284975,2.512372,2.063715,2.576186,2.409388,2.369309,1.99447,2.49246,1.984343,2.593194,2.806756,2.360273,2.491558,2.429415,2.390794,2.825627,2.139903,2.39918,1.94134,2.045114,2.538592,2.516611,2.487707,2.101606,2.6445,2.34486,2.906039,2.203376,2.479163,2.650604,2.487676,2.432678,2.266505,2.405849,1.927561,2.557759,2.378572,2.4282,2.785256,1.99228,2.510639,2.498752,2.511649,2.40036,2.519058,2.416581,2.38335,1.793607,2.460965,2.470414,2.278076,2.034328,1.855927,2.207901,2.387337,2.709988,2.456251,2.461658,2.589948,2.387838,2.056813,2.431863,2.47,2.278761,2.669976,2.184396,2.50537,2.497214,1.974584,1.817137,2.023247,2.003098,2.532809,2.258775,2.412525,2.615696,2.5519,1.873439,2.435615,2.401814,2.385866,2.525769,2.012105,2.435133,2.32145,0.887453,2.386744,2.237844,2.431284,2.587771,2.585727,2.48945,2.499703,2.090283,2.455885,1.996087,2.488211,2.747732,1.923782,2.593993,2.661347,2.645931,2.462117,2.211663,2.382341,2.744653,2.546234,2.705935,2.284904,2.726695,2.266985,2.79901,2.268376,2.282386,2.467811,2.228202,2.436372,2.486526,2.482785,2.427398,2.649818,2.184376,2.368342,2.676703,2.142772,1.839423,2.376691,2.400639,2.466783,2.326979,2.035177,2.282886,1.992425,2.795572,2.448023,2.499468,2.253212,2.567494,2.378672,2.410847,2.348834,2.572547,2.482672,2.468286,2.604575,1.825566,2.290337,2.460326,2.38687,2.611959,2.53012,2.397307,2.408846,2.497394,2.608252,2.529612,2.395428,2.277117,2.598885,2.582701,2.319226,2.42093,2.493205,2.36651,2.548446,2.709813,2.203807,1.960416,2.393026,2.563166,2.502107,1.979449,2.27817,2.535586,2.682707,2.023539,2.557767,2.106403,2.569568,1.918993,2.598817,2.63012,2.16562,2.372143,2.464213,2.507679,1.509507,2.459894,2.532621,2.611947,1.873226,1.451609,0.873068,1.507175,1.370198,1.337026,0.542871,1.168773,1.052381,1.361305,1.205763,1.316309,1.545503,1.373617,1.346212,1.378905,1.450366,1.372689,1.577827,1.472313,1.282475,1.226887,1.321852,1.38988,1.530707,1.278118,1.698951,1.457573,1.350219,0.734797,1.426415,1.116985,1.328873,1.425924,1.432487,1.15739,1.291616,1.533029,1.257384,1.439381,1.694039,1.472631,1.534007,1.703732,1.546579,1.081434,1.405172,1.447181,1.307805,1.37513,1.226256,1.32392,1.269335,1.378694,1.176068,1.189424,1.589318,1.472203,1.392489,1.54868,1.65596,1.398851,1.377896,1.456501,1.548904,0.863664,1.358282,1.377703,1.388008,3.07776,1.226226,1.648239,1.310923,1.235637,1.572233,1.535958,1.417871,1.339792,1.36561,1.372263,0.878759,1.27591,1.433725,1.43432,1.442349,0.728772,1.355112,1.495507,1.420357,1.271516,1.254941,1.499588,1.352564,1.184815,1.615235,1.523036,1.221451,1.340205,1.523329,1.326951,1.578474,1.429487,1.443677,1.585238,1.627051,1.288435,1.437949,1.587061,1.420339,1.542493,1.593181,1.287701,1.581101,1.384512,1.216999,1.350132,1.351405,1.410688,1.433633,1.492631,1.329771,1.356843,1.016007,1.424585,1.398494,1.395426,0.773151,1.570321,1.404215,1.362366,1.658203,1.163558,1.374075,1.557446,1.310952,1.602988,2.663496,1.358993,1.377992,1.6492,1.345186,0.918971,0.915915,1.045367,1.271844,1.3002,1.479599,1.175982,1.298311,1.200051,1.348142,1.146518,1.047058,1.23253,1.336482,1.552355,1.538983,1.456771,1.428194,1.493379,0.986838,1.444949,1.490811,1.378081,1.247501,1.462104,1.606163,1.309522,1.31344,1.546898,1.324669,1.347637,1.198871,1.283499,1.617502,1.514197,1.304956,1.103404,1.351248,1.244666,2.179316,1.539226,1.023734,1.483796,1.157546,1.278345,1.370669,1.415046,1.488564,0.707914,0.921098,1.218571,1.615242,1.301283,1.098433,1.422374,1.021985,1.54172,1.461086,1.194443,0.979504,1.346751,0.881797,1.710535,1.602752,1.296485,1.438342,1.240706,1.374595,3.686193,1.141107,1.361027,1.119765,1.137682,1.452947,1.294702,1.469604,0.963966,1.5049,1.188284,3.35446,1.063295,1.502364,1.475061,1.144183,1.36933,1.303373,1.399739,0.855995,1.400695,1.384467,1.284687,1.731605,1.044219,1.47373,1.386845,1.428565,1.420343,1.450092,1.594293,1.330814,0.733376,1.392799,1.513457,1.136232,1.060654,0.923388,1.140062,1.31058,1.471831,1.558134,1.498227,1.524653,1.247509,1.094212,1.474443,1.652402,1.043264,1.614091,1.154902,1.402944,1.701094,0.999415,1.541207,1.135141,1.48277,1.413376,1.173311,1.345356,1.500386,1.520166,0.828264,1.422589,1.302662,1.375878,1.472845,1.193459,1.307843,1.277927,0.568834,1.340484,1.163376,1.348385,1.494592,1.507615,1.492269,1.37488,2.265013,1.352972,0.908678,1.318431,1.572155,1.097068,1.396133,1.566597,1.588988,1.465789,1.039578,1.440679,1.518713,1.525624,1.71682,1.518885,1.563492,1.328193,1.627306,1.238113,1.335884,1.378961,0.926811,1.295457,1.496077,1.482566,1.416775,1.414534,1.110109,1.174102,1.434897,1.236167,1.50211,1.238025,1.343233,1.446214,1.283604,1.506051,1.294865,1.079944,2.804473,1.276789,1.491145,1.108357,1.50822,1.268057,1.277292,1.305346,1.551649,1.42735,1.434159,1.390352,0.944331,1.098727,1.325469,1.523672,1.560828,1.237817,1.348674,1.230404,1.359842,1.442747,1.311544,1.342781,1.081361,1.50474,1.457578,1.311738,1.380079,1.362,1.42215,1.404854,1.629569,1.616786,0.809509,1.231428,1.412988,1.59879,0.791528,1.143669,1.346903,1.593552,0.984954,1.561255,1.066744,1.434838,0.842069,1.504124,1.593388,1.207101,1.266067,1.488557,1.492854,0.744757,1.484142,1.426548,1.524166,0.975931],"weights":[-0.081457,0.243648,-0.225218,-0.169947,0.225016,0.170034,0.03206,0.054691,-0.018925,0.143766,-0.026322,0.055291,-0.047651,0.032654,0.205422,-0.070852,0.098549,-0.108047,-0.073795,-0.340322,-0.093948,-0.138501,0.007231,0.204754,0.026447,-0.016591,-0.056891,-0.196476,-0.014824,0.429538,0.247424,-0.06594,0.116814,0.157796,0.013285,0.157843,-0.024776,0.044651,-0.00997,0.202294,0.044879,0.137424,-0.123622,-0.067153,-0.138646,0.064572,0.078377,-0.053077,-0.038814,0.07101,-0.049879,-0.16953,-0.104095,0.022557,-0.001668,0.011751,0.028149,-0.102688,0.036642,-0.168124,-0.020827,0.01907,0.097448,-0.187312,-0.126548,0.082511,0.054171,0.089187,-0.095548,-0.133465,-0.039426,0.156973,0.021203,-0.125457,0.114095,0.081166,0.117216,-0.145833,-0.09563,-0.103718,-0.058805,0.014085,-0.148769,-0.097828,-0.027833,-0.067145,-0.009173,0.116523,0.055617,-0.06809,0.004511,0.169872,-0.109988,-0.161624,0.12829,-0.075347,0.136846,0.00019,0.073358,-0.064854,-0.099912,0.435489,-0.107479,-0.075336,0.003926,-0.002231,0.183309,0.314958,0.071703,-0.138815,0.122821,-0.120271,0.070813,0.132543,0.143431,-0.032286,0.055921,0.064292,-0.019539,0.000705,0.027086,0.674251,-0.044296,0.100988,-0.143357,-0.194966,0.08067,-0.180376,0.029048,-0.09401,0.062155,0.061872,0.159053,0.035346,0.038791,0.298283,0.158273,0.037271,0.067471,0.04207,0.082619,-0.0774,0.056161,0.008148,0.094685,-0.071021,-0.050006,0.008676,-0.098756,-0.07124,-0.004173,-0.092651,-0.095455,0.056193,0.046074,0.047616,-0.119663,-0.049501,0.023162,-0.394534,-0.135531,0.102286,-0.251315,-0.10251,0.037699,0.188043,-0.000192,0.065561,-0.233373,-0.027913,0.063757,-0.201134,0.146926,-0.124252,0.314485,0.088858,-0.1119,-0.126078,0.066581,-0.058273,-0.197029,0.124338,-0.214286,-0.051568,0.093482,-0.162371,0.099643,0.095765,-0.108806,0.07045,0.060139,0.080126,-0.102542,-0.147891,0.094386,0.16546,-0.055066,0.025554,0.099738,-0.365377,-0.156143,-0.283326,-0.071636,0.005434,-0.117091,0.06598,-0.099219,0.016595,-0.414636,0.026287,0.114357,-0.152953,0.273808,0.011443,-0.245307,-0.094156,-0.151094,-0.263426,0.074924,0.012132,-0.115646,0.019402,-0.035212,-0.146809,-0.074407,-0.129001,-0.092195,0.071077,-0.387747,-0.021007,0.089693,-0.086846,0.210338,0.077302,-0.132677,0.004301,-0.001034,-0.099452,-0.130119,-0.034428,-0.112476,-0.022546,-0.085149,0.137015,0.312603,-0.015583,-0.102079,0.177807,0.031654,0.037381,-0.030275,0.164051,-0.036915,0.124149,0.095516,0.024521,-0.089554,-0.058733,-0.143653,-0.095884,-0.137739,0.12333,0.235751,-0.17705,-0.039127,-0.054714,0.137955,-0.095921,0.133185,-0.38074,0.106537,-0.087855,-0.026327,0.075363,-0.089438,-0.062773,-0.064974,0.11573,0.097177,-0.001606,0.035532,0.08109,0.049199,-0.227145,-0.065545,-0.060277,0.022414,-0.006485,-0.031386,0.119625,0.102448,-0.188357,-0.063515,0.042441,0.016031,0.29159,0.069047,0.007328,0.031445,-0.176366,-0.08358,-0.037083,0.06106,-0.120694,0.187841,0.002445,-0.275092,0.141698,-0.015408,0.193978,-0.155578,0.155919,-0.035422,-0.114471,0.236957,0.167128,0.127266,-0.240741,0.083647,0.090334,0.052485,-0.252682,-0.128539,-0.398054,0.151615,-0.036786,0.352297,0.005128,0.191412,-0.025162,-0.008338,0.147737,-0.10208,-0.104898,0.313876,0.134905,-0.15745,0.182032,0.091668,0.119143,0.007621,0.004981,0.200833,-0.008415,0.383005,0.146449,-0.036689,-0.184246,0.209787,-0.040478,0.167321,0.09463,-0.24097,-0.18644,0.108458,-0.07613,0.076612,0.119228,-0.038336,-0.01566,-0.080516,-0.087887,0.17265,0.026148,-0.283115,-0.014933,0.219139,0.070329,0.012642,0.040184,0.144651,0.169792,-0.583839,-0.140227,-0.016112,-0.224718,-0.089589,0.114248,-0.110299,-0.28979,0.038565,-0.061427,-0.01873,0.04439,-0.056265,-0.035865,0.048661,0.117036,-0.012862,0.130876,0.117224,-0.171824,0.038375,-0.031332,-0.086314,-0.010104,0.050006,-0.139123,0.258927,-0.149445,-0.013002,-0.054082,-0.001516,-0.163914,0.066577,-0.329434,-0.056079,0.199027,0.218349,-0.143964,0.028616,-0.01767,0.255606,0.019351,-0.237984,-0.238015,-0.014418,-0.079807,0.038086,-0.090441,-0.170147,-0.197393,0.044074,0.156245,0.025269,0.105257,0.126224,0.067614,-0.116274,0.050055,-0.036691,-0.076149,0.254499,-0.024493,0.063384,-0.04706,0.029765,0.168353,0.005363,-0.100667,0.219408,0.094198,0.178848,-0.305266,0.018123,0.174171,-0.055421,-0.115201,-0.203174,0.015376,-0.073919,0.003862,-0.268183,0.041964,-0.040446,-0.302749,0.22499,0.26372,0.110751,0.101927,-0.423837,0.121622,0.060784,0.128127,0.0856,-0.013953,0.079741,0.350311,0.086559,0.00716,-0.274383,0.008423,-0.175252,-0.033616,0.063535,0.058031,0.186615,0.101766,0.097673,0.042975,0.014053,0.042877,-0.063415,-0.008634,0.088639,-0.124177,-0.15965,-0.232323,-0.092798,-0.076249,0.008717,0.040389,0.110181,-0.149078,0.064759,-0.069419,-0.189416,-0.016244,-0.266373,-0.118572,-0.377839,-0.123671,0.09747,-0.085846,0.095556,-0.525107,-0.090147,0.256864,-0.074322,0.016612,0.096516,0.04498,-0.080052,0.024206,0.106356,0.038869,-0.021533,-0.150991,-0.058703,0.233279,-0.182667,0.039223,-0.337572,-0.083162,0.190308,0.11053,-0.094335,0.148717,0.280603,-0.071604,0.013325,-0.093145,0.176479,-0.135395,0.224458,-0.011949,0.000563,0.099575,-0.145454,-0.161416,0.163031,-0.01824,0.10996,-0.075753,0.106943,0.010894,-0.130705,0.053814,0.129077,0.164393,0.010224,-0.075681,0.289722,0.103859,0.118684,0.116485,0.088848,-0.287096,0.237279,0.121324,-0.216554,-0.037481,0.103655,0.176615,-0.05177,-0.004725,0.044608,0.236358,-0.04354,0.092989,0.093324,-0.174783,0.079028,0.127601,0.146458,-0.19123,0.014011,-0.101307,-0.038114,-0.172168,0.071626,0.086095,-0.147336,-0.000212,0.131615,0.120906,-0.048134,0.102588,0.238975,0.313415,0.178945,-0.014734,-0.198558,-0.024199,-0.353183,-0.105753,-0.146657,-0.11517,0.185532,0.037829,-0.080533,-0.192221,-0.110014,-0.02279,0.073505,-0.206699,-0.318547,-0.034564,-0.046703,0.061234,0.189022,-0.021279,0.005977,-0.009736,-0.093911,0.031461,0.081592,0.146584,0.00192,0.032365,0.077123,-0.012098,-0.051313,0.204698,0.070688,-0.11474,0.253649,-0.002112,0.219313,0.042202,0.365921,-0.154353,-0.485518,0.091765,-0.030512,0.469405,0.085303,0.107868,0.032859,-0.070756,-0.081762,0.085716,-0.088679,0.116826,-0.041618,0.019496,0.288136,-0.076379,0.290843,0.059277,-0.221325,-0.060858,-0.128098,0.329421,0.006754,-0.216244,-0.010112,0.014993,-0.121952,-0.124906,0.014636,0.036092,-0.050246,0.035799,0.113942,-0.080357,0.000055,-0.28208,0.343512,-0.100207,0.060561,0.030195,0.106094,0.044598,0.138056,-0.111851,0.316635,0.144566,0.315448,-0.223404,-0.146216,0.144168,0.031196,-0.035985,-0.021097,-0.150297,-0.066331,-0.104001,0.118236,0.101161,-0.112572,-0.196233,0.166055,-0.04059,0.100159,-0.041086,0.082764,0.09781,-0.167007,-0.014734,0.108889,-0.017342,0.107201,-0.133385,0.019889,-0.053159,-0.081804,0.077919,-0.089554,-0.032317,0.184395,-0.108852,0.154564,-0.264223,0.081922,-0.065863,0.095774,-0.283429,0.004652,-0.118008,-0.003448,-0.046645,0.016908,-0.178154,-0.241081,-0.003112,0.103053,-0.03818,-0.016019,0.256059,0.093395,0.085516,-0.25439,-0.097247,-0.224456,-0.23207,0.143807,0.096084,0.016272,0.221791,-0.018835,0.142323,0.170375,-0.138686,0.243539,0.052488,0.077392,-0.06885,0.23759,-0.147734,-0.174491,-0.240178,-0.063987,-0.035578,-0.130591,0.045047,0.507429,0.015757,0.02958,-0.160653,0.036911,-0.224094,-0.151191,0.226922,-0.113722,0.232051,-0.037799,-0.251835],"bias":0.032176,"trainedOn":"11405 images (see eval/fetch-train.mjs sources)"} \ No newline at end of file diff --git a/src/fuse.js b/src/fuse.js index cc4e0a4..6531f5f 100644 --- a/src/fuse.js +++ b/src/fuse.js @@ -6,11 +6,11 @@ export const DEFAULT_THRESHOLD = 0.65; export const UNCERTAIN_LOW = 0.45; /** CF scores below this need the saturated sub-floor tier to be rescued. */ -export const DINO_CF_FLOOR = 0.03; +export const DINO_CF_FLOOR = 0.02; /** CF below this requires near-saturated DINO before it can be rescued. */ -export const DINO_STRONG_RESCUE_FLOOR = 0.30; +export const DINO_STRONG_RESCUE_FLOOR = 0.10; /** DINO must be this confident to lift a low CF score into the rescue band. */ -export const DINO_STRONG_RESCUE_MIN = 0.96; +export const DINO_STRONG_RESCUE_MIN = 0.90; /** DINO must be this confident to lift CF in the normal uncertain band. */ export const DINO_RESCUE_MIN = 0.70; /** @@ -18,12 +18,14 @@ export const DINO_RESCUE_MIN = 0.70; * faintly awake AND DINO is saturated. CF emits hard zeros on real photos * it is certain about, while AI images in its blind spots still elicit a * faint response, so "CF flatlined" is itself evidence of a real photo. - * Derived on the Pillow-path bench with a 240-image stock/catalog stress - * guard (zero stress regression allowed); see PR for the measurement. + * Bands re-derived for the hard-negative probe (trained with stock, + * catalog, product, and interior reals) on the Pillow-path bench under a + * 240-image stress guard; a deliberately conservative near-optimum was + * chosen over the grid maximum. See PR for the measurement. */ -export const DINO_SUBFLOOR_CF_MIN = 0.005; +export const DINO_SUBFLOOR_CF_MIN = 0.0005; /** DINO saturation required for the sub-floor rescue. */ -export const DINO_SUBFLOOR_MIN = 0.999; +export const DINO_SUBFLOOR_MIN = 0.995; export const URL_HINT_MAX_BOOST = 0.05; /** diff --git a/tests/dino.test.mjs b/tests/dino.test.mjs index 29113c9..03ab7c9 100644 --- a/tests/dino.test.mjs +++ b/tests/dino.test.mjs @@ -109,9 +109,9 @@ describe('fuseNeuralScores', () => { it('does not let saturated DINO override a hard-zero CF', () => { // CF hard zeros mark confident reals; no rescue tier may touch them. assert.equal(fuseNeuralScores(0.0, 0.9999), 0.0); - assert.equal(fuseNeuralScores(0.004, 0.9999), 0.004); + assert.equal(fuseNeuralScores(0.0004, 0.9999), 0.0004); // Below the CF floor, high-but-unsaturated DINO still cannot rescue. - assert.equal(fuseNeuralScores(0.02, 0.99), 0.02); + assert.equal(fuseNeuralScores(0.015, 0.99), 0.015); }); it('ignores DINO rescue when it is not high-confidence', () => { @@ -125,12 +125,12 @@ describe('fuseNeuralScores', () => { }); it('only rescues low CF scores with near-saturated DINO', () => { - assert.equal(fuseNeuralScores(0.10, 0.99), 0.99); - assert.equal(fuseNeuralScores(0.10, 0.70), 0.10); - assert.equal(fuseNeuralScores(0.25, 0.97), 0.97); - assert.equal(fuseNeuralScores(0.25, 0.95), 0.25); + assert.equal(fuseNeuralScores(0.05, 0.99), 0.99); + assert.equal(fuseNeuralScores(0.05, 0.89), 0.05); + assert.equal(fuseNeuralScores(0.25, 0.75), 0.75); + assert.equal(fuseNeuralScores(0.25, 0.65), 0.25); // Sub-floor tier: faintly awake CF plus saturated DINO rescues. - assert.equal(fuseNeuralScores(0.01, 0.9995), 0.9995); + assert.equal(fuseNeuralScores(0.01, 0.996), 0.996); assert.equal(fuseNeuralScores(0.01, 0.99), 0.01); }); diff --git a/tests/fuse.test.mjs b/tests/fuse.test.mjs index 17669d2..8fc8e2f 100644 --- a/tests/fuse.test.mjs +++ b/tests/fuse.test.mjs @@ -46,23 +46,23 @@ describe('fuseNeuralScores policy', () => { }); it('CF flatlined below the sub-floor CF minimum is never rescued', () => { - assert.equal(DINO_SUBFLOOR_CF_MIN, 0.005); - const fused = fuseNeuralScores(0.004, 0.9999); - assert.equal(fused, 0.004); + assert.equal(DINO_SUBFLOOR_CF_MIN, 0.0005); + const fused = fuseNeuralScores(0.0004, 0.9999); + assert.equal(fused, 0.0004); assert.equal(isAiAtThreshold(fused), false); }); it('sub-floor rescue needs saturated DINO, not just high DINO', () => { - assert.equal(DINO_SUBFLOOR_MIN, 0.999); + assert.equal(DINO_SUBFLOOR_MIN, 0.995); const notSaturated = fuseNeuralScores(0.01, 0.99); assert.equal(notSaturated, 0.01); - const saturated = fuseNeuralScores(0.01, 0.9995); - assert.equal(saturated, 0.9995); + const saturated = fuseNeuralScores(0.01, 0.996); + assert.equal(saturated, 0.996); assert.equal(isAiAtThreshold(saturated), true); }); it('graphic gate blocks the sub-floor rescue too', () => { - const fused = fuseNeuralScores(0.01, 0.9995, { graphicGate: true }); + const fused = fuseNeuralScores(0.01, 0.996, { graphicGate: true }); assert.equal(fused, 0.01); assert.equal(isAiAtThreshold(fused), false); }); @@ -81,17 +81,17 @@ describe('fuseNeuralScores policy', () => { }); it('CF below DINO floor ignores non-saturated DINO even when high', () => { - assert.equal(DINO_CF_FLOOR, 0.03); - const fused = fuseNeuralScores(0.02, 0.99); - assert.equal(fused, 0.02); + assert.equal(DINO_CF_FLOOR, 0.02); + const fused = fuseNeuralScores(0.015, 0.99); + assert.equal(fused, 0.015); assert.equal(isAiAtThreshold(fused), false); }); it('low CF is only rescued by near-saturated DINO', () => { - assert.equal(DINO_STRONG_RESCUE_FLOOR, 0.30); - assert.equal(DINO_STRONG_RESCUE_MIN, 0.96); - assert.equal(fuseNeuralScores(0.25, 0.97), 0.97); - assert.equal(fuseNeuralScores(0.25, 0.95), 0.25); + assert.equal(DINO_STRONG_RESCUE_FLOOR, 0.10); + assert.equal(DINO_STRONG_RESCUE_MIN, 0.90); + assert.equal(fuseNeuralScores(0.05, 0.91), 0.91); + assert.equal(fuseNeuralScores(0.05, 0.89), 0.05); }); it('includes the DINO floor boundary in the lift band', () => {