Currently the live swatch grid in Stage 3 — Interactive Measurement hard-codes CIEDE2000 (ΔE₀₀) quality bands:
Band
Condition
CSS class
Colour
Good
ΔE₀₀ < 2
de-good
Green
Warning
ΔE₀₀ < 5
de-warning
Amber
Bad
ΔE₀₀ ≥ 5
de-bad
Red
These fixed values are industry-common defaults but are not universally appropriate. Different media, instruments, customer SLAs, or quality standards (e.g. ISO 12647, GRACoL, FOGRA, internal print-house tolerances) require different acceptance thresholds.
This feature makes the two threshold values (good upper-bound and warning upper-bound) user-configurable via the existing Settings dialog, persists them, and applies them to all subsequent Stage 3 swatch rendering and statistics.
Motivation / User Value
Print-house operators and colour scientists can match ICCery’s visual quality indicators to their contractual or process-control limits.
Avoids false “bad” flags on high-gamut or noisy media where a slightly higher ΔE is still acceptable.
Allows tighter thresholds for critical proofing workflows.
Completes the Settings surface that already manages Argyll path, default instrument and log level.
Scope & Technical Requirements
1. Settings schema extension
Extend the persisted settings object (currently loaded/saved via load_settings / save_settings) with:
Defaults remain the current hard-coded values (2.0 / 5.0) so existing behaviour is unchanged for users who never open Settings.
2. Settings UI
Add a new section inside the existing Settings dialog (#settingsDialog), preferably under a heading such as “Measurement Quality Indicators” or “ΔE₀₀ Thresholds”:
Two numeric inputs (step 0.1, min 0):
“Good (green) when ΔE₀₀ < …”
“Warning (amber) when ΔE₀₀ < …”
Live validation: if the user enters a good value larger than the warning value, show an inline error and disable Save until corrected.
Optional “Reset to defaults (2.0 / 5.0)” link/button.
Short explanatory tooltip or help text: “These thresholds control the traffic-light colours on the Stage 3 live swatch grid and the average/max ΔE statistics.”
3. Runtime application
On Settings load / app start, expose the two values to the frontend (either via the existing settings object or a small dedicated getter).
swatch_grid.js must read the configured thresholds instead of the literals 2 and 5.
The same thresholds are used for any future aggregate statistics or summary badges that rely on the same bands.
Changing thresholds while a measurement session is in progress should either:
re-classify already-rendered patches immediately, or
apply only to newly completed rows (document the chosen behaviour in the UI).
4. Persistence & defaults
Values are stored in the same settings file / store already used for argyll_binary_dir, default_instrument and log_level.
On first run (or missing keys) the defaults 2.0 / 5.0 are written so the schema is always complete.
No migration of existing measurement artefacts is required; thresholds only affect live visualisation.
5. Out of scope (this feature)
Per-profile or per-preset threshold overrides (can be a later enhancement).
Changing the ΔE formula itself (stays CIEDE2000).
Exporting thresholds into the generated .ti3 / ICC metadata.
Colour-blind-safe alternative palettes (separate accessibility ticket).
Acceptance Criteria
Settings dialog contains two editable numeric fields for the good and warning ΔE₀₀ upper bounds, defaulting to 2.0 and 5.0.
Validation prevents saving when good-max > warning-max.
Saved values persist across application restarts.
Stage 3 swatch grid uses the configured thresholds for de-good / de-warning / de-bad classification and for the average/max statistics panel.
Existing behaviour is identical when the user has never changed the thresholds.
Tooltip / help text clearly explains the effect of the settings.
No regression in chartread state machine, JSON row parsing, or multi-pass averaging.
Implementation Notes
Frontend
src/js/settings.js — load / save the two new fields; add validation on the Save button path.
src/js/swatch_grid.js — replace hard-coded 2 / 5 with values obtained from settings (cache them at listener start or read once per row).
HTML of the Settings dialog — add the new form controls and any required labels/tooltips.
Optional: small CSS variable or data-attribute approach if the traffic-light colours themselves later become themeable.
Backend (Rust / Tauri)
Extend the settings struct (or equivalent) with the two f64 fields and their serde defaults.
Ensure load_settings / save_settings round-trip the new keys.
Testing suggestions
Unit-style: feed synthetic Lab pairs with known ΔE₀₀ and assert correct CSS classes for various threshold pairs.
Manual: set thresholds to 1.0 / 3.0, re-measure a strip, confirm visual bands move accordingly; restart app and confirm persistence.
Dependencies & Ordering
Depends on: Existing Settings dialog and persistence infrastructure (already present).
Blocks: None.
Suggested ordering: Can be implemented independently of other Stage 3 work; natural fit for a dedicated “Settings & Preferences” milestone or as a small follow-up to the current measurement polish.
References
Current hard-coded logic: src/js/swatch_grid.js (ΔE classification block).
Industry context: ISO 12647, GRACoL, FOGRA tolerances frequently use ΔE₀₀ bands in the 1.5–5 range depending on process and substrate.
## Description
Currently the live swatch grid in **Stage 3 — Interactive Measurement** hard-codes CIEDE2000 (ΔE₀₀) quality bands:
| Band | Condition | CSS class | Colour |
|-------------|-------------|---------------|--------|
| Good | ΔE₀₀ < 2 | `de-good` | Green |
| Warning | ΔE₀₀ < 5 | `de-warning` | Amber |
| Bad | ΔE₀₀ ≥ 5 | `de-bad` | Red |
These fixed values are industry-common defaults but are not universally appropriate. Different media, instruments, customer SLAs, or quality standards (e.g. ISO 12647, GRACoL, FOGRA, internal print-house tolerances) require different acceptance thresholds.
This feature makes the two threshold values (good upper-bound and warning upper-bound) user-configurable via the existing Settings dialog, persists them, and applies them to all subsequent Stage 3 swatch rendering and statistics.
---
## Motivation / User Value
- Print-house operators and colour scientists can match ICCery’s visual quality indicators to their contractual or process-control limits.
- Avoids false “bad” flags on high-gamut or noisy media where a slightly higher ΔE is still acceptable.
- Allows tighter thresholds for critical proofing workflows.
- Completes the Settings surface that already manages Argyll path, default instrument and log level.
---
## Scope & Technical Requirements
### 1. Settings schema extension
Extend the persisted settings object (currently loaded/saved via `load_settings` / `save_settings`) with:
```json
{
"delta_e_good_max": 2.0,
"delta_e_warning_max": 5.0
}
```
- Both values are floating-point ≥ 0.
- Invariant: `delta_e_good_max` ≤ `delta_e_warning_max`.
- Defaults remain the current hard-coded values (2.0 / 5.0) so existing behaviour is unchanged for users who never open Settings.
### 2. Settings UI
Add a new section inside the existing Settings dialog (`#settingsDialog`), preferably under a heading such as **“Measurement Quality Indicators”** or **“ΔE₀₀ Thresholds”**:
- Two numeric inputs (step 0.1, min 0):
- “Good (green) when ΔE₀₀ < …”
- “Warning (amber) when ΔE₀₀ < …”
- Live validation: if the user enters a good value larger than the warning value, show an inline error and disable Save until corrected.
- Optional “Reset to defaults (2.0 / 5.0)” link/button.
- Short explanatory tooltip or help text: “These thresholds control the traffic-light colours on the Stage 3 live swatch grid and the average/max ΔE statistics.”
### 3. Runtime application
- On Settings load / app start, expose the two values to the frontend (either via the existing settings object or a small dedicated getter).
- `swatch_grid.js` must read the configured thresholds instead of the literals `2` and `5`.
- Classification logic becomes:
```js
if (deltaE < goodMax) {
patchEl.classList.add("de-good");
} else if (deltaE < warningMax) {
patchEl.classList.add("de-warning");
} else {
patchEl.classList.add("de-bad");
}
```
- The same thresholds are used for any future aggregate statistics or summary badges that rely on the same bands.
- Changing thresholds while a measurement session is in progress should either:
- re-classify already-rendered patches immediately, **or**
- apply only to newly completed rows (document the chosen behaviour in the UI).
### 4. Persistence & defaults
- Values are stored in the same settings file / store already used for `argyll_binary_dir`, `default_instrument` and `log_level`.
- On first run (or missing keys) the defaults 2.0 / 5.0 are written so the schema is always complete.
- No migration of existing measurement artefacts is required; thresholds only affect live visualisation.
### 5. Out of scope (this feature)
- Per-profile or per-preset threshold overrides (can be a later enhancement).
- Changing the ΔE formula itself (stays CIEDE2000).
- Exporting thresholds into the generated `.ti3` / ICC metadata.
- Colour-blind-safe alternative palettes (separate accessibility ticket).
---
## Acceptance Criteria
- [ ] Settings dialog contains two editable numeric fields for the good and warning ΔE₀₀ upper bounds, defaulting to 2.0 and 5.0.
- [ ] Validation prevents saving when good-max > warning-max.
- [ ] Saved values persist across application restarts.
- [ ] Stage 3 swatch grid uses the configured thresholds for `de-good` / `de-warning` / `de-bad` classification and for the average/max statistics panel.
- [ ] Existing behaviour is identical when the user has never changed the thresholds.
- [ ] Tooltip / help text clearly explains the effect of the settings.
- [ ] No regression in chartread state machine, JSON row parsing, or multi-pass averaging.
---
## Implementation Notes
**Frontend**
- `src/js/settings.js` — load / save the two new fields; add validation on the Save button path.
- `src/js/swatch_grid.js` — replace hard-coded `2` / `5` with values obtained from settings (cache them at listener start or read once per row).
- HTML of the Settings dialog — add the new form controls and any required labels/tooltips.
- Optional: small CSS variable or data-attribute approach if the traffic-light colours themselves later become themeable.
**Backend (Rust / Tauri)**
- Extend the settings struct (or equivalent) with the two `f64` fields and their serde defaults.
- Ensure `load_settings` / `save_settings` round-trip the new keys.
**Testing suggestions**
- Unit-style: feed synthetic Lab pairs with known ΔE₀₀ and assert correct CSS classes for various threshold pairs.
- Manual: set thresholds to 1.0 / 3.0, re-measure a strip, confirm visual bands move accordingly; restart app and confirm persistence.
---
## Dependencies & Ordering
- **Depends on:** Existing Settings dialog and persistence infrastructure (already present).
- **Blocks:** None.
- **Suggested ordering:** Can be implemented independently of other Stage 3 work; natural fit for a dedicated “Settings & Preferences” milestone or as a small follow-up to the current measurement polish.
---
## References
- Current hard-coded logic: `src/js/swatch_grid.js` (ΔE classification block).
- Settings surface: `src/js/settings.js` + Settings dialog markup.
- CIEDE2000 implementation: `src/js/delta_e.js`.
- Industry context: ISO 12647, GRACoL, FOGRA tolerances frequently use ΔE₀₀ bands in the 1.5–5 range depending on process and substrate.
Implemented in `feat/184-configurable-delta-e` (stacked on `enh/178-swatch-grid`):
- Added `delta_e_good_max` and `delta_e_warning_max` to `AppSettings` in `src-tauri/src/settings.rs` with defaults `2.0` and `5.0`.
- Added a Stage 3 ΔE₀₀ threshold section to the Settings dialog.
- Enforced the invariant `good_max < warning_max` on save.
- Updated `swatch_grid.js` to load thresholds from settings and apply them to traffic-light classification.
- Added live re-classification of rendered patches when settings change.
Closes #184.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Description
Currently the live swatch grid in Stage 3 — Interactive Measurement hard-codes CIEDE2000 (ΔE₀₀) quality bands:
de-goodde-warningde-badThese fixed values are industry-common defaults but are not universally appropriate. Different media, instruments, customer SLAs, or quality standards (e.g. ISO 12647, GRACoL, FOGRA, internal print-house tolerances) require different acceptance thresholds.
This feature makes the two threshold values (good upper-bound and warning upper-bound) user-configurable via the existing Settings dialog, persists them, and applies them to all subsequent Stage 3 swatch rendering and statistics.
Motivation / User Value
Scope & Technical Requirements
1. Settings schema extension
Extend the persisted settings object (currently loaded/saved via
load_settings/save_settings) with:delta_e_good_max≤delta_e_warning_max.2. Settings UI
Add a new section inside the existing Settings dialog (
#settingsDialog), preferably under a heading such as “Measurement Quality Indicators” or “ΔE₀₀ Thresholds”:3. Runtime application
swatch_grid.jsmust read the configured thresholds instead of the literals2and5.4. Persistence & defaults
argyll_binary_dir,default_instrumentandlog_level.5. Out of scope (this feature)
.ti3/ ICC metadata.Acceptance Criteria
de-good/de-warning/de-badclassification and for the average/max statistics panel.Implementation Notes
Frontend
src/js/settings.js— load / save the two new fields; add validation on the Save button path.src/js/swatch_grid.js— replace hard-coded2/5with values obtained from settings (cache them at listener start or read once per row).Backend (Rust / Tauri)
f64fields and their serde defaults.load_settings/save_settingsround-trip the new keys.Testing suggestions
Dependencies & Ordering
References
src/js/swatch_grid.js(ΔE classification block).src/js/settings.js+ Settings dialog markup.src/js/delta_e.js.Implemented in
feat/184-configurable-delta-e(stacked onenh/178-swatch-grid):delta_e_good_maxanddelta_e_warning_maxtoAppSettingsinsrc-tauri/src/settings.rswith defaults2.0and5.0.good_max < warning_maxon save.swatch_grid.jsto load thresholds from settings and apply them to traffic-light classification.Closes #184.