Commit Graph
4107 Commits
Author SHA1 Message Date
MarekSpodBiedry 5be931e48a Show the applied profile when hovering it in the profile browser (#2057) 2026-10-17 00:23:38 +02:00
helgehelge123andClaude Opus 5.5 53f57b9404 LR-MASK-OBJECTS: SAM 3 falls back to the CPU when the GPU can't run it (#1974)
On an Intel Mac with an AMD Radeon Pro 5300M the Metal compiler crashes
on candle's mlx_gemm kernel, candle-metal-kernels panics on the compile
error, and the worker reported "the AI model failed unexpectedly" and
loaded the model on Metal again for every next job, so AI masks never
worked there.

The worker now retries a job that fails on the GPU (a panic or a candle
error) once on the CPU, after freeing the model. When that works, the
model stays on the CPU for the session and the job's outcome carries a
notice that segment_poll shows once; when the CPU fails too, the GPU
was not the cause and the next job uses it again. Missing or damaged
model files, render and remote-worker errors are not retried. Only
builds with a GPU path (macOS) retry; LIGHTCRAFT_GPU=0 and
LIGHTCRAFT_GPU_BACKEND=off now keep SAM 3 on the CPU from the start
(lightcraft_gpu::env_off_reason), like AI Denoise and the face models.

lightcraft-segment: Sam3::load_cpu, GPU_BUILD; text_logits returns the
crate's Error so Describe failures are classified like clicks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 23:55:32 +02:00
aiongg 7b934ca2b2 Sidecars: write XMP only beside an existing local original 2026-10-16 17:57:30 +00:00
aiongg 346681561a Lightroom import: follow catalog paths only on this computer or the catalog's share 2026-10-16 17:44:52 +00:00
NetterSilverandClaude Haiku 5.5 3accb56196 Start crop drags in the zone the cursor showed at the press
Fixes #1930

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 16:32:19 +00:00
FredApps b427378eaf Address #1890: refresh catalog render diagnostics onto main
Partial scope only: catalog-backed renderer diagnostics. Broader import/export paths remain open. Preserve already-merged workflow/package changes; the exact candidate tree passed both diagnostic regressions, renderer tests and all eight local CI gates.
2026-10-16 17:28:49 +02:00
sanyamsingh001andCodex b0403c06f9 LR-META-XMP: reread embedded JPEG metadata
Manual metadata reread now finds standard embedded JPEG XMP when no sidecar exists. Existing sidecars remain authoritative, metadata updates remain undoable, and rereading does not write a sidecar. The reader retains its bounded header policy; Extended XMP assembly is unsupported.

Co-authored-by: Codex <codex@openai.com>
2026-10-16 15:00:33 +00:00
Aleksandr Batyrev 14ede0b7d9 fix(camera-profiles): fingerprint subsecond profile modification times 2026-10-16 19:58:40 +05:00
NetterSilverandClaude Haiku 5.5 0a9675c6d9 Ignore zero or negative ISO when importing XMP
Found while testing crates/meta/src/xmp.rs:509-512

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-16 14:54:06 +00:00
NetterSilverandClaude Haiku 5.5 312dd04830 Reject out-of-range start in photo.rename and photo.renamePreview
Found while testing crates/engine/src/rename.rs:919 (start parsed at crates/engine/src/cmd/manage.rs:12)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-16 16:21:24 +02:00
Matthew James SivakandClaude Opus 5.5 0d30c99e87 LR-VIEW-CLIPPING: merge main into #937 (⌥-drag previews)
Conflict only in docs/parity-checklist.md: the generated summary is
refreshed with `cargo xtask parity --write`, and the Last updated line
keeps main's format with this PR's change note (today's date) instead of
the duplicated note the branch carried. ⌥-drag preview still wins over
AllMasks and the selected mask in view_overlay; overlay kinds 6–9 unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 15:52:08 +02:00
ronibalthazar a43c3c2a89 #1952: expire idle control connections 2026-10-16 14:15:48 +01:00
Claude 6dd3f160bc #1999: starred presets in a Favorites section on top of the Presets panel
As in the Profile browser, starred presets are listed in a Favorites
section above the groups, and stay in their own group too. The section
has its own open state and widget ids, so a user group named
"Favorites" and the same preset listed twice don't clash.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbegtYaPuwqZ81pGfELsFK
2026-10-16 12:11:26 +00:00
Alexander Bystrow 085d18d692 LR-IMP-LOCAL: Opening on Missing Photos picks no photo from it either
Review round 1: with no active photo saved (an empty Missing view leaves
none), open_stores worked the view out to pick its first photo, with the
same synchronous check of every original. Skip that on Missing Photos;
the test now opens both an empty and a full Missing view.
2026-10-16 13:54:33 +02:00
Alexander Bystrow bf82b57a0a LR-IMP-LOCAL: Opening on Missing Photos no longer checks every original
Forgetting untouched Local records on open kept the visible photos, and on
Missing Photos working them out stats every original on the UI thread
before the availability worker runs. A 37k-photo library on a sleeping
SMB share froze the window for minutes. Missing Photos lists library
photos only, never Local records, so it can keep nothing: skip it.
2026-10-16 13:46:30 +02:00
GSibilleandCopilot App b9640ef1d5 #1944: keyword.export refuses library originals and writes durably
Export Keywords wrote with std::fs::write to any path, replacing a library
original or its XMP sidecar. It now goes through check_write_target and
write_file_durable like preset.export and curve.exportPresets.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-10-16 13:35:53 +02:00
ubergenericandClaude Opus 5.5 9392039726 Detail: at rest the whole frame renders at the preview level, shrunk once
Rendered at the drawn size, the pipeline itself shrinks the 2560 px preview
source (Mitchell prefilter, then the bilinear sampling pass) before the display
fit shrinks it again. At rest the whole-frame render now asks for no less than
the preview level (the photo's own size if smaller, a user's explicit Preview
size if lower, the texture limit at most): the source is copied 1:1 and shrunk
once, by the Lanczos display fit. Drags still render drafts at the planned size.

On a line-grating chart at Fit this takes 1.8 px bars from 0.83 to 1.00 of their
contrast (1920 x 1200 window), at the cost of a larger settled render.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 21:28:14 +11:00
ubergenericandClaude Opus 5.5 7db0a64d7e Detail: Fit is as sharp as the photo (display fit, whole-pixel draw, Lanczos decode)
At Fit the loupe was softer than a good downscale of the same file. Four
resamples stacked up between the source and the screen:

- the render edge is rounded up to a 64 px step, so the texture was drawn up
  to ~6 % smaller than its size and the GPU shrank it with 2-tap bilinear
  sampling;
- the fitted texture sat on a fractional pixel position, so even at the right
  size every screen pixel was averaged with its neighbour (#1831 fixed the
  same for 100 %);
- the render box truncated its short side (2560 x 1706 for a 2560 x 1707
  source), a slightly anisotropic resample that blurred one axis only;
- the codec's decode-time shrink at 2:1 and more, and SourceRef::Fit, used a
  box filter, which halves the contrast of detail near the output's limit.

RenderJob::display_fit shrinks a full-quality render that is larger than its
drawn size to exactly that size with Lanczos-3 on the worker (after the caches
have the full render; drafts untouched; part of the key). The Detail view sets
it for the After and Before renders at rest, and snap_fit_rect draws a texture
that is its drawn size on whole physical pixels. The render boxes round their
short side, and the 2:1-and-more shrinks use Lanczos-3.

Refs #1472, #1042.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 21:28:12 +11:00
Andrew FrahnandClaude Opus 5.5 340ed4c2d8 LR-EDIT-COLOR-TEMP: Kelvin white balance from Canon CR2 ColorData presets
Canon's maker-note ColorData lists the levels of each white-balance preset
with Canon's colour temperature for it. For versions -4 and 13-15 the
Daylight, Shade, Cloudy, Tungsten and Flash rows now give a Kelvin curve
(kelvin_presets, generalised from five fixed points to any number, with a
from_unordered constructor that sorts and drops points that would turn the
curve back). Fluorescent (off the locus) and the Kelvin row (the dial's last
setting) are left out. Enabled for the PowerShot G1 X Mark III, which has no
colour matrices: its nine as-shot white balances read within 4 % of the
camera's own ColorTempAsShot.

Sources: own design on the existing kelvin_presets model; ColorData row
positions from the ExifTool Canon tag-name documentation, confirmed with
ExifTool run as a black-box tool on sample files.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 21:19:18 +11:00
Andrew FrahnandClaude Opus 5.5 b03f1dd396 LR-EDIT-COLOR-TEMP: Kelvin white balance for the Nikon Z5II from built-in presets
The Z5II has no colour matrices and its NEFs carry no preset table, so its Temp slider
showed the relative -100..+100 scale. A small per-model table (crates/raw/src/kelvin_builtin.rs)
gives five (Kelvin, multipliers) points that feed the existing KelvinPresets curve: the NEF
decoder attaches them to ColorData::kelvin_presets and kelvin_presets::covers accepts the model.

Points: as-shot WB_RBLevels of the body's own shots at Incandescent, Direct sunlight, Kelvin
5500 K, Cloudy and Shade, placed at the temperature the camera itself writes for each preset
(maker note ColorTemperatureAuto: 3000, 5210, 5500, 5990, 8000 K). Fluorescent and flash are
left out. Natural Auto (camera: 5030 K) reads back at 5036 K.

Sources: own design on the existing kelvin_presets model; the camera's own stated temperatures;
ExifTool Nikon tag-name documentation (prose), exiftool used as a black-box tool.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 21:13:35 +11:00
wstockandClaude Fable 5.1 76689a563a Crop: a fresh crop starts locked to the photo's own shape (#991)
With no aspect ever chosen, every crop started free, so the Lock had to
be switched on photo after photo. Nothing chosen yet now means locked to
Original, as Lightroom starts; switching the Lock off once is remembered
as free, and an explicit ratio is remembered as before.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011K1peyrh5MdZ6ttHkVq8Gh
2026-10-16 09:38:38 +00:00
wstockandClaude Fable 5.1 50690745e8 Library: a picked photo's flag is drawn filled (#1013)
The Pick flag on thumbnails, in Compare, in the loupe and on the Pick
button was the same outline as the button's idle state, so a pick was
hard to tell at a glance. A new filled pennant (`Icon::FlagPickFilled`)
marks a pick wherever a photo's own flag is shown; buttons, filters and
the reject flag keep their outlines.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011K1peyrh5MdZ6ttHkVq8Gh
2026-10-16 09:38:37 +00:00
wstockandClaude Fable 5.1 b2305da45a Workspace rust-version is 1.95, what the workspace needs (#1841)
`[workspace.package] rust-version` said 1.90 while `jixel` needs 1.94,
`lightcraft-ui-egui` declared 1.95 on its own and the README asks for
1.95. One declaration now, inherited by every crate; the flake's note
says the same.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011K1peyrh5MdZ6ttHkVq8Gh
2026-10-16 09:38:36 +00:00
Matthew James SivakandClaude Opus 5.5 62e82479d2 LR-PROF-CAMERACOLOR: fit a DNG's tone with a look table and a 1024 px preview
A DNG whose profile has a LookTable but no ProfileToneCurve (Adobe Standard in
Lightroom-written DNGs) was not tone-fitted and rendered with the near-linear
default tone: flat and ~0.8 EV darker than Lightroom. A look table defines colour,
not tone, and the fit already applies the tables to its proxy. The preview may now
be 10% of the raw's long edge (and 384 px), so Lightroom's 1024 px previews
qualify. Two lossy ILCE-7CM2 DNGs now match Lightroom's mean linear RGB within 3%.
Render cache 65, look version 10.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 10:46:01 +02:00
Matthew James SivakandClaude Opus 5.5 ed5afb7eb0 LR-IMP-FORMATS: document why lossy JPEG XL DNG tiles keep their declared curve
Lightroom Classic's lossy LinearRaw DNGs linearise the sRGB-coded samples with a
cubic MapPolynomial in OpcodeList2; measured against Lightroom's preview, the
declared-curve reading tracks its rendering and the linear one is 3.6 EV dark.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 10:46:01 +02:00
Matthew James SivakandClaude Opus 5.5 2d57a1466d LR-IMP-FORMATS: decode lossy JPEG XL DNG tiles with a non-linear declared transfer curve
Lightroom Classic 15.1 writes lossy LinearRaw DNGs (e.g. Denoise output) whose
JPEG XL tiles declare Rec. 2100 primaries with the sRGB transfer curve. These
were rejected ("declared encoding that is not linear RGB") and fell back to the
embedded preview. The tile's samples mean what they would in a lossless tile with
the same header, so the declared curve (sRGB, BT.709, DCI, gamma) is now applied
after the primaries matrix, mirrored and unclipped. PQ / HLG / unknown stay
unsupported.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 10:46:01 +02:00
Claude 5902a07354 Windows: folder-drop tests name folders as the Folders tree does; offline test waits for its worker
tests_folder_drop built widget ids from OS paths (C:\...), but the Folders
tree names folders with '/' on every platform (libfolder:C:/Users/...), so
8 tests found no row on Windows. tests_offline asserted that the background
probe had run without waiting for the worker thread; it now waits up to 5 s.
Found by running the tests on windows-latest (gap 9). Test-only changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbegtYaPuwqZ81pGfELsFK
2026-10-16 08:25:46 +00:00
Claude 109e4dabd3 Windows: compare exported paths as paths in the same-folder export test
same_folder_as_original_exports_next_to_each_photo compared path strings.
The export joins the subfolder with '/', so on Windows it reports
C:\...\A/Exports/IMG_1.jpg (a valid path) while the test expected
C:\...\A\Exports/IMG_1.jpg. Found by running the tests on windows-latest
(gap 9). Test-only change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbegtYaPuwqZ81pGfELsFK
2026-10-16 07:25:39 +00:00
Sergio PereaandDeepSeek V4.1 Flash fa26767b81 macOS bundle: drop Info.plist UTI declarations LightCraft cannot open (#1951)
The template was copied from a sibling app: it exported a "LightCraft Document"
UTI for PhotoCraft's `.pcraft` extension (MIME `application/x-lightcraft`) and
imported `.psb` (Photoshop Large Document) and `.qoi`. LightCraft reads none of
them, so the declarations only made Launch Services type PhotoCraft documents as
LightCraft's and left `.pcraft` with three claimant apps among the Craft suite.

Remove both `UTExportedTypeDeclarations` and `UTImportedTypeDeclarations`. No
CFBundleDocumentTypes is added: the formats LightCraft opens are already declared
by the system or another app, so adding them is out of scope here.

`packaging/check-app-specific.sh` now parses the template as a property list and
fails if it declares any of those types again, while still checking the required
bundle keys.

Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
2026-10-16 09:07:29 +02:00
LochLogicandClaude Opus 5.5 16f5a9f0ca Control port: don't clone the connection's socket (Windows: launched programs held it open)
serve() read through stream.try_clone(). On Windows a cloned socket handle is
inheritable (std's accept/connect sockets are not), so every program the app
started while a control client was connected (the browser for a link,
Explorer for Show in Explorer, an external editor) got a copy of the
connection. When the server then closed it, the client saw nothing until that
program exited, and then a reset instead of a clean close. Read and write
through the one stream (&TcpStream is Read and Write) instead.

Regression test (Windows): a program started while a client is connected no
longer delays or resets the close; it failed with ConnectionReset before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 23:16:51 -06:00
Marco Arnulfo b67bb01952 TIFF: read strips and tiles larger than 128 MiB (fixes #1983) 2026-10-16 07:04:45 +02:00
Marco Arnulfo 38973dba3a Imported LUTs no longer leave a copy in the temp folder without a library on disk (part of #1952) 2026-10-16 06:45:40 +02:00
lincleejunandClaude Opus 5.5 389a2cdd65 GPU: a lost device is not polled again, and a poll that panics fails the render (#1858)
Once a Vulkan or DX12 device is lost, wgpu 30 panics in `Device::poll`
instead of returning an error: the device error is not a `PollError`, so
`wgpu_core.rs` hands it to `handle_error_fatal`. The readback assumed the
wait would fail. A render whose readback found the device lost panicked
(caught by `try_render`), and while it unwound, a buffer going back to
the pool polled again from a destructor (`Gpu::trim`). That second panic
aborted the app ("panic in a destructor during cleanup"), as in the
reporter's logs on an Intel UHD 620 under Vulkan, each time a merge lost
the device.

The render device's three polls (the readback, `trim`, `sync`) now go
through `Gpu::poll`, which stops polling a lost device (the device-lost
callback, or a poll that panicked) and turns a panicking poll into an
error that retires the GPU. The render then fails over to the CPU and the
app keeps running. A GPU retired for another reason (a validation error)
keeps a live device and is still polled, so its pooled buffers are freed.

Regression tests run in a child process (they lose the device):
- `a_poll_on_a_lost_device_neither_panics_nor_aborts`: polls panic as
  wgpu's do on a lost Vulkan device; a readback, then an unwinding render
  whose destructor trims the pool. Before the fix the child aborts with
  SIGABRT and the log line above.
- `a_really_lost_device_is_not_polled_again`: a Metal device really lost
  (4200 unsubmitted command buffers, past wgpu-hal's 4096) is not polled
  again. Before the fix the poll still reaches wgpu.
- `a_retired_but_live_device_is_still_polled`: a GPU retired by a
  validation error still polls (and releases its buffers).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RbXK4njy12cpm4PG12Xrqt
2026-10-15 21:40:29 -07:00
Ted Mao 8677e5fe3e Use GitHub nickname for contributor display name
Generated by an AI coding agent.
2026-10-15 21:26:36 -07:00
Marco Arnulfo ef6e62449f LR-EDIT-COLOR-GRADING: a wheel drag holds the pointer and puts it back where it was pressed (#1899) 2026-10-16 05:38:10 +02:00
skylar taylor-barrick f34c7a8a89 Merge pull request #967 from dylanmtaylor/refactor/dry-github-actions
ci: refactor workflows to use storytold/craft-common-actions
2026-10-15 21:34:12 -06:00
Ted Mao 2b83edc8f1 Test previews against reduced full-size renders
Generated by an AI coding agent.
2026-10-15 20:26:22 -07:00
Ted Mao 8b069bf87e Reduce CPU guided-filter coefficient allocations
Generated by an AI coding agent.
2026-10-15 20:26:21 -07:00
skylartaylor 3885b61e6b ci: retain LightCraft installer and package checks 2026-10-16 05:25:18 +02:00
LochLogicandClaude Opus 5.5 2e0906b71a Tests: make the Windows-only failures pass (paths with /, MCP sockets vs child processes)
On Windows 11, `cargo test --workspace` on main fails 11 tests:

- tests_export::same_folder_as_original_exports_next_to_each_photo built its
  expected paths with Path::join (`\`), but export joins the subfolder and
  file name with `/` (join_path) on every platform. Expect what export writes.
- tests_folder_drop (8 tests) looked rows up as
  `source:libfolder:C:\...`, while the Folders section names them with `/`
  (`source:libfolder:C:/...`), so no row was found. Look them up the same way.
- mcp backend::tests::{valid_replies_and_errors_are_preserved,
  malformed_replies_are_rejected_without_resending} failed only when the whole
  crate ran: the shutdown and one-shot-process tests start a copy of the test
  binary, the child can inherit a socket a fake server just accepted, and when
  the child exits Windows closes its copy abortively, resetting the test's
  connection. A test-only lock keeps socket tests and child-process tests from
  overlapping (passes 6 of 6 whole-crate runs, failed 4 of 4 before).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 21:11:32 -06:00
Gert Pellin 27974fac0f Tone: test the edited-curve shoulder at white, not past its end (#1945) 2026-10-16 04:46:51 +02:00
Gert Pellin c5cebdef39 Tone: neutral display tone map is the identity up to white (#1945)
The SDR shoulder in ToneMap::display_hdr ran at neutral Contrast, Whites
and Blacks too, so an unedited JPEG or PNG exported neutral 255, 254 and
253 one level darker and a white background never came out as 255. The
shoulder now shapes edited curves only; neutral sliders are the identity
up to white and clip above it. Edited curves render as before (V1).

Tests: the identity test runs to 1.0, a new pipeline test renders the
issue's neutral greys back exactly, the sRGB ramp round trip is exact,
and a guard keeps the shoulder on edited curves.
2026-10-16 04:27:35 +02:00
Marco Arnulfo 1162c2a018 crop.set refuses a crop smaller than the crop tool allows, instead of exporting 1×1 (part of #1952) 2026-10-16 04:09:25 +02:00
LochLogicandClaude Opus 5.5 180fdb3b41 CI: catalog's staging-link test module compiles only on Unix (clippy -D warnings on Windows)
`tests_staging` holds one `#[cfg(unix)]` test (#1502), so on Windows its
`use super::*` is unused and `cargo clippy --workspace --all-targets -- -D
warnings` (the clippy step of `cargo xtask ci`) fails in lightcraft-catalog.
Gate the module itself on Unix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 19:49:57 -06:00
Dylan M. Taylor 0802892132 ci: refactor workflows to use storytold/craft-common-actions 2026-10-15 21:19:37 -04:00
Marco Arnulfo e14db89462 LR-EXP-BITDEPTH: app.export refuses a bitDepth the format doesn't have (part of #1952) 2026-10-16 02:21:07 +02:00
Marco Arnulfo c8f741fd0b Contributors: add my name for the About window 2026-10-16 02:20:02 +02:00
Claude 54c6c43b07 #1927: Constrain Crop tightens the stored crop
Constrain Crop only applied at render time, and the Crop tool shows the
uncropped view with the stored crop, so in the Crop panel (where the
checkbox is) ticking it or moving a Geometry slider changed nothing.
Session::set_develop now shrinks the stored crop about its centre until it
fits the warped photo when Constrain Crop is turned on, or when an edit
changes the warp (Geometry, Upright, lens corrections, section eyes) while
it is on. A crop edit itself is kept as drawn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbegtYaPuwqZ81pGfELsFK
2026-10-16 00:01:00 +00:00
helgehelge123andClaude Opus 5.5 90a248edad M12: Describe selections from SAM 3's semantic mask: sure inside, no lines between instances
Describe merged the detector's per-instance masks. Those stay near 0 even well inside what they
found: a sky came out about 87 % selected, a volleyball net about 70 %, a person about 94 %.
Two instances that touch both fade out where they meet, so a line showed between people standing
side by side.

- The detector's semantic head is now ported: semantic_projection over the pixel decoder, the
  transformers implementation's semantic_seg. It matches the reference to about 1e-3, like the
  instance masks. tools/sam3_reference.py writes it and the reference test checks it; older
  reference files still pass.
- Each instance found (score above the threshold, as before) takes the semantic logits where it
  is the strongest instance and near (above -4). The semantic mask is sure inside and runs on
  across the boundary between two instances. Far from every instance nothing changes, so
  Describe selects nothing it didn't find before.

On 16 prompts over three photos (a mountain landscape, two gym photos), the median coverage
inside each selection rises, e.g.:
- sky 0.87 -> 1.00
- mountains 0.81 -> 0.99
- net 0.71 -> 0.99
- floor 0.92 -> 1.00
- person 0.94 -> 0.99

Each selection gains 0 to 1.9 % of the photo at its soft rim and loses none.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 01:35:59 +02:00
Claude 37a3ab4177 #1507: web start-up treats only NotFoundError as a missing file
OPFS lookups turned any exception into "absent", and start-up only logged
other read errors, so a library with an unreadable file opened incomplete
and the next save could overwrite the stored copy. Only NotFoundError now
means absent; when a stored library file or the active-library pointer
can't be read, the library isn't opened, nothing is saved and the window
names the file. An unreadable thumbnail index no longer deletes every
stored thumbnail as unindexed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbegtYaPuwqZ81pGfELsFK
2026-10-15 23:08:54 +00:00