Commit Graph
19 Commits
Author SHA1 Message Date
dtourolle e8898a5c38 Specify a scene-referred pipeline (D19)
The spec missed Ansel, and with it Aurélien Pierre's argument that a
display-referred curve early in the pipeline throws away what every
later stage needs. Read against that argument, the code broke it four
ways: the base curve was flat past its last point and so clipped every
recovered highlight; the detail stage was handed curved, clipped values
while its comments promised linear ones; the edits ran in camera RGB
because the matrix had drifted to after them, against ARCH §5.2; and the
tone curve clamped to [0, 1] around a 2.2 gamma mid-chain.

D19 records the decision: unbounded scene-linear colour from the matrix
to one view transform, last, after the detail stage. FR-DEV-3j specifies
that view transform as an adjustable operation (contrast, white) with a
default fitted to where the retired default curve put middle grey.
FR-DEV-3e retires the per-body base curves, whose own file called them
hand-tuned shapes of unknown provenance. FR-DEV-3f makes a film stock
the view transform when one is chosen, instead of a rendering at order
25 that the later edits acted on. FR-DEV-2 gains the acceptance test
that holds the rule, and ARCH gains §6.14 and the corrected §5.2 order.
2026-09-27 16:52:52 -04:00
dtourolle 7558053932 Say that a mask layer's settings add to the photograph's
fc54523 (0.18.1) stopped running a layer as a second chain after every
global operation and made its settings offsets applied at each
operation's own place, and nothing outside the code said so. The
manual still read as though a mask's slider were a setting of its own,
frame-budget.md described the masks as "a separate chain per layer",
and no document said how a layer is blended at all.

architecture.md §5.2 now says it: the offset, the blend by the layer's
weighted difference from the global result, what a photograph with no
layers composes to, and the film as the one operation whose settings
are averaged instead (6b99f67). FR-DEV-3 records the change as resolved
beside its local-adjustments bullet, frame-budget.md's note on what it
does not measure describes the cost as it now is, and the manual gives
the arithmetic in one sentence: -20 in a mask over -30 is -50 there.
The bundled manual is regenerated to match.
2026-09-27 07:59:29 -04:00
dtourolle 6bccc2db13 Say where hot and dead photosites are repaired
c50d96e added a repair pass ahead of the demosaic and no document said
so: FR-RAW-3's text names levels, the CFA and the colour matrices, and
architecture.md §5.2's stage diagram went from the upload straight to
black and white levels.

FR-RAW-3 now carries a status note: what counts as hot or dead, what
the photosite becomes, that Bayer and X-Trans share the pass, that
export and every other demosaicing path get it with no setting, the
test that holds it, and that the DNG defect map dr-decode can read is
still not used. §5.2 gains the stage and a paragraph on why it sits
before the demosaic, and its pointer to the raw histogram's tap names
the demosaic box rather than a row count the new stage would have made
wrong.
2026-09-27 07:59:00 -04:00
dtourolle adbb9ac9e6 Tag the judgement dispatch R7 and record which half of FR-CULL-13 is met
apply_judgement and apply_label carry TRACES: R7, the burst
representative callback FR-CULL-13 with a note that choosing it writes
the grouping and no verdict. The register's status for FR-CULL-13 says
the write-path test is met and the evidence chips are outstanding.
Traceability matrix regenerated.
2026-09-27 07:20:41 -04:00
dtourolle 3912bc0d1d Point architecture §7.1 at the executors module and record NFR-ARCH-1
§7.1 now says where its table lives in code, how the UI thread is
marked and guarded, and that the counts are a budget rather than a
bound until work is pooled by executor. The register's status note says
what is met — named, spawned through one module, block_on guarded and
tested — and what is not: pooling, a guard for synchronous file reads
and catalog queries, the two mask workers, and threads the core crates
start.
2026-09-27 07:08:37 -04:00
dtourolle 6b99f67f47 Develop a mask layer's film on its own settings
A layer offered the film's sliders and they moved nothing: its copy of
the node was never given the stock, so it stayed inactive. Film now
works in a layer the way the other adjustments do, as offsets to the
photograph's settings, but blended as settings rather than as results,
since a film is a rendering and cross-fading two developments is not
what a region on a pushed film looks like.

- dr-film bakes no slider. Exposure is a gain in the shader; push
  interpolates the stock's measured processes, one curve row each; the
  print is split at the paper's log exposure, so print exposure is an
  addition between two lookups and exact at any setting. The enlarger
  stays balanced at the photograph's exposure.
- film_sim reads all four settings as uniforms, format one-hot over a
  grain count per format, so every uniform is linear in what it does.
- Operation::blends_settings lets the composer average each overlapping
  layer's uniforms with the global ones by mask weight, the global
  setting taking whatever weight the layers leave, and run the fragment
  once. Three layers at full weight give the mean of their settings.
- The stock picker is hidden on a layer. Only the photograph's exposure
  re-solves the print balance; push, print exposure and format need no
  rebake at all now.
2026-09-26 23:29:13 -04:00
dtourolle 9f95d23ff4 Say that no workflow builds the Flatpak yet
NFR-COMPAT-2's table has CI building every channel, the Flatpak
included. No workflow in .gitea/workflows/ builds it, and the sweep
before this one records that none has been built by hand either. A
status note under the table says so, so the decision and the state are
not read as the same thing.
2026-09-26 14:58:46 -04:00
dtourolle caaae11d98 Say the folder dialogue is the portal, and what the Flatpak has not proved
distribution.md §4, outstanding.md's FR-PLAT-LIN-3 entry, the Flatpak
manifest's comment and the README all said a library was chosen by
typing a path and that nothing in the tree called the FileChooser
portal. Since 6683c14 every folder the desktop asks for is chosen
through rfd's xdg-portal backend, so those sentences were false.

What they now say instead is narrower than "it works in the sandbox":
no Flatpak has been built here, so whether the portal's path opens a
library, holds across a restart and takes a sidecar is unobserved, and
volumes() still cannot see a host card. The chooser also landed in ui/
rather than behind the dr-plat seam distribution.md had proposed, and
both documents say so. FR-PLAT-LIN-3 gets a status note to the same
effect.
2026-09-26 14:52:44 -04:00
dtourolle 1abb18d972 Specify albums and pointing at folders, and describe them in the manual
FR-EXP-10 is the album: a named export destination beneath the
collections, whose folder holds only the exported files while the
catalog links each back to its original; how albums sync, why a device
folder does not, and why the tables are made on first use rather than
by a migration. FR-EXP-6 now says the destination is an album, never
inside the library, and that folders are chosen by pointing — the
portal or Windows dialogue, SAF's tree picker, the server browser —
each able to make a folder.

The manual's launch and export sections say the same in the words on
screen. Its pictures still show the 0.16.0 launch screen and export
settings; they are re-recorded with the rig, not edited by hand.
2026-09-26 14:13:53 -04:00
dtourolle a59f14c797 Describe shipped presets and looks in the manual and FR-DEV-6
The presets sheet now lists the shipped collection beside the
photographer's own, a copy under a shipped name overrides it, and
shipped and imported presets are looks that leave a photograph's own
corrections alone. The manual says so where it introduces the sheet,
and FR-DEV-6 states the rule. The sheet's screenshot (media/presets.png)
predates the sections and needs re-recording.
2026-09-26 13:44:32 -04:00
dtourolle e31990550f Record progressive refinement as built, and the fit view's two speed-ups
display-and-extension.md still called FR-DSP-4 absent, and
frame-budget.md ended its reading at "satisfied vacuously". 0.15.0 built
it (refine.rs, the provisional histogram, the fade), so the table row
says so, frame-budget.md gains a note under its FR-DSP-4 section, and the
register gains a status note like FR-RAW-2's and FR-UI-5's.

frame-budget.md also gains a short section with the figures 1dc7b45
(the fit view's gather cached per framing) and d430ec9 (an identity
detail pass dropped) measured, since its fit rows no longer describe the
fused path. They are quoted from those commits, on the machine they name,
and are marked as not re-run here.
2026-09-26 07:45:26 -04:00
dtourolle 7c9a4ee358 Describe consolidating duplicate originals in the manual and the register
FR-CAT-11a records what #67 built: groups of the same file listed on
demand, proved the same before anything moves, merged onto one survivor
and the rest trashed a group at a time. The manual's new section under
The library says how to reach the page, how the copy that stays is
chosen, what the check reads and what merges.
2026-09-26 07:19:14 -04:00
dtourolle b5ae5c2be1 Record FR-DEV-16 as met and where FR-UI-5 stands
FR-DEV-16's promise that the gesture book cannot describe a binding the
application lacks is now enforced by the gestures gate in both directions,
and every binding it names is bound and tagged, so it is marked met, with
what develop answers beyond the list.

FR-UI-5 is not met in full: its keyboard half and the 2026-09-19 amendment
are, but no develop slider takes the scroll wheel, so its status says that
rather than rounding up.
2026-09-24 23:42:28 -04:00
dtourolle ff89a4fa21 Specify perspective correction as FR-DEV-20
Issue #13 asks for a vertical and horizontal keystone, and its number was
renumbered from FR-DEV-19 when the spec gave that to mask editing. The
clause was never written into the register, so the work had nothing to
trace to.

It is written as part of framing: after the crop and the straightening,
before the stored orientation and the lens warp, carrying framing's
Compose attribute, and with the inscribed crop accounting for it.
2026-09-24 22:13:11 -04:00
dtourolle 9772785f81 Measure which mask layers a crop takes out of the frame
Mask geometry is stored in source coordinates, so re-cropping tighter
never destroys a layer. It makes it invisible: the layer stays in the
panel and the sidecar, its adjustment lands on pixels nobody will see,
and nothing says so. The spec had no clause for this; FR-DEV-17 now
states it, under the ID issue #10 reserved.

dr_pipeline::orphan samples each layer's mask on a 64x64 lattice over
the source, with the gradient, radial, brush and model-raster geometry
the mask shader uses, folds the parts by their joins and inversions, and
maps the samples through the framing to see how much of the coverage
the crop keeps. `hidden_by_crop` reports the layers whose share fell
below a tenth, and only those the change newly hid, so an already
stranded layer is not announced again on every later adjustment.

Ranges follow the picture and region selections need a label map this
crate does not hold, so a layer that adds either is never reported: a
false alarm on the common path would teach the notice to be dismissed
unread.
2026-09-24 21:52:02 -04:00
dtourolle 733a033274 Test that a stub decoder reaches the scan, the ladder and export
FR-RAW-2's "without changing callers" needs a test that would fail if a
caller named the concrete decoder; passing a real RAW through rawler
cannot tell the two apart, because both routes give the same answer.

The decoder_seam tests hand a stub decoder, for a container no real
decoder reads, to the catalog scan (read_metadata_only over a folder
backend), the preview ladder (the remote two-stage fetch, an import's
thumbnail and the viewer's no-GPU fallback) and export (open_for_export,
skipped without an adapter). Each assertion is on something only the
stub produces: its camera and date, a header fetched at its 64-byte
budget rather than HEADER_BYTES, preview and sensor sizes turned by its
orientation. Switching collect_metadata or make_thumbnail back to the
free functions fails two of the three tests.

The develop test_support module is widened to the crate so the export
test shares the one headless GPU context the other tests use. The
requirements note for FR-RAW-2 now records the trait as built and the
second decoder as not.
2026-09-24 21:33:14 -04:00
dtourolle e8f68a92f8 Record intersection as built in the requirement and the mask plan
FR-DEV-19a said a part is added to the mask or taken out of it, and
mask-editing.md listed Intersect as an M2 item with nothing built. Both
now say what shipped: the requirement names the third join and why it is
a product rather than a minimum, and how old and new sidecars read across
it; the plan marks the blend-table row built, names the tests that hold
the GPU to the definition, and splits M2 into what is done and what is
still outstanding (joining non-painted parts from the panel, per-part
distance fields, folding two layers).
2026-09-24 21:25:48 -04:00
dtourolle af162dd010 Merge: origin's sync ordering and adoption work, its scan-complete trigger ported into library_ui/ 2026-09-21 11:32:05 +02:00
dtourolle 84fade99ec Put the developer docs under docs/dev and index the folder for users first
docs/ had 26 developer documents flat beside the manual, and the two
audiences are very differently sized: most readers want the manual and
the gesture reference, a few want the register, the designs and the
measurements. The manual and gestures.md stay at the top; everything for
someone changing the code moves to docs/dev/, and the two documents that
name their own successors — the v0.1 milestone and the UI-refinement plan
— go to docs/dev/archive/ rather than being deleted, since both are still
cited. docs/README.md is the index, users first.

Every reference follows: code comments, Cargo manifests, the workflows,
the pre-commit hook, the bench and traceability tools (which locate the
repo root by docs/dev/requirements.md now), packaging, the Docker READMEs,
CLAUDE.md, CONTRIBUTING.md and the README. The matrix links one level
deeper and is regenerated. Links out of the moved documents into the tree
gain a level; a link checker over every Markdown file finds none broken.
2026-09-20 21:16:03 +02:00